From 49ae2cf08fa85bc9cfe75e152b9aba31d7dac692 Mon Sep 17 00:00:00 2001 From: "Blue (Lukas Rieger)" Date: Sat, 2 Nov 2019 17:23:48 +0100 Subject: [PATCH] Initial commit: Merging Projects BlueMapCore, BlueMapCLI and BlueMapSponge into one --- .gitignore | 24 + BlueMapCLI/build.gradle | 4 + .../bluecolored/bluemap/cli/BlueMapCLI.java | 555 +++ .../bluemap/cli/RenderManager.java | 176 + BlueMapCore/build.gradle | 21 + .../bluemap/core/logger/AbstractLogger.java | 69 + .../bluemap/core/logger/Logger.java | 99 + .../core/logger/PrintStreamLogger.java | 59 + .../bluemap/core/logger/VoidLogger.java | 59 + .../bluecolored/bluemap/core/mca/Chunk.java | 75 + .../bluemap/core/mca/ChunkAnvil112.java | 172 + .../bluemap/core/mca/ChunkAnvil113.java | 224 + .../bluemap/core/mca/MCABlock.java | 92 + .../bluemap/core/mca/MCAWorld.java | 438 ++ .../bluemap/core/mca/MCAWorldChunk.java | 85 + .../mca/extensions/BlockStateExtension.java | 40 + .../core/mca/extensions/ConnectExtension.java | 57 + .../ConnectSameOrFullBlockExtension.java | 41 + .../core/mca/extensions/DoorExtension.java | 74 + .../mca/extensions/DoublePlantExtension.java | 64 + .../core/mca/extensions/FireExtension.java | 67 + .../extensions/GlassPaneConnectExtension.java | 45 + .../NetherFenceConnectExtension.java | 43 + .../mca/extensions/RedstoneExtension.java | 84 + .../core/mca/extensions/SnowyExtension.java | 58 + .../mca/extensions/StairShapeExtension.java | 129 + .../extensions/TripwireConnectExtension.java | 43 + .../mca/extensions/WallConnectExtension.java | 64 + .../WoodenFenceConnectExtension.java | 48 + .../core/mca/mapping/BiomeIdMapper.java | 69 + .../core/mca/mapping/BlockIdMapper.java | 119 + .../core/mca/mapping/BlockProperties.java | 49 + .../core/mca/mapping/BlockPropertyMapper.java | 103 + .../core/mca/mapping/BlockStateMapping.java | 63 + .../bluemap/core/mca/mapping/LightData.java | 52 + .../bluecolored/bluemap/core/model/Face.java | 218 + .../bluecolored/bluemap/core/model/Model.java | 149 + .../bluemap/core/render/RenderSettings.java | 88 + .../core/render/StaticRenderSettings.java | 80 + .../bluemap/core/render/TileRenderer.java | 74 + .../bluemap/core/render/WorldTile.java | 69 + .../core/render/context/BlockContext.java | 57 + .../render/context/EmptyBlockContext.java | 168 + .../render/context/ExtendedBlockContext.java | 72 + .../context/SlicedWorldChunkBlockContext.java | 52 + .../context/WorldChunkBlockContext.java | 79 + .../bluemap/core/render/hires/HiresModel.java | 94 + .../core/render/hires/HiresModelManager.java | 168 + .../core/render/hires/HiresModelRenderer.java | 115 + .../hires/blockmodel/BlockStateModel.java | 68 + .../blockmodel/BlockStateModelFactory.java | 98 + .../hires/blockmodel/LiquidModelBuilder.java | 245 + .../blockmodel/ResourceModelBuilder.java | 386 ++ .../core/render/lowres/LowresModel.java | 229 + .../render/lowres/LowresModelManager.java | 309 ++ .../core/resourcepack/BlockColorProvider.java | 239 + .../BlockModelElementFaceResource.java | 142 + .../BlockModelElementResource.java | 144 + .../core/resourcepack/BlockModelResource.java | 142 + .../core/resourcepack/BlockStateResource.java | 154 + .../InvalidResourceDeclarationException.java | 43 + .../resourcepack/NoSuchResourceException.java | 43 + .../resourcepack/NoSuchTextureException.java | 43 + .../core/resourcepack/ResourcePack.java | 189 + .../core/resourcepack/TextureProvider.java | 231 + .../bluemap/core/threejs/BufferGeometry.java | 312 ++ .../bluecolored/bluemap/core/util/AABB.java | 438 ++ .../bluecolored/bluemap/core/util/Axis.java | 51 + .../bluemap/core/util/ConfigUtil.java | 135 + .../bluemap/core/util/Direction.java | 75 + .../bluemap/core/util/FileUtil.java | 76 + .../bluemap/core/util/IntersectionPoint.java | 47 + .../bluemap/core/util/MathUtil.java | 102 + .../bluemap/core/util/ModelUtils.java | 90 + .../bluemap/core/util/UpdateDeamon.java | 54 + .../bluemap/core/util/Updateable.java | 31 + .../bluemap/core/util/WeighedArrayList.java | 76 + .../core/web/BlueMapWebRequestHandler.java | 276 ++ .../bluemap/core/web/BlueMapWebServer.java | 54 + .../bluemap/core/web/WebFilesManager.java | 73 + .../bluemap/core/web/WebServerConfig.java | 40 + .../bluemap/core/web/WebSettings.java | 132 + .../core/webserver/HttpConnection.java | 126 + .../bluemap/core/webserver/HttpRequest.java | 206 + .../core/webserver/HttpRequestHandler.java | 31 + .../bluemap/core/webserver/HttpResponse.java | 149 + .../core/webserver/HttpStatusCode.java | 70 + .../bluemap/core/webserver/WebServer.java | 113 + .../bluecolored/bluemap/core/world/Block.java | 91 + .../bluemap/core/world/BlockState.java | 199 + .../bluemap/core/world/CachedBlock.java | 130 + .../world/ChunkNotGeneratedException.java | 43 + .../bluecolored/bluemap/core/world/World.java | 78 + .../bluemap/core/world/WorldChunk.java | 85 + .../src/main/resources/DefaultResources.zip | Bin 0 -> 1028645 bytes BlueMapCore/src/main/resources/biomes.json | 452 ++ .../src/main/resources/blockColors.json | 11 + .../src/main/resources/blockIdMappings.json | 1487 ++++++ .../src/main/resources/blockProperties.json | 4402 +++++++++++++++++ BlueMapCore/src/main/resources/webroot.zip | Bin 0 -> 203135 bytes .../src/main/webroot/assets/compass.svg | 17 + BlueMapCore/src/main/webroot/assets/gear.svg | 19 + .../src/main/webroot/assets/skybox/down.png | Bin 0 -> 4533 bytes .../src/main/webroot/assets/skybox/east.png | Bin 0 -> 4605 bytes .../src/main/webroot/assets/skybox/north.png | Bin 0 -> 4605 bytes .../src/main/webroot/assets/skybox/south.png | Bin 0 -> 4605 bytes .../src/main/webroot/assets/skybox/up.png | Bin 0 -> 4536 bytes .../src/main/webroot/assets/skybox/west.png | Bin 0 -> 4605 bytes BlueMapCore/src/main/webroot/index.html | 22 + .../src/main/webroot/js/libs/bluemap.js | 1201 +++++ .../src/main/webroot/js/libs/jquery.min.js | 2 + .../src/main/webroot/js/libs/three.min.js | 946 ++++ BlueMapCore/src/main/webroot/js/site.js | 6 + BlueMapCore/src/main/webroot/style/style.css | 290 ++ BlueMapSponge/build.gradle | 4 + .../bluemap/sponge/Slf4jLogger.java | 59 + .../bluemap/sponge/SpongePlugin.java | 70 + LICENSE | 22 + README.md | 17 + build.gradle | 41 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 188 + gradlew.bat | 100 + settings.gradle | 8 + 125 files changed, 20404 insertions(+) create mode 100644 .gitignore create mode 100644 BlueMapCLI/build.gradle create mode 100644 BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java create mode 100644 BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/RenderManager.java create mode 100644 BlueMapCore/build.gradle create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/AbstractLogger.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/Logger.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/PrintStreamLogger.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/VoidLogger.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/Chunk.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil112.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCABlock.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorldChunk.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/BlockStateExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectSameOrFullBlockExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoorExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoublePlantExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/FireExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/GlassPaneConnectExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/NetherFenceConnectExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/RedstoneExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/SnowyExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/StairShapeExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/TripwireConnectExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WallConnectExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WoodenFenceConnectExtension.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BiomeIdMapper.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockIdMapper.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockProperties.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockPropertyMapper.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockStateMapping.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/LightData.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Model.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/RenderSettings.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/StaticRenderSettings.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/TileRenderer.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/WorldTile.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/BlockContext.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/EmptyBlockContext.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/ExtendedBlockContext.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/SlicedWorldChunkBlockContext.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/WorldChunkBlockContext.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModel.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelManager.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModel.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModelFactory.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/LiquidModelBuilder.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/ResourceModelBuilder.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModel.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModelManager.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockColorProvider.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementFaceResource.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementResource.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelResource.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockStateResource.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/InvalidResourceDeclarationException.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchResourceException.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchTextureException.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/ResourcePack.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/TextureProvider.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/threejs/BufferGeometry.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Axis.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ConfigUtil.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Direction.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/FileUtil.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/IntersectionPoint.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtil.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ModelUtils.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/UpdateDeamon.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Updateable.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/WeighedArrayList.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebRequestHandler.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebServer.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebServerConfig.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpConnection.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequestHandler.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpResponse.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpStatusCode.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/WebServer.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/Block.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/CachedBlock.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ChunkNotGeneratedException.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java create mode 100644 BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/WorldChunk.java create mode 100644 BlueMapCore/src/main/resources/DefaultResources.zip create mode 100644 BlueMapCore/src/main/resources/biomes.json create mode 100644 BlueMapCore/src/main/resources/blockColors.json create mode 100644 BlueMapCore/src/main/resources/blockIdMappings.json create mode 100644 BlueMapCore/src/main/resources/blockProperties.json create mode 100644 BlueMapCore/src/main/resources/webroot.zip create mode 100644 BlueMapCore/src/main/webroot/assets/compass.svg create mode 100644 BlueMapCore/src/main/webroot/assets/gear.svg create mode 100644 BlueMapCore/src/main/webroot/assets/skybox/down.png create mode 100644 BlueMapCore/src/main/webroot/assets/skybox/east.png create mode 100644 BlueMapCore/src/main/webroot/assets/skybox/north.png create mode 100644 BlueMapCore/src/main/webroot/assets/skybox/south.png create mode 100644 BlueMapCore/src/main/webroot/assets/skybox/up.png create mode 100644 BlueMapCore/src/main/webroot/assets/skybox/west.png create mode 100644 BlueMapCore/src/main/webroot/index.html create mode 100644 BlueMapCore/src/main/webroot/js/libs/bluemap.js create mode 100644 BlueMapCore/src/main/webroot/js/libs/jquery.min.js create mode 100644 BlueMapCore/src/main/webroot/js/libs/three.min.js create mode 100644 BlueMapCore/src/main/webroot/js/site.js create mode 100644 BlueMapCore/src/main/webroot/style/style.css create mode 100644 BlueMapSponge/build.gradle create mode 100644 BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java create mode 100644 BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java create mode 100644 LICENSE create mode 100644 README.md create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..8e5a0b3c --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +.gradle/ +.gradle/* +*/.gradle/* + +build/ +build/* +*/build/* + +.settings/ +.settings/* +*/.settings/* + +bin/ +bin/* +*/bin/* + +.classpath +*/.classpath + +.project +*/.project + +# exclude generated resource +src/main/resources/webroot.zip \ No newline at end of file diff --git a/BlueMapCLI/build.gradle b/BlueMapCLI/build.gradle new file mode 100644 index 00000000..b17d6fa5 --- /dev/null +++ b/BlueMapCLI/build.gradle @@ -0,0 +1,4 @@ +dependencies { + compile group: 'commons-cli', name: 'commons-cli', version: '1.4' + compile project(':BlueMapCore') +} diff --git a/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java b/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java new file mode 100644 index 00000000..3b009d28 --- /dev/null +++ b/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java @@ -0,0 +1,555 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.cli; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.render.StaticRenderSettings; +import de.bluecolored.bluemap.core.render.TileRenderer; +import de.bluecolored.bluemap.core.render.hires.HiresModelManager; +import de.bluecolored.bluemap.core.render.lowres.LowresModelManager; +import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException; +import de.bluecolored.bluemap.core.resourcepack.ResourcePack; +import de.bluecolored.bluemap.core.web.BlueMapWebRequestHandler; +import de.bluecolored.bluemap.core.web.WebFilesManager; +import de.bluecolored.bluemap.core.web.WebSettings; +import de.bluecolored.bluemap.core.webserver.WebServer; +import de.bluecolored.bluemap.core.world.World; + +public class BlueMapCLI { + + private File webroot = new File("web"); + private File dataPath = new File(webroot, "data"); + + private File extraResourceFile = null; + private int threadCount; + + private String mapId = null; + private String mapName = null; + + private int highresTileSize = 32; + private int lowresTileSize = 50; + private int samplesPerHighresTile = 4; + + private float highresViewDistance = 6f; + private float lowresViewDistance = 5f; + + private boolean excludeFacesWithoutSunlight = true; + private float ambientOcclusion = 0.25f; + private float lighting = 0.8f; + private int sliceY = Integer.MAX_VALUE; + private int maxY = Integer.MAX_VALUE; + private int minY = 0; + + private int port = 8100; + private int maxConnections = 100; + private InetAddress bindAdress = null; + + public BlueMapCLI() { + threadCount = Runtime.getRuntime().availableProcessors(); + } + + public void renderMap(File mapPath, boolean updateOnly) throws IOException, NoSuchResourceException { + dataPath.mkdirs(); + + if (!mapPath.exists() || !mapPath.isDirectory()) { + throw new IOException("Save folder '" + mapPath + "' does not exist or is not a directory!"); + } + + Logger.global.logInfo("Reading world..."); + World world = MCAWorld.load(mapPath.toPath(), UUID.randomUUID()); + + if (mapName == null) { + mapName = world.getName(); + } + + if (mapId == null) { + mapId = mapPath.getName().toLowerCase(); + } + + Logger.global.logInfo("Starting Render:" + + "\n map: " + mapPath.getAbsolutePath() + + "\n map-id: " + mapId + + "\n map-name: " + mapName + + "\n thread-count: " + threadCount + + "\n data-path: " + dataPath.getAbsolutePath() + + "\n render-all: " + !excludeFacesWithoutSunlight + + "\n ambient-occlusion: " + ambientOcclusion + + "\n lighting: " + lighting + + "\n sliceY: " + (sliceY < Integer.MAX_VALUE ? sliceY : "-") + + "\n maxY: " + (maxY < Integer.MAX_VALUE ? maxY : "-") + + "\n minY: " + (minY > 0 ? minY : "-") + + "\n hr-tilesize: " + highresTileSize + + "\n lr-tilesize: " + lowresTileSize + + "\n lr-resolution: " + samplesPerHighresTile + + "\n hr-viewdistance: " + highresViewDistance + + "\n lr-viewdistance: " + lowresViewDistance + ); + + Logger.global.logInfo("Loading Resources..."); + ResourcePack resourcePack = loadResources(); + + Logger.global.logInfo("Initializing renderer..."); + HiresModelManager hiresModelManager = new HiresModelManager( + dataPath.toPath().resolve("hires").resolve(mapId), + resourcePack, + new Vector2i(highresTileSize, highresTileSize), + ForkJoinPool.commonPool() + ); + + LowresModelManager lowresModelManager = new LowresModelManager( + dataPath.toPath().resolve("lowres").resolve(mapId), + new Vector2i(lowresTileSize, lowresTileSize), + new Vector2i(samplesPerHighresTile, samplesPerHighresTile) + ); + + TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager, new StaticRenderSettings( + ambientOcclusion, + excludeFacesWithoutSunlight, + lighting, + maxY, + minY, + sliceY + )); + + File webSettingsFile = new File(dataPath, "settings.json"); + Logger.global.logInfo("Writing '" + webSettingsFile.getAbsolutePath() + "'..."); + WebSettings webSettings = new WebSettings(webSettingsFile); + webSettings.setName(mapName, mapId); + webSettings.setFrom(tileRenderer, mapId); + webSettings.setHiresViewDistance(highresViewDistance, mapId); + webSettings.setLowresViewDistance(lowresViewDistance, mapId); + webSettings.save(); + + + Logger.global.logInfo("Collecting tiles to render..."); + + Collection chunks; + if (updateOnly) { + long lastRender = webSettings.getLong(mapId, "last-render"); + chunks = world.getChunkList(lastRender); + } else { + chunks = world.getChunkList(); + } + + Set tiles = new HashSet<>(); + for (Vector2i chunk : chunks) { + Vector3i minBlockPos = new Vector3i(chunk.getX() * 16, 0, chunk.getY() * 16); + tiles.add(hiresModelManager.posToTile(minBlockPos)); + tiles.add(hiresModelManager.posToTile(minBlockPos.add(0, 0, 15))); + tiles.add(hiresModelManager.posToTile(minBlockPos.add(15, 0, 0))); + tiles.add(hiresModelManager.posToTile(minBlockPos.add(15, 0, 15))); + } + Logger.global.logInfo("Found " + tiles.size() + " tiles to render! (" + chunks.size() + " chunks)"); + + if (tiles.isEmpty()) { + Logger.global.logInfo("Render finished!"); + return; + } + + Logger.global.logInfo("Starting Render..."); + long starttime = System.currentTimeMillis(); + RenderManager renderManager = new RenderManager(world, tileRenderer, tiles, threadCount); + renderManager.start(() -> { + Logger.global.logInfo("Waiting for threads to quit..."); + if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) { + Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored."); + } + + try { + webSettings.set(starttime, mapId, "last-render"); + webSettings.save(); + } catch (IOException e) { + Logger.global.logError("Failed to update web-settings!", e); + } + + Logger.global.logInfo("Render finished!"); + }); + } + + public void updateWebFiles() throws IOException { + webroot.mkdirs(); + + Logger.global.logInfo("Creating webfiles in " + webroot.getAbsolutePath()); + WebFilesManager webFilesManager = new WebFilesManager(webroot.toPath()); + webFilesManager.updateFiles(); + } + + public void startWebserver() throws UnknownHostException { + if (bindAdress == null) bindAdress = InetAddress.getLocalHost(); + + Logger.global.logInfo("Starting webserver:" + + "\n address: " + this.bindAdress.toString() + "" + + "\n port: " + this.port + + "\n max connections: " + this.maxConnections + + "\n webroot: " + this.webroot.getAbsolutePath() + ); + + WebServer webserver = new WebServer( + this.port, + this.maxConnections, + this.bindAdress, + new BlueMapWebRequestHandler(this.webroot.toPath()) + ); + + webserver.start(); + } + + private ResourcePack loadResources() throws IOException, NoSuchResourceException { + File defaultResourceFile; + try { + defaultResourceFile = File.createTempFile("res", ".zip"); + defaultResourceFile.delete(); + } catch (IOException e) { + throw new IOException("Failed to create temporary resource file!", e); + } + try { + ResourcePack.createDefaultResource(defaultResourceFile); + } catch (IOException e) { + throw new IOException("Failed to create default resources!", e); + } + + List resourcePacks = new ArrayList<>(); + resourcePacks.add(defaultResourceFile); + if (this.extraResourceFile != null) resourcePacks.add(extraResourceFile); + + ResourcePack resourcePack = new ResourcePack(resourcePacks, new File(dataPath, "textures.json")); + + defaultResourceFile.delete(); + + return resourcePack; + } + + public static void main(String[] args) throws IOException, NoSuchResourceException { + CommandLineParser parser = new DefaultParser(); + + try { + CommandLine cmd = parser.parse(BlueMapCLI.createOptions(), args, false); + + if (cmd.hasOption("h")) { + BlueMapCLI.printHelp(); + return; + } + + boolean executed = false; + + BlueMapCLI bluemapcli = new BlueMapCLI(); + + if (cmd.hasOption("o")) bluemapcli.dataPath = new File(cmd.getOptionValue("o")); + if (cmd.hasOption("r")) bluemapcli.extraResourceFile = new File(cmd.getOptionValue("r")); + if (cmd.hasOption("t")) bluemapcli.threadCount = Integer.parseInt(cmd.getOptionValue("t")); + + if (cmd.hasOption("d")) bluemapcli.webroot = new File(cmd.getOptionValue("d")); + if (cmd.hasOption("i")) bluemapcli.bindAdress = InetAddress.getByName(cmd.getOptionValue("i")); + bluemapcli.port = Integer.parseInt(cmd.getOptionValue("p", Integer.toString(bluemapcli.port))); + bluemapcli.maxConnections = Integer.parseInt(cmd.getOptionValue("connections", Integer.toString(bluemapcli.maxConnections))); + + bluemapcli.mapName = cmd.getOptionValue("n", bluemapcli.mapName); + bluemapcli.mapId = cmd.getOptionValue("id", bluemapcli.mapId); + + bluemapcli.ambientOcclusion = Float.parseFloat(cmd.getOptionValue("ao", Float.toString(bluemapcli.ambientOcclusion))); + bluemapcli.lighting = Float.parseFloat(cmd.getOptionValue("lighting", Float.toString(bluemapcli.lighting))); + bluemapcli.sliceY = Integer.parseInt(cmd.getOptionValue("y-slice", Integer.toString(bluemapcli.sliceY))); + bluemapcli.maxY = Integer.parseInt(cmd.getOptionValue("y-max", Integer.toString(bluemapcli.maxY))); + bluemapcli.minY = Integer.parseInt(cmd.getOptionValue("y-min", Integer.toString(bluemapcli.minY))); + + bluemapcli.highresTileSize = Integer.parseInt(cmd.getOptionValue("hr-tilesize", Integer.toString(bluemapcli.highresTileSize))); + bluemapcli.highresViewDistance = Float.parseFloat(cmd.getOptionValue("hr-viewdist", Float.toString(bluemapcli.highresViewDistance))); + bluemapcli.lowresTileSize = Integer.parseInt(cmd.getOptionValue("lr-tilesize", Integer.toString(bluemapcli.lowresTileSize))); + bluemapcli.samplesPerHighresTile = Integer.parseInt(cmd.getOptionValue("lr-resolution", Integer.toString(bluemapcli.samplesPerHighresTile))); + bluemapcli.lowresViewDistance = Float.parseFloat(cmd.getOptionValue("lr-viewdist", Float.toString(bluemapcli.lowresViewDistance))); + + if (cmd.hasOption("c")) { + bluemapcli.updateWebFiles(); + executed = true; + } + + if (cmd.hasOption("s")) { + bluemapcli.startWebserver(); + executed = true; + } + + if (cmd.hasOption("w")) { + bluemapcli.renderMap(new File(cmd.getOptionValue("w")), !cmd.hasOption("f")); + executed = true; + } + + if (executed) return; + + } catch (ParseException e) { + Logger.global.logError("Failed to parse provided arguments!", e); + } catch (NumberFormatException e) { + Logger.global.logError("One argument expected a number but got the wrong format!", e); + } + + BlueMapCLI.printHelp(); + } + + private static Options createOptions() { + Options options = new Options(); + + options.addOption("h", "help", false, "Displays this message"); + + options.addOption( + Option.builder("o") + .longOpt("out") + .hasArg() + .argName("directory-path") + .desc("Defines the render-output directory. Default is '/data' (See option -d)") + .build() + ); + options.addOption( + Option.builder("d") + .longOpt("dir") + .hasArg() + .argName("directory-path") + .desc("Defines the webroot directory. Default is './web'") + .build() + ); + + options.addOption("s", "webserver", false, "Starts the integrated webserver"); + options.addOption( + Option.builder("c") + .longOpt("create-web") + .desc("The webfiles will be (re)created, existing web-files in the webroot will be replaced!") + .build() + ); + options.addOption( + Option.builder("i") + .longOpt("ip") + .hasArg() + .argName("ip-adress") + .desc("Specifies the IP adress the webserver will use") + .build() + ); + options.addOption( + Option.builder("p") + .longOpt("port") + .hasArg() + .argName("port") + .desc("Specifies the port the webserver will use. Default is 8100") + .build() + ); + options.addOption( + Option.builder() + .longOpt("connections") + .hasArg() + .argName("count") + .desc("Sets the maximum count of simultaneous client-connections that the webserver will allow. Default is 100") + .build() + ); + + options.addOption( + Option.builder("w") + .longOpt("world") + .hasArg() + .argName("directory-path") + .desc("Defines the world-save folder that will be rendered") + .build() + ); + options.addOption( + Option.builder("f") + .longOpt("force-render") + .desc("Rerenders all tiles even if there are no changes since the last render") + .build() + ); + options.addOption( + Option.builder("r") + .longOpt("resource") + .hasArg() + .argName("file") + .desc("Defines the resourcepack that will be used to render the map") + .build() + ); + options.addOption( + Option.builder("t") + .longOpt("threads") + .hasArg() + .argName("thread-count") + .desc("Defines the number of threads that will be used to render the map. Default is the number of system cores") + .build() + ); + options.addOption( + Option.builder("I") + .longOpt("id") + .hasArg() + .argName("id") + .desc("The id of the world. Default is the name of the world-folder") + .build() + ); + options.addOption( + Option.builder("n") + .longOpt("name") + .hasArg() + .argName("name") + .desc("The name of the world. Default is the world-name defined in the level.dat") + .build() + ); + options.addOption( + Option.builder() + .longOpt("render-all") + .desc("Also renders blocks that are normally omitted due to a sunlight value of 0. Enabling this can cause a big performance impact in the web-viewer, but it might fix some cases where blocks are missing.") + .build() + ); + options.addOption( + Option.builder("ao") + .longOpt("ambient-occlusion") + .hasArg() + .argName("value") + .desc("The strength of ambient-occlusion baked into the model (a value between 0 and 1). Default is 0.25") + .build() + ); + options.addOption( + Option.builder("l") + .longOpt("lighting") + .hasArg() + .argName("value") + .desc("The max strength of shadows baked into the model (a value between 0 and 1 where 0 is fully bright (no lighting) and 1 is max lighting-contrast). Default is 0.8") + .build() + ); + options.addOption( + Option.builder("ys") + .longOpt("y-slice") + .hasArg() + .argName("value") + .desc("Using this, BlueMap pretends that every Block above the defined value is AIR. Default is disabled") + .build() + ); + options.addOption( + Option.builder("yM") + .longOpt("y-max") + .hasArg() + .argName("value") + .desc("Blocks above this height will not be rendered. Default is no limit") + .build() + ); + options.addOption( + Option.builder("ym") + .longOpt("y-min") + .hasArg() + .argName("value") + .desc("Blocks below this height will not be rendered. Default is no limit") + .build() + ); + + options.addOption( + Option.builder() + .longOpt("hr-tilesize") + .hasArg() + .argName("value") + .desc("Defines the size of one map-tile in blocks. If you change this value, the lowres values might need adjustment as well! Default is 32") + .build() + ); + options.addOption( + Option.builder() + .longOpt("hr-viewdist") + .hasArg() + .argName("value") + .desc("The View-Distance for hires tiles on the web-map (the value is the radius in tiles). Default is 6") + .build() + ); + options.addOption( + Option.builder() + .longOpt("lr-tilesize") + .hasArg() + .argName("value") + .desc("Defines the size of one lowres-map-tile in grid-points. Default is 50") + .build() + ); + options.addOption( + Option.builder() + .longOpt("lr-resolution") + .hasArg() + .argName("value") + .desc("Defines resolution of the lowres model. E.g. If the hires.tileSize is 32, a value of 4 means that every 8*8 blocks will be summarized by one point on the lowres map. Calculation: 32 / 4 = 8! You have to use values that result in an integer if you use the above calculation! Default is 4") + .build() + ); + options.addOption( + Option.builder() + .longOpt("lr-viewdist") + .hasArg() + .argName("value") + .desc("The View-Distance for lowres tiles on the web-map (the value is the radius in tiles). Default is 5") + .build() + ); + + return options; + } + + private static void printHelp() { + HelpFormatter formatter = new HelpFormatter(); + + String filename = "bluemapcli.jar"; + try { + File file = new File(BlueMapCLI.class.getProtectionDomain() + .getCodeSource() + .getLocation() + .getPath()); + + if (file.isFile()) { + try { + filename = "./" + new File(".").toPath().relativize(file.toPath()).toString(); + } catch (IllegalArgumentException ex) { + filename = file.getAbsolutePath(); + } + } + } catch (Exception ex) {} + + String command = "java -jar " + filename; + + formatter.printHelp(command + " [options]", "\nOptions:", createOptions(), "\n" + + "Examples:\n\n" + + command + " -w ./world/\n" + + " -> Renders the whole world to ./web/data/\n\n" + + command + " -csi localhost\n" + + " -> Creates all neccesary web-files in ./web/ and starts the webserver. (Open http://localhost:8100/ in your browser)" + ); + } + +} diff --git a/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/RenderManager.java b/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/RenderManager.java new file mode 100644 index 00000000..3f0638b3 --- /dev/null +++ b/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/RenderManager.java @@ -0,0 +1,176 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.cli; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; + +import org.apache.commons.lang3.time.DurationFormatUtils; + +import com.flowpowered.math.GenericMath; +import com.flowpowered.math.vector.Vector2d; +import com.flowpowered.math.vector.Vector2i; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.render.TileRenderer; +import de.bluecolored.bluemap.core.render.WorldTile; +import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; +import de.bluecolored.bluemap.core.world.World; + +public class RenderManager extends Thread { + + private World world; + private TileRenderer tileRenderer; + private Deque tilesToRender; + + private int tileCount; + private long startTime = -1; + private int renderedTiles = 0; + + private Thread[] threads; + + private Runnable onFinished; + + public RenderManager(World world, TileRenderer tileRenderer, Collection tilesToRender, int threadCount) { + this.world = world; + this.tileRenderer = tileRenderer; + + //Sort the chunks to opimize the chunk-cache usage of MCAWorld and generate the world in a nicer order, so you can see the first results early in the web-map during render + Vector2d sortGridSize = new Vector2d(20, 20).div(tileRenderer.getHiresModelManager().getTileSize().toDouble().div(16)).ceil().max(1, 1); //Find a good grid size to match the MCAWorlds chunk-cache size of 500 + ArrayList sortedTiles = new ArrayList<>(tilesToRender); + sortedTiles.sort((v1, v2) -> { + Vector2i v1SortGridPos = v1.toDouble().div(sortGridSize).floor().toInt(); + Vector2i v2SortGridPos = v2.toDouble().div(sortGridSize).floor().toInt(); + + if (v1SortGridPos != v2SortGridPos){ + int v1Dist = v1SortGridPos.distanceSquared(Vector2i.ZERO); + int v2Dist = v2SortGridPos.distanceSquared(Vector2i.ZERO); + + if (v1Dist < v2Dist) return -1; + if (v1Dist > v2Dist) return 1; + } + + if (v1.getY() < v1.getY()) return -1; + if (v1.getY() > v1.getY()) return 1; + if (v1.getX() < v1.getX()) return -1; + if (v1.getX() > v1.getX()) return 1; + + return 0; + }); + + this.tilesToRender = new ArrayDeque<>(sortedTiles); + + this.tileCount = this.tilesToRender.size(); + this.threads = new Thread[threadCount]; + + + } + + public synchronized void start(Runnable onFinished) { + this.onFinished = onFinished; + + start(); + } + + @Override + public void run() { + this.startTime = System.currentTimeMillis(); + + for (int i = 0; i < threads.length; i++) { + if (threads[i] != null) threads[i].interrupt(); + + threads[i] = new Thread(this::renderThread); + threads[i].start(); + } + + long lastLogUpdate = startTime; + long lastSave = startTime; + + while (!Thread.interrupted()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + + boolean stillRendering = false; + for (Thread t : threads) { + if (t.isAlive()) { + stillRendering = true; + break; + } + } + if (!stillRendering) break; + + long now = System.currentTimeMillis(); + if (lastLogUpdate < now - 10000) { // print update all 10 seconds + lastLogUpdate = now; + + long time = now - startTime; + String durationString = DurationFormatUtils.formatDurationWords(time, true, true); + double pct = (double)renderedTiles / (double)tileCount; + + long ert = (long)(((double) time / pct) * (1d - pct)); + String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true); + + Logger.global.logInfo("Rendered " + renderedTiles + " of " + tileCount + " tiles in " + durationString); + Logger.global.logInfo(GenericMath.round(pct * 100, 3) + "% | Estimated remaining time: " + ertDurationString); + } + + if (lastSave < now - 5 * 60000) { // save every 5 minutes + lastSave = now; + tileRenderer.save(); + } + } + + tileRenderer.save(); + + onFinished.run(); + } + + private void renderThread() { + Vector2i tilePos; + + while (!Thread.interrupted()) { + synchronized (tilesToRender) { + if (tilesToRender.isEmpty()) break; + tilePos = tilesToRender.poll(); + } + + WorldTile tile = new WorldTile(world, tilePos); + try { + tileRenderer.render(tile); + } catch (IOException e) { + Logger.global.logError("Failed to render tile " + tilePos, e); + } catch (ChunkNotGeneratedException e) {} + + renderedTiles++; + } + } + +} diff --git a/BlueMapCore/build.gradle b/BlueMapCore/build.gradle new file mode 100644 index 00000000..7344d013 --- /dev/null +++ b/BlueMapCore/build.gradle @@ -0,0 +1,21 @@ +dependencies { + compile 'com.google.guava:guava:21.0' + compile 'com.google.code.gson:gson:2.8.0' + compile 'org.apache.commons:commons-lang3:3.5' + compile group: 'commons-io', name: 'commons-io', version: '2.6' + compile 'com.flowpowered:flow-math:1.0.3' + compile 'ninja.leaping.configurate:configurate-hocon:3.3' + compile 'ninja.leaping.configurate:configurate-gson:3.3' + compile 'com.github.Querz:NBT:4.0' + compile group: 'commons-cli', name: 'commons-cli', version: '1.4' +} + +task zipWebroot(type: Zip) { + from fileTree('src/main/webroot') + archiveName 'webroot.zip' + destinationDir(file('/src/main/resources/')) + outputs.upToDateWhen { false } +} + +//always update the zip before build +compileJava.dependsOn(zipWebroot) diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/AbstractLogger.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/AbstractLogger.java new file mode 100644 index 00000000..40a8dcb0 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/AbstractLogger.java @@ -0,0 +1,69 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.logger; + +import java.util.Set; + +import com.google.common.collect.Sets; + +public abstract class AbstractLogger extends Logger { + + private Set noFloodLog; + + public AbstractLogger() { + noFloodLog = Sets.newConcurrentHashSet(); + } + + @Override + public void noFloodError(String key, String message, Throwable throwable){ + if (noFloodLog.add(key)) logError(message, throwable); + } + + @Override + public void noFloodWarning(String key, String message){ + if (noFloodLog.add(key)) logWarning(message); + } + + @Override + public void noFloodInfo(String key, String message){ + if (noFloodLog.add(key)) logInfo(message); + } + + @Override + public void noFloodDebug(String key, String message){ + if (noFloodLog.add(key)) logDebug(message); + } + + @Override + public void clearNoFloodLog() { + noFloodLog.clear(); + } + + @Override + public void removeNoFloodKey(String key) { + noFloodLog.remove(key); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/Logger.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/Logger.java new file mode 100644 index 00000000..104d30ed --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/Logger.java @@ -0,0 +1,99 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.logger; + +public abstract class Logger { + + public static Logger global = stdOut(); + + public abstract void logError(String message, Throwable throwable); + + public abstract void logWarning(String message); + + public abstract void logInfo(String message); + + public abstract void logDebug(String message); + + /** + * Only log the error if no message has been logged before with the same key. + */ + public abstract void noFloodError(String key, String message, Throwable throwable); + + /** + * Only log the warning if no message has been logged before with the same key. + */ + public abstract void noFloodWarning(String key, String message); + + /** + * Only log the info if no message has been logged before with the same key. + */ + public abstract void noFloodInfo(String key, String message); + + /** + * Only log the debug-message if no message has been logged before with the same key. + */ + public abstract void noFloodDebug(String key, String message); + + /** + * Only log the error if no message has been logged before with the same content. + */ + public void noFloodError(String message, Throwable throwable){ + noFloodError(message, message, throwable); + } + + /** + * Only log the warning if no message has been logged before with the same content. + */ + public void noFloodWarning(String message){ + noFloodWarning(message, message); + } + + /** + * Only log the info if no message has been logged before with the same content. + */ + public void noFloodInfo(String message){ + noFloodInfo(message, message); + } + + /** + * Only log the debug-message if no message has been logged before with the same content. + */ + public void noFloodDebug(String message){ + noFloodDebug(message, message); + } + + public abstract void clearNoFloodLog(); + + public abstract void removeNoFloodKey(String key); + + public void removeNoFloodMessage(String message){ + removeNoFloodKey(message); + } + + public static Logger stdOut(){ + return new PrintStreamLogger(System.out, System.err); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/PrintStreamLogger.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/PrintStreamLogger.java new file mode 100644 index 00000000..724e8904 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/PrintStreamLogger.java @@ -0,0 +1,59 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.logger; + +import java.io.PrintStream; + +public class PrintStreamLogger extends AbstractLogger { + + private PrintStream out, err; + + public PrintStreamLogger(PrintStream out, PrintStream err) { + this.out = out; + this.err = err; + } + + @Override + public void logError(String message, Throwable throwable) { + err.println("[ERROR] " + message); + throwable.printStackTrace(err); + } + + @Override + public void logWarning(String message) { + out.println("[WARNING] " + message); + } + + @Override + public void logInfo(String message) { + out.println("[INFO] " + message); + } + + @Override + public void logDebug(String message) { + out.println("[DEBUG] " + message); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/VoidLogger.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/VoidLogger.java new file mode 100644 index 00000000..32bd8464 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/logger/VoidLogger.java @@ -0,0 +1,59 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.logger; + +public class VoidLogger extends Logger { + + @Override + public void logError(String message, Throwable throwable) {} + + @Override + public void logWarning(String message) {} + + @Override + public void logInfo(String message) {} + + @Override + public void logDebug(String message) {} + + @Override + public void noFloodError(String key, String message, Throwable throwable) {} + + @Override + public void noFloodWarning(String key, String message) {} + + @Override + public void noFloodInfo(String key, String message) {} + + @Override + public void noFloodDebug(String key, String message) {} + + @Override + public void clearNoFloodLog() {} + + @Override + public void removeNoFloodKey(String key) {} + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/Chunk.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/Chunk.java new file mode 100644 index 00000000..7db25414 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/Chunk.java @@ -0,0 +1,75 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca; + +import java.io.IOException; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.mca.mapping.LightData; +import de.bluecolored.bluemap.core.world.BlockState; +import net.querz.nbt.CompoundTag; + +public abstract class Chunk { + + private final MCAWorld world; + private final Vector2i chunkPos; + + protected Chunk(MCAWorld world, CompoundTag chunkTag) { + this.world = world; + + CompoundTag levelData = chunkTag.getCompoundTag("Level"); + + chunkPos = new Vector2i( + levelData.getInt("xPos"), + levelData.getInt("zPos") + ); + } + + public abstract boolean isGenerated(); + + public Vector2i getChunkPos() { + return chunkPos; + } + + public MCAWorld getWorld() { + return world; + } + + public abstract BlockState getBlockState(Vector3i pos); + + public abstract LightData getLightData(Vector3i pos); + + public abstract String getBiomeId(Vector3i pos); + + public static Chunk create(MCAWorld world, CompoundTag chunkTag) throws IOException { + int version = chunkTag.getInt("DataVersion"); + + if (version <= 1343) return new ChunkAnvil112(world, chunkTag); + return new ChunkAnvil113(world, chunkTag); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil112.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil112.java new file mode 100644 index 00000000..e17ae016 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil112.java @@ -0,0 +1,172 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.mca.mapping.BiomeIdMapper; +import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper; +import de.bluecolored.bluemap.core.mca.mapping.LightData; +import de.bluecolored.bluemap.core.world.BlockState; +import net.querz.nbt.CompoundTag; +import net.querz.nbt.ListTag; +import net.querz.nbt.mca.MCAUtil; + +class ChunkAnvil112 extends Chunk { + private BlockIdMapper blockIdMapper; + private BiomeIdMapper biomeIdMapper; + + private boolean isGenerated; + private Section[] sections; + private byte[] biomes; + + @SuppressWarnings("unchecked") + public ChunkAnvil112(MCAWorld world, CompoundTag chunkTag) { + super(world, chunkTag); + + blockIdMapper = getWorld().getBlockIdMapper(); + biomeIdMapper = getWorld().getBiomeIdMapper(); + + CompoundTag levelData = chunkTag.getCompoundTag("Level"); + + isGenerated = + levelData.getBoolean("LightPopulated") && + levelData.getBoolean("TerrainPopulated"); + + sections = new Section[32]; //32 supports a max world-height of 512 which is the max that the hightmaps of Minecraft V1.13+ can store with 9 bits, i believe? + for (CompoundTag sectionTag : ((ListTag) levelData.getListTag("Sections"))) { + Section section = new Section(sectionTag); + sections[section.getSectionY()] = section; + } + + biomes = levelData.getByteArray("Biomes"); + } + + @Override + public boolean isGenerated() { + return isGenerated; + } + + @Override + public BlockState getBlockState(Vector3i pos) { + int sectionY = MCAUtil.blockToChunk(pos.getY()); + + Section section = this.sections[sectionY]; + if (section == null) return BlockState.AIR; + + return section.getBlockState(pos); + } + + @Override + public LightData getLightData(Vector3i pos) { + int sectionY = MCAUtil.blockToChunk(pos.getY()); + + Section section = this.sections[sectionY]; + if (section == null) return LightData.FULL; + + return section.getLightData(pos); + } + + @Override + public String getBiomeId(Vector3i pos) { + int x = pos.getX() & 0xF; // Math.floorMod(pos.getX(), 16) + int z = pos.getZ() & 0xF; + int biomeByteIndex = z * 16 + x; + + return biomeIdMapper.get(biomes[biomeByteIndex]); + } + + private class Section { + private int sectionY; + private byte[] blocks; + private byte[] add; + private byte[] blockLight; + private byte[] skyLight; + private byte[] data; + + public Section(CompoundTag sectionData) { + this.sectionY = sectionData.getByte("Y"); + this.blocks = sectionData.getByteArray("Blocks"); + this.add = sectionData.getByteArray("Add"); + this.blockLight = sectionData.getByteArray("BlockLight"); + this.skyLight = sectionData.getByteArray("SkyLight"); + this.data = sectionData.getByteArray("Data"); + } + + public int getSectionY() { + return sectionY; + } + + public BlockState getBlockState(Vector3i pos) { + int x = pos.getX() & 0xF; // Math.floorMod(pos.getX(), 16) + int y = pos.getY() & 0xF; + int z = pos.getZ() & 0xF; + int blockByteIndex = y * 256 + z * 16 + x; + int blockHalfByteIndex = blockByteIndex >> 1; // blockByteIndex / 2 + boolean largeHalf = (blockByteIndex & 0x1) != 0; // (blockByteIndex % 2) == 0 + + int blockId = this.blocks[blockByteIndex] & 0xFF; + + if (this.add.length > 0) { + blockId = blockId & (getByteHalf(this.add[blockHalfByteIndex], largeHalf) << 8); + } + + int blockData = getByteHalf(this.data[blockHalfByteIndex], largeHalf); + + BlockState blockState = blockIdMapper.get(blockId, blockData); + + return blockState; + } + + public LightData getLightData(Vector3i pos) { + int x = pos.getX() & 0xF; // Math.floorMod(pos.getX(), 16) + int y = pos.getY() & 0xF; + int z = pos.getZ() & 0xF; + int blockByteIndex = y * 256 + z * 16 + x; + int blockHalfByteIndex = blockByteIndex >> 1; // blockByteIndex / 2 + boolean largeHalf = (blockByteIndex & 0x1) != 0; // (blockByteIndex % 2) == 0 + + int blockLight = getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf); + int skyLight = getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf); + + return new LightData(skyLight, blockLight); + } + + /** + * Extracts the 4 bits of the left (largeHalf = true) or the right (largeHalf = false) side of the byte stored in value.
+ * The value is treated as an unsigned byte. + */ + private int getByteHalf(int value, boolean largeHalf) { + value = value & 0xFF; + if (largeHalf) { + value = value >> 4; + } + value = value & 0xF; + return value; + } + + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java new file mode 100644 index 00000000..c6c2e2c9 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java @@ -0,0 +1,224 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.mca.mapping.BiomeIdMapper; +import de.bluecolored.bluemap.core.mca.mapping.LightData; +import de.bluecolored.bluemap.core.world.BlockState; +import net.querz.nbt.ByteArrayTag; +import net.querz.nbt.CompoundTag; +import net.querz.nbt.IntArrayTag; +import net.querz.nbt.ListTag; +import net.querz.nbt.StringTag; +import net.querz.nbt.Tag; +import net.querz.nbt.mca.MCAUtil; + +class ChunkAnvil113 extends Chunk { + private BiomeIdMapper biomeIdMapper; + + private boolean isGenerated; + private Section[] sections; + private int[] biomes; + + @SuppressWarnings("unchecked") + public ChunkAnvil113(MCAWorld world, CompoundTag chunkTag) { + super(world, chunkTag); + + biomeIdMapper = getWorld().getBiomeIdMapper(); + + CompoundTag levelData = chunkTag.getCompoundTag("Level"); + + String status = levelData.getString("Status"); + isGenerated = status.equals("full") || status.equals("spawn"); // full is normal fully generated and spawn seems to be converted from old format but not yet loaded if you optimized your world + + sections = new Section[32]; //32 supports a max world-height of 512 which is the max that the hightmaps of Minecraft V1.13+ can store with 9 bits, i believe? + if (levelData.containsKey("Sections")) { + for (CompoundTag sectionTag : ((ListTag) levelData.getListTag("Sections"))) { + Section section = new Section(sectionTag); + if (section.getSectionY() >= 0) sections[section.getSectionY()] = section; + } + } + + Tag tag = levelData.get("Biomes"); //tag can be byte-array or int-array + if (tag instanceof ByteArrayTag) { + byte[] bs = ((ByteArrayTag) tag).getValue(); + biomes = new int[bs.length]; + + for (int i = 0; i < bs.length; i++) { + biomes[i] = bs[i]; + } + } + else if (tag instanceof IntArrayTag) { + biomes = ((IntArrayTag) tag).getValue(); + } + else { + biomes = new int[2048]; + } + } + + @Override + public boolean isGenerated() { + return isGenerated; + } + + @Override + public BlockState getBlockState(Vector3i pos) { + int sectionY = MCAUtil.blockToChunk(pos.getY()); + + Section section = this.sections[sectionY]; + if (section == null) return BlockState.AIR; + + return section.getBlockState(pos); + } + + @Override + public LightData getLightData(Vector3i pos) { + int sectionY = MCAUtil.blockToChunk(pos.getY()); + + Section section = this.sections[sectionY]; + if (section == null) return LightData.FULL; + + return section.getLightData(pos); + } + + @Override + public String getBiomeId(Vector3i pos) { + int x = pos.getX() & 0xF; // Math.floorMod(pos.getX(), 16) + int z = pos.getZ() & 0xF; + int biomeByteIndex = z * 16 + x; + + return biomeIdMapper.get(biomes[biomeByteIndex]); + } + + private class Section { + private int sectionY; + private byte[] blockLight; + private byte[] skyLight; + private long[] blocks; + private BlockState[] palette; + + @SuppressWarnings("unchecked") + public Section(CompoundTag sectionData) { + this.sectionY = sectionData.getByte("Y"); + this.blockLight = sectionData.getByteArray("BlockLight"); + if (blockLight.length == 0) blockLight = new byte[2048]; + this.skyLight = sectionData.getByteArray("SkyLight"); + if (skyLight.length == 0) skyLight = new byte[2048]; + this.blocks = sectionData.getLongArray("BlockStates"); + + //read block palette + ListTag paletteTag = (ListTag) sectionData.getListTag("Palette"); + if (paletteTag != null) { + this.palette = new BlockState[paletteTag.size()]; + for (int i = 0; i < this.palette.length; i++) { + CompoundTag stateTag = paletteTag.get(i); + + String id = stateTag.getString("Name"); + Map properties = new HashMap<>(); + + if (stateTag.containsKey("Properties")) { + CompoundTag propertiesTag = stateTag.getCompoundTag("Properties"); + for (Entry> property : propertiesTag) { + properties.put(property.getKey(), ((StringTag) property.getValue()).getValue()); + } + } + + palette[i] = new BlockState(id, properties); + } + } else { + this.palette = new BlockState[0]; + } + } + + public int getSectionY() { + return sectionY; + } + + public BlockState getBlockState(Vector3i pos) { + if (blocks.length == 0) return BlockState.AIR; + + int x = pos.getX() & 0xF; // Math.floorMod(pos.getX(), 16) + int y = pos.getY() & 0xF; + int z = pos.getZ() & 0xF; + int blockIndex = y * 256 + z * 16 + x; + int bitsPerBlock = blocks.length * 64 / 4096; //64 bits per long and 4096 blocks per section + int index = blockIndex * bitsPerBlock; + int firstLong = index >> 6; // index / 64 + int bitoffset = index & 0x3F; // Math.floorMod(index, 64) + + long value = blocks[firstLong] >>> bitoffset; + + if (bitoffset > 0 && firstLong + 1 < blocks.length) { + long value2 = blocks[firstLong + 1]; + value2 = value2 << -bitoffset; + value = value | value2; + } + + value = value & (0xFFFFFFFFFFFFFFFFL >>> -bitsPerBlock); + + if (value >= palette.length) { + Logger.global.noFloodWarning("palettewarning", "Got palette value " + value + " but palette has size of " + palette.length + " (Future occasions of this error will not be logged)"); + return BlockState.AIR; + } + + return palette[(int) value]; + } + + public LightData getLightData(Vector3i pos) { + int x = pos.getX() & 0xF; // Math.floorMod(pos.getX(), 16) + int y = pos.getY() & 0xF; + int z = pos.getZ() & 0xF; + int blockByteIndex = y * 256 + z * 16 + x; + int blockHalfByteIndex = blockByteIndex >> 1; // blockByteIndex / 2 + boolean largeHalf = (blockByteIndex & 0x1) != 0; // (blockByteIndex % 2) == 0 + + int blockLight = getByteHalf(this.blockLight[blockHalfByteIndex], largeHalf); + int skyLight = getByteHalf(this.skyLight[blockHalfByteIndex], largeHalf); + + return new LightData(skyLight, blockLight); + } + + /** + * Extracts the 4 bits of the left (largeHalf = true) or the right (largeHalf = false) side of the byte stored in value.
+ * The value is treated as an unsigned byte. + */ + private int getByteHalf(int value, boolean largeHalf) { + value = value & 0xFF; + if (largeHalf) { + value = value >> 4; + } + value = value & 0xF; + return value; + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCABlock.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCABlock.java new file mode 100644 index 00000000..dd3672ed --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCABlock.java @@ -0,0 +1,92 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.mca.mapping.BlockProperties; +import de.bluecolored.bluemap.core.mca.mapping.LightData; +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.BlockState; + +public class MCABlock extends Block { + + private MCAWorld world; + private BlockState blockState; + private LightData lightData; + private String biome; + private BlockProperties properties; + private Vector3i pos; + + public MCABlock(MCAWorld world, BlockState blockState, LightData lightData, String biome, BlockProperties properties, Vector3i pos) { + this.world = world; + this.blockState = blockState; + this.lightData = lightData; + this.biome = biome; + this.properties = properties; + this.pos = pos; + } + + @Override + public BlockState getBlock() { + return blockState; + } + + @Override + public MCAWorld getWorld() { + return world; + } + + @Override + public Vector3i getPosition() { + return pos; + } + + @Override + public double getSunLightLevel() { + return lightData.getSkyLight(); + } + + @Override + public double getBlockLightLevel() { + return lightData.getBlockLight(); + } + + @Override + public boolean isCullingNeighborFaces() { + return properties.isCulling(); + } + + @Override + public boolean isOccludingNeighborFaces() { + return properties.isOccluding(); + } + + @Override + public String getBiome() { + return biome; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java new file mode 100644 index 00000000..5ecc3144 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java @@ -0,0 +1,438 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.mca.extensions.BlockStateExtension; +import de.bluecolored.bluemap.core.mca.extensions.DoorExtension; +import de.bluecolored.bluemap.core.mca.extensions.DoublePlantExtension; +import de.bluecolored.bluemap.core.mca.extensions.FireExtension; +import de.bluecolored.bluemap.core.mca.extensions.GlassPaneConnectExtension; +import de.bluecolored.bluemap.core.mca.extensions.NetherFenceConnectExtension; +import de.bluecolored.bluemap.core.mca.extensions.RedstoneExtension; +import de.bluecolored.bluemap.core.mca.extensions.SnowyExtension; +import de.bluecolored.bluemap.core.mca.extensions.StairShapeExtension; +import de.bluecolored.bluemap.core.mca.extensions.TripwireConnectExtension; +import de.bluecolored.bluemap.core.mca.extensions.WallConnectExtension; +import de.bluecolored.bluemap.core.mca.extensions.WoodenFenceConnectExtension; +import de.bluecolored.bluemap.core.mca.mapping.BiomeIdMapper; +import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper; +import de.bluecolored.bluemap.core.mca.mapping.BlockProperties; +import de.bluecolored.bluemap.core.mca.mapping.BlockPropertyMapper; +import de.bluecolored.bluemap.core.mca.mapping.LightData; +import de.bluecolored.bluemap.core.util.AABB; +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.BlockState; +import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; +import de.bluecolored.bluemap.core.world.World; +import de.bluecolored.bluemap.core.world.WorldChunk; +import net.querz.nbt.CompoundTag; +import net.querz.nbt.NBTUtil; +import net.querz.nbt.Tag; +import net.querz.nbt.mca.CompressionType; +import net.querz.nbt.mca.MCAUtil; + +public class MCAWorld implements World { + + private static final Cache CHUNK_CACHE = CacheBuilder.newBuilder().maximumSize(500).build(); + private static final Multimap BLOCK_STATE_EXTENSIONS = MultimapBuilder.hashKeys().arrayListValues().build(); + + public static final BlockIdMapper DEFAULT_BLOCK_ID_MAPPER; + public static final BlockPropertyMapper DEFAULT_BLOCK_PROPERTY_MAPPER; + public static final BiomeIdMapper DEFAULT_BIOME_ID_MAPPER; + + static { + try { + DEFAULT_BLOCK_ID_MAPPER = BlockIdMapper.create(); + DEFAULT_BLOCK_PROPERTY_MAPPER = BlockPropertyMapper.create(); + DEFAULT_BIOME_ID_MAPPER = BiomeIdMapper.create(); + } catch (IOException e) { + throw new RuntimeException("Failed to load essential resources!", e); + } + + registerBlockStateExtension(new SnowyExtension()); + registerBlockStateExtension(new StairShapeExtension()); + registerBlockStateExtension(new FireExtension()); + registerBlockStateExtension(new RedstoneExtension()); + registerBlockStateExtension(new DoorExtension()); + registerBlockStateExtension(new NetherFenceConnectExtension()); + registerBlockStateExtension(new TripwireConnectExtension()); + registerBlockStateExtension(new WallConnectExtension()); + registerBlockStateExtension(new WoodenFenceConnectExtension()); + registerBlockStateExtension(new GlassPaneConnectExtension()); + registerBlockStateExtension(new DoublePlantExtension()); + } + + private final UUID uuid; + private final Path worldFolder; + private String name; + private AABB boundaries; + private int seaLevel; + private Vector3i spawnPoint; + + private BlockIdMapper blockIdMapper; + private BlockPropertyMapper blockPropertyMapper; + private BiomeIdMapper biomeIdMapper; + + private MCAWorld( + Path worldFolder, + UUID uuid, + String name, + int worldHeight, + int seaLevel, + Vector3i spawnPoint, + BlockIdMapper blockIdMapper, + BlockPropertyMapper blockPropertyMapper, + BiomeIdMapper biomeIdMapper + ) { + this.uuid = uuid; + this.worldFolder = worldFolder; + this.name = name; + this.boundaries = new AABB(new Vector3i(-10000000, 0, -10000000), new Vector3i(10000000, worldHeight, 10000000)); + this.seaLevel = seaLevel; + this.spawnPoint = spawnPoint; + + this.blockIdMapper = blockIdMapper; + this.blockPropertyMapper = blockPropertyMapper; + this.biomeIdMapper = biomeIdMapper; + } + + public BlockState getBlockState(Vector3i pos) { + try { + + Vector2i chunkPos = blockToChunk(pos); + Chunk chunk = getChunk(chunkPos); + return chunk.getBlockState(pos); + + } catch (Exception ex) { + return BlockState.AIR; + } + } + + @Override + public Block getBlock(Vector3i pos) throws ChunkNotGeneratedException { + try { + + Vector2i chunkPos = blockToChunk(pos); + Chunk chunk = getChunk(chunkPos); + BlockState blockState = getExtendedBlockState(chunk, pos); + LightData lightData = chunk.getLightData(pos); + String biome = chunk.getBiomeId(pos); + BlockProperties properties = blockPropertyMapper.map(blockState); + return new MCABlock(this, blockState, lightData, biome, properties, pos); + + } catch (IOException ex) { + throw new ChunkNotGeneratedException(ex); // to resolve the error, act like the chunk has not been generated yet + } + } + + private BlockState getExtendedBlockState(Chunk chunk, Vector3i pos) throws ChunkNotGeneratedException { + BlockState blockState = chunk.getBlockState(pos); + + for (BlockStateExtension ext : BLOCK_STATE_EXTENSIONS.get(blockState.getId())) { + blockState = ext.extend(this, pos, blockState); + } + + return blockState; + } + + @Override + public AABB getBoundaries() { + return boundaries; + } + + @Override + public WorldChunk getWorldChunk(AABB boundaries) { + return new MCAWorldChunk(this, boundaries); + } + + public Chunk getChunk(Vector2i chunkPos) throws IOException, ChunkNotGeneratedException { + try { + Chunk chunk = CHUNK_CACHE.get(new WorldChunkHash(this, chunkPos), () -> this.loadChunk(chunkPos)); + if (!chunk.isGenerated()) throw new ChunkNotGeneratedException(); + return chunk; + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + + if (cause instanceof IOException) { + throw (IOException) cause; + } + + else if (cause instanceof ChunkNotGeneratedException) { + throw (ChunkNotGeneratedException) cause; + } + + else throw new IOException(cause); + } + } + + private Chunk loadChunk(Vector2i chunkPos) throws IOException, ChunkNotGeneratedException { + Vector2i regionPos = chunkToRegion(chunkPos); + Path regionPath = getMCAFilePath(regionPos); + + try (RandomAccessFile raf = new RandomAccessFile(regionPath.toFile(), "r")) { + + int xzChunk = Math.floorMod(chunkPos.getY(), 32) * 32 + Math.floorMod(chunkPos.getX(), 32); + + raf.seek(xzChunk * 4); + int offset = raf.read() << 16; + offset |= (raf.read() & 0xFF) << 8; + offset |= raf.read() & 0xFF; + offset *= 4096; + + int size = raf.readByte() * 4096; + if (size == 0) throw new ChunkNotGeneratedException(); + + raf.seek(offset + 4); // +4 skip chunk size + + byte compressionTypeByte = raf.readByte(); + CompressionType compressionType = CompressionType.getFromID(compressionTypeByte); + if (compressionType == null) { + throw new IOException("invalid compression type " + compressionTypeByte); + } + + DataInputStream dis = new DataInputStream(new BufferedInputStream(compressionType.decompress(new FileInputStream(raf.getFD())))); + Tag tag = Tag.deserialize(dis, Tag.DEFAULT_MAX_DEPTH); + if (tag instanceof CompoundTag) { + return Chunk.create(this, (CompoundTag) tag); + } else { + throw new IOException("invalid data tag: " + (tag == null ? "null" : tag.getClass().getName())); + } + + } + } + + public boolean isChunkGenerated(Vector2i chunkPos) { + try { + getChunk(chunkPos); + } catch (ChunkNotGeneratedException | IOException e) { + return false; + } + + return true; + } + + @Override + public Collection getChunkList(long modifiedSinceMillis){ + List chunks = new ArrayList<>(10000); + + for (File file : getRegionFolder().toFile().listFiles()) { + if (!file.getName().endsWith(".mca")) continue; + + try (RandomAccessFile raf = new RandomAccessFile(file, "r")) { + + String[] filenameParts = file.getName().split("\\."); + int rX = Integer.parseInt(filenameParts[1]); + int rZ = Integer.parseInt(filenameParts[2]); + + for (int x = 0; x < 32; x++) { + for (int z = 0; z < 32; z++) { + int xzChunk = z * 32 + x; + + raf.seek(xzChunk * 4 + 3); + int size = raf.readByte() * 4096; + + if (size == 0) continue; + + raf.seek(xzChunk * 4 + 4096); + int timestamp = raf.read() << 24; + timestamp |= (raf.read() & 0xFF) << 16; + timestamp |= (raf.read() & 0xFF) << 8; + timestamp |= raf.read() & 0xFF; + + if (timestamp >= (modifiedSinceMillis / 1000)) chunks.add(new Vector2i(rX * 32 + x, rZ * 32 + z)); + } + } + } catch (Exception ex) { + Logger.global.logWarning("Failed to read .mca file: " + file.getAbsolutePath() + " (" + ex.toString() + ")"); + } + } + + return chunks; + } + + @Override + public String getName() { + return name; + } + + @Override + public UUID getUUID() { + return uuid; + } + + @Override + public int getSeaLevel() { + return seaLevel; + } + + @Override + public Vector3i getSpawnPoint() { + return spawnPoint; + } + + public BlockIdMapper getBlockIdMapper() { + return blockIdMapper; + } + + public BlockPropertyMapper getBlockPropertyMapper() { + return blockPropertyMapper; + } + + public BiomeIdMapper getBiomeIdMapper() { + return biomeIdMapper; + } + + public void setBlockIdMapper(BlockIdMapper blockIdMapper) { + this.blockIdMapper = blockIdMapper; + } + + public void setBlockPropertyMapper(BlockPropertyMapper blockPropertyMapper) { + this.blockPropertyMapper = blockPropertyMapper; + } + + public void setBiomeIdMapper(BiomeIdMapper biomeIdMapper) { + this.biomeIdMapper = biomeIdMapper; + } + + public Path getWorldFolder() { + return worldFolder; + } + + private Path getRegionFolder() { + return worldFolder.resolve("region"); + } + + private Path getMCAFilePath(Vector2i region) { + return getRegionFolder().resolve(MCAUtil.createNameFromRegionLocation(region.getX(), region.getY())); + } + + public static MCAWorld load(Path worldFolder, UUID uuid) throws IOException { + try { + CompoundTag level = (CompoundTag) NBTUtil.readTag(worldFolder.resolve("level.dat").toFile()); + CompoundTag levelData = level.getCompoundTag("Data"); + + String name = levelData.getString("LevelName"); + int worldHeight = 255; + int seaLevel = 63; + Vector3i spawnPoint = new Vector3i( + levelData.getInt("SpawnX"), + levelData.getInt("SpawnY"), + levelData.getInt("SpawnZ") + ); + + return new MCAWorld( + worldFolder, + uuid, + name, + worldHeight, + seaLevel, + spawnPoint, + DEFAULT_BLOCK_ID_MAPPER, + DEFAULT_BLOCK_PROPERTY_MAPPER, + DEFAULT_BIOME_ID_MAPPER + ); + } catch (ClassCastException | NullPointerException ex) { + throw new IOException("Invaid level.dat format!", ex); + } + } + + public static Vector2i blockToChunk(Vector3i pos) { + return new Vector2i( + MCAUtil.blockToChunk(pos.getX()), + MCAUtil.blockToChunk(pos.getZ()) + ); + } + + public static Vector2i blockToRegion(Vector3i pos) { + return new Vector2i( + MCAUtil.blockToRegion(pos.getX()), + MCAUtil.blockToRegion(pos.getZ()) + ); + } + + public static Vector2i chunkToRegion(Vector2i pos) { + return new Vector2i( + MCAUtil.chunkToRegion(pos.getX()), + MCAUtil.chunkToRegion(pos.getY()) + ); + } + + public static void registerBlockStateExtension(BlockStateExtension extension) { + for (String id : extension.getAffectedBlockIds()) { + BLOCK_STATE_EXTENSIONS.put(id, extension); + } + } + + private static class WorldChunkHash { + + private final UUID world; + private final Vector2i chunk; + + public WorldChunkHash(MCAWorld world, Vector2i chunk) { + this.world = world.getUUID(); + this.chunk = chunk; + } + + @Override + public int hashCode() { + return Objects.hash(world, chunk); + } + + @Override + public boolean equals(Object obj) { + + if (obj instanceof WorldChunkHash) { + WorldChunkHash other = (WorldChunkHash) obj; + return other.chunk.equals(chunk) && world.equals(other.world); + } + + return false; + } + + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorldChunk.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorldChunk.java new file mode 100644 index 00000000..a4170372 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorldChunk.java @@ -0,0 +1,85 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.util.AABB; +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; +import de.bluecolored.bluemap.core.world.World; +import de.bluecolored.bluemap.core.world.WorldChunk; + +public class MCAWorldChunk implements WorldChunk { + + private MCAWorld world; + private AABB boundaries, extendedBounds; + + public MCAWorldChunk(MCAWorld world, AABB boundaries) { + this.world = world; + this.boundaries = boundaries; + this.extendedBounds = boundaries.expand(2, 2, 2); + } + + @Override + public World getWorld() { + return world; + } + + @Override + public Block getBlock(Vector3i pos) throws ChunkNotGeneratedException { + return world.getBlock(pos); + } + + @Override + public AABB getBoundaries() { + return boundaries; + } + + @Override + public WorldChunk getWorldChunk(AABB boundaries) { + return new MCAWorldChunk(world, boundaries); + } + + @Override + public boolean isGenerated() { + + //check one more block in every direction to make sure that extended block states can be generated! + Vector2i minChunk = MCAWorld.blockToChunk(extendedBounds.getMin().toInt()); + Vector2i maxChunk = MCAWorld.blockToChunk(extendedBounds.getMax().toInt()); + + for (int x = minChunk.getX(); x <= maxChunk.getX(); x++) { + for (int z = minChunk.getY(); z <= maxChunk.getY(); z++) { + if (!world.isChunkGenerated(new Vector2i(x, z))) { + return false; + } + } + } + + return true; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/BlockStateExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/BlockStateExtension.java new file mode 100644 index 00000000..9b295ba2 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/BlockStateExtension.java @@ -0,0 +1,40 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Collection; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.world.BlockState; + +public interface BlockStateExtension { + + BlockState extend(MCAWorld world, Vector3i pos, BlockState state); + + Collection getAffectedBlockIds(); + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectExtension.java new file mode 100644 index 00000000..d29c5d05 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectExtension.java @@ -0,0 +1,57 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Set; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.BlockState; + +public abstract class ConnectExtension implements BlockStateExtension { + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + return state + .with("north", String.valueOf(connectsTo(world, pos.add(Direction.NORTH.toVector())))) + .with("east", String.valueOf(connectsTo(world, pos.add(Direction.EAST.toVector())))) + .with("south", String.valueOf(connectsTo(world, pos.add(Direction.SOUTH.toVector())))) + .with("west", String.valueOf(connectsTo(world, pos.add(Direction.WEST.toVector())))); + } + + public boolean connectsTo(MCAWorld world, Vector3i pos) { + return connectsTo(world, pos, world.getBlockState(pos)); + } + + public boolean connectsTo(MCAWorld world, Vector3i pos, BlockState block) { + return getAffectedBlockIds().contains(block.getFullId()); + } + + @Override + public abstract Set getAffectedBlockIds(); + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectSameOrFullBlockExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectSameOrFullBlockExtension.java new file mode 100644 index 00000000..94f0ae24 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/ConnectSameOrFullBlockExtension.java @@ -0,0 +1,41 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.world.BlockState; + +public abstract class ConnectSameOrFullBlockExtension extends ConnectExtension { + + @Override + public boolean connectsTo(MCAWorld world, Vector3i pos, BlockState block) { + if (super.connectsTo(world, pos, block)) return true; + + return world.getBlockPropertyMapper().map(block).isCulling(); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoorExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoorExtension.java new file mode 100644 index 00000000..07aa4051 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoorExtension.java @@ -0,0 +1,74 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Collection; +import java.util.Map.Entry; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Lists; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.BlockState; + +public class DoorExtension implements BlockStateExtension { + + private static final Collection AFFECTED_BLOCK_IDS = Lists.newArrayList( + "minecraft:wooden_door", + "minecraft:iron_door", + "minecraft:spruce_door", + "minecraft:birch_door", + "minecraft:jungle_door", + "minecraft:acacia_door", + "minecraft:dark_oak_door" + ); + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + BlockState otherDoor; + + if (state.getProperties().get("half").equals("lower")) { + otherDoor = world.getBlockState(pos.add(Direction.UP.toVector())); + } else { + otherDoor = world.getBlockState(pos.add(Direction.DOWN.toVector())); + } + + //copy all properties from the other door + for (Entry prop : otherDoor.getProperties().entrySet()) { + if (!state.getProperties().containsKey(prop.getKey())) { + state = state.with(prop.getKey(), prop.getValue()); + } + } + + return state; + } + + @Override + public Collection getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoublePlantExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoublePlantExtension.java new file mode 100644 index 00000000..c5203205 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/DoublePlantExtension.java @@ -0,0 +1,64 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Collection; +import java.util.Map.Entry; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Lists; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.BlockState; + +public class DoublePlantExtension implements BlockStateExtension { + + private static final Collection AFFECTED_BLOCK_IDS = Lists.newArrayList( + "minecraft:double_plant" + ); + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + if (state.getProperties().get("half").equals("upper")) { + BlockState otherPlant = world.getBlockState(pos.add(Direction.DOWN.toVector())); + + //copy all properties from the other half + for (Entry prop : otherPlant.getProperties().entrySet()) { + if (!state.getProperties().containsKey(prop.getKey())) { + state = state.with(prop.getKey(), prop.getValue()); + } + } + } + + return state; + } + + @Override + public Collection getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/FireExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/FireExtension.java new file mode 100644 index 00000000..e09f00fc --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/FireExtension.java @@ -0,0 +1,67 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Collection; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Lists; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.BlockState; + +public class FireExtension implements BlockStateExtension { + + private static final Collection AFFECTED_BLOCK_IDS = Lists.newArrayList( + "minecraft:fire" + ); + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + BlockState below = world.getBlockState(pos.add(0, -1, 0)); + + boolean isOnGround = world.getBlockPropertyMapper().map(below).isCulling(); + for (Direction dir : Direction.values()) { + if (dir != Direction.DOWN) { + if (!isOnGround) { + BlockState neighbor = world.getBlockState(pos.add(dir.toVector())); + + state = state.with(dir.name().toLowerCase(), String.valueOf(!world.getBlockPropertyMapper().map(neighbor).isCulling())); + } else { + state = state.with(dir.name().toLowerCase(), "false"); + } + } + } + + return state; + } + + @Override + public Collection getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/GlassPaneConnectExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/GlassPaneConnectExtension.java new file mode 100644 index 00000000..c24b4c81 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/GlassPaneConnectExtension.java @@ -0,0 +1,45 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.HashSet; +import java.util.Set; + +import com.google.common.collect.Sets; + +public class GlassPaneConnectExtension extends ConnectSameOrFullBlockExtension { + + private static final HashSet AFFECTED_BLOCK_IDS = Sets.newHashSet( + "minecraft:glass_pane", + "minecraft:stained_glass_pane", + "minecraft:iron_bars" + ); + + @Override + public Set getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/NetherFenceConnectExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/NetherFenceConnectExtension.java new file mode 100644 index 00000000..39ff3760 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/NetherFenceConnectExtension.java @@ -0,0 +1,43 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.HashSet; +import java.util.Set; + +import com.google.common.collect.Sets; + +public class NetherFenceConnectExtension extends ConnectSameOrFullBlockExtension { + + private static final HashSet AFFECTED_BLOCK_IDS = Sets.newHashSet( + "minecraft:nether_brick_fence" + ); + + @Override + public Set getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/RedstoneExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/RedstoneExtension.java new file mode 100644 index 00000000..1bc58378 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/RedstoneExtension.java @@ -0,0 +1,84 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Collection; +import java.util.Set; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.BlockState; + +public class RedstoneExtension implements BlockStateExtension { + + private static final Collection AFFECTED_BLOCK_IDS = Lists.newArrayList( + "minecraft:redstone_wire" + ); + + + private static final Set CONNECTIBLE = Sets.newHashSet( + "minecraft:redstone_wire", + "minecraft:unlit_redstone_torch", + "minecraft:redstone_torch", + "minecraft:stone_button", + "minecraft:wooden_button", + "minecraft:stone_button", + "minecraft:lever", + "minecraft:stone_pressure_plate", + "minecraft:wooden_pressure_plate", + "minecraft:light_weighted_pressure_plate", + "minecraft:heavy_weighted_pressure_plate" + ); + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + state = state + .with("north", connection(world, pos, state, Direction.NORTH)) + .with("east", connection(world, pos, state, Direction.EAST)) + .with("south", connection(world, pos, state, Direction.SOUTH)) + .with("west", connection(world, pos, state, Direction.WEST)); + + return state; + } + + private String connection(MCAWorld world, Vector3i pos, BlockState state, Direction direction) { + BlockState next = world.getBlockState(pos.add(direction.toVector())); + if (CONNECTIBLE.contains(next.getId())) return "side"; + + //TODO: up + + return "none"; + } + + @Override + public Collection getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/SnowyExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/SnowyExtension.java new file mode 100644 index 00000000..d72b4a94 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/SnowyExtension.java @@ -0,0 +1,58 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Collection; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Lists; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.world.BlockState; + +public class SnowyExtension implements BlockStateExtension { + + private static final Collection AFFECTED_BLOCK_IDS = Lists.newArrayList( + "minecraft:grass", + "minecraft:dirt" + ); + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + BlockState above = world.getBlockState(pos.add(0, 1, 0)); + + if (above.getId().equals("minecraft:snow_layer") || above.getId().equals("minecraft:snow")) { + return state.with("snowy", "true"); + } else { + return state.with("snowy", "false"); + } + } + + @Override + public Collection getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/StairShapeExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/StairShapeExtension.java new file mode 100644 index 00000000..f20df86d --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/StairShapeExtension.java @@ -0,0 +1,129 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.Collection; +import java.util.HashSet; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Sets; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.BlockState; + +public class StairShapeExtension implements BlockStateExtension { + + private static final HashSet AFFECTED_BLOCK_IDS = Sets.newHashSet( + "minecraft:oak_stairs", + "minecraft:stone_stairs", + "minecraft:brick_stairs", + "minecraft:stone_brick_stairs", + "minecraft:nether_brick_stairs", + "minecraft:sandstone_stairs", + "minecraft:spruce_stairs", + "minecraft:birch_stairs", + "minecraft:jungle_stairs", + "minecraft:quartz_stairs", + "minecraft:acacia_stairs", + "minecraft:dark_oak_stairs", + "minecraft:red_sandstone_stairs", + "minecraft:purpur_stairs" + ); + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + try { + Direction facing = Direction.fromString(state.getProperties().get("facing")); + BlockState back = world.getBlockState(pos.add(facing.toVector())); + + if (isStairs(back) && state.getProperties().get("half").equals(back.getProperties().get("half"))) { + Direction backFacing = Direction.fromString(back.getProperties().get("facing")); + + if (facing.getAxis() != backFacing.getAxis()){ + BlockState next = world.getBlockState(pos.add(backFacing.opposite().toVector())); + + if (!isStairs(next) || !isEqualStairs(state, next)) { + + if (backFacing == rotateYCCW(facing)){ + return state.with("shape", "outer_left"); + } + + return state.with("shape", "outer_right"); + } + } + } + + BlockState front = world.getBlockState(pos.add(facing.opposite().toVector())); + + if (isStairs(front) && state.getProperties().get("half").equals(front.getProperties().get("half"))) { + Direction frontFacing = Direction.fromString(front.getProperties().get("facing")); + + if (facing.getAxis() != frontFacing.getAxis()){ + BlockState next = world.getBlockState(pos.add(frontFacing.toVector())); + + if (!isStairs(next) || !isEqualStairs(state, next)) { + if (frontFacing == rotateYCCW(facing)){ + return state.with("shape", "inner_left"); + } + + return state.with("shape", "inner_right"); + } + } + } + + return state.with("shape", "straight"); + + } catch (IllegalArgumentException | NullPointerException ex) { + return state.with("shape", "straight"); + } + } + + private boolean isStairs(BlockState state) { + return AFFECTED_BLOCK_IDS.contains(state.getId()); + } + + private boolean isEqualStairs(BlockState stair1, BlockState stair2) { + return + stair1.getProperties().get("facing").equals(stair2.getProperties().get("facing")) && + stair1.getProperties().get("half").equals(stair2.getProperties().get("half")); + } + + private Direction rotateYCCW(Direction dir) { + switch (dir) { + case NORTH: return Direction.WEST; + case WEST: return Direction.SOUTH; + case SOUTH: return Direction.EAST; + case EAST: return Direction.NORTH; + default: return dir; + } + } + + @Override + public Collection getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/TripwireConnectExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/TripwireConnectExtension.java new file mode 100644 index 00000000..7c953b41 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/TripwireConnectExtension.java @@ -0,0 +1,43 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.HashSet; +import java.util.Set; + +import com.google.common.collect.Sets; + +public class TripwireConnectExtension extends ConnectExtension { + + private static final HashSet AFFECTED_BLOCK_IDS = Sets.newHashSet( + "minecraft:tripwire" + ); + + @Override + public Set getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WallConnectExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WallConnectExtension.java new file mode 100644 index 00000000..dc2592a8 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WallConnectExtension.java @@ -0,0 +1,64 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.HashSet; +import java.util.Set; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Sets; + +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.BlockState; + +public class WallConnectExtension extends ConnectSameOrFullBlockExtension { + + private static final HashSet AFFECTED_BLOCK_IDS = Sets.newHashSet( + "minecraft:cobblestone_wall" + ); + + @Override + public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) { + state = super.extend(world, pos, state); + + if ( + state.getProperties().get("north").equals(state.getProperties().get("south")) && + state.getProperties().get("east").equals(state.getProperties().get("west")) && + !state.getProperties().get("north").equals(state.getProperties().get("east")) && + !connectsTo(world, pos.add(Direction.UP.toVector())) + ) { + return state.with("up", "false"); + } else { + return state.with("up", "true"); + } + } + + @Override + public Set getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WoodenFenceConnectExtension.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WoodenFenceConnectExtension.java new file mode 100644 index 00000000..169dfd36 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/extensions/WoodenFenceConnectExtension.java @@ -0,0 +1,48 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.extensions; + +import java.util.HashSet; +import java.util.Set; + +import com.google.common.collect.Sets; + +public class WoodenFenceConnectExtension extends ConnectSameOrFullBlockExtension { + + private static final HashSet AFFECTED_BLOCK_IDS = Sets.newHashSet( + "minecraft:fence", + "minecraft:spruce_fence", + "minecraft:birch_fence", + "minecraft:jungle_fence", + "minecraft:dark_oak_fence", + "minecraft:acacia_fence" + ); + + @Override + public Set getAffectedBlockIds() { + return AFFECTED_BLOCK_IDS; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BiomeIdMapper.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BiomeIdMapper.java new file mode 100644 index 00000000..4427cac9 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BiomeIdMapper.java @@ -0,0 +1,69 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.mapping; + +import java.io.IOException; +import java.util.Map.Entry; + +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; + +public class BiomeIdMapper { + private static final String DEFAULT_BIOME = "ocean"; + + private String[] biomes; + + public BiomeIdMapper() throws IOException { + biomes = new String[256]; + for (int i = 0; i < biomes.length; i++) { + biomes[i] = DEFAULT_BIOME; + } + + GsonConfigurationLoader loader = GsonConfigurationLoader.builder() + .setURL(getClass().getResource("/biomes.json")) + .build(); + + ConfigurationNode node = loader.load(); + + for (Entry e : node.getChildrenMap().entrySet()){ + String biome = e.getKey().toString(); + int id = e.getValue().getNode("id").getInt(-1); + if (id >= 0 && id < biomes.length) { + biomes[id] = biome; + } + } + + } + + public String get(int id) { + if (id < 0 || id >= biomes.length) return DEFAULT_BIOME; + return biomes[id]; + } + + public static BiomeIdMapper create() throws IOException { + return new BiomeIdMapper(); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockIdMapper.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockIdMapper.java new file mode 100644 index 00000000..89f6c116 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockIdMapper.java @@ -0,0 +1,119 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.mapping; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.world.BlockState; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; + +public class BlockIdMapper { + + private Map mappings; + + public BlockIdMapper() throws IOException { + mappings = new HashMap<>(); + + GsonConfigurationLoader loader = GsonConfigurationLoader.builder() + .setURL(getClass().getResource("/blockIdMappings.json")) + .build(); + + ConfigurationNode node = loader.load(); + + for (Entry e : node.getChildrenMap().entrySet()){ + String key = e.getKey().toString(); + String value = e.getValue().getString(); + + int splitIndex = key.indexOf(':'); + int blockId = Integer.parseInt(key.substring(0, splitIndex)); + int blockMeta = Integer.parseInt(key.substring(splitIndex + 1)); + + BlockIDMeta idmeta = new BlockIDMeta(blockId, blockMeta); + BlockState state = BlockState.fromString(value); + + mappings.put(idmeta, state); + } + } + + public BlockState get(int id, int meta) { + if (id == 0) return BlockState.AIR; + + BlockState state = mappings.get(new BlockIDMeta(id, meta)); + + if (state == null) { + state = mappings.get(new BlockIDMeta(id, 0)); //fallback + + if (state == null) { + Logger.global.noFloodDebug(id + ":" + meta + "-blockidmapper-mappingerr", "Block ID can not be mapped: " + id + ":" + meta); + return BlockState.AIR; + } + } + + return state; + } + + class BlockIDMeta { + private final int id; + private final int meta; + + public BlockIDMeta(int id, int meta) { + this.id = id; + this.meta = meta; + } + + public int getId() { + return id; + } + + public int getMeta() { + return meta; + } + + @Override + public int hashCode() { + return id * 0xFFFF + meta; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BlockIDMeta) { + BlockIDMeta other = (BlockIDMeta) obj; + return other.id == id && other.meta == meta; + } + + return false; + } + } + + public static BlockIdMapper create() throws IOException { + return new BlockIdMapper(); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockProperties.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockProperties.java new file mode 100644 index 00000000..6ea12599 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockProperties.java @@ -0,0 +1,49 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.mapping; + +public class BlockProperties { + + private final boolean culling, occluding, flammable; + + public BlockProperties(boolean culling, boolean occluding, boolean flammable) { + this.culling = culling; + this.occluding = occluding; + this.flammable = flammable; + } + + public boolean isCulling() { + return culling; + } + + public boolean isOccluding() { + return occluding; + } + + public boolean isFlammable() { + return flammable; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockPropertyMapper.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockPropertyMapper.java new file mode 100644 index 00000000..4fac6b1d --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockPropertyMapper.java @@ -0,0 +1,103 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.mapping; + +import java.io.IOException; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; + +import de.bluecolored.bluemap.core.world.BlockState; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; + +public class BlockPropertyMapper { + + private static final BlockProperties DEFAULT_PROPERTIES = new BlockProperties(false, false, false); + + private Multimap> mappings; + private LoadingCache mappingCache; + + private BlockPropertyMapper() throws IOException { + mappings = HashMultimap.create(); + + GsonConfigurationLoader loader = GsonConfigurationLoader.builder() + .setURL(getClass().getResource("/blockProperties.json")) + .build(); + + ConfigurationNode node = loader.load(); + + for (Entry e : node.getChildrenMap().entrySet()){ + String key = e.getKey().toString(); + BlockState bsKey = BlockState.fromString(key); + BlockProperties bsValue = new BlockProperties( + e.getValue().getNode("culling").getBoolean(false), + e.getValue().getNode("occluding").getBoolean(false), + e.getValue().getNode("flammable").getBoolean(false) + ); + BlockStateMapping mapping = new BlockStateMapping<>(bsKey, bsValue); + mappings.put(bsKey.getId(), mapping); + } + + mappings = Multimaps.unmodifiableMultimap(mappings); + + mappingCache = CacheBuilder.newBuilder() + .concurrencyLevel(8) + .maximumSize(10000) + .build(new CacheLoader(){ + @Override public BlockProperties load(BlockState key) { return mapNoCache(key); } + }); + } + + public BlockProperties map(BlockState from){ + try { + return mappingCache.get(from); + } catch (ExecutionException e) { + //should never happen, since the CacheLoader does not throw any exceptions + throw new RuntimeException("Unexpected error while trying to map a BlockState's properties", e.getCause()); + } + } + + private BlockProperties mapNoCache(BlockState bs){ + for (BlockStateMapping bm : mappings.get(bs.getId())){ + if (bm.fitsTo(bs)){ + return bm.getMapping(); + } + } + + return DEFAULT_PROPERTIES; + } + + public static BlockPropertyMapper create() throws IOException { + return new BlockPropertyMapper(); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockStateMapping.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockStateMapping.java new file mode 100644 index 00000000..6ce1ad03 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/BlockStateMapping.java @@ -0,0 +1,63 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.mapping; + +import java.util.Map.Entry; + +import de.bluecolored.bluemap.core.world.BlockState; + +class BlockStateMapping { + private BlockState blockState; + private T mapping; + + public BlockStateMapping(BlockState blockState, T mapping) { + this.blockState = blockState; + this.mapping = mapping; + } + + /** + * Returns true if the all the properties on this BlockMapping-key are the same in the provided BlockState.
+ * Properties that are not defined in this Mapping are ignored on the provided BlockState.
+ */ + public boolean fitsTo(BlockState blockState){ + if (!this.blockState.getId().equals(blockState.getId())) return false; + for (Entry e : this.blockState.getProperties().entrySet()){ + if (!e.getValue().equals(blockState.getProperties().get(e.getKey()))){ + return false; + } + } + + return true; + } + + public BlockState getBlockState(){ + return blockState; + } + + public T getMapping(){ + return mapping; + } + +} \ No newline at end of file diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/LightData.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/LightData.java new file mode 100644 index 00000000..2d801889 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/mapping/LightData.java @@ -0,0 +1,52 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.mca.mapping; + +public class LightData { + + public static final LightData ZERO = new LightData(0, 0); + public static final LightData FULL = new LightData(15, 15); + + private final int skyLight, blockLight; + + public LightData(int skyLight, int blockLight) { + this.skyLight = skyLight; + this.blockLight = blockLight; + } + + public int getSkyLight() { + return skyLight; + } + + public int getBlockLight() { + return blockLight; + } + + @Override + public String toString() { + return "LightData[B:" + getBlockLight() + "|S:" + getSkyLight() + "]"; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java new file mode 100644 index 00000000..d3b771c9 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Face.java @@ -0,0 +1,218 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.model; + +import com.flowpowered.math.imaginary.Quaternionf; +import com.flowpowered.math.matrix.Matrix3f; +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector3f; + +import de.bluecolored.bluemap.core.util.MathUtil; + +public class Face { + + private Vector3f p1, p2, p3; + private Vector3f n1, n2, n3; + private Vector3f c1, c2, c3; + private Vector2f uv1, uv2, uv3; + private int materialIndex; + private boolean normalizedNormals; + + public Face(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f uv1, Vector2f uv2, Vector2f uv3, int materialIndex) { + this.p1 = p1; + this.p2 = p2; + this.p3 = p3; + + this.uv1 = uv1; + this.uv2 = uv2; + this.uv3 = uv3; + + this.materialIndex = materialIndex; + + Vector3f faceNormal = getFaceNormal(); + this.n1 = faceNormal; + this.n2 = faceNormal; + this.n3 = faceNormal; + this.normalizedNormals = true; + + Vector3f color = Vector3f.ONE; + this.c1 = color; + this.c2 = color; + this.c3 = color; + } + + public void rotate(Quaternionf rotation){ + p1 = rotation.rotate(p1); + p2 = rotation.rotate(p2); + p3 = rotation.rotate(p3); + + n1 = rotation.rotate(n1); + n2 = rotation.rotate(n2); + n3 = rotation.rotate(n3); + } + + public void transform(Matrix3f transformation){ + p1 = transformation.transform(p1); + p2 = transformation.transform(p2); + p3 = transformation.transform(p3); + + n1 = transformation.transform(n1); + n2 = transformation.transform(n2); + n3 = transformation.transform(n3); + + normalizedNormals = false; + } + + public void translate(Vector3f translation){ + p1 = translation.add(p1); + p2 = translation.add(p2); + p3 = translation.add(p3); + } + + public Vector3f getP1() { + return p1; + } + + public void setP1(Vector3f p1) { + this.p1 = p1; + } + + public Vector3f getP2() { + return p2; + } + + public void setP2(Vector3f p2) { + this.p2 = p2; + } + + public Vector3f getP3() { + return p3; + } + + public void setP3(Vector3f p3) { + this.p3 = p3; + } + + public Vector3f getN1() { + normlizeNormals(); + return n1; + } + + public void setN1(Vector3f n1) { + this.n1 = n1; + normalizedNormals = false; + } + + public Vector3f getN2() { + normlizeNormals(); + return n2; + } + + public void setN2(Vector3f n2) { + this.n2 = n2; + normalizedNormals = false; + } + + public Vector3f getN3() { + normlizeNormals(); + return n3; + } + + public void setN3(Vector3f n3) { + this.n3 = n3; + normalizedNormals = false; + } + + public Vector3f getC1() { + return c1; + } + + public void setC1(Vector3f c1) { + this.c1 = c1; + } + + public Vector3f getC2() { + return c2; + } + + public void setC2(Vector3f c2) { + this.c2 = c2; + } + + public Vector3f getC3() { + return c3; + } + + public void setC3(Vector3f c3) { + this.c3 = c3; + } + + public Vector2f getUv1() { + return uv1; + } + + public void setUv1(Vector2f uv1) { + this.uv1 = uv1; + } + + public Vector2f getUv2() { + return uv2; + } + + public void setUv2(Vector2f uv2) { + this.uv2 = uv2; + } + + public Vector2f getUv3() { + return uv3; + } + + public void setUv3(Vector2f uv3) { + this.uv3 = uv3; + } + + public int getMaterialIndex() { + return materialIndex; + } + + public void setMaterialIndex(int materialIndex) { + this.materialIndex = materialIndex; + } + + public Vector3f getFaceNormal(){ + return MathUtil.getSurfaceNormal(p1, p2, p3); + } + + private void normlizeNormals(){ + if (normalizedNormals) return; + + n1 = n1.normalize(); + n2 = n2.normalize(); + n3 = n3.normalize(); + + normalizedNormals = true; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Model.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Model.java new file mode 100644 index 00000000..38fa89da --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/model/Model.java @@ -0,0 +1,149 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.flowpowered.math.imaginary.Quaternionf; +import com.flowpowered.math.matrix.Matrix3f; +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector3f; + +import de.bluecolored.bluemap.core.threejs.BufferGeometry; + +public class Model { + + private List faces; + + public Model() { + this.faces = new ArrayList<>(); + } + + /** + * Merges the given Model into this model
+ * Faces are not cloned: So changes to the faces of the previous model will mirror in this model, but adding and removing faces will not. + */ + public void merge(Model model){ + faces.addAll(model.getFaces()); + } + + public void addFace(Face face){ + faces.add(face); + } + + public void removeFace(Face face){ + faces.remove(face); + } + + public Collection getFaces(){ + return faces; + } + + public void rotate(Quaternionf rotation){ + for (Face f : faces){ + f.rotate(rotation); + } + } + + public void transform(Matrix3f transformation){ + for (Face f : faces){ + f.transform(transformation); + } + } + + public void translate(Vector3f translation){ + for (Face f : faces){ + f.translate(translation); + } + } + + public BufferGeometry toBufferGeometry() { + + //sort faces by material index + faces.sort((f1, f2) -> (int) Math.signum(f1.getMaterialIndex() - f2.getMaterialIndex())); + + //reorganize all faces into arrays and create material-groups + int count = faces.size(); + + List groups = new ArrayList<>(); + int groupStart = 0; + int currentMaterialIndex = -1; + if (count > 0) currentMaterialIndex = faces.get(0).getMaterialIndex(); + + float[] position = new float[count * 3 * 3]; + float[] normal = new float[count * 3 * 3]; + float[] color = new float[count * 3 * 3]; + float[] uv = new float[count * 2 * 3]; + + for (int itemIndex = 0; itemIndex < count; itemIndex++){ + Face f = faces.get(itemIndex); + + if (currentMaterialIndex != f.getMaterialIndex()){ + groups.add(new BufferGeometry.MaterialGroup(currentMaterialIndex, groupStart * 3, (itemIndex - groupStart) * 3)); + groupStart = itemIndex; + currentMaterialIndex = f.getMaterialIndex(); + } + + addVector3fToArray( position, f.getP1(), (itemIndex * 3 + 0) * 3 ); + addVector3fToArray( normal, f.getN1(), (itemIndex * 3 + 0) * 3 ); + addVector3fToArray( color, f.getC1(), (itemIndex * 3 + 0) * 3 ); + addVector2fToArray( uv, f.getUv1(), (itemIndex * 3 + 0) * 2 ); + + addVector3fToArray( position, f.getP2(), (itemIndex * 3 + 1) * 3 ); + addVector3fToArray( normal, f.getN2(), (itemIndex * 3 + 1) * 3 ); + addVector3fToArray( color, f.getC2(), (itemIndex * 3 + 1) * 3 ); + addVector2fToArray( uv, f.getUv2(), (itemIndex * 3 + 1) * 2 ); + + addVector3fToArray( position, f.getP3(), (itemIndex * 3 + 2) * 3 ); + addVector3fToArray( normal, f.getN3(), (itemIndex * 3 + 2) * 3 ); + addVector3fToArray( color, f.getC3(), (itemIndex * 3 + 2) * 3 ); + addVector2fToArray( uv, f.getUv3(), (itemIndex * 3 + 2) * 2 ); + } + + groups.add(new BufferGeometry.MaterialGroup(currentMaterialIndex, groupStart * 3, (count - groupStart) * 3)); + + return new BufferGeometry( + position, + normal, + color, + uv, + groups.toArray(new BufferGeometry.MaterialGroup[groups.size()]) + ); + } + + private void addVector3fToArray(float[] array, Vector3f v, int startIndex){ + array[startIndex] = v.getX(); + array[startIndex + 1] = v.getY(); + array[startIndex + 2] = v.getZ(); + } + + private void addVector2fToArray(float[] array, Vector2f v, int startIndex){ + array[startIndex] = v.getX(); + array[startIndex + 1] = v.getY(); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/RenderSettings.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/RenderSettings.java new file mode 100644 index 00000000..5085db86 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/RenderSettings.java @@ -0,0 +1,88 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render; + +public interface RenderSettings { + + /** + * The strenght of ao-shading calculated for each vertex.
+ * A value of 0 turns off ao.
+ * The value represents the amount that each occluding face subtracts of the light-multiplier. (There are at most 3 occluding faces) + */ + default float getAmbientOcclusionStrenght() { + return 0.25f; + } + + /** + * Whether faces that have a sky-light-value of 0 will be rendered or not. + */ + default boolean isExcludeFacesWithoutSunlight() { + return true; + } + + /** + * A multiplier to how much faces are shaded due to their light value
+ * This can be used to make sure blocks with a light value of 0 are not pitch black + */ + default float getLightShadeMultiplier() { + return 0.8f; + } + + /** + * The maximum height of rendered blocks + */ + default int getMaxY() { + return Integer.MAX_VALUE; + } + + /** + * The minimum height of rendered blocks + */ + default int getMinY() { + return 0; + } + + /** + * The same as the maximum height, but blocks that are above this value are treated as AIR.
+ * This leads to the top-faces being rendered instead of them being culled. + */ + default int getSliceY() { + return Integer.MAX_VALUE; + } + + + + default RenderSettings copy() { + return new StaticRenderSettings( + getAmbientOcclusionStrenght(), + isExcludeFacesWithoutSunlight(), + getLightShadeMultiplier(), + getMaxY(), + getMinY(), + getSliceY() + ); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/StaticRenderSettings.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/StaticRenderSettings.java new file mode 100644 index 00000000..710f14cb --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/StaticRenderSettings.java @@ -0,0 +1,80 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render; + +public class StaticRenderSettings implements RenderSettings { + + private float ambientOcclusion; + private boolean excludeFacesWithoutSunlight; + private float lightShade; + private int maxY, minY, sliceY; + + public StaticRenderSettings( + float ambientOcclusion, + boolean excludeFacesWithoutSunlight, + float ligheShade, + int maxY, + int minY, + int sliceY + ) { + this.ambientOcclusion = ambientOcclusion; + this.excludeFacesWithoutSunlight = excludeFacesWithoutSunlight; + this.lightShade = ligheShade; + this.maxY = maxY; + this.minY = minY; + this.sliceY = sliceY; + } + + @Override + public float getAmbientOcclusionStrenght() { + return ambientOcclusion; + } + + @Override + public boolean isExcludeFacesWithoutSunlight() { + return excludeFacesWithoutSunlight; + } + + @Override + public float getLightShadeMultiplier() { + return lightShade; + } + + @Override + public int getMaxY() { + return maxY; + } + + @Override + public int getMinY() { + return minY; + } + + @Override + public int getSliceY() { + return sliceY; + } + +} \ No newline at end of file diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/TileRenderer.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/TileRenderer.java new file mode 100644 index 00000000..bd1539d9 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/TileRenderer.java @@ -0,0 +1,74 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render; + +import java.io.IOException; + +import de.bluecolored.bluemap.core.render.hires.HiresModel; +import de.bluecolored.bluemap.core.render.hires.HiresModelManager; +import de.bluecolored.bluemap.core.render.lowres.LowresModelManager; +import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; + +public class TileRenderer { + private HiresModelManager hiresModelManager; + private LowresModelManager lowresModelManager; + private RenderSettings renderSettings; + + public TileRenderer(HiresModelManager hiresModelManager, LowresModelManager lowresModelManager, RenderSettings renderSettings) { + this.hiresModelManager = hiresModelManager; + this.lowresModelManager = lowresModelManager; + this.renderSettings = renderSettings.copy(); + } + + /** + * Renders the provided WorldTile + * @throws ChunkNotGeneratedException if that WorldTile's WorldChunk is not fully generated + * @throws IOException if a lowres-model that needs to be updated could not be loaded + */ + public void render(WorldTile tile) throws IOException, ChunkNotGeneratedException { + HiresModel hiresModel = hiresModelManager.render(tile, renderSettings); + lowresModelManager.render(hiresModel); + } + + /** + * Saves changes to disk + */ + public void save(){ + lowresModelManager.save(); + } + + public HiresModelManager getHiresModelManager() { + return hiresModelManager; + } + + public LowresModelManager getLowresModelManager() { + return lowresModelManager; + } + + public RenderSettings getRenderSettings() { + return renderSettings; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/WorldTile.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/WorldTile.java new file mode 100644 index 00000000..3393a79c --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/WorldTile.java @@ -0,0 +1,69 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render; + +import java.util.Objects; + +import com.flowpowered.math.vector.Vector2i; + +import de.bluecolored.bluemap.core.world.World; + +public class WorldTile { + + private World world; + private Vector2i tile; + + private int hash; + + public WorldTile(World world, Vector2i tile) { + this.world = world; + this.tile = tile; + + this.hash = Objects.hash(world.getUUID(), tile); + } + + public World getWorld() { + return world; + } + + public Vector2i getTile() { + return tile; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof WorldTile)) return false; + WorldTile that = (WorldTile) obj; + + if (!this.world.getUUID().equals(that.world.getUUID())) return false; + return this.tile.equals(that.tile); + } + + @Override + public int hashCode() { + return hash; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/BlockContext.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/BlockContext.java new file mode 100644 index 00000000..1ae43cfd --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/BlockContext.java @@ -0,0 +1,57 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.context; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.Block; + +public interface BlockContext { + + Vector3i getPosition(); + + /** + * This returns neighbour blocks.
+ * The distance can not be larger than one block in each direction!
+ */ + Block getRelativeBlock(Vector3i direction); + + /** + * This returns neighbour blocks.
+ * The distance can not be larger than one block in each direction!
+ */ + default Block getRelativeBlock(int x, int y, int z){ + return getRelativeBlock(new Vector3i(x, y, z)); + } + + /** + * This returns neighbour blocks. + */ + default Block getRelativeBlock(Direction direction){ + return getRelativeBlock(direction.toVector()); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/EmptyBlockContext.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/EmptyBlockContext.java new file mode 100644 index 00000000..14e8f4f2 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/EmptyBlockContext.java @@ -0,0 +1,168 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.context; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3d; +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.util.AABB; +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.BlockState; +import de.bluecolored.bluemap.core.world.World; +import de.bluecolored.bluemap.core.world.WorldChunk; + +public class EmptyBlockContext implements ExtendedBlockContext { + + private static final EmptyBlockContext instance = new EmptyBlockContext(); + + public static final Block AIR_BLOCK = new AirBlock(); + + private EmptyBlockContext() {} + + @Override + public Block getRelativeBlock(Vector3i direction) { + return AIR_BLOCK; + } + + @Override + public Vector3i getPosition() { + return Vector3i.ZERO; + } + + public static ExtendedBlockContext instance() { + return instance; + } + + private static class AirBlock extends Block { + + private BlockState state = BlockState.AIR; + + @Override + public BlockState getBlock() { + return state; + } + + @Override + public World getWorld() { + return new EmptyWorld(); + } + + @Override + public Vector3i getPosition() { + return Vector3i.ZERO; + } + + @Override + public double getSunLightLevel() { + return 0d; + } + + @Override + public double getBlockLightLevel() { + return 0d; + } + + @Override + public boolean isCullingNeighborFaces() { + return false; + } + + @Override + public String getBiome() { + return "ocean"; + } + + } + + private static class EmptyWorld implements World { + + private AABB bounds; + + public EmptyWorld() { + this.bounds = new AABB(Vector3d.from(Double.POSITIVE_INFINITY), Vector3d.from(Double.NEGATIVE_INFINITY)); + } + + public EmptyWorld(AABB bounds){ + this.bounds = bounds; + } + + @Override + public World getWorld() { + return this; + } + + @Override + public Block getBlock(Vector3i pos) { + return new AirBlock(); + } + + @Override + public AABB getBoundaries() { + return bounds; + } + + @Override + public WorldChunk getWorldChunk(AABB boundaries) { + return new EmptyWorld(boundaries); + } + + @Override + public boolean isGenerated() { + return false; + } + + @Override + public String getName() { + return "-empty-"; + } + + @Override + public UUID getUUID() { + return new UUID(0, 0); + } + + @Override + public int getSeaLevel() { + return 63; + } + + @Override + public Vector3i getSpawnPoint() { + return new Vector3i(0, 63, 0); + } + + @Override + public Collection getChunkList(long modifiedSince) { + return Collections.emptyList(); + } + + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/ExtendedBlockContext.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/ExtendedBlockContext.java new file mode 100644 index 00000000..faa278b2 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/ExtendedBlockContext.java @@ -0,0 +1,72 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.context; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.world.Block; + +/** + * A BlockContext that has a range of TWO blocks instead of one + */ +public interface ExtendedBlockContext extends BlockContext { + + /** + * This returns neighbour blocks.
+ * The distance can not be larger than two blocks in each direction!
+ */ + Block getRelativeBlock(Vector3i direction); + + /** + * This returns neighbour blocks.
+ * The distance can not be larger than two blocks in each direction!
+ */ + default Block getRelativeBlock(int x, int y, int z){ + return getRelativeBlock(new Vector3i(x, y, z)); + } + + /** + * Returns a relative view of this ExtendedBlockContext! + * The distance can not be larger than two blocks in each direction!
+ */ + default BlockContext getRelativeView(final Vector3i relative) { + final ExtendedBlockContext parent = this; + + return new BlockContext() { + + @Override + public Block getRelativeBlock(Vector3i direction) { + return parent.getRelativeBlock(direction.add(relative)); + } + + @Override + public Vector3i getPosition() { + return parent.getPosition().add(relative); + } + }; + + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/SlicedWorldChunkBlockContext.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/SlicedWorldChunkBlockContext.java new file mode 100644 index 00000000..27bdd957 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/SlicedWorldChunkBlockContext.java @@ -0,0 +1,52 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.context; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.WorldChunk; + +public class SlicedWorldChunkBlockContext extends WorldChunkBlockContext { + + private int sliceY; + + /** + * Same as a {@link WorldChunkBlockContext} but if the requested Block is above the slice-value it will return air. + */ + public SlicedWorldChunkBlockContext(WorldChunk worldChunk, Vector3i blockPos, int sliceY) { + super(worldChunk, blockPos); + + this.sliceY = sliceY; + } + + @Override + protected Block getBlock(Vector3i position) { + if (position.getY() > sliceY) return EmptyBlockContext.AIR_BLOCK; + + return super.getBlock(position); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/WorldChunkBlockContext.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/WorldChunkBlockContext.java new file mode 100644 index 00000000..53755b5e --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/context/WorldChunkBlockContext.java @@ -0,0 +1,79 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.context; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; +import de.bluecolored.bluemap.core.world.WorldChunk; + +public class WorldChunkBlockContext implements ExtendedBlockContext { + + private Vector3i blockPos; + private WorldChunk chunk; + + /** + * A BlockContext backed by a WorldChunk. + * + * This Context assumes that the world-chunk is generated around that block-position. + * If the given world chunk is not generated, using this context will result in a RuntimeException! + */ + public WorldChunkBlockContext(WorldChunk worldChunk, Vector3i blockPos) { + this.blockPos = blockPos; + this.chunk = worldChunk; + } + + @Override + public Vector3i getPosition() { + return blockPos; + } + + @Override + public Block getRelativeBlock(int x, int y, int z) { + Vector3i pos = blockPos.add(x, y, z); + return getBlock(pos); + } + + @Override + public Block getRelativeBlock(Vector3i direction) { + Vector3i pos = blockPos.add(direction); + return getBlock(pos); + } + + protected Block getBlock(Vector3i position) { + if (!chunk.containsBlock(position)) { + return EmptyBlockContext.AIR_BLOCK; + } + + try { + return chunk.getBlock(position); + } catch (ChunkNotGeneratedException e) { + //we assume the chunk being generated + throw new RuntimeException(e); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModel.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModel.java new file mode 100644 index 00000000..c44595f8 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModel.java @@ -0,0 +1,94 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.hires; + +import java.util.UUID; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; +import com.flowpowered.math.vector.Vector4f; + +import de.bluecolored.bluemap.core.model.Model; + +/** + * A model, containing additional information about the tile it represents + */ +public class HiresModel extends Model { + + private UUID world; + private Vector2i tile; + private Vector3i blockMin, blockMax, blockSize; + + private int[][] heights; + private Vector4f[][] colors; + + public HiresModel(UUID world, Vector2i tile, Vector3i blockMin, Vector3i blockMax) { + this.world = world; + this.tile = tile; + this.blockMin = blockMin; + this.blockMax = blockMax; + this.blockSize = blockMax.sub(blockMin).add(Vector3i.ONE); + + heights = new int[blockSize.getX()][blockSize.getZ()]; + colors = new Vector4f[blockSize.getX()][blockSize.getZ()]; + } + + public void setColor(int x, int z, Vector4f color){ + colors[x - blockMin.getX()][z - blockMin.getZ()] = color; + } + + public Vector4f getColor(int x, int z){ + return colors[x - blockMin.getX()][z - blockMin.getZ()]; + } + + public void setHeight(int x, int z, int height){ + heights[x - blockMin.getX()][z - blockMin.getZ()] = height; + } + + public int getHeight(int x, int z){ + return heights[x - blockMin.getX()][z - blockMin.getZ()]; + } + + public UUID getWorld(){ + return world; + } + + public Vector3i getBlockMin(){ + return blockMin; + } + + public Vector3i getBlockMax(){ + return blockMax; + } + + public Vector3i getBlockSize(){ + return blockSize; + } + + public Vector2i getTile(){ + return tile; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelManager.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelManager.java new file mode 100644 index 00000000..00722b15 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelManager.java @@ -0,0 +1,168 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.hires; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.concurrent.ExecutorService; +import java.util.zip.GZIPOutputStream; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3d; +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.render.WorldTile; +import de.bluecolored.bluemap.core.resourcepack.ResourcePack; +import de.bluecolored.bluemap.core.util.AABB; +import de.bluecolored.bluemap.core.util.FileUtil; +import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; + +public class HiresModelManager { + + private Path fileRoot; + private HiresModelRenderer renderer; + + private Vector2i tileSize; + private Vector2i gridOrigin; + + private ExecutorService savingExecutor; + + public HiresModelManager(Path fileRoot, ResourcePack resourcePack, Vector2i tileSize, ExecutorService savingExecutor) { + this(fileRoot, new HiresModelRenderer(resourcePack), tileSize, new Vector2i(2, 2), savingExecutor); + } + + public HiresModelManager(Path fileRoot, HiresModelRenderer renderer, Vector2i tileSize, Vector2i gridOrigin, ExecutorService savingExecutor) { + this.fileRoot = fileRoot; + this.renderer = renderer; + + this.tileSize = tileSize; + this.gridOrigin = gridOrigin; + + this.savingExecutor = savingExecutor; + } + + /** + * Renders the given world tile with the provided render-settings + * @throws ChunkNotGeneratedException if a minecraft-chunk needed for thies tile is not yet generated + */ + public HiresModel render(WorldTile tile, RenderSettings renderSettings) throws ChunkNotGeneratedException { + HiresModel model = renderer.render(tile, getTileRegion(tile), renderSettings); + save(model); + return model; + } + + private void save(final HiresModel model) { + final String modelJson = model.toBufferGeometry().toJson(); + savingExecutor.submit(() -> save(model, modelJson)); + } + + private void save(HiresModel model, String modelJson){ + File file = getFile(model.getTile()); + + try { + if (!file.exists()){ + file.getParentFile().mkdirs(); + file.createNewFile(); + } + + FileOutputStream fos = new FileOutputStream(file); + GZIPOutputStream zos = new GZIPOutputStream(fos); + OutputStreamWriter osw = new OutputStreamWriter(zos, StandardCharsets.UTF_8); + try ( + PrintWriter pw = new PrintWriter(osw); + ){ + pw.print(modelJson); + } + + //logger.logDebug("Saved hires model: " + model.getTile()); + } catch (IOException e){ + Logger.global.logError("Failed to save hires model: " + file, e); + } + } + + /** + * Returns the region of blocks that a tile includes + */ + public AABB getTileRegion(WorldTile tile) { + Vector3i min = new Vector3i( + tile.getTile().getX() * tileSize.getX() + gridOrigin.getX(), + tile.getWorld().getBoundaries().getMin().getFloorY(), + tile.getTile().getY() * tileSize.getY() + gridOrigin.getY() + ); + Vector3i max = min.add( + tileSize.getX() - 1, + tile.getWorld().getBoundaries().getMax().getFloorY(), + tileSize.getY() - 1 + ); + return new AABB(min, max); + } + + /** + * Returns the tile-size + */ + public Vector2i getTileSize() { + return tileSize; + } + + /** + * Returns the grid-origin + */ + public Vector2i getGridOrigin() { + return gridOrigin; + } + + /** + * Converts a block-position to a map-tile-coordinate + */ + public Vector2i posToTile(Vector3i pos){ + return posToTile(pos.toDouble()); + } + + /** + * Converts a block-position to a map-tile-coordinate + */ + public Vector2i posToTile(Vector3d pos){ + pos = pos.sub(new Vector3d(gridOrigin.getX(), 0.0, gridOrigin.getY())); + return Vector2i.from( + (int) Math.floor(pos.getX() / (double) getTileSize().getX()), + (int) Math.floor(pos.getZ() / (double) getTileSize().getY()) + ); + } + + /** + * Returns the file for a tile + */ + public File getFile(Vector2i tilePos){ + return FileUtil.coordsToFile(fileRoot, tilePos, "json.gz"); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java new file mode 100644 index 00000000..bff2d4f2 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java @@ -0,0 +1,115 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.hires; + +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector3i; +import com.flowpowered.math.vector.Vector4f; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.render.WorldTile; +import de.bluecolored.bluemap.core.render.context.SlicedWorldChunkBlockContext; +import de.bluecolored.bluemap.core.render.hires.blockmodel.BlockStateModel; +import de.bluecolored.bluemap.core.render.hires.blockmodel.BlockStateModelFactory; +import de.bluecolored.bluemap.core.resourcepack.InvalidResourceDeclarationException; +import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException; +import de.bluecolored.bluemap.core.resourcepack.NoSuchTextureException; +import de.bluecolored.bluemap.core.resourcepack.ResourcePack; +import de.bluecolored.bluemap.core.util.AABB; +import de.bluecolored.bluemap.core.util.MathUtil; +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; +import de.bluecolored.bluemap.core.world.WorldChunk; + +public class HiresModelRenderer { + + private BlockStateModelFactory modelFactory; + + public HiresModelRenderer(ResourcePack resourcePack) { + this(new BlockStateModelFactory(resourcePack)); + } + + public HiresModelRenderer(BlockStateModelFactory modelFactory) { + this.modelFactory = modelFactory; + } + + public HiresModel render(WorldTile tile, AABB region, RenderSettings renderSettings) throws ChunkNotGeneratedException { + Vector3i min = region.getMin().toInt(); + Vector3i max = region.getMax().toInt(); + + min = new Vector3i(min.getX(), Math.max(min.getY(), renderSettings.getMinY()), min.getZ()); + max = new Vector3i(max.getX(), Math.min(max.getY(), Math.min(renderSettings.getMaxY(), renderSettings.getSliceY())), max.getZ()); + + WorldChunk chunk = tile.getWorld().getWorldChunk(region.expand(4, 0, 4)); + + if (!chunk.isGenerated()) throw new ChunkNotGeneratedException(); + + HiresModel model = new HiresModel(tile.getWorld().getUUID(), tile.getTile(), min, max); + + for (int x = min.getX(); x <= max.getX(); x++){ + for (int z = min.getZ(); z <= max.getZ(); z++){ + + int maxHeight = 0; + Vector4f color = Vector4f.ZERO; + + for (int y = min.getY(); y <= max.getY(); y++){ + Block block = chunk.getBlock(x, y, z); + if (block.getBlock().getId().equals("air")) continue; + + maxHeight = y; + + BlockStateModel blockModel; + try { + blockModel = modelFactory.createFrom(block.getBlock(), new SlicedWorldChunkBlockContext(chunk, new Vector3i(x, y, z), renderSettings.getSliceY()), renderSettings); + } catch (NoSuchResourceException | InvalidResourceDeclarationException | NoSuchTextureException e) { + blockModel = new BlockStateModel(); + Logger.global.noFloodDebug(block.getBlock().getId() + "-hiresModelRenderer-blockmodelerr", "Failed to create BlockModel for BlockState: " + block.getBlock() + " (" + e.toString() + ")"); + } + + blockModel.translate(new Vector3f(x, y, z).sub(min.toFloat())); + + color = MathUtil.overlayColors(blockModel.getMapColor(), color); + + //TODO: quick hack to random offset grass + if (block.getBlock().getId().equals("grass")){ + float dx = (MathUtil.hashToFloat(x, y, z, 123984) - 0.5f) * 0.75f; + float dz = (MathUtil.hashToFloat(x, y, z, 345542) - 0.5f) * 0.75f; + blockModel.translate(new Vector3f(dx, 0, dz)); + } + + model.merge(blockModel); + } + + model.setHeight(x, z, maxHeight); + model.setColor(x, z, color); + + } + } + + return model; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModel.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModel.java new file mode 100644 index 00000000..f3f2e1b8 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModel.java @@ -0,0 +1,68 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.hires.blockmodel; + +import com.flowpowered.math.vector.Vector4f; + +import de.bluecolored.bluemap.core.model.Model; +import de.bluecolored.bluemap.core.util.MathUtil; + +/** + * A model with some extra information about the BlockState it represents + */ +public class BlockStateModel extends Model { + + private Vector4f mapColor; + + public BlockStateModel(){ + this(Vector4f.ZERO); + } + + public BlockStateModel(Vector4f mapColor) { + this.mapColor = mapColor; + } + + @Override + public void merge(Model model) { + super.merge(model); + + if (model instanceof BlockStateModel){ + mergeMapColor(((BlockStateModel) model).getMapColor()); + } + } + + public Vector4f getMapColor() { + return mapColor; + } + + public void setMapColor(Vector4f mapColor) { + this.mapColor = mapColor; + } + + public void mergeMapColor(Vector4f mapColor) { + this.mapColor = MathUtil.blendColors(this.mapColor, mapColor); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModelFactory.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModelFactory.java new file mode 100644 index 00000000..9d0d1c80 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/BlockStateModelFactory.java @@ -0,0 +1,98 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.hires.blockmodel; + +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.render.context.EmptyBlockContext; +import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext; +import de.bluecolored.bluemap.core.resourcepack.BlockStateResource; +import de.bluecolored.bluemap.core.resourcepack.InvalidResourceDeclarationException; +import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException; +import de.bluecolored.bluemap.core.resourcepack.NoSuchTextureException; +import de.bluecolored.bluemap.core.resourcepack.ResourcePack; +import de.bluecolored.bluemap.core.world.BlockState; + +public class BlockStateModelFactory { + + private ResourcePack resourcePack; + + public BlockStateModelFactory(ResourcePack resources) { + this.resourcePack = resources; + } + + public BlockStateModel createFrom(BlockState blockState) throws NoSuchResourceException, InvalidResourceDeclarationException, NoSuchTextureException { + return createFrom(blockState, EmptyBlockContext.instance(), new RenderSettings() { + @Override + public float getLightShadeMultiplier() { + return 0; + } + + @Override + public boolean isExcludeFacesWithoutSunlight() { + return false; + } + + @Override + public float getAmbientOcclusionStrenght() { + return 0; + } + }); + } + + public BlockStateModel createFrom(BlockState blockState, ExtendedBlockContext context, RenderSettings renderSettings) throws NoSuchResourceException, InvalidResourceDeclarationException, NoSuchTextureException { + + //air won't be rendered + if ( + blockState.getId().equals("air") || + blockState.getId().equals("cave_air") || + blockState.getId().equals("void_air") + ) { + return new BlockStateModel(); + } + + // if it is a liquid, use the LiquidModelBuilder + if ( + blockState.getId().equals("water") || + blockState.getId().equals("lava") + ){ + return new LiquidModelBuilder(blockState, context, resourcePack, renderSettings).build(); + } + + // if no other model builder matched try to find a model definition from the resource-packs and use the default ResourceModelBuilder + BlockStateResource resource = resourcePack.getBlockStateResource(blockState); + BlockStateModel model = new ResourceModelBuilder(resource, context, resourcePack, renderSettings).build(); + + // if block is waterlogged + if (LiquidModelBuilder.isWaterlogged(blockState)) { + BlockStateModel watermodel = new LiquidModelBuilder(WATERLOGGED_BLOCKSTATE, context, resourcePack, renderSettings).build(); + model.merge(watermodel); + } + + return model; + } + + private BlockState WATERLOGGED_BLOCKSTATE = new BlockState("minecraft:water"); + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/LiquidModelBuilder.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/LiquidModelBuilder.java new file mode 100644 index 00000000..42cfa7d7 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/LiquidModelBuilder.java @@ -0,0 +1,245 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.hires.blockmodel; + +import java.util.HashSet; + +import com.flowpowered.math.matrix.Matrix3f; +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector4f; +import com.google.common.collect.Sets; + +import de.bluecolored.bluemap.core.model.Face; +import de.bluecolored.bluemap.core.model.Model; +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext; +import de.bluecolored.bluemap.core.resourcepack.NoSuchTextureException; +import de.bluecolored.bluemap.core.resourcepack.ResourcePack; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.world.Block; +import de.bluecolored.bluemap.core.world.BlockState; + +/** + * A model builder for all liquid blocks + */ +public class LiquidModelBuilder { + + private static final HashSet DEFAULT_WATERLOGGED_BLOCK_IDS = Sets.newHashSet( + "minecraft:seagrass", + "minecraft:tall_seagrass", + "minecraft:kelp" + ); + + private BlockState blockState; + private ExtendedBlockContext context; + private ResourcePack resourcePack; + private RenderSettings renderSettings; + + private float[] heights; + + public LiquidModelBuilder(BlockState blockState, ExtendedBlockContext context, ResourcePack resourcePack, RenderSettings renderSettings) { + this.blockState = blockState; + this.context = context; + this.resourcePack = resourcePack; + this.renderSettings = renderSettings; + + this.heights = new float[]{14f, 14f, 14f, 14f}; + } + + public BlockStateModel build() throws NoSuchTextureException { + if (this.renderSettings.isExcludeFacesWithoutSunlight() && context.getRelativeBlock(0, 0, 0).getSunLightLevel() == 0) return new BlockStateModel(); + + int level = getLiquidLevel(blockState); + + if (level >= 8 ||level == 0 && isLiquid(context.getRelativeBlock(0, 1, 0))){ + this.heights = new float[]{16f, 16f, 16f, 16f}; + return buildModel(); + } + + this.heights = new float[]{ + getLiquidCornerHeight(-1, 0, -1), + getLiquidCornerHeight(-1, 0, 0), + getLiquidCornerHeight(0, 0, -1), + getLiquidCornerHeight(0, 0, 0) + }; + + return buildModel(); + } + + private float getLiquidCornerHeight(int x, int y, int z){ + for (int ix = x; ix <= x+1; ix++){ + for (int iz = z; iz<= z+1; iz++){ + if (isLiquid(context.getRelativeBlock(ix, y+1, iz))){ + return 16f; + } + } + } + + float sumHeight = 0f; + int count = 0; + + for (int ix = x; ix <= x+1; ix++){ + for (int iz = z; iz<= z+1; iz++){ + Block b = context.getRelativeBlock(ix, y, iz); + if (isLiquid(b)){ + if (getLiquidLevel(b.getBlock()) == 0) return 14f; + + sumHeight += getLiquidBaseHeight(b.getBlock()); + count++; + } + + else if (!isLiquidBlockingBlock(b)){ + count++; + } + } + } + + //should both never happen + if (sumHeight == 0) return 3f; + if (count == 0) return 3f; + + return sumHeight / count; + } + + private boolean isLiquidBlockingBlock(Block b){ + if (b.getBlock().getId().equals("air")) return false; + return true; + } + + private boolean isLiquid(Block block){ + return isLiquid(block.getBlock()); + } + + private boolean isLiquid(BlockState blockstate){ + if (blockstate.getId().equals(blockState.getId())) return true; + return LiquidModelBuilder.isWaterlogged(blockstate); + } + + private float getLiquidBaseHeight(BlockState block){ + int level = getLiquidLevel(block); + float baseHeight = 14f - level * 1.9f; + return baseHeight; + } + + private int getLiquidLevel(BlockState block){ + if (block.getProperties().containsKey("level")) { + return Integer.parseInt(block.getProperties().get("level")); + } + return 0; + } + + private BlockStateModel buildModel() throws NoSuchTextureException { + BlockStateModel model = new BlockStateModel(); + + Vector3f[] c = new Vector3f[]{ + new Vector3f( 0, 0, 0 ), + new Vector3f( 0, 0, 16 ), + new Vector3f( 16, 0, 0 ), + new Vector3f( 16, 0, 16 ), + new Vector3f( 0, heights[0], 0 ), + new Vector3f( 0, heights[1], 16 ), + new Vector3f( 16, heights[2], 0 ), + new Vector3f( 16, heights[3], 16 ), + }; + + int textureId = resourcePack.getTextureProvider().getTextureIndex("block/" + blockState.getId() + "_still"); + Vector3f tintcolor = Vector3f.ONE; + if (blockState.getId().equals("water")) { + tintcolor = resourcePack.getBlockColorProvider().getBiomeWaterAverageColor(context); + } + + createElementFace(model, Direction.DOWN, c[0], c[2], c[3], c[1], tintcolor, textureId); + createElementFace(model, Direction.UP, c[5], c[7], c[6], c[4], tintcolor, textureId); + createElementFace(model, Direction.NORTH, c[2], c[0], c[4], c[6], tintcolor, textureId); + createElementFace(model, Direction.SOUTH, c[1], c[3], c[7], c[5], tintcolor, textureId); + createElementFace(model, Direction.WEST, c[0], c[1], c[5], c[4], tintcolor, textureId); + createElementFace(model, Direction.EAST, c[3], c[2], c[6], c[7], tintcolor, textureId); + + //scale down + model.transform(Matrix3f.createScaling(1f / 16f)); + + //calculate mapcolor + Vector4f mapcolor = resourcePack.getTextureProvider().getTexture("block/" + blockState.getId() + "_still").getColor(); + mapcolor = mapcolor.mul(tintcolor.toVector4(1)); + model.setMapColor(mapcolor); + + return model; + } + + private void createElementFace(Model model, Direction faceDir, Vector3f c0, Vector3f c1, Vector3f c2, Vector3f c3, Vector3f color, int textureId) throws NoSuchTextureException { + + //face culling + Block bl = context.getRelativeBlock(faceDir); + if (isLiquid(bl) || (faceDir != Direction.UP && bl.isCullingNeighborFaces())) return; + + //UV + Vector4f uv = new Vector4f(0, 0, 16, 16).div(16); + + //create both triangles + Vector2f[] uvs = new Vector2f[4]; + uvs[0] = new Vector2f(uv.getX(), uv.getW()); + uvs[1] = new Vector2f(uv.getZ(), uv.getW()); + uvs[2] = new Vector2f(uv.getZ(), uv.getY()); + uvs[3] = new Vector2f(uv.getX(), uv.getY()); + + Face f1 = new Face(c0, c1, c2, uvs[0], uvs[1], uvs[2], textureId); + Face f2 = new Face(c0, c2, c3, uvs[0], uvs[2], uvs[3], textureId); + + //move face in a tiny bit to avoid z-fighting with waterlogged blocks + f1.translate(faceDir.opposite().toVector().toFloat().mul(0.01)); + f2.translate(faceDir.opposite().toVector().toFloat().mul(0.01)); + + float light = 1f; + if (renderSettings.getLightShadeMultiplier() > 0) { + light = 0f; + for (Direction d : Direction.values()){ + Block b = context.getRelativeBlock(d.toVector()); + float l = (float) (Math.max(b.getBlockLightLevel(), b.getSunLightLevel()) / 15f) * renderSettings.getLightShadeMultiplier() + (1 - renderSettings.getLightShadeMultiplier()); + if (l > light) light = l; + } + } + + color = color.mul(light); + + f1.setC1(color); + f1.setC2(color); + f1.setC3(color); + + f2.setC1(color); + f2.setC2(color); + f2.setC3(color); + + //add the face + model.addFace(f1); + model.addFace(f2); + } + + public static boolean isWaterlogged(BlockState blockState) { + if (DEFAULT_WATERLOGGED_BLOCK_IDS.contains(blockState.getFullId())) return true; + return blockState.getProperties().getOrDefault("waterlogged", "false").equals("true"); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/ResourceModelBuilder.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/ResourceModelBuilder.java new file mode 100644 index 00000000..293d5444 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/blockmodel/ResourceModelBuilder.java @@ -0,0 +1,386 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.hires.blockmodel; + +import com.flowpowered.math.TrigMath; +import com.flowpowered.math.imaginary.Complexf; +import com.flowpowered.math.imaginary.Quaternionf; +import com.flowpowered.math.matrix.Matrix3f; +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector3i; +import com.flowpowered.math.vector.Vector4f; + +import de.bluecolored.bluemap.core.model.Face; +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.render.context.BlockContext; +import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext; +import de.bluecolored.bluemap.core.resourcepack.BlockModelElementFaceResource; +import de.bluecolored.bluemap.core.resourcepack.BlockModelElementResource; +import de.bluecolored.bluemap.core.resourcepack.BlockModelResource; +import de.bluecolored.bluemap.core.resourcepack.BlockStateResource; +import de.bluecolored.bluemap.core.resourcepack.NoSuchTextureException; +import de.bluecolored.bluemap.core.resourcepack.ResourcePack; +import de.bluecolored.bluemap.core.resourcepack.TextureProvider.Texture; +import de.bluecolored.bluemap.core.util.Direction; +import de.bluecolored.bluemap.core.util.MathUtil; +import de.bluecolored.bluemap.core.util.WeighedArrayList; +import de.bluecolored.bluemap.core.world.Block; + +/** + * This model builder creates a BlockStateModel using the information from parsed resource-pack json files. + */ +public class ResourceModelBuilder { + + private static final Vector3f HALF_3F = Vector3f.ONE.mul(0.5); + private static final Vector3f NEG_HALF_3F = HALF_3F.negate(); + private static final Vector2f HALF_2F = Vector2f.ONE.mul(0.5); + + private BlockStateResource resource; + private ExtendedBlockContext context; + private ResourcePack resourcePack; + private RenderSettings renderSettings; + + public ResourceModelBuilder(BlockStateResource resource, ExtendedBlockContext context, ResourcePack resourcePack, RenderSettings renderSettings) { + this.resource = resource; + this.context = context; + this.resourcePack = resourcePack; + this.renderSettings = renderSettings; + } + + public BlockStateModel build() throws NoSuchTextureException { + BlockStateModel model = new BlockStateModel(); + + for (WeighedArrayList bmrList : resource.getModelResources()){ + BlockModelResource bmr = bmrList.get((int) Math.floor(MathUtil.hashToFloat(context.getPosition(), 23489756) * (float) bmrList.size())); + + model.merge(fromModelResource(bmr)); + } + + return model; + } + + private BlockStateModel fromModelResource(BlockModelResource bmr) throws NoSuchTextureException { + BlockStateModel model = new BlockStateModel(); + + for (BlockModelElementResource bmer : bmr.getElements()){ + model.merge(fromModelElementResource(bmer)); + } + + model.translate(NEG_HALF_3F); + model.rotate(Quaternionf.fromAxesAnglesDeg( + -bmr.getXRot(), + -bmr.getYRot(), + 0 + )); + model.translate(HALF_3F); + + return model; + } + + private BlockStateModel fromModelElementResource(BlockModelElementResource bmer) throws NoSuchTextureException { + BlockStateModel model = new BlockStateModel(); + + //create faces + Vector3f min = bmer.getFrom().min(bmer.getTo()); + Vector3f max = bmer.getFrom().max(bmer.getTo()); + + Vector3f[] c = new Vector3f[]{ + new Vector3f( min .getX(), min .getY(), min .getZ()), + new Vector3f( min .getX(), min .getY(), max .getZ()), + new Vector3f( max .getX(), min .getY(), min .getZ()), + new Vector3f( max .getX(), min .getY(), max .getZ()), + new Vector3f( min .getX(), max .getY(), min .getZ()), + new Vector3f( min .getX(), max .getY(), max .getZ()), + new Vector3f( max .getX(), max .getY(), min .getZ()), + new Vector3f( max .getX(), max .getY(), max .getZ()), + }; + + createElementFace(model, bmer.getDownFace(), Direction.DOWN, c[0], c[2], c[3], c[1]); + createElementFace(model, bmer.getUpFace(), Direction.UP, c[5], c[7], c[6], c[4]); + createElementFace(model, bmer.getNorthFace(), Direction.NORTH, c[2], c[0], c[4], c[6]); + createElementFace(model, bmer.getSouthFace(), Direction.SOUTH, c[1], c[3], c[7], c[5]); + createElementFace(model, bmer.getWestFace(), Direction.WEST, c[0], c[1], c[5], c[4]); + createElementFace(model, bmer.getEastFace(), Direction.EAST, c[3], c[2], c[6], c[7]); + + //rotate + if (bmer.isRotation()){ + Vector3f translation = bmer.getRotationOrigin(); + model.translate(translation.negate()); + + model.rotate(Quaternionf.fromAngleDegAxis( + bmer.getRotationAngle(), + bmer.getRotationAxis().toVector().toFloat() + )); + + if (bmer.isRotationRescale()){ + Vector3f scale = + Vector3f.ONE + .sub(bmer.getRotationAxis().toVector().toFloat()) + .mul(Math.abs(TrigMath.sin(bmer.getRotationAngle() * TrigMath.DEG_TO_RAD))) + .mul(1 - (TrigMath.SQRT_OF_TWO - 1)) + .add(Vector3f.ONE); + model.transform(Matrix3f.createScaling(scale)); + } + + model.translate(translation); + + } + + //scale down + model.transform(Matrix3f.createScaling(1f / 16f)); + + return model; + } + + private void createElementFace(BlockStateModel model, BlockModelElementFaceResource face, Direction faceDir, Vector3f c0, Vector3f c1, Vector3f c2, Vector3f c3) throws NoSuchTextureException { + if (face == null) return; + BlockModelResource m = face.getElement().getModel(); + + //face culling + if (face.isCullface()){ + Block b = getRotationRelativeBlock(m, face.getCullface()); + if (b.isCullingNeighborFaces()) return; + } + + //light calculation + Block b = getRotationRelativeBlock(m, faceDir); + BlockContext bContext = context.getRelativeView(getRotationRelativeDirectionVector(m, faceDir.toVector().toFloat()).toInt()); + float skyLight = b.getPassedSunLight(bContext); + + //filter out faces that are not skylighted + if (skyLight == 0f && renderSettings.isExcludeFacesWithoutSunlight()) return; + + float light = 1; + if (renderSettings.getLightShadeMultiplier() > 0) { + float blockLight = b.getPassedBlockLight(bContext); + light = (Math.max(skyLight, blockLight) / 15f) * renderSettings.getLightShadeMultiplier() + (1 - renderSettings.getLightShadeMultiplier()); + if (light > 1) light = 1; + if (light < 0) light = 0; + } + + //UV + Vector4f uv = face.getUv().toFloat().div(16); + + //UV-Lock counter-rotation + int uvLockAngle = 0; + if (m.isUvLock()){ + Quaternionf rot = Quaternionf.fromAxesAnglesDeg(m.getXRot(), m.getYRot(), 0); + uvLockAngle = (int) rot.getAxesAnglesDeg().dot(faceDir.toVector().toFloat()); + + //TODO: my math has stopped working, there has to be a more consistent solution + if (m.getXRot() >= 180 && m.getYRot() != 90 && m.getYRot() != 270) uvLockAngle += 180; + } + + //create both triangles + Vector2f[] uvs = new Vector2f[4]; + uvs[0] = new Vector2f(uv.getX(), uv.getW()); + uvs[1] = new Vector2f(uv.getZ(), uv.getW()); + uvs[2] = new Vector2f(uv.getZ(), uv.getY()); + uvs[3] = new Vector2f(uv.getX(), uv.getY()); + + //face texture rotation + uvs = rotateUVOuter(uvs, uvLockAngle); + uvs = rotateUVInner(uvs, face.getRotation()); + + String textureName = face.getResolvedTexture(); + if (textureName == null) throw new NoSuchTextureException("There is no Texture-Definition for a face: " + faceDir + " of block: " + resource.getBlock()); + + int textureId = resourcePack.getTextureProvider().getTextureIndex(textureName); + + Face f1 = new Face(c0, c1, c2, uvs[0], uvs[1], uvs[2], textureId); + Face f2 = new Face(c0, c2, c3, uvs[0], uvs[2], uvs[3], textureId); + + //calculate ao + double ao0 = 1d, ao1 = 1d, ao2 = 1d, ao3 = 1d; + if (renderSettings.getAmbientOcclusionStrenght() > 0f && m.isAmbientOcclusion()){ + ao0 = testAo(m, c0, faceDir); + ao1 = testAo(m, c1, faceDir); + ao2 = testAo(m, c2, faceDir); + ao3 = testAo(m, c3, faceDir); + } + + //tint the face + Vector3f color = Vector3f.ONE; + if (face.isTinted()){ + color = resourcePack.getBlockColorProvider().getBlockColor(context); + } + + color = color.mul(light); + + Vector3f aoColor; + + aoColor = color.mul(ao0); + f1.setC1(aoColor); + f2.setC1(aoColor); + + aoColor = color.mul(ao1); + f1.setC2(aoColor); + + aoColor = color.mul(ao2); + f1.setC3(aoColor); + f2.setC2(aoColor); + + aoColor = color.mul(ao3); + f2.setC3(aoColor); + + //add the face + model.addFace(f1); + model.addFace(f2); + + //if is top face set model-color + Vector3f dir = getRotationRelativeDirectionVector(m, faceDir.toVector().toFloat()); + + BlockModelElementResource bmer = face.getElement(); + if (bmer.isRotation()){ + Quaternionf rot = Quaternionf.fromAngleDegAxis( + bmer.getRotationAngle(), + bmer.getRotationAxis().toVector().toFloat() + ); + dir = rot.rotate(dir); + } + + float a = dir.getY(); + if (a > 0){ + Texture t = resourcePack.getTextureProvider().getTexture(textureId); + if (t != null){ + Vector4f c = t.getColor(); + c = c.mul(color.toVector4(1f)); + c = new Vector4f(c.getX(), c.getY(), c.getZ(), c.getW() * a); + model.mergeMapColor(c); + } + } + + } + + private Block getRotationRelativeBlock(BlockModelResource model, Direction direction){ + return getRotationRelativeBlock(model, direction.toVector()); + } + + private Block getRotationRelativeBlock(BlockModelResource model, Vector3i direction){ + Vector3i dir = getRotationRelativeDirectionVector(model, direction.toFloat()).round().toInt(); + return context.getRelativeBlock(dir); + } + + private Vector3f getRotationRelativeDirectionVector(BlockModelResource model, Vector3f direction){ + Quaternionf rot = Quaternionf.fromAxesAnglesDeg( + -model.getXRot(), + -model.getYRot(), + 0 + ); + Vector3f dir = rot.rotate(direction); + return dir; + } + + private double testAo(BlockModelResource model, Vector3f vertex, Direction dir){ + int occluding = 0; + + int x = 0; + if (vertex.getX() == 16){ + x = 1; + } else if (vertex.getX() == 0){ + x = -1; + } + + int y = 0; + if (vertex.getY() == 16){ + y = 1; + } else if (vertex.getY() == 0){ + y = -1; + } + + int z = 0; + if (vertex.getZ() == 16){ + z = 1; + } else if (vertex.getZ() == 0){ + z = -1; + } + + Vector3i rel = new Vector3i(x, y, 0); + if (rel.dot(dir.toVector()) > 0){ + if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++; + } + + rel = new Vector3i(x, 0, z); + if (rel.dot(dir.toVector()) > 0){ + if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++; + } + + rel = new Vector3i(0, y, z); + if (rel.dot(dir.toVector()) > 0){ + if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++; + } + + rel = new Vector3i(x, y, z); + if (rel.dot(dir.toVector()) > 0){ + if (getRotationRelativeBlock(model, rel).isOccludingNeighborFaces()) occluding++; + } + + if (occluding > 3) + occluding = 3; + + return Math.max(0.0, Math.min(1.0 - ((double) occluding * renderSettings.getAmbientOcclusionStrenght()), 1.0)); + } + + private Vector2f[] rotateUVInner(Vector2f[] uv, int angle){ + if (uv.length == 0) return uv; + + int steps = getRotationSteps(angle); + + for (int i = 0; i < steps; i++){ + Vector2f first = uv[uv.length - 1]; + System.arraycopy(uv, 0, uv, 1, uv.length - 1); + uv[0] = first; + } + + return uv; + } + + private Vector2f[] rotateUVOuter(Vector2f[] uv, float angle){ + angle %= 360; + if (angle < 0) angle += 360; + + if (angle == 0) return uv; + + Complexf c = Complexf.fromAngleDeg(angle); + + for (int i = 0; i < uv.length; i++){ + uv[i] = uv[i].sub(HALF_2F); + uv[i] = c.rotate(uv[i]); + uv[i] = uv[i].add(HALF_2F); + } + + return uv; + } + + private int getRotationSteps(int angle){ + angle = -Math.floorDiv(angle, 90); + angle %= 4; + if (angle < 0) angle += 4; + + return angle; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModel.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModel.java new file mode 100644 index 00000000..b0f3c534 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModel.java @@ -0,0 +1,229 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.lowres; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.zip.GZIPOutputStream; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3f; + +import de.bluecolored.bluemap.core.threejs.BufferGeometry; +import de.bluecolored.bluemap.core.util.FileUtil; +import de.bluecolored.bluemap.core.util.MathUtil; +import de.bluecolored.bluemap.core.util.ModelUtils; + +public class LowresModel { + + private UUID world; + private Vector2i tilePos; + private BufferGeometry model; + + private Map changes; + + private boolean hasUnsavedChanges; + + private final Object + fileLock = new Object(), + modelLock = new Object(); + + public LowresModel(UUID world, Vector2i tilePos, Vector2i gridSize) { + this( + world, + tilePos, + ModelUtils.makeGrid(gridSize).toBufferGeometry() + ); + } + + public LowresModel(UUID world, Vector2i tilePos, BufferGeometry model) { + this.world = world; + this.tilePos = tilePos; + this.model = model; + + this.changes = new ConcurrentHashMap<>(); + + this.hasUnsavedChanges = true; + } + + /** + * Searches for all vertices at that point on the grid-model and change the height and color.
+ *
+ * + * Implementation note:
+ * The vertex x, z -coords are rounded, so we can compare them using == without worrying about floating point rounding differences.
+ *
+ */ + public void update(Vector2i point, float height, Vector3f color){ + changes.put(point, new LowresPoint(height, color)); + this.hasUnsavedChanges = true; + } + + /** + * Saves this model to its file + * @param force if this is false, the model is only saved if it has any changes + */ + public void save(File file, boolean force) throws IOException { + if (!force && !hasUnsavedChanges) return; + this.hasUnsavedChanges = false; + + flush(); + + String json; + synchronized (modelLock) { + json = model.toJson(); + } + + synchronized (fileLock) { + if (!file.exists()){ + file.getParentFile().mkdirs(); + file.createNewFile(); + } + + try { + FileUtil.waitForFile(file, 10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new IOException("Failed to get write-access to file: " + file, e); + } + + FileOutputStream fos = new FileOutputStream(file); + GZIPOutputStream zos = new GZIPOutputStream(fos); + OutputStreamWriter osw = new OutputStreamWriter(zos, StandardCharsets.UTF_8); + try ( + PrintWriter pw = new PrintWriter(osw); + ){ + pw.print(json); + } + + } + } + + public void flush(){ + if (changes.isEmpty()) return; + + synchronized (modelLock) { + if (changes.isEmpty()) return; + + Map points = changes; + changes = new HashMap<>(); + + int vertexCount = model.position.length / 3; + + for (int i = 0; i < vertexCount; i++){ + int j = i * 3; + int px = Math.round(model.position[j + 0]); + int pz = Math.round(model.position[j + 2]); + + Vector2i p = new Vector2i(px, pz); + + LowresPoint lrp = points.get(p); + if (lrp == null) continue; + + model.position[j + 1] = lrp.height; + + model.color[j + 0] = lrp.color.getX(); + model.color[j + 1] = lrp.color.getY(); + model.color[j + 2] = lrp.color.getZ(); + + //recalculate normals + int f = Math.floorDiv(i, 3) * 3 * 3; + Vector3f p1 = new Vector3f(model.position[f + 0], model.position[f + 1], model.position[f + 2]); + Vector3f p2 = new Vector3f(model.position[f + 3], model.position[f + 4], model.position[f + 5]); + Vector3f p3 = new Vector3f(model.position[f + 6], model.position[f + 7], model.position[f + 8]); + + Vector3f n = MathUtil.getSurfaceNormal(p1, p2, p3); + + model.normal[f + 0] = n.getX(); model.normal[f + 1] = n.getY(); model.normal[f + 2] = n.getZ(); + model.normal[f + 3] = n.getX(); model.normal[f + 4] = n.getY(); model.normal[f + 5] = n.getZ(); + model.normal[f + 6] = n.getX(); model.normal[f + 7] = n.getY(); model.normal[f + 8] = n.getZ(); + } + } + } + + public BufferGeometry getBufferGeometry(){ + flush(); + return model; + } + + public UUID getWorld(){ + return world; + } + + public Vector2i getTile(){ + return tilePos; + } + + @Override + public int hashCode() { + return Objects.hash(world, tilePos); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof LowresModel){ + LowresModel other = (LowresModel) obj; + if (!other.world.equals(world)) return false; + if (other.tilePos.equals(tilePos)) return true; + } + + return false; + } + + /** + * a point on this lowres-model-grid + */ + public class LowresPoint { + private float height; + private Vector3f color; + + public LowresPoint(float height, Vector3f color) { + this.height = height; + this.color = color; + } + + public LowresPoint add(LowresPoint other){ + float newHeight = height + other.height; + Vector3f newColor = color.add(other.color); + return new LowresPoint(newHeight, newColor); + } + + public LowresPoint div(float divisor){ + float newHeight = height / divisor; + Vector3f newColor = color.div(divisor); + return new LowresPoint(newHeight, newColor); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModelManager.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModelManager.java new file mode 100644 index 00000000..6d6dbead --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModelManager.java @@ -0,0 +1,309 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.render.lowres; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.zip.GZIPInputStream; + +import org.apache.commons.io.IOUtils; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3d; +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector3i; +import com.flowpowered.math.vector.Vector4f; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.render.hires.HiresModel; +import de.bluecolored.bluemap.core.threejs.BufferGeometry; +import de.bluecolored.bluemap.core.util.FileUtil; + +public class LowresModelManager { + + private Path fileRoot; + + private Vector2i gridSize; + private Vector2i pointsPerHiresTile; + + private Map models; + + public LowresModelManager(Path fileRoot, Vector2i gridSize, Vector2i pointsPerHiresTile) { + this.fileRoot = fileRoot; + + this.gridSize = gridSize; + this.pointsPerHiresTile = pointsPerHiresTile; + + models = new ConcurrentHashMap<>(); + } + + /** + * Renders all points from the given highres-model onto the lowres-grid + */ + public void render(HiresModel hiresModel) throws IOException { + Vector3i min = hiresModel.getBlockMin(); + Vector3i max = hiresModel.getBlockMax(); + Vector3i size = max.sub(min).add(Vector3i.ONE); + + Vector2i blocksPerPoint = + size + .toVector2(true) + .div(pointsPerHiresTile); + + Vector2i pointMin = min + .toVector2(true) + .toDouble() + .div(blocksPerPoint.toDouble()) + .floor() + .toInt(); + + for (int tx = 0; tx < pointsPerHiresTile.getX(); tx++){ + for (int tz = 0; tz < pointsPerHiresTile.getY(); tz++){ + + double height = 0; + + Vector3d color = Vector3d.ZERO; + double colorCount = 0; + + for (int x = 0; x < blocksPerPoint.getX(); x++){ + for (int z = 0; z < blocksPerPoint.getY(); z++){ + + int rx = tx * blocksPerPoint.getX() + x + min.getX(); + int rz = tz * blocksPerPoint.getY() + z + min.getZ(); + height += hiresModel.getHeight(rx, rz); + + Vector4f c = hiresModel.getColor(rx, rz); + color = color.add(c.toVector3().toDouble().mul(c.getW())); + colorCount += c.getW(); + } + } + + if (colorCount > 0) color = color.div(colorCount); + + int count = blocksPerPoint.getX() * blocksPerPoint.getY(); + height /= count; + + Vector2i point = pointMin.add(tx, tz); + update(hiresModel.getWorld(), point, (float) height, color.toFloat()); + + } + } + } + + /** + * Saves all unsaved changes to the models to disk + */ + public synchronized void save(){ + for (CachedModel model : models.values()){ + saveModel(model); + } + + tidyUpModelCache(); + } + + /** + * Updates a point on the lowresmodel-grid + */ + public void update(UUID world, Vector2i point, float height, Vector3f color) throws IOException { + Vector2i tile = pointToTile(point); + Vector2i relPoint = getPointRelativeToTile(tile, point); + LowresModel model = getModel(world, tile); + model.update(relPoint, height, color); + + if (relPoint.getX() == 0){ + Vector2i tile2 = tile.add(-1, 0); + Vector2i relPoint2 = getPointRelativeToTile(tile2, point); + LowresModel model2 = getModel(world, tile2); + model2.update(relPoint2, height, color); + } + + if (relPoint.getY() == 0){ + Vector2i tile2 = tile.add(0, -1); + Vector2i relPoint2 = getPointRelativeToTile(tile2, point); + LowresModel model2 = getModel(world, tile2); + model2.update(relPoint2, height, color); + } + + if (relPoint.getX() == 0 && relPoint.getY() == 0){ + Vector2i tile2 = tile.add(-1, -1); + Vector2i relPoint2 = getPointRelativeToTile(tile2, point); + LowresModel model2 = getModel(world, tile2); + model2.update(relPoint2, height, color); + } + } + + /** + * Returns the file for a tile + */ + public File getFile(Vector2i tile){ + return FileUtil.coordsToFile(fileRoot, tile, "json.gz"); + } + + private LowresModel getModel(UUID world, Vector2i tile) throws IOException { + + File modelFile = getFile(tile); + CachedModel model = models.get(modelFile); + + if (model == null){ + synchronized (this) { + model = models.get(modelFile); + if (model == null){ + if (modelFile.exists()){ + + FileInputStream fis = new FileInputStream(modelFile); + try( + GZIPInputStream zis = new GZIPInputStream(fis); + ){ + String json = IOUtils.toString(zis, StandardCharsets.UTF_8); + + try { + model = new CachedModel(world, tile, BufferGeometry.fromJson(json)); + } catch (IllegalArgumentException | IOException ex){ + Logger.global.logError("Failed to load lowres model: " + modelFile, ex); + //gridFile.renameTo(gridFile.toPath().getParent().resolve(gridFile.getName() + ".broken").toFile()); + modelFile.delete(); + } + } + + } + + if (model == null){ + model = new CachedModel(world, tile, gridSize); + } + + models.put(modelFile, model); + + tidyUpModelCache(); + } + } + } + + return model; + } + + /** + * This Method tidies up the model cache:
+ * it saves all modified models that have not been saved for 2 minutes and
+ * saves and removes the oldest models from the cache until the cache size is 10 or less.
+ *
+ * This method gets automatically called if the cache grows, but if you want to ensure model will be saved after 2 minutes, you could e.g call this method every second.
+ */ + public synchronized void tidyUpModelCache() { + List> entries = new ArrayList<>(models.size()); + entries.addAll(models.entrySet()); + entries.sort((e1, e2) -> (int) Math.signum(e1.getValue().cacheTime - e2.getValue().cacheTime)); + + int size = entries.size(); + for (Entry e : entries) { + if (size > 10) { + saveAndRemoveModel(e.getValue()); + continue; + } + + if (e.getValue().getCacheTime() > 120000) { + saveModel(e.getValue()); + } + } + } + + private synchronized void saveAndRemoveModel(CachedModel model) { + File modelFile = getFile(model.getTile()); + models.remove(modelFile); + try { + model.save(modelFile, false); + //logger.logDebug("Saved and unloaded lowres tile: " + model.getTile()); + } catch (IOException ex) { + Logger.global.logError("Failed to save and unload lowres-model: " + modelFile, ex); + } + } + + private void saveModel(CachedModel model) { + File modelFile = getFile(model.getTile()); + try { + model.save(modelFile, false); + //logger.logDebug("Saved lowres tile: " + model.getTile()); + } catch (IOException ex) { + Logger.global.logError("Failed to save lowres-model: " + modelFile, ex); + } + + model.resetCacheTime(); + } + + private Vector2i pointToTile(Vector2i point){ + return point + .toDouble() + .div(gridSize.toDouble()) + .floor() + .toInt(); + } + + private Vector2i getPointRelativeToTile(Vector2i tile, Vector2i point){ + return point.sub(tile.mul(gridSize)); + } + + public Vector2i getTileSize() { + return gridSize; + } + + public Vector2i getPointsPerHiresTile() { + return pointsPerHiresTile; + } + + private class CachedModel extends LowresModel { + + private long cacheTime; + + public CachedModel(UUID world, Vector2i tilePos, BufferGeometry model) { + super(world, tilePos, model); + + cacheTime = System.currentTimeMillis(); + } + + public CachedModel(UUID world, Vector2i tilePos, Vector2i gridSize) { + super(world, tilePos, gridSize); + + cacheTime = System.currentTimeMillis(); + } + + public long getCacheTime() { + return System.currentTimeMillis() - cacheTime; + } + + public void resetCacheTime() { + cacheTime = System.currentTimeMillis(); + } + + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockColorProvider.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockColorProvider.java new file mode 100644 index 00000000..6cf6961b --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockColorProvider.java @@ -0,0 +1,239 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.concurrent.ConcurrentHashMap; + +import javax.imageio.ImageIO; + +import com.flowpowered.math.GenericMath; +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3f; + +import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext; +import de.bluecolored.bluemap.core.world.Block; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; + +public class BlockColorProvider { + + private BufferedImage foliageMap; + private BufferedImage grassMap; + private Map biomeInfos; + private Map blockColors; + + public BlockColorProvider(ResourcePack resourcePack) throws IOException, NoSuchResourceException { + + this.foliageMap = ImageIO.read(resourcePack.getResource(Paths.get("assets", "minecraft", "textures", "colormap", "foliage.png"))); + this.grassMap = ImageIO.read(resourcePack.getResource(Paths.get("assets", "minecraft", "textures", "colormap", "grass.png"))); + + + this.biomeInfos = new ConcurrentHashMap<>(); + GsonConfigurationLoader loader = GsonConfigurationLoader.builder() + .setURL(getClass().getResource("/biomes.json")) + .build(); + ConfigurationNode biomesConfig = loader.load(); + + for (Entry n : biomesConfig.getChildrenMap().entrySet()){ + String key = n.getKey().toString(); + BiomeInfo value = new BiomeInfo(); + value.humidity = n.getValue().getNode("humidity").getFloat(0.4f); + value.temp = n.getValue().getNode("temp").getFloat(0.8f); + value.watercolor = n.getValue().getNode("watercolor").getInt(4159204); + + biomeInfos.put(key, value); + } + + this.blockColors = new ConcurrentHashMap<>(); + loader = GsonConfigurationLoader.builder() + .setURL(getClass().getResource("/blockColors.json")) + .build(); + ConfigurationNode blockConfig = loader.load(); + + for (Entry n : blockConfig.getChildrenMap().entrySet()){ + String blockId = n.getKey().toString(); + String color = n.getValue().getString(); + blockColors.put(blockId, color); + } + + } + + public Vector3f getBlockColor(ExtendedBlockContext context){ + Block block = context.getRelativeBlock(0, 0, 0); + String blockId = block.getBlock().getId(); + + // water color + if (blockId.equals("water")) { + return getBiomeWaterAverageColor(context); + } + + String colorDef = blockColors.get(blockId); + if (colorDef == null) colorDef = blockColors.get("default"); + if (colorDef == null) colorDef = "#foliage"; + + // grass map + if (colorDef.equals("#grass")){ + return getBiomeGrassAverageColor(context); + } + + // foliage map + if (colorDef.equals("#foliage")){ + return getBiomeFoliageAverageColor(context); + } + + int cValue = Integer.parseInt(colorDef, 16); + return colorFromInt(cValue); + } + + public Vector3f getBiomeFoliageAverageColor(ExtendedBlockContext context){ + Vector3f color = Vector3f.ZERO; + + for (int x = -1; x <= 1; x++){ + for (int z = -1; z <= 1; z++){ + color = color.add(getBiomeFoliageColor(context.getRelativeBlock(x, 0, z))); + } + } + + return color.div(9f); + } + + private Vector3f getBiomeFoliageColor(Block block){ + Vector3f color = Vector3f.ONE; + + if (block.getBiome().contains("mesa")){ + return colorFromInt(0x9e814d); + } + + if (block.getBiome().contains("swamp")) { + return colorFromInt(0x6A7039); + } + + int blocksAboveSeaLevel = Math.max(block.getPosition().getY() - block.getWorld().getSeaLevel(), 0); + color = getFoliageColor(block.getBiome(), blocksAboveSeaLevel); + + //improvised to match the original better + if (block.getBiome().contains("roofed_forest")){ + color = color.mul(2f).add(colorFromInt(0x28340a)).div(3f); + } + + return color; + } + + public Vector3f getBiomeGrassAverageColor(ExtendedBlockContext context){ + Vector3f color = Vector3f.ZERO; + + for (int x = -1; x <= 1; x++){ + for (int z = -1; z <= 1; z++){ + color = color.add(getBiomeGrassColor(context.getRelativeBlock(x, 0, z))); + } + } + + return color.div(9f); + } + + private Vector3f getBiomeGrassColor(Block block){ + Vector3f color = Vector3f.ONE; + + if (block.getBiome().contains("mesa")){ + return colorFromInt(0x90814d); + } + + if (block.getBiome().contains("swamp")) { + return colorFromInt(0x6A7039); + } + + int blocksAboveSeaLevel = Math.max(block.getPosition().getY() - block.getWorld().getSeaLevel(), 0); + color = getGrassColor(block.getBiome(), blocksAboveSeaLevel); + + if (block.getBiome().contains("roofed_forest")){ + color = color.add(colorFromInt(0x28340a)).div(2f); + } + + return color; + } + + public Vector3f getBiomeWaterAverageColor(ExtendedBlockContext context){ + Vector3f color = Vector3f.ZERO; + + for (int x = -1; x <= 1; x++){ + for (int z = -1; z <= 1; z++){ + color = color.add(getBiomeWaterColor(context.getRelativeBlock(x, 0, z))); + } + } + + return color.div(9f); + } + + private Vector3f getBiomeWaterColor(Block block){ + return colorFromInt(biomeInfos.get(block.getBiome()).watercolor); + } + + private Vector3f colorFromInt(int cValue){ + Color c = new Color(cValue, false); + return new Vector3f(c.getRed(), c.getGreen(), c.getBlue()).div(0xff); + } + + private Vector3f getFoliageColor(String biomeId, int blocksAboveSeaLevel){ + return getColorFromMap(biomeId, blocksAboveSeaLevel, foliageMap); + } + + private Vector3f getGrassColor(String biomeId, int blocksAboveSeaLevel){ + return getColorFromMap(biomeId, blocksAboveSeaLevel, grassMap); + } + + private Vector3f getColorFromMap(String biomeId, int blocksAboveSeaLevel, BufferedImage map){ + Vector2i pixel = getColorMapPosition(biomeId, blocksAboveSeaLevel).mul(map.getWidth(), map.getHeight()).floor().toInt(); + int cValue = map.getRGB(GenericMath.clamp(pixel.getX(), 0, map.getWidth() - 1), GenericMath.clamp(pixel.getY(), 0, map.getHeight() - 1)); + Color color = new Color(cValue, false); + return new Vector3f(color.getRed(), color.getGreen(), color.getBlue()).div(0xff); + + } + + private Vector2f getColorMapPosition(String biomeId, int blocksAboveSeaLevel){ + BiomeInfo bi = biomeInfos.get(biomeId); + + if (bi == null){ + throw new NoSuchElementException("No biome found with id: " + biomeId); + } + + float adjTemp = (float) GenericMath.clamp(bi.temp - (0.00166667 * (double) blocksAboveSeaLevel), 0d, 1d); + float adjHumidity = (float) GenericMath.clamp(bi.humidity, 0d, 1d) * adjTemp; + return new Vector2f(1 - adjTemp, 1 - adjHumidity); + } + + class BiomeInfo { + float humidity; + float temp; + int watercolor; + } +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementFaceResource.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementFaceResource.java new file mode 100644 index 00000000..e5c0522d --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementFaceResource.java @@ -0,0 +1,142 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector4f; + +import de.bluecolored.bluemap.core.util.ConfigUtil; +import de.bluecolored.bluemap.core.util.Direction; +import ninja.leaping.configurate.ConfigurationNode; + +public class BlockModelElementFaceResource { + + private BlockModelElementResource element; + + private Vector4f uv; + private String texture; + private String resolvedTexture; + private Direction cullface; + private int rotation; + private int tintIndex; + + protected BlockModelElementFaceResource(BlockModelElementResource element, ConfigurationNode declaration) throws InvalidResourceDeclarationException { + this.element = element; + + try { + this.uv = getDefaultUV(declaration.getKey().toString(), element.getFrom(), element.getTo()); + + ConfigurationNode uv = declaration.getNode("uv"); + if (!uv.isVirtual()) this.uv = ConfigUtil.readVector4f(declaration.getNode("uv")); + + this.texture = declaration.getNode("texture").getString(); + this.resolvedTexture = null; + + this.cullface = null; + ConfigurationNode cf = declaration.getNode("cullface"); + if (!cf.isVirtual()) this.cullface = Direction.fromString(cf.getString()); + + this.rotation = declaration.getNode("rotation").getInt(0); + this.tintIndex = declaration.getNode("tintindex").getInt(-1); + + } catch (NullPointerException | IllegalArgumentException e){ + throw new InvalidResourceDeclarationException(e); + } + } + + public Vector4f getDefaultUV(String faceId, Vector3f from, Vector3f to){ + switch (faceId){ + + case "down" : + case "up" : + return new Vector4f( + from.getX(), from.getZ(), + to.getX(), to.getZ() + ); + + case "north" : + case "south" : + return new Vector4f( + from.getX(), from.getY(), + to.getX(), to.getY() + ); + + case "west" : + case "east" : + return new Vector4f( + from.getZ(), from.getY(), + to.getZ(), to.getY() + ); + + default : + return new Vector4f( + 0, 0, + 16, 16 + ); + + } + } + + public BlockModelElementResource getElement(){ + return element; + } + + public Vector4f getUv() { + return uv; + } + + public String getTexture() { + return texture; + } + + public String getResolvedTexture() { + if (resolvedTexture == null){ + resolvedTexture = getElement().getModel().resolveTexture(getTexture()); + } + + return resolvedTexture; + } + + public boolean isCullface() { + return cullface != null; + } + + public Direction getCullface() { + return cullface; + } + + public int getRotation() { + return rotation; + } + + public boolean isTinted(){ + return tintIndex >= 0; + } + + public int getTintIndex() { + return tintIndex; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementResource.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementResource.java new file mode 100644 index 00000000..00faf907 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelElementResource.java @@ -0,0 +1,144 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +import com.flowpowered.math.vector.Vector3f; + +import de.bluecolored.bluemap.core.util.Axis; +import de.bluecolored.bluemap.core.util.ConfigUtil; +import ninja.leaping.configurate.ConfigurationNode; + +public class BlockModelElementResource { + + private BlockModelResource model; + + private Vector3f from, to; + + private Vector3f rotOrigin; + private Axis rotAxis; + private float rotAngle; + private boolean rotRescale; + + private boolean shade; + + private BlockModelElementFaceResource down, up, north, south, west, east; + + protected BlockModelElementResource(BlockModelResource model, ConfigurationNode declaration) throws InvalidResourceDeclarationException { + this.model = model; + + try { + this.from = ConfigUtil.readVector3f(declaration.getNode("from")); + this.to = ConfigUtil.readVector3f(declaration.getNode("to")); + + this.rotAngle = 0f; + ConfigurationNode rotation = declaration.getNode("rotation"); + if (!rotation.isVirtual()){ + this.rotOrigin = ConfigUtil.readVector3f(rotation.getNode("origin")); + this.rotAxis = Axis.fromString(rotation.getNode("axis").getString()); + this.rotAngle = rotation.getNode("angle").getFloat(); + this.rotRescale = rotation.getNode("rescale").getBoolean(false); + } + + this.shade = declaration.getNode("shade").getBoolean(true); + + ConfigurationNode faces = declaration.getNode("faces"); + this.down = loadFace(faces.getNode("down")); + this.up = loadFace(faces.getNode("up")); + this.north = loadFace(faces.getNode("north")); + this.south = loadFace(faces.getNode("south")); + this.west = loadFace(faces.getNode("west")); + this.east = loadFace(faces.getNode("east")); + + } catch (NullPointerException e){ + throw new InvalidResourceDeclarationException(e); + } + } + + private BlockModelElementFaceResource loadFace(ConfigurationNode faceNode) throws InvalidResourceDeclarationException { + if (faceNode.isVirtual()) return null; + return new BlockModelElementFaceResource(this, faceNode); + } + + public BlockModelResource getModel(){ + return model; + } + + public Vector3f getFrom() { + return from; + } + + public Vector3f getTo() { + return to; + } + + public boolean isRotation(){ + return rotAngle != 0f; + } + + public Vector3f getRotationOrigin() { + return rotOrigin; + } + + public Axis getRotationAxis() { + return rotAxis; + } + + public float getRotationAngle() { + return rotAngle; + } + + public boolean isRotationRescale() { + return rotRescale; + } + + public boolean isShade() { + return shade; + } + + public BlockModelElementFaceResource getDownFace() { + return down; + } + + public BlockModelElementFaceResource getUpFace() { + return up; + } + + public BlockModelElementFaceResource getNorthFace() { + return north; + } + + public BlockModelElementFaceResource getSouthFace() { + return south; + } + + public BlockModelElementFaceResource getWestFace() { + return west; + } + + public BlockModelElementFaceResource getEastFace() { + return east; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelResource.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelResource.java new file mode 100644 index 00000000..3dc7a1d0 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockModelResource.java @@ -0,0 +1,142 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; + +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; + +public class BlockModelResource { + + private BlockStateResource blockState; + + private int xRot, yRot; + private boolean uvLock; + private boolean ambientOcclusion; + private Collection elements; + private Map textures; + + protected BlockModelResource(BlockStateResource blockState, ConfigurationNode declaration, ResourcePack resources) throws InvalidResourceDeclarationException { + this.blockState = blockState; + + this.xRot = declaration.getNode("x").getInt(0); + this.yRot = declaration.getNode("y").getInt(0); + this.uvLock = declaration.getNode("uvlock").getBoolean(false); + this.ambientOcclusion = true; + this.elements = new Vector<>(); + this.textures = new ConcurrentHashMap<>(); + + try { + loadModelResource(declaration.getNode("model").getString(), resources); + } catch (IOException e) { + throw new InvalidResourceDeclarationException("Model not found: " + declaration.getNode("model").getString(), e); + } + } + + private void loadModelResource(String modelId, ResourcePack resources) throws IOException, InvalidResourceDeclarationException { + Path resourcePath = Paths.get("assets", "minecraft", "models", modelId + ".json"); + + ConfigurationNode data = GsonConfigurationLoader.builder() + .setSource(() -> new BufferedReader(new InputStreamReader(resources.getResource(resourcePath), StandardCharsets.UTF_8))) + .build() + .load(); + + //load parent first + ConfigurationNode parent = data.getNode("parent"); + if (!parent.isVirtual()){ + loadModelResource(parent.getString(), resources); + } + + for (Entry texture : data.getNode("textures").getChildrenMap().entrySet()){ + String key = texture.getKey().toString(); + String value = texture.getValue().getString(); + textures.put(key, value); + } + + ambientOcclusion = data.getNode("ambientocclusion").getBoolean(ambientOcclusion); + + if (!data.getNode("elements").isVirtual()){ + elements.clear(); + for (ConfigurationNode e : data.getNode("elements").getChildrenList()){ + elements.add(new BlockModelElementResource(this, e)); + } + } + } + + public BlockStateResource getBlockState(){ + return blockState; + } + + public int getXRot() { + return xRot; + } + + public int getYRot() { + return yRot; + } + + public boolean isUvLock() { + return uvLock; + } + + public boolean isAmbientOcclusion() { + return ambientOcclusion; + } + + public Collection getElements() { + return Collections.unmodifiableCollection(elements); + } + + public String resolveTexture(String key){ + if (key == null) return null; + if (!key.startsWith("#")) return key; + String texture = textures.get(key.substring(1)); + if (texture == null) return key; + return resolveTexture(texture); + } + + public Collection getAllTextureIds(){ + List list = new ArrayList<>(); + for (String tex : textures.values()){ + if (!tex.startsWith("#")) list.add(tex); + } + return list; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockStateResource.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockStateResource.java new file mode 100644 index 00000000..ca8803c1 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/BlockStateResource.java @@ -0,0 +1,154 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Vector; + +import com.google.common.base.Preconditions; + +import de.bluecolored.bluemap.core.util.WeighedArrayList; +import de.bluecolored.bluemap.core.world.BlockState; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; + +public class BlockStateResource { + private BlockState block; + private Collection> modelResources; + + protected BlockStateResource(BlockState block, ResourcePack resources) throws NoSuchResourceException, InvalidResourceDeclarationException { + this.block = Preconditions.checkNotNull(block); + this.modelResources = new Vector<>(); + + try { + ConfigurationNode data = GsonConfigurationLoader.builder() + .setSource(() -> new BufferedReader(new InputStreamReader(resources.getResource(getResourcePath()), StandardCharsets.UTF_8))) + .build() + .load(); + + load(data, resources); + } catch (IOException e) { + throw new NoSuchResourceException("There is no definition for resource-id: " + block.getId(), e); + } catch (NullPointerException e){ + throw new InvalidResourceDeclarationException(e); + } + + this.modelResources = Collections.unmodifiableCollection(this.modelResources); + } + + private void load(ConfigurationNode data, ResourcePack resources) throws InvalidResourceDeclarationException { + + //load variants + ConfigurationNode variants = data.getNode("variants"); + for (Entry e : variants.getChildrenMap().entrySet()){ + if (getBlock().checkVariantCondition(e.getKey().toString())){ + addModelResource(e.getValue(), resources); + break; + } + } + + //load multipart + ConfigurationNode multipart = data.getNode("multipart"); + for (ConfigurationNode part : multipart.getChildrenList()){ + + ConfigurationNode when = part.getNode("when"); + if (when.isVirtual() || checkMultipartCondition(when)){ + addModelResource(part.getNode("apply"), resources); + } + } + + } + + private void addModelResource(ConfigurationNode n, ResourcePack resources) throws InvalidResourceDeclarationException { + WeighedArrayList models = new WeighedArrayList<>(); + + if (n.hasListChildren()){ + + //if it is a weighted list of alternative models, select one by random and weight + List cList = n.getChildrenList(); + for (ConfigurationNode c : cList){ + int weight = c.getNode("weight").getInt(1); + models.add(new BlockModelResource(this, c, resources), weight); + } + + } else { + models.add(new BlockModelResource(this, n, resources)); + } + + modelResources.add(models); + } + + private boolean checkMultipartCondition(ConfigurationNode when){ + ConfigurationNode or = when.getNode("OR"); + if (!or.isVirtual()){ + for (ConfigurationNode condition : or.getChildrenList()){ + if (checkMultipartCondition(condition)) return true; + } + + return false; + } + + Map blockProperties = getBlock().getProperties(); + for (Entry e : when.getChildrenMap().entrySet()){ + String key = e.getKey().toString(); + String[] values = e.getValue().getString().split("\\|"); + + boolean found = false; + for (String value : values){ + if (value.equals(blockProperties.get(key))){ + found = true; + break; + } + } + + if (!found) return false; + } + + return true; + } + + public BlockState getBlock() { + return block; + } + + public Collection> getModelResources(){ + return modelResources; + } + + private Path getResourcePath(){ + return Paths.get("assets", block.getNamespace(), "blockstates", block.getId() + ".json"); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/InvalidResourceDeclarationException.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/InvalidResourceDeclarationException.java new file mode 100644 index 00000000..c9bb0a86 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/InvalidResourceDeclarationException.java @@ -0,0 +1,43 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +public class InvalidResourceDeclarationException extends Exception { + private static final long serialVersionUID = 0L; + + public InvalidResourceDeclarationException() {} + + public InvalidResourceDeclarationException(Throwable e) { + super(e); + } + + public InvalidResourceDeclarationException(String message){ + super(message); + } + + public InvalidResourceDeclarationException(String message, Throwable e) { + super(message, e); + } +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchResourceException.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchResourceException.java new file mode 100644 index 00000000..f6fc55ef --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchResourceException.java @@ -0,0 +1,43 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +public class NoSuchResourceException extends Exception { + private static final long serialVersionUID = 0L; + + public NoSuchResourceException() {} + + public NoSuchResourceException(Throwable e) { + super(e); + } + + public NoSuchResourceException(String message){ + super(message); + } + + public NoSuchResourceException(String message, Throwable e) { + super(message, e); + } +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchTextureException.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchTextureException.java new file mode 100644 index 00000000..db69169d --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/NoSuchTextureException.java @@ -0,0 +1,43 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +public class NoSuchTextureException extends Exception { + private static final long serialVersionUID = 0L; + + public NoSuchTextureException() {} + + public NoSuchTextureException(Throwable e) { + super(e); + } + + public NoSuchTextureException(String message){ + super(message); + } + + public NoSuchTextureException(String message, Throwable e) { + super(message, e); + } +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/ResourcePack.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/ResourcePack.java new file mode 100644 index 00000000..3f6f481f --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/ResourcePack.java @@ -0,0 +1,189 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.commons.io.FileUtils; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.world.BlockState; + +public class ResourcePack { + + private Map resources; + + private TextureProvider textureProvider; + private BlockColorProvider blockColorProvider; + private Cache blockStateResourceCache; + + public ResourcePack(List dataSources, File textureExportFile) throws IOException, NoSuchResourceException { + this.resources = new HashMap<>(); + + load(dataSources); + + blockStateResourceCache = CacheBuilder.newBuilder() + .maximumSize(10000) + .build(); + + textureProvider = new TextureProvider(); + if (textureExportFile.exists()){ + textureProvider.load(textureExportFile); + } else { + textureProvider.generate(this); + textureProvider.save(textureExportFile); + } + + blockColorProvider = new BlockColorProvider(this); + } + + private void load(List dataSources) throws IOException { + resources.clear(); + + //load resourcepacks in order + for (File resourcePath : dataSources) overrideResourcesWith(resourcePath); + } + + private void overrideResourcesWith(File resourcePath){ + if (resourcePath.isFile() && resourcePath.getName().endsWith(".zip") || resourcePath.getName().endsWith(".jar")){ + overrideResourcesWithZipFile(resourcePath); + return; + } + + overrideResourcesWith(resourcePath, Paths.get("")); + } + + private void overrideResourcesWith(File resource, Path resourcePath){ + if (resource.isDirectory()){ + for (File childFile : resource.listFiles()){ + overrideResourcesWith(childFile, resourcePath.resolve(childFile.getName())); + } + return; + } + + if (resource.isFile()){ + try { + byte[] bytes = Files.readAllBytes(resource.toPath()); + resources.put(resourcePath, new Resource(bytes)); + } catch (IOException e) { + Logger.global.logError("Failed to load resource: " + resource, e); + } + } + } + + private void overrideResourcesWithZipFile(File resourceFile){ + try ( + ZipFile zipFile = new ZipFile(resourceFile); + ){ + Enumeration files = zipFile.entries(); + byte[] buffer = new byte[1024]; + while (files.hasMoreElements()){ + ZipEntry file = files.nextElement(); + if (file.isDirectory()) continue; + + Path resourcePath = Paths.get("", file.getName().split("/")); + InputStream fileInputStream = zipFile.getInputStream(file); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(Math.max(8, (int) file.getSize())); + int bytesRead; + while ((bytesRead = fileInputStream.read(buffer)) != -1){ + bos.write(buffer, 0, bytesRead); + } + + resources.put(resourcePath, new Resource(bos.toByteArray())); + } + } catch (IOException e) { + Logger.global.logError("Failed to load resource: " + resourceFile, e); + } + } + + public BlockStateResource getBlockStateResource(BlockState block) throws NoSuchResourceException, InvalidResourceDeclarationException { + BlockStateResource bsr = blockStateResourceCache.getIfPresent(block); + + if (bsr == null){ + bsr = new BlockStateResource(block, this); + blockStateResourceCache.put(block, bsr); + } + + return bsr; + } + + public TextureProvider getTextureProvider(){ + return textureProvider; + } + + public BlockColorProvider getBlockColorProvider(){ + return blockColorProvider; + } + + public Map getAllResources() { + return Collections.unmodifiableMap(resources); + } + + public InputStream getResource(Path resourcePath) throws NoSuchResourceException { + Resource resource = resources.get(resourcePath); + if (resource == null) throw new NoSuchResourceException("There is no resource with that path: " + resourcePath); + return resource.getStream(); + } + + public class Resource { + + private byte[] data; + + public Resource(byte[] data) { + this.data = data; + } + + public InputStream getStream(){ + return new ByteArrayInputStream(data); + } + + } + + public static void createDefaultResource(File file) throws IOException { + if (!file.exists()) { + file.getParentFile().mkdirs(); + FileUtils.copyURLToFile(ResourcePack.class.getResource("/DefaultResources.zip"), file, 10000, 10000); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/TextureProvider.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/TextureProvider.java new file mode 100644 index 00000000..51babbd8 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/resourcepack/TextureProvider.java @@ -0,0 +1,231 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.resourcepack; + +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; + +import javax.imageio.ImageIO; + +import com.flowpowered.math.vector.Vector4f; + +import de.bluecolored.bluemap.core.resourcepack.ResourcePack.Resource; +import de.bluecolored.bluemap.core.util.ConfigUtil; +import de.bluecolored.bluemap.core.util.MathUtil; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; + +public class TextureProvider { + + private Map indexMap; + private List textures; + + public TextureProvider() throws IOException { + this.indexMap = new ConcurrentHashMap<>(); + this.textures = new Vector<>(); + } + + public int getTextureIndex(String textureId) throws NoSuchTextureException { + Integer tex = indexMap.get(textureId); + + if (tex == null){ + throw new NoSuchTextureException("There is no texture with id: " + textureId); + } + + return tex.intValue(); + } + + public Texture getTexture(String textureId) throws NoSuchTextureException { + return getTexture(getTextureIndex(textureId)); + } + + public Texture getTexture(int index){ + return textures.get(index); + } + + public void generate(ResourcePack resources) throws IOException { + indexMap.clear(); + textures.clear(); + + Path textureRoot = Paths.get("assets", "minecraft", "textures"); + for (Entry entry : resources.getAllResources().entrySet()){ + if (entry.getKey().startsWith(textureRoot) && entry.getKey().toString().endsWith(".png")){ + BufferedImage image = ImageIO.read(entry.getValue().getStream()); + if (image == null) throw new IOException("Failed to read Image: " + entry.getKey()); + + String path = textureRoot.relativize(entry.getKey()).normalize().toString(); + String id = path + .substring(0, path.length() - ".png".length()) + .replace(File.separatorChar, '/'); + + Texture texture = new Texture(id, image); + textures.add(texture); + indexMap.put(id, textures.size() - 1); + } + } + } + + public void load(File file) throws IOException { + + indexMap.clear(); + textures.clear(); + + GsonConfigurationLoader loader = GsonConfigurationLoader.builder().setFile(file).build(); + ConfigurationNode node = loader.load(); + + int i = 0; + for(ConfigurationNode n : node.getNode("textures").getChildrenList()){ + Texture t = new Texture( + n.getNode("id").getString(), + n.getNode("texture").getString(), + n.getNode("transparent").getBoolean(false), + ConfigUtil.readVector4f(n.getNode("color")) + ); + + textures.add(t); + indexMap.put(t.getId(), i++); + } + } + + public void save(File file) throws IOException { + + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + + GsonConfigurationLoader loader = GsonConfigurationLoader.builder().setFile(file).build(); + ConfigurationNode node = loader.createEmptyNode(); + + for (Texture t : textures){ + ConfigurationNode n = node.getNode("textures").getAppendedNode(); + n.getNode("id").setValue(t.getId()); + n.getNode("texture").setValue(t.getBase64()); + n.getNode("transparent").setValue(t.isHalfTransparent()); + ConfigUtil.writeVector4f(n.getNode("color"), t.getColor()); + } + + loader.save(node); + } + + public class Texture { + + private String id; + private String base64; + private boolean halfTransparent; + private Vector4f color; + + public Texture(String id, String base64, boolean halfTransparent, Vector4f color){ + this.id = id; + this.halfTransparent = halfTransparent; + this.base64 = base64; + this.color = color; + } + + public Texture(String id, BufferedImage image) throws IOException { + this.id = id; + + //crop off animation frames + if (image.getHeight() > image.getWidth()){ + BufferedImage cropped = new BufferedImage(image.getWidth(), image.getWidth(), image.getType()); + Graphics2D g = cropped.createGraphics(); + g.drawImage(image, 0, 0, null); + image = cropped; + } + + //check halfTransparency + this.halfTransparent = checkHalfTransparent(image); + + //calculate color + this.color = calculateColor(image); + + //write to Base64 + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ImageIO.write(image, "png", os); + this.base64 = "data:image/png;base64," + Base64.getEncoder().encodeToString(os.toByteArray()); + } + + private Vector4f calculateColor(BufferedImage image){ + Vector4f color = Vector4f.ZERO; + + for (int x = 0; x < image.getWidth(); x++){ + for (int y = 0; y < image.getHeight(); y++){ + int pixel = image.getRGB(x, y); + double alpha = (double)((pixel >> 24) & 0xff) / (double) 0xff; + double red = (double)((pixel >> 16) & 0xff) / (double) 0xff; + double green = (double)((pixel >> 8) & 0xff) / (double) 0xff; + double blue = (double)((pixel >> 0) & 0xff) / (double) 0xff; + + color = MathUtil.blendColors(new Vector4f(red, green, blue, alpha), color); + } + } + + return color; + } + + private boolean checkHalfTransparent(BufferedImage image){ + for (int x = 0; x < image.getWidth(); x++){ + for (int y = 0; y < image.getHeight(); y++){ + int pixel = image.getRGB(x, y); + int alpha = (pixel >> 24) & 0xff; + if (alpha > 0x00 && alpha < 0xff){ + return true; + } + } + } + + return false; + } + + public String getId() { + return id; + } + + public String getBase64() { + return base64; + } + + public boolean isHalfTransparent() { + return halfTransparent; + } + + public Vector4f getColor(){ + return color; + } + + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/threejs/BufferGeometry.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/threejs/BufferGeometry.java new file mode 100644 index 00000000..08c9a8aa --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/threejs/BufferGeometry.java @@ -0,0 +1,312 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.threejs; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import com.flowpowered.math.GenericMath; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +public class BufferGeometry { + + public final float[] position, normal, color, uv; + public final MaterialGroup[] groups; + + public BufferGeometry(float[] position, float[] normal, float[] color, float[] uv, MaterialGroup[] groups) { + this.position = position; + this.normal = normal; + this.color = color; + this.uv = uv; + this.groups = groups; + } + + public int getFaceCount(){ + return Math.floorDiv(position.length, 3); + } + + public String toJson() { + try { + + StringWriter sw = new StringWriter(); + Gson gson = new GsonBuilder().create(); + JsonWriter json = gson.newJsonWriter(sw); + + json.beginObject(); + + //set special values + json.name("type").value("BufferGeometry"); + json.name("uuid").value(UUID.randomUUID().toString().toUpperCase()); + + json.name("data").beginObject(); + json.name("attributes").beginObject(); + + json.name("position"); + floatArray2Json(json, position, 3, false); + + json.name("normal"); + floatArray2Json(json, normal, 3, true); + + json.name("color"); + floatArray2Json(json, color, 3, false); + + json.name("uv"); + floatArray2Json(json, uv, 2, false); + + json.endObject(); //attributes + + + json.name("groups").beginArray(); + + //write groups into json + for (BufferGeometry.MaterialGroup g : groups){ + json.beginObject(); + + json.name("materialIndex").value(g.getMaterialIndex()); + json.name("start").value(g.getStart()); + json.name("count").value(g.getCount()); + + json.endObject(); + } + + json.endArray(); //groups + json.endObject(); //data + json.endObject(); //main-object + + //save and return + json.flush(); + return sw.toString(); + + } catch (IOException e){ + //since we are using a StringWriter there should never be an IO exception thrown + throw new RuntimeException(e); + } + } + + public static BufferGeometry fromJson(String jsonString) throws IOException { + + Gson gson = new GsonBuilder().create(); + JsonReader json = gson.newJsonReader(new StringReader(jsonString)); + + List positionList = new ArrayList<>(300); + List normalList = new ArrayList<>(300); + List colorList = new ArrayList<>(300); + List uvList = new ArrayList<>(200); + List groups = new ArrayList<>(10); + + json.beginObject(); //root + while (json.hasNext()){ + String name1 = json.nextName(); + + if(name1.equals("data")){ + json.beginObject(); //data + while (json.hasNext()){ + String name2 = json.nextName(); + + if(name2.equals("attributes")){ + json.beginObject(); //attributes + while (json.hasNext()){ + String name3 = json.nextName(); + + if(name3.equals("position")){ + json2FloatList(json, positionList); + } + + else if(name3.equals("normal")){ + json2FloatList(json, normalList); + } + + else if(name3.equals("color")){ + json2FloatList(json, colorList); + } + + else if(name3.equals("uv")){ + json2FloatList(json, uvList); + } + + else json.skipValue(); + } + json.endObject(); //attributes + } + + else if (name2.equals("groups")){ + json.beginArray(); //groups + while (json.hasNext()){ + MaterialGroup group = new MaterialGroup(0, 0, 0); + json.beginObject(); //group + while (json.hasNext()){ + String name3 = json.nextName(); + + if(name3.equals("materialIndex")){ + group.setMaterialIndex(json.nextInt()); + } + + else if(name3.equals("start")){ + group.setStart(json.nextInt()); + } + + else if(name3.equals("count")){ + group.setCount(json.nextInt()); + } + + else json.skipValue(); + } + json.endObject(); //group + groups.add(group); + } + json.endArray(); //groups + } + + else json.skipValue(); + } + json.endObject();//data + } + + else json.skipValue(); + } + json.endObject(); //root + + //check if this is a valid BufferGeometry + int faceCount = Math.floorDiv(positionList.size(), 3); + if (positionList.size() != faceCount * 3) throw new IllegalArgumentException("Wrong count of positions! (Got " + positionList.size() + " but expected " + (faceCount * 3) + ")"); + if (normalList.size() != faceCount * 3) throw new IllegalArgumentException("Wrong count of normals! (Got " + normalList.size() + " but expected " + (faceCount * 3) + ")"); + if (colorList.size() != faceCount * 3) throw new IllegalArgumentException("Wrong count of colors! (Got " + colorList.size() + " but expected " + (faceCount * 3) + ")"); + if (uvList.size() != faceCount * 2) throw new IllegalArgumentException("Wrong count of uvs! (Got " + uvList.size() + " but expected " + (faceCount * 2) + ")"); + + groups.sort((g1, g2) -> (int) Math.signum(g1.getStart() - g2.getStart())); + int nextGroup = 0; + for (MaterialGroup g : groups){ + if(g.getStart() != nextGroup) throw new IllegalArgumentException("Group did not start at correct index! (Got " + g.getStart() + " but expected " + nextGroup + ")"); + if(g.getCount() < 0) throw new IllegalArgumentException("Group has a negative count! (" + g.getCount() + ")"); + nextGroup += g.getCount(); + } + + //collect values in arrays + float[] position = new float[positionList.size()]; + for (int i = 0; i < position.length; i++) { + position[i] = positionList.get(i); + } + + float[] normal = new float[normalList.size()]; + for (int i = 0; i < normal.length; i++) { + normal[i] = normalList.get(i); + } + + float[] color = new float[colorList.size()]; + for (int i = 0; i < color.length; i++) { + color[i] = colorList.get(i); + } + + float[] uv = new float[uvList.size()]; + for (int i = 0; i < uv.length; i++) { + uv[i] = uvList.get(i); + } + + return new BufferGeometry(position, normal, color, uv, + groups.toArray(new MaterialGroup[groups.size()]) + ); + } + + private static void json2FloatList(JsonReader json, List list) throws IOException { + json.beginObject(); //root + while (json.hasNext()){ + String name = json.nextName(); + + if(name.equals("array")){ + json.beginArray(); //array + while (json.hasNext()){ + list.add(new Float(json.nextDouble())); + } + json.endArray(); //array + } + + else json.skipValue(); + } + json.endObject(); //root + } + + private static void floatArray2Json(JsonWriter json, float[] array, int itemSize, boolean normalized) throws IOException { + json.beginObject(); + + json.name("type").value("Float32Array"); + json.name("itemSize").value(itemSize); + json.name("normalized").value(normalized); + + json.name("array").beginArray(); + for (int i = 0; i < array.length; i++){ + //rounding and remove ".0" to save string space + double d = GenericMath.round(array[i], 3); + if (d == (int) d) json.value((int) d); + else json.value(d); + } + json.endArray(); + + json.endObject(); + } + + public static class MaterialGroup { + private int materialIndex; + private int start; + private int count; + + public MaterialGroup(int materialIndex, int start, int count) { + this.materialIndex = materialIndex; + this.start = start; + this.count = count; + } + + public int getMaterialIndex() { + return materialIndex; + } + + public int getStart() { + return start; + } + + public int getCount() { + return count; + } + + public void setMaterialIndex(int materialIndex) { + this.materialIndex = materialIndex; + } + + public void setStart(int start) { + this.start = start; + } + + public void setCount(int count) { + this.count = count; + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java new file mode 100644 index 00000000..1c1aa58f --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java @@ -0,0 +1,438 @@ +/* + * This file is part of SpongeAPI, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Optional; + +import com.flowpowered.math.vector.Vector3d; +import com.flowpowered.math.vector.Vector3i; + +/** + * An axis aligned bounding box. That is, an un-rotated cuboid. + * It is represented by its minimum and maximum corners. + * + *

The box will never be degenerate: the corners are always not equal and + * respect the minimum and maximum properties.

+ * + *

This class is immutable, all objects returned are either new instances or + * itself.

+ */ +public class AABB { + + private final Vector3d min; + private final Vector3d max; + private Vector3d size = null; + private Vector3d center = null; + + /** + * Constructs a new bounding box from two opposite corners. + * Fails the resulting box would be degenerate (a dimension is 0). + * + * @param firstCorner The first corner + * @param secondCorner The second corner + */ + public AABB(Vector3i firstCorner, Vector3i secondCorner) { + this(checkNotNull(firstCorner, "firstCorner").toDouble(), checkNotNull(secondCorner, "secondCorner").toDouble()); + } + + /** + * Constructs a new bounding box from two opposite corners. + * Fails the resulting box would be degenerate (a dimension is 0). + * + * @param x1 The first corner x coordinate + * @param y1 The first corner y coordinate + * @param z1 The first corner z coordinate + * @param x2 The second corner x coordinate + * @param y2 The second corner y coordinate + * @param z2 The second corner z coordinate + */ + public AABB(double x1, double y1, double z1, double x2, double y2, double z2) { + this(new Vector3d(x1, y1, z1), new Vector3d(x2, y2, z2)); + } + + /** + * Constructs a new bounding box from two opposite corners. + * Fails the resulting box would be degenerate (a dimension is 0). + * + * @param firstCorner The first corner + * @param secondCorner The second corner + */ + public AABB(Vector3d firstCorner, Vector3d secondCorner) { + checkNotNull(firstCorner, "firstCorner"); + checkNotNull(secondCorner, "secondCorner"); + this.min = firstCorner.min(secondCorner); + this.max = firstCorner.max(secondCorner); + checkArgument(this.min.getX() != this.max.getX(), "The box is degenerate on x"); + checkArgument(this.min.getY() != this.max.getY(), "The box is degenerate on y"); + checkArgument(this.min.getZ() != this.max.getZ(), "The box is degenerate on z"); + } + + /** + * The minimum corner of the box. + * + * @return The minimum corner + */ + public Vector3d getMin() { + return this.min; + } + + /** + * The maximum corner of the box. + * + * @return The maximum corner + */ + public Vector3d getMax() { + return this.max; + } + + /** + * Returns the center of the box, halfway between each corner. + * + * @return The center + */ + public Vector3d getCenter() { + if (this.center == null) { + this.center = this.min.add(getSize().div(2)); + } + return this.center; + } + + /** + * Gets the size of the box. + * + * @return The size + */ + public Vector3d getSize() { + if (this.size == null) { + this.size = this.max.sub(this.min); + } + return this.size; + } + + /** + * Checks if the bounding box contains a point. + * + * @param point The point to check + * @return Whether or not the box contains the point + */ + public boolean contains(Vector3i point) { + checkNotNull(point, "point"); + return contains(point.getX(), point.getY(), point.getZ()); + } + + /** + * Checks if the bounding box contains a point. + * + * @param point The point to check + * @return Whether or not the box contains the point + */ + public boolean contains(Vector3d point) { + checkNotNull(point, "point"); + return contains(point.getX(), point.getY(), point.getZ()); + } + + /** + * Checks if the bounding box contains a point. + * + * @param x The x coordinate of the point + * @param y The y coordinate of the point + * @param z The z coordinate of the point + * @return Whether or not the box contains the point + */ + public boolean contains(double x, double y, double z) { + return this.min.getX() <= x && this.max.getX() >= x + && this.min.getY() <= y && this.max.getY() >= y + && this.min.getZ() <= z && this.max.getZ() >= z; + } + + /** + * Checks if the bounding box intersects another. + * + * @param other The other bounding box to check + * @return Whether this bounding box intersects with the other + */ + public boolean intersects(AABB other) { + checkNotNull(other, "other"); + return this.max.getX() >= other.getMin().getX() && other.getMax().getX() >= this.min.getX() + && this.max.getY() >= other.getMin().getY() && other.getMax().getY() >= this.min.getY() + && this.max.getZ() >= other.getMin().getZ() && other.getMax().getZ() >= this.min.getZ(); + } + + /** + * Tests for intersection between the box and a ray defined by a starting + * point and a direction. + * + * @param start The starting point of the ray + * @param direction The direction of the ray + * @return An intersection point, if any + */ + public Optional intersects(Vector3d start, Vector3d direction) { + checkNotNull(start, "start"); + checkNotNull(direction, "direction"); + // Adapted from: https://github.com/flow/react/blob/develop/src/main/java/com/flowpowered/react/collision/RayCaster.java#L156 + // The box is interpreted as 6 infinite perpendicular places, one for each face (being expanded infinitely) + // "t" variables are multipliers: start + direction * t gives the intersection point + // Find the intersections on the -x and +x planes, oriented by direction + final double txMin; + final double txMax; + final Vector3d xNormal; + if (Math.copySign(1, direction.getX()) > 0) { + txMin = (this.min.getX() - start.getX()) / direction.getX(); + txMax = (this.max.getX() - start.getX()) / direction.getX(); + xNormal = Vector3d.UNIT_X; + } else { + txMin = (this.max.getX() - start.getX()) / direction.getX(); + txMax = (this.min.getX() - start.getX()) / direction.getX(); + xNormal = Vector3d.UNIT_X.negate(); + } + // Find the intersections on the -y and +y planes, oriented by direction + final double tyMin; + final double tyMax; + final Vector3d yNormal; + if (Math.copySign(1, direction.getY()) > 0) { + tyMin = (this.min.getY() - start.getY()) / direction.getY(); + tyMax = (this.max.getY() - start.getY()) / direction.getY(); + yNormal = Vector3d.UNIT_Y; + } else { + tyMin = (this.max.getY() - start.getY()) / direction.getY(); + tyMax = (this.min.getY() - start.getY()) / direction.getY(); + yNormal = Vector3d.UNIT_Y.negate(); + } + // The ray should intersect the -x plane before the +y plane and intersect + // the -y plane before the +x plane, else it is outside the box + if (txMin > tyMax || txMax < tyMin) { + return Optional.empty(); + } + // Keep track of the intersection normal which also helps with floating point errors + Vector3d normalMax; + Vector3d normalMin; + // The ray intersects only the furthest min plane on the box and only the closest + // max plane on the box + double tMin; + if (tyMin == txMin) { + tMin = tyMin; + normalMin = xNormal.negate().sub(yNormal); + } else if (tyMin > txMin) { + tMin = tyMin; + normalMin = yNormal.negate(); + } else { + tMin = txMin; + normalMin = xNormal.negate(); + } + double tMax; + if (tyMax == txMax) { + tMax = tyMax; + normalMax = xNormal.add(yNormal); + } else if (tyMax < txMax) { + tMax = tyMax; + normalMax = yNormal; + } else { + tMax = txMax; + normalMax = xNormal; + } + // Find the intersections on the -z and +z planes, oriented by direction + final double tzMin; + final double tzMax; + final Vector3d zNormal; + if (Math.copySign(1, direction.getZ()) > 0) { + tzMin = (this.min.getZ() - start.getZ()) / direction.getZ(); + tzMax = (this.max.getZ() - start.getZ()) / direction.getZ(); + zNormal = Vector3d.UNIT_Z; + } else { + tzMin = (this.max.getZ() - start.getZ()) / direction.getZ(); + tzMax = (this.min.getZ() - start.getZ()) / direction.getZ(); + zNormal = Vector3d.UNIT_Z.negate(); + } + // The ray intersects only the furthest min plane on the box and only the closest + // max plane on the box + if (tMin > tzMax || tMax < tzMin) { + return Optional.empty(); + } + // The ray should intersect the closest plane outside first and the furthest + // plane outside last + if (tzMin == tMin) { + normalMin = normalMin.sub(zNormal); + } else if (tzMin > tMin) { + tMin = tzMin; + normalMin = zNormal.negate(); + } + if (tzMax == tMax) { + normalMax = normalMax.add(zNormal); + } else if (tzMax < tMax) { + tMax = tzMax; + normalMax = zNormal; + } + // Both intersection points are behind the start, there are no intersections + if (tMax < 0) { + return Optional.empty(); + } + // Find the final intersection multiplier and normal + final double t; + Vector3d normal; + if (tMin < 0) { + // Only the furthest intersection is after the start, so use it + t = tMax; + normal = normalMax; + } else { + // Both are after the start, use the closest one + t = tMin; + normal = normalMin; + } + normal = normal.normalize(); + // To avoid rounding point errors leaving the intersection point just off the plane + // we check the normal to use the actual plane value from the box coordinates + final double x; + final double y; + final double z; + if (normal.getX() > 0) { + x = this.max.getX(); + } else if (normal.getX() < 0) { + x = this.min.getX(); + } else { + x = direction.getX() * t + start.getX(); + } + if (normal.getY() > 0) { + y = this.max.getY(); + } else if (normal.getY() < 0) { + y = this.min.getY(); + } else { + y = direction.getY() * t + start.getY(); + } + if (normal.getZ() > 0) { + z = this.max.getZ(); + } else if (normal.getZ() < 0) { + z = this.min.getZ(); + } else { + z = direction.getZ() * t + start.getZ(); + } + return Optional.of(new IntersectionPoint(new Vector3d(x, y, z), normal)); + } + + /** + * Offsets this bounding box by a given amount and returns a new box. + * + * @param offset The offset to apply + * @return The new offset box + */ + public AABB offset(Vector3i offset) { + checkNotNull(offset, "offset"); + return offset(offset.getX(), offset.getY(), offset.getZ()); + } + + /** + * Offsets this bounding box by a given amount and returns a new box. + * + * @param offset The offset to apply + * @return The new offset box + */ + public AABB offset(Vector3d offset) { + checkNotNull(offset, "offset"); + return offset(offset.getX(), offset.getY(), offset.getZ()); + } + + /** + * Offsets this bounding box by a given amount and returns a new box. + * + * @param x The amount of offset for the x coordinate + * @param y The amount of offset for the y coordinate + * @param z The amount of offset for the z coordinate + * @return The new offset box + */ + public AABB offset(double x, double y, double z) { + return new AABB(this.min.add(x, y, z), this.max.add(x, y, z)); + } + + /** + * Expands this bounding box by a given amount in both directions and + * returns a new box. The expansion is applied half and half to the + * minimum and maximum corners. + * + * @param amount The amount of expansion to apply + * @return The new expanded box + */ + public AABB expand(Vector3i amount) { + checkNotNull(amount, "amount"); + return expand(amount.getX(), amount.getY(), amount.getZ()); + } + + /** + * Expands this bounding box by a given amount in both directions and + * returns a new box. The expansion is applied half and half to the + * minimum and maximum corners. + * + * @param amount The amount of expansion to apply + * @return The new expanded box + */ + public AABB expand(Vector3d amount) { + checkNotNull(amount, "amount"); + return expand(amount.getX(), amount.getY(), amount.getZ()); + } + + /** + * Expands this bounding box by a given amount in both directions and + * returns a new box. The expansion is applied half and half to the + * minimum and maximum corners. + * + * @param x The amount of expansion for the x coordinate + * @param y The amount of expansion for the y coordinate + * @param z The amount of expansion for the z coordinate + * @return The new expanded box + */ + public AABB expand(double x, double y, double z) { + x /= 2; + y /= 2; + z /= 2; + return new AABB(this.min.sub(x, y, z), this.max.add(x, y, z)); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof AABB)) { + return false; + } + final AABB aabb = (AABB) other; + return this.min.equals(aabb.min) && this.max.equals(aabb.max); + + } + + @Override + public int hashCode() { + int result = this.min.hashCode(); + result = 31 * result + this.max.hashCode(); + return result; + } + + @Override + public String toString() { + return "AABB(" + this.min + " to " + this.max + ")"; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Axis.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Axis.java new file mode 100644 index 00000000..3da8e288 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Axis.java @@ -0,0 +1,51 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.base.Preconditions; + +public enum Axis { + + X (Vector3i.UNIT_X), + Y (Vector3i.UNIT_Y), + Z (Vector3i.UNIT_Z); + + private final Vector3i axisVector; + + Axis(Vector3i axisVector){ + this.axisVector = axisVector; + } + + public Vector3i toVector(){ + return axisVector; + } + + public static Axis fromString(String name){ + Preconditions.checkNotNull(name); + + return valueOf(name.toUpperCase()); + } +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ConfigUtil.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ConfigUtil.java new file mode 100644 index 00000000..3e143c55 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ConfigUtil.java @@ -0,0 +1,135 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import java.util.List; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector3i; +import com.flowpowered.math.vector.Vector4f; +import com.flowpowered.math.vector.Vector4i; + +import ninja.leaping.configurate.ConfigurationNode; + +public class ConfigUtil { + + private ConfigUtil(){} + + public static Vector2i readVector2i(ConfigurationNode vectorNode){ + if (vectorNode.hasListChildren()){ + List list = vectorNode.getChildrenList(); + return new Vector2i( + list.get(0).getInt(), + list.get(1).getInt() + ); + } + + return new Vector2i( + vectorNode.getNode("x").getInt(), + vectorNode.getNode("y").getInt() + ); + } + + public static Vector3i readVector3i(ConfigurationNode vectorNode){ + if (vectorNode.hasListChildren()){ + List list = vectorNode.getChildrenList(); + return new Vector3i( + list.get(0).getInt(), + list.get(1).getInt(), + list.get(2).getInt() + ); + } + + return new Vector3i( + vectorNode.getNode("x").getInt(), + vectorNode.getNode("y").getInt(), + vectorNode.getNode("z").getInt() + ); + } + + public static Vector3f readVector3f(ConfigurationNode vectorNode){ + if (vectorNode.hasListChildren()){ + List list = vectorNode.getChildrenList(); + return new Vector3f( + list.get(0).getFloat(), + list.get(1).getFloat(), + list.get(2).getFloat() + ); + } + + return new Vector3f( + vectorNode.getNode("x").getFloat(), + vectorNode.getNode("y").getFloat(), + vectorNode.getNode("z").getFloat() + ); + } + + public static Vector4i readVector4i(ConfigurationNode vectorNode){ + if (vectorNode.hasListChildren()){ + List list = vectorNode.getChildrenList(); + return new Vector4i( + list.get(0).getInt(), + list.get(1).getInt(), + list.get(2).getInt(), + list.get(3).getInt() + ); + } + + return new Vector4i( + vectorNode.getNode("x").getInt(), + vectorNode.getNode("y").getInt(), + vectorNode.getNode("z").getInt(), + vectorNode.getNode("w").getInt() + ); + } + + public static Vector4f readVector4f(ConfigurationNode vectorNode){ + if (vectorNode.hasListChildren()){ + List list = vectorNode.getChildrenList(); + return new Vector4f( + list.get(0).getFloat(), + list.get(1).getFloat(), + list.get(2).getFloat(), + list.get(3).getFloat() + ); + } + + return new Vector4f( + vectorNode.getNode("x").getFloat(), + vectorNode.getNode("y").getFloat(), + vectorNode.getNode("z").getFloat(), + vectorNode.getNode("w").getFloat() + ); + } + + public static void writeVector4f(ConfigurationNode vectorNode, Vector4f v){ + vectorNode.getAppendedNode().setValue(v.getX()); + vectorNode.getAppendedNode().setValue(v.getY()); + vectorNode.getAppendedNode().setValue(v.getZ()); + vectorNode.getAppendedNode().setValue(v.getW()); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Direction.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Direction.java new file mode 100644 index 00000000..97f8c1ec --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Direction.java @@ -0,0 +1,75 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import com.flowpowered.math.vector.Vector3i; +import com.google.common.base.Preconditions; + +public enum Direction { + + UP ( 0, 1, 0, Axis.Y), + DOWN ( 0,-1, 0, Axis.Y), + NORTH ( 0, 0,-1, Axis.Z), + SOUTH ( 0, 0, 1, Axis.Z), + WEST (-1, 0, 0, Axis.X), + EAST ( 1, 0, 0, Axis.X); + + static { + UP.opposite = DOWN; + DOWN.opposite = UP; + NORTH.opposite = SOUTH; + SOUTH.opposite = NORTH; + WEST.opposite = EAST; + EAST.opposite = WEST; + } + + private Vector3i dir; + private Axis axis; + private Direction opposite; + + private Direction(int x, int y, int z, Axis axis) { + this.dir = new Vector3i(x, y, z); + this.axis = axis; + this.opposite = null; + } + + public Vector3i toVector(){ + return dir; + } + + public Direction opposite() { + return opposite; + } + + public Axis getAxis() { + return axis; + } + + public static Direction fromString(String name){ + Preconditions.checkNotNull(name); + + return valueOf(name.toUpperCase()); + } +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/FileUtil.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/FileUtil.java new file mode 100644 index 00000000..355dd0bb --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/FileUtil.java @@ -0,0 +1,76 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import com.flowpowered.math.vector.Vector2i; + +public class FileUtil { + + private FileUtil(){} + + public static File coordsToFile(Path root, Vector2i coords, String fileType){ + String path = "x" + coords.getX() + "z" + coords.getY(); + char[] cs = path.toCharArray(); + List folders = new ArrayList<>(); + String folder = ""; + for (char c : cs){ + folder += c; + if (c >= '0' && c <= '9'){ + folders.add(folder); + folder = ""; + } + } + String fileName = folders.remove(folders.size() - 1); + + Path p = root; + for (String s : folders){ + p = p.resolve(s); + } + + return p.resolve(fileName + "." + fileType).toFile(); + } + + /** + * Blocks until a file can be read and written.
+ * (Do not use this method to sync file-access from different threads!) + */ + public static void waitForFile(File file, long time, TimeUnit unit) throws InterruptedException { + long start = System.currentTimeMillis(); + long timeout = start + TimeUnit.MILLISECONDS.convert(time, unit); + long sleepTime = 1; + while(!file.canWrite() || !file.canRead()){ + Thread.sleep(sleepTime); + sleepTime = (long) Math.min(Math.ceil(sleepTime * 1.5), 1000); + if (System.currentTimeMillis() > timeout) throw new InterruptedException(); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/IntersectionPoint.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/IntersectionPoint.java new file mode 100644 index 00000000..f2fc82c4 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/IntersectionPoint.java @@ -0,0 +1,47 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import com.flowpowered.math.vector.Vector3d; + +public class IntersectionPoint { + + private final Vector3d intersection; + private final Vector3d normal; + + public IntersectionPoint(Vector3d intersection, Vector3d normal){ + this.intersection = intersection; + this.normal = normal; + } + + public Vector3d getIntersection() { + return intersection; + } + + public Vector3d getNormal() { + return normal; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtil.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtil.java new file mode 100644 index 00000000..2d6eab19 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/MathUtil.java @@ -0,0 +1,102 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import com.flowpowered.math.vector.Vector3d; +import com.flowpowered.math.vector.Vector3f; +import com.flowpowered.math.vector.Vector3i; +import com.flowpowered.math.vector.Vector4f; + +public class MathUtil { + + private MathUtil() {} + + public static Vector3d getSurfaceNormal(Vector3d p1, Vector3d p2, Vector3d p3){ + Vector3d u = p2.sub(p1); + Vector3d v = p3.sub(p1); + + double nX = u.getY() * v.getZ() - u.getZ() * v.getY(); + double nY = u.getZ() * v.getX() - u.getX() * v.getZ(); + double nZ = u.getX() * v.getY() - u.getY() * v.getX(); + + return new Vector3d(nX, nY, nZ); + } + + public static Vector3f getSurfaceNormal(Vector3f p1, Vector3f p2, Vector3f p3) { + Vector3f u = p2.sub(p1); + Vector3f v = p3.sub(p1); + + float nX = u.getY() * v.getZ() - u.getZ() * v.getY(); + float nY = u.getZ() * v.getX() - u.getX() * v.getZ(); + float nZ = u.getX() * v.getY() - u.getY() * v.getX(); + + Vector3f n = new Vector3f(nX, nY, nZ); + n = n.normalize(); + + return n; + } + + public static float hashToFloat(Vector3i pos, long seed) { + return hashToFloat(pos.getX(), pos.getY(), pos.getZ(), seed); + } + + /** + * Adapted from https://github.com/SpongePowered/SpongeAPI/blob/ecd761a70219e467dea47a09fc310e8238e9911f/src/main/java/org/spongepowered/api/extra/skylands/SkylandsUtil.java + */ + public static float hashToFloat(int x, int y, int z, long seed) { + final long hash = x * 73428767 ^ y * 9122569 ^ z * 4382893 ^ seed * 457; + return (hash * (hash + 456149) & 0x00ffffff) / (float) 0x01000000; + } + + public static Vector4f blendColors(Vector4f top, Vector4f bottom){ + if (top.getW() > 0 && bottom.getW() > 0){ + float a = 1 - (1 - top.getW()) * (1 - bottom.getW()); + float r = (top.getX() * top.getW() / a) + (bottom.getX() * bottom.getW() * (1 - top.getW()) / a); + float g = (top.getY() * top.getW() / a) + (bottom.getY() * bottom.getW() * (1 - top.getW()) / a); + float b = (top.getZ() * top.getW() / a) + (bottom.getZ() * bottom.getW() * (1 - top.getW()) / a); + return new Vector4f(r, g, b, a); + } else if (bottom.getW() > 0) { + return bottom; + } else { + return top; + } + } + + public static Vector4f overlayColors(Vector4f top, Vector4f bottom){ + if (top.getW() > 0 && bottom.getW() > 0){ + float p = (1 - top.getW()) * bottom.getW(); + float a = p + top.getW(); + float r = (p * bottom.getX() + top.getW() * top.getX()) / a; + float g = (p * bottom.getY() + top.getW() * top.getY()) / a; + float b = (p * bottom.getZ() + top.getW() * top.getZ()) / a; + return new Vector4f(r, g, b, a); + } else if (bottom.getW() > 0) { + return bottom; + } else { + return top; + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ModelUtils.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ModelUtils.java new file mode 100644 index 00000000..b5c0d8f0 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/ModelUtils.java @@ -0,0 +1,90 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import com.flowpowered.math.vector.Vector2f; +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3f; + +import de.bluecolored.bluemap.core.model.Face; +import de.bluecolored.bluemap.core.model.Model; + +public class ModelUtils { + + private ModelUtils() {} + + /** + * Creates a plane-grid with alternating face-rotations. + */ + public static Model makeGrid(Vector2i gridSize){ + Model m = new Model(); + + float y = 0; + + for (int x = 0; x < gridSize.getX(); x++){ + for (int z = 0; z < gridSize.getY(); z++){ + + Vector3f[] p = new Vector3f[]{ + new Vector3f(x , y, z + 1), + new Vector3f(x + 1, y, z + 1), + new Vector3f(x + 1, y, z ), + new Vector3f(x , y, z ), + }; + + Vector2f[] uv = new Vector2f[]{ + new Vector2f(0, 1), + new Vector2f(1, 1), + new Vector2f(1, 0), + new Vector2f(0, 0), + }; + + Face f1, f2; + if (x % 2 == z % 2){ + f1 = new Face(p[0], p[1], p[2], uv[0], uv[1], uv[2], -1); + f2 = new Face(p[0], p[2], p[3], uv[0], uv[2], uv[3], -1); + } else { + f1 = new Face(p[0], p[1], p[3], uv[0], uv[1], uv[3], -1); + f2 = new Face(p[1], p[2], p[3], uv[1], uv[2], uv[3], -1); + } + + Vector3f color = Vector3f.ZERO; + + f1.setC1(color); + f1.setC2(color); + f1.setC3(color); + + f2.setC1(color); + f2.setC2(color); + f2.setC3(color); + + m.addFace(f1); + m.addFace(f2); + } + } + + return m; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/UpdateDeamon.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/UpdateDeamon.java new file mode 100644 index 00000000..29a83089 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/UpdateDeamon.java @@ -0,0 +1,54 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import java.lang.ref.WeakReference; + +public class UpdateDeamon extends Thread { + + public WeakReference subject; + public long frequency; + + public UpdateDeamon(Runnable subject, long frequency) { + this((Updateable) (()->subject.run()), frequency); + } + + public UpdateDeamon(Updateable subject, long frequency) { + this.subject = new WeakReference(subject); + this.frequency = frequency; + this.setDaemon(true); + } + + @Override + public void run() { + try { + while (true) { + Thread.sleep(frequency); + subject.get().update(); + } + } catch (NullPointerException | InterruptedException ex) {} + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Updateable.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Updateable.java new file mode 100644 index 00000000..a8a66cfc --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/Updateable.java @@ -0,0 +1,31 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +public interface Updateable { + + public void update(); + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/WeighedArrayList.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/WeighedArrayList.java new file mode 100644 index 00000000..f9df25a2 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/WeighedArrayList.java @@ -0,0 +1,76 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.util; + +import java.util.ArrayList; +import java.util.List; + +public class WeighedArrayList extends ArrayList implements List { + private static final long serialVersionUID = 1L; + + public WeighedArrayList() {} + + public WeighedArrayList(int capacity) { + super(capacity); + } + + /** + * Adds the element weight times to this list. + * @return Always true + */ + public void add(E e, int weight) { + for (int i = 0; i < weight; i++){ + add(e); + } + } + + /** + * Removes the first weight number of items that equal o from this list.
+ * @return The number of elements removed. + */ + public int remove(Object o, int weight) { + int removed = 0; + if (o == null){ + for (int i = 0; i < size(); i++){ + if (get(i) == null){ + remove(i); + removed++; + if (removed >= weight) break; + } + } + } else { + for (int i = 0; i < size(); i++){ + if (o.equals(get(i))){ + remove(i); + removed++; + if (removed >= weight) break; + } + } + } + + return removed; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebRequestHandler.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebRequestHandler.java new file mode 100644 index 00000000..ddd3116a --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebRequestHandler.java @@ -0,0 +1,276 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.web; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.time.DateFormatUtils; + +import de.bluecolored.bluemap.core.webserver.HttpRequest; +import de.bluecolored.bluemap.core.webserver.HttpRequestHandler; +import de.bluecolored.bluemap.core.webserver.HttpResponse; +import de.bluecolored.bluemap.core.webserver.HttpStatusCode; + +public class BlueMapWebRequestHandler implements HttpRequestHandler { + + private static final long DEFLATE_MIN_SIZE = 10L * 1024L; + private static final long DEFLATE_MAX_SIZE = 10L * 1024L * 1024L; + private static final long INFLATE_MAX_SIZE = 10L * 1024L * 1024L; + + private Path webRoot; + + public BlueMapWebRequestHandler(Path webRoot) { + this.webRoot = webRoot; + } + + @Override + public HttpResponse handle(HttpRequest request) { + if ( + !request.getMethod().equalsIgnoreCase("GET") && + !request.getMethod().equalsIgnoreCase("POST") + ) return new HttpResponse(HttpStatusCode.NOT_IMPLEMENTED); + + HttpResponse response = generateResponse(request); + response.addHeader("Server", "BlueMap/WebServer"); + + HttpStatusCode status = response.getStatusCode(); + if (status.getCode() >= 400){ + response.setData(status.getCode() + " - " + status.getMessage() + "\nBlueMap/Webserver"); + } + + return response; + } + + private HttpResponse generateResponse(HttpRequest request) { + String adress = request.getPath(); + if (adress.isEmpty()) adress = "/"; + String[] adressParts = adress.split("\\?", 2); + String path = adressParts[0]; + String getParamString = adressParts.length > 1 ? adressParts[1] : ""; + + Map getParams = new HashMap<>(); + for (String getParam : getParamString.split("&")){ + if (getParam.isEmpty()) continue; + String[] kv = getParam.split("=", 2); + String key = kv[0]; + String value = kv.length > 1 ? kv[1] : ""; + getParams.put(key, value); + } + + if (path.startsWith("/")) path = path.substring(1); + if (path.endsWith("/")) path = path.substring(0, path.length() - 1); + + Path filePath = webRoot; + try { + filePath = webRoot.resolve(path); + } catch (InvalidPathException e){ + return new HttpResponse(HttpStatusCode.NOT_FOUND); + } + + //can we use deflation? + boolean isDeflationPossible = request.getLowercaseHeader("Accept-Encoding").contains("gzip"); + boolean isDeflated = false; + + //check if file is in web-root + if (!filePath.normalize().startsWith(webRoot.normalize())){ + return new HttpResponse(HttpStatusCode.FORBIDDEN); + } + + File file = filePath.toFile(); + + if (!file.exists() || file.isDirectory()){ + file = new File(filePath.toString() + ".gz"); + isDeflated = true; + } + + if (!file.exists() || file.isDirectory()){ + file = new File(filePath.toString() + "/index.html"); + isDeflated = false; + } + + if (!file.exists() || file.isDirectory()){ + file = new File(filePath.toString() + "/index.html.gz"); + isDeflated = true; + } + + if (!file.exists()){ + return new HttpResponse(HttpStatusCode.NOT_FOUND); + } + + if (isDeflationPossible && (!file.getName().endsWith(".gz"))){ + File deflatedFile = new File(file.getAbsolutePath() + ".gz"); + if (deflatedFile.exists()){ + file = deflatedFile; + isDeflated = true; + } + } + + //check if file is still in web-root + if (!file.toPath().normalize().startsWith(webRoot.normalize())){ + return new HttpResponse(HttpStatusCode.FORBIDDEN); + } + + //check modified + long lastModified = file.lastModified(); + Set modStringSet = request.getHeader("If-Modified-Since"); + if (!modStringSet.isEmpty()){ + try { + long since = stringToTimestamp(modStringSet.iterator().next()); + if (since + 1000 >= lastModified){ + return new HttpResponse(HttpStatusCode.NOT_MODIFIED); + } + } catch (IllegalArgumentException e){} + } + + + HttpResponse response = new HttpResponse(HttpStatusCode.OK); + if (lastModified > 0) response.addHeader("Last-Modified", timestampToString(lastModified)); + + //add content type header + String filetype = file.getName().toString(); + if (filetype.endsWith(".gz")) filetype = filetype.substring(3); + int pointIndex = filetype.lastIndexOf('.'); + if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1); + + String contentType = "text/plain"; + switch (filetype) { + case "json" : + contentType = "application/json"; + break; + case "png" : + contentType = "image/png"; + break; + case "jpg" : + case "jpeg" : + case "jpe" : + contentType = "image/jpeg"; + break; + case "svg" : + contentType = "image/svg+xml"; + break; + case "css" : + contentType = "text/css"; + break; + case "js" : + contentType = "text/javascript"; + break; + case "html" : + case "htm" : + case "shtml" : + contentType = "text/html"; + break; + case "xml" : + contentType = "text/xml"; + break; + } + response.addHeader("Content-Type", contentType); + + + try { + if (isDeflated){ + if (isDeflationPossible || file.length() > INFLATE_MAX_SIZE){ + response.addHeader("Content-Encoding", "gzip"); + response.setData(new FileInputStream(file)); + return response; + } else { + response.setData(new GZIPInputStream(new FileInputStream(file))); + return response; + } + } else { + if (isDeflationPossible && file.length() > DEFLATE_MIN_SIZE && file.length() < DEFLATE_MAX_SIZE){ + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + GZIPOutputStream zos = new GZIPOutputStream(byteOut); + IOUtils.copyLarge(fis, zos); + zos.close(); + fis.close(); + byte[] compressedData = byteOut.toByteArray(); + response.setData(new ByteArrayInputStream(compressedData)); + response.addHeader("Content-Encoding", "gzip"); + return response; + } else { + response.setData(new FileInputStream(file)); + return response; + } + } + + } catch (FileNotFoundException e) { + return new HttpResponse(HttpStatusCode.NOT_FOUND); + } catch (IOException e) { + return new HttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR); + } + } + + private static String timestampToString(long time){ + return DateFormatUtils.format(time, "EEE, dd MMM yyy HH:mm:ss 'GMT'", TimeZone.getTimeZone("GMT"), Locale.ENGLISH); + } + + private static long stringToTimestamp(String timeString) throws IllegalArgumentException { + try { + int day = Integer.parseInt(timeString.substring(5, 7)); + int month = 1; + switch (timeString.substring(8, 11)){ + case "Jan" : month = 0; break; + case "Feb" : month = 1; break; + case "Mar" : month = 2; break; + case "Apr" : month = 3; break; + case "May" : month = 4; break; + case "Jun" : month = 5; break; + case "Jul" : month = 6; break; + case "Aug" : month = 7; break; + case "Sep" : month = 8; break; + case "Oct" : month = 9; break; + case "Nov" : month = 10; break; + case "Dec" : month = 11; break; + } + int year = Integer.parseInt(timeString.substring(12, 16)); + int hour = Integer.parseInt(timeString.substring(17, 19)); + int min = Integer.parseInt(timeString.substring(20, 22)); + int sec = Integer.parseInt(timeString.substring(23, 25)); + GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + cal.set(year, month, day, hour, min, sec); + return cal.getTimeInMillis(); + } catch (NumberFormatException | IndexOutOfBoundsException e){ + throw new IllegalArgumentException(e); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebServer.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebServer.java new file mode 100644 index 00000000..79db02cc --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/BlueMapWebServer.java @@ -0,0 +1,54 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.web; + +import java.io.IOException; + +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.webserver.WebServer; + +public class BlueMapWebServer extends WebServer { + + private WebFilesManager webFilesManager; + + public BlueMapWebServer(WebServerConfig config) { + super( + config.getWebserverPort(), + config.getWebserverMaxConnections(), + config.getWebserverBindAdress(), + new BlueMapWebRequestHandler(config.getWebRoot()) + ); + + this.webFilesManager = new WebFilesManager(config.getWebRoot()); + } + + public void updateWebfiles() throws IOException { + if (webFilesManager.needsUpdate()) { + Logger.global.logInfo("Webfiles are missing or outdated, updating..."); + webFilesManager.updateFiles(); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java new file mode 100644 index 00000000..3d73d14d --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java @@ -0,0 +1,73 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.web; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.commons.io.FileUtils; + +public class WebFilesManager { + + private Path webRoot; + + public WebFilesManager(Path webRoot) { + this.webRoot = webRoot; + } + + public boolean needsUpdate() { + if (!webRoot.resolve("index.html").toFile().exists()) return true; + + return false; + } + + public void updateFiles() throws IOException { + URL fileResource = getClass().getResource("/webroot.zip"); + File tempFile = File.createTempFile("bluemap_webroot_extraction", null); + + try { + FileUtils.copyURLToFile(fileResource, tempFile, 10000, 10000); + try (ZipFile zipFile = new ZipFile(tempFile)){ + Enumeration entries = zipFile.entries(); + while(entries.hasMoreElements()) { + ZipEntry zipEntry = entries.nextElement(); + if (zipEntry.isDirectory()) webRoot.resolve(zipEntry.getName()).toFile().mkdirs(); + else { + File target = webRoot.resolve(zipEntry.getName()).toFile(); + FileUtils.copyInputStreamToFile(zipFile.getInputStream(zipEntry), target); + } + } + } + } finally { + tempFile.delete(); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebServerConfig.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebServerConfig.java new file mode 100644 index 00000000..df43550b --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebServerConfig.java @@ -0,0 +1,40 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.web; + +import java.net.InetAddress; +import java.nio.file.Path; + +public interface WebServerConfig { + + Path getWebRoot(); + + InetAddress getWebserverBindAdress(); + + int getWebserverPort(); + + int getWebserverMaxConnections(); + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java new file mode 100644 index 00000000..1314d3a8 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java @@ -0,0 +1,132 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.web; + +import java.io.File; +import java.io.IOException; + +import com.flowpowered.math.vector.Vector2i; + +import de.bluecolored.bluemap.core.render.TileRenderer; +import ninja.leaping.configurate.ConfigurationNode; +import ninja.leaping.configurate.gson.GsonConfigurationLoader; +import ninja.leaping.configurate.loader.ConfigurationLoader; + +public class WebSettings { + + private ConfigurationLoader configLoader; + private ConfigurationNode rootNode; + + public WebSettings(File settingsFile) throws IOException { + + if (!settingsFile.exists()) { + settingsFile.getParentFile().mkdirs(); + settingsFile.createNewFile(); + } + + configLoader = GsonConfigurationLoader.builder() + .setFile(settingsFile) + .build(); + + load(); + } + + public void load() throws IOException { + rootNode = configLoader.load(); + } + + public void save() throws IOException { + configLoader.save(rootNode); + } + + public void set(Object value, Object... path) { + rootNode.getNode(path).setValue(value); + } + + public Object get(Object... path) { + return rootNode.getNode(path).getValue(); + } + + public String getString(Object... path) { + return rootNode.getNode(path).getString(); + } + + public long getInt(Object... path) { + return rootNode.getNode(path).getInt(); + } + + public long getLong(Object... path) { + return rootNode.getNode(path).getLong(); + } + + public double getFloat(Object... path) { + return rootNode.getNode(path).getFloat(); + } + + public double getDouble(Object... path) { + return rootNode.getNode(path).getDouble(); + } + + public void setFrom(TileRenderer tileRenderer, String mapId) { + Vector2i hiresTileSize = tileRenderer.getHiresModelManager().getTileSize(); + Vector2i gridOrigin = tileRenderer.getHiresModelManager().getGridOrigin(); + Vector2i lowresTileSize = tileRenderer.getLowresModelManager().getTileSize(); + Vector2i lowresPointsPerHiresTile = tileRenderer.getLowresModelManager().getPointsPerHiresTile(); + + set(hiresTileSize.getX(), mapId, "hires", "tileSize", "x"); + set(hiresTileSize.getY(), mapId, "hires", "tileSize", "z"); + set(1, mapId, "hires", "scale", "x"); + set(1, mapId, "hires", "scale", "z"); + set(gridOrigin.getX(), mapId, "hires", "translate", "x"); + set(gridOrigin.getY(), mapId, "hires", "translate", "z"); + + Vector2i pointSize = hiresTileSize.div(lowresPointsPerHiresTile); + Vector2i tileSize = pointSize.mul(lowresTileSize); + + set(tileSize.getX(), mapId, "lowres", "tileSize", "x"); + set(tileSize.getY(), mapId, "lowres", "tileSize", "z"); + set(pointSize.getX(), mapId, "lowres", "scale", "x"); + set(pointSize.getY(), mapId, "lowres", "scale", "z"); + set(pointSize.getX() / 2, mapId, "lowres", "translate", "x"); + set(pointSize.getY() / 2, mapId, "lowres", "translate", "z"); + } + + public void setHiresViewDistance(float hiresViewDistance, String mapId) { + set(hiresViewDistance, mapId, "hires", "viewDistance"); + } + + public void setLowresViewDistance(float lowresViewDistance, String mapId) { + set(lowresViewDistance, mapId, "lowres", "viewDistance"); + } + + public void setName(String name, String mapId) { + set(name, mapId, "name"); + } + + public String getName(String mapId) { + return getString(mapId, "name"); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpConnection.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpConnection.java new file mode 100644 index 00000000..298e3b3f --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpConnection.java @@ -0,0 +1,126 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.webserver; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.util.concurrent.TimeUnit; + +import de.bluecolored.bluemap.core.logger.Logger; + +public class HttpConnection implements Runnable { + + private HttpRequestHandler handler; + + private ServerSocket server; + private Socket connection; + private InputStream in; + private OutputStream out; + + public HttpConnection(ServerSocket server, Socket connection, HttpRequestHandler handler, int timeout, TimeUnit timeoutUnit) throws IOException { + this.server = server; + this.connection = connection; + this.handler = handler; + + if (isClosed()){ + throw new IOException("Socket already closed!"); + } + + connection.setSoTimeout((int) timeoutUnit.toMillis(timeout)); + + in = this.connection.getInputStream(); + out = this.connection.getOutputStream(); + } + + @Override + public void run() { + while (!isClosed() && !server.isClosed()){ + try { + HttpRequest request = acceptRequest(); + HttpResponse response = handler.handle(request); + sendResponse(response); + } catch (InvalidRequestException e){ + try { + sendResponse(new HttpResponse(HttpStatusCode.BAD_REQUEST)); + } catch (IOException e1) {} + break; + } catch (SocketTimeoutException e) { + break; + } catch (SocketException e){ + break; + } catch (ConnectionClosedException e){ + break; + } catch (IOException e) { + Logger.global.logError("Unexpected error while processing a HttpRequest!", e); + break; + } + } + + try { + close(); + } catch (IOException e){ + Logger.global.logError("Error while closing HttpConnection!", e); + } + } + + private void sendResponse(HttpResponse response) throws IOException { + response.write(out); + out.flush(); + } + + private HttpRequest acceptRequest() throws ConnectionClosedException, InvalidRequestException, IOException { + return HttpRequest.read(in); + } + + public boolean isClosed(){ + return !connection.isBound() || connection.isClosed() || !connection.isConnected() || connection.isOutputShutdown() || connection.isInputShutdown(); + } + + public void close() throws IOException { + try { + in.close(); + } finally { + try { + out.close(); + } finally { + connection.close(); + } + } + } + + public static class ConnectionClosedException extends IOException { + private static final long serialVersionUID = 1L; + } + + public static class InvalidRequestException extends IOException { + private static final long serialVersionUID = 1L; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java new file mode 100644 index 00000000..a8597c51 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java @@ -0,0 +1,206 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.webserver; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import de.bluecolored.bluemap.core.webserver.HttpConnection.ConnectionClosedException; +import de.bluecolored.bluemap.core.webserver.HttpConnection.InvalidRequestException; + +public class HttpRequest { + + private static final Pattern REQUEST_PATTERN = Pattern.compile("^(\\w+) (\\S+) (.+)$"); + + private String method; + private String path; + private String version; + private Map> header; + private Map> headerLC; + private byte[] data; + + public HttpRequest(String method, String path, String version, Map> header) { + this.method = method; + this.path = path; + this.version = version; + this.header = header; + this.headerLC = new HashMap<>(); + + for (Entry> e : header.entrySet()){ + Set values = new HashSet<>(); + for (String v : e.getValue()){ + values.add(v.toLowerCase()); + } + + headerLC.put(e.getKey().toLowerCase(), values); + } + + this.data = new byte[0]; + } + + public String getMethod() { + return method; + } + + public String getPath(){ + return path; + } + + public String getVersion() { + return version; + } + + public Map> getHeader() { + return header; + } + + public Map> getLowercaseHeader() { + return header; + } + + public Set getHeader(String key){ + Set headerValues = header.get(key); + if (headerValues == null) return Collections.emptySet(); + return headerValues; + } + + public Set getLowercaseHeader(String key){ + Set headerValues = headerLC.get(key.toLowerCase()); + if (headerValues == null) return Collections.emptySet(); + return headerValues; + } + + public InputStream getData(){ + return new ByteArrayInputStream(data); + } + + public static HttpRequest read(InputStream in) throws IOException, InvalidRequestException { + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + List header = new ArrayList<>(20); + while(header.size() < 1000){ + String headerLine = readLine(reader); + if (headerLine.isEmpty()) break; + header.add(headerLine); + } + + if (header.isEmpty()) throw new InvalidRequestException(); + + Matcher m = REQUEST_PATTERN.matcher(header.remove(0)); + if (!m.find()) throw new InvalidRequestException(); + + String method = m.group(1); + if (method == null) throw new InvalidRequestException(); + + String adress = m.group(2); + if (adress == null) throw new InvalidRequestException(); + + String version = m.group(3); + if (version == null) throw new InvalidRequestException(); + + Map> headerMap = new HashMap>(); + for (String line : header){ + if (line.trim().isEmpty()) continue; + + String[] kv = line.split(":", 2); + if (kv.length < 2) continue; + + Set values = new HashSet<>(); + if (kv[0].trim().equalsIgnoreCase("If-Modified-Since")){ + values.add(kv[1].trim()); + } else { + for(String v : kv[1].split(",")){ + values.add(v.trim()); + } + } + + headerMap.put(kv[0].trim(), values); + } + + HttpRequest request = new HttpRequest(method, adress, version, headerMap); + + if (request.getLowercaseHeader("Transfer-Encoding").contains("chunked")){ + try { + ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); + while (dataStream.size() < 1000000){ + String hexSize = reader.readLine(); + int chunkSize = Integer.parseInt(hexSize, 16); + if (chunkSize <= 0) break; + byte[] data = new byte[chunkSize]; + in.read(data); + dataStream.write(data); + } + + if (dataStream.size() >= 1000000) { + throw new InvalidRequestException(); + } + + request.data = dataStream.toByteArray(); + + return request; + } catch (NumberFormatException ex){ + return request; + } + } else { + Set clSet = request.getLowercaseHeader("Content-Length"); + if (clSet.isEmpty()){ + return request; + } else { + try { + int cl = Integer.parseInt(clSet.iterator().next()); + byte[] data = new byte[cl]; + in.read(data); + request.data = data; + return request; + } catch (NumberFormatException ex){ + return request; + } + } + } + } + + private static String readLine(BufferedReader in) throws ConnectionClosedException, IOException { + String line = in.readLine(); + if (line == null){ + throw new ConnectionClosedException(); + } + return line; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequestHandler.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequestHandler.java new file mode 100644 index 00000000..23f887ef --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequestHandler.java @@ -0,0 +1,31 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.webserver; + +public interface HttpRequestHandler { + + HttpResponse handle(HttpRequest request); + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpResponse.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpResponse.java new file mode 100644 index 00000000..6110a93c --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpResponse.java @@ -0,0 +1,149 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.webserver; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; + +public class HttpResponse { + + private String version; + private HttpStatusCode statusCode; + private Map> header; + private InputStream data; + + public HttpResponse(HttpStatusCode statusCode) { + this.version = "HTTP/1.1"; + this.statusCode = statusCode; + + this.header = new HashMap<>(); + + addHeader("Connection", "keep-alive"); + } + + public void addHeader(String key, String value){ + Set valueSet = header.get(key); + if (valueSet == null){ + valueSet = new HashSet<>(); + header.put(key, valueSet); + } + + valueSet.add(value); + } + + public void removeHeader(String key, String value){ + Set valueSet = header.get(key); + if (valueSet == null){ + valueSet = new HashSet<>(); + header.put(key, valueSet); + } + + valueSet.remove(value); + } + + public void setData(InputStream dataStream){ + this.data = dataStream; + } + + public void setData(String data){ + setData(new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8))); + } + + /** + * Writes this Response to an Output-Stream.
+ *
+ * This method closes the data-Stream of this response so it can't be used again! + */ + public void write(OutputStream out) throws IOException { + OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); + + if (data != null){ + addHeader("Transfer-Encoding", "chunked"); + } else { + addHeader("Content-Length", "0"); + } + + writeLine(writer, version + " " + statusCode.getCode() + " " + statusCode.getMessage()); + for (Entry> e : header.entrySet()){ + if (e.getValue().isEmpty()) continue; + writeLine(writer, e.getKey() + ": " + StringUtils.join(e.getValue(), ", ")); + } + + writeLine(writer, ""); + writer.flush(); + + if(data != null){ + chunkedPipe(data, out); + out.flush(); + data.close(); + } + } + + private void writeLine(OutputStreamWriter writer, String line) throws IOException { + writer.write(line + "\r\n"); + } + + private void chunkedPipe(InputStream input, OutputStream output) throws IOException { + byte[] buffer = new byte[1024]; + int byteCount; + while ((byteCount = input.read(buffer)) != -1) { + output.write((Integer.toHexString(byteCount) + "\r\n").getBytes()); + output.write(buffer, 0, byteCount); + output.write("\r\n".getBytes()); + } + output.write("0\r\n\r\n".getBytes()); + } + + public HttpStatusCode getStatusCode(){ + return statusCode; + } + + public String getVersion(){ + return version; + } + + public Map> getHeader() { + return header; + } + + public Set getHeader(String key){ + Set headerValues = header.get(key); + if (headerValues == null) return Collections.emptySet(); + return headerValues; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpStatusCode.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpStatusCode.java new file mode 100644 index 00000000..820a2b09 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpStatusCode.java @@ -0,0 +1,70 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.webserver; + +public enum HttpStatusCode { + + CONTINUE (100, "Continue"), + PROCESSING (102, "Processing"), + + OK (200, "OK"), + + MOVED_PERMANENTLY (301, "Moved Permanently"), + FOUND (302, "Found"), + SEE_OTHER (303, "See Other"), + NOT_MODIFIED (304, "Not Modified"), + + BAD_REQUEST (400, "Bad Request"), + UNAUTHORIZED (401, "Unauthorized"), + FORBIDDEN (403, "Forbidden"), + NOT_FOUND (404, "Not Found"), + + INTERNAL_SERVER_ERROR (500, "Internal Server Error"), + NOT_IMPLEMENTED (501, "Not Implemented"), + SERVICE_UNAVAILABLE (503, "Service Unavailable"), + HTTP_VERSION_NOT_SUPPORTED (505, "HTTP Version not supported"); + + private int code; + private String message; + + private HttpStatusCode(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode(){ + return code; + } + + public String getMessage(){ + return message; + } + + @Override + public String toString() { + return getCode() + " " + getMessage(); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/WebServer.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/WebServer.java new file mode 100644 index 00000000..ba8a290e --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/WebServer.java @@ -0,0 +1,113 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.webserver; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import de.bluecolored.bluemap.core.logger.Logger; + +public class WebServer extends Thread { + + private final int port; + private final int maxConnections; + private final InetAddress bindAdress; + + private HttpRequestHandler handler; + + private ThreadPoolExecutor connectionThreads; + + private ServerSocket server; + + public WebServer(int port, int maxConnections, InetAddress bindAdress, HttpRequestHandler handler) { + this.port = port; + this.maxConnections = maxConnections; + this.bindAdress = bindAdress; + + this.handler = handler; + + connectionThreads = null; + } + + @Override + public void run(){ + close(); + + connectionThreads = new ThreadPoolExecutor(maxConnections, maxConnections, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); + connectionThreads.allowCoreThreadTimeOut(true); + + try { + server = new ServerSocket(port, maxConnections, bindAdress); + server.setSoTimeout(0); + } catch (IOException e){ + Logger.global.logError("Error while starting the WebServer!", e); + return; + } + + Logger.global.logInfo("WebServer started."); + + while (!server.isClosed() && server.isBound()){ + + try { + Socket connection = server.accept(); + + try { + connectionThreads.execute(new HttpConnection(server, connection, handler, 10, TimeUnit.SECONDS)); + } catch (RejectedExecutionException e){ + connection.close(); + Logger.global.logWarning("Dropped an incoming HttpConnection! (Too many connections?)"); + } + + } catch (SocketException e){ + // this mainly occurs if the socket got closed, so we ignore this error + } catch (IOException e){ + Logger.global.logError("Error while creating a new HttpConnection!", e); + } + + } + + Logger.global.logInfo("WebServer closed."); + } + + public void close(){ + if (connectionThreads != null) connectionThreads.shutdown(); + + try { + if (server != null && !server.isClosed()){ + server.close(); + } + } catch (IOException e) { + Logger.global.logError("Error while closing WebServer!", e); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/Block.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/Block.java new file mode 100644 index 00000000..7799bff3 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/Block.java @@ -0,0 +1,91 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.world; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.render.context.BlockContext; +import de.bluecolored.bluemap.core.util.Direction; + +public abstract class Block { + + private float sunLight; + private float blockLight; + + public Block() { + sunLight = -1; + blockLight = -1; + } + + public abstract BlockState getBlock(); + + public abstract World getWorld(); + + public abstract Vector3i getPosition(); + + public abstract double getSunLightLevel(); + + public abstract double getBlockLightLevel(); + + public abstract boolean isCullingNeighborFaces(); + + public boolean isOccludingNeighborFaces(){ + return isCullingNeighborFaces(); + } + + public abstract String getBiome(); + + /** + * This is internally used for light rendering + * It is basically the sun light that is projected onto adjacent faces + */ + public float getPassedSunLight(BlockContext context) { + if (sunLight < 0) calculateLight(context); + return sunLight; + } + + /** + * This is internally used for light rendering + * It is basically the block light that is projected onto adjacent faces + */ + public float getPassedBlockLight(BlockContext context) { + if (blockLight < 0) calculateLight(context); + return blockLight; + } + + private void calculateLight(BlockContext context) { + sunLight = (float) getSunLightLevel(); + blockLight = (float) getBlockLightLevel(); + + if (blockLight > 0 || sunLight > 0) return; + + for (Direction direction : Direction.values()) { + Block neighbor = context.getRelativeBlock(direction); + sunLight = (float) Math.max(neighbor.getSunLightLevel(), sunLight); + blockLight = (float) Math.max(neighbor.getBlockLightLevel(), blockLight); + } + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java new file mode 100644 index 00000000..6eb256f5 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java @@ -0,0 +1,199 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.world; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import java.util.Objects; +import java.util.StringJoiner; + +/** + * Represents a BlockState
+ * It is important that {@link #hashCode} and {@link #equals} are implemented correctly, for the caching to work properly.
+ *
+ * The implementation of this class has to be thread-save!
+ */ +public class BlockState { + + private static Pattern BLOCKSTATE_SERIALIZATION_PATTERN = Pattern.compile("^(.+?)(?:\\[(.+)\\])?$"); + + public static final BlockState AIR = new BlockState("minecraft:air", Collections.emptyMap()); + + private boolean hashed; + private int hash; + + private final String namespace; + private final String id; + private final Map properties; + + public BlockState(String id) { + this(id, Collections.emptyMap()); + } + + public BlockState(String id, Map properties) { + this.hashed = false; + this.hash = 0; + + this.properties = Collections.unmodifiableMap(new HashMap<>(properties)); + + //resolve namespace + String namespace = "minecraft"; + int namespaceSeperator = id.indexOf(':'); + if (namespaceSeperator > 0) { + namespace = id.substring(0, namespaceSeperator); + id = id.substring(namespaceSeperator + 1); + } + + this.id = id; + this.namespace = namespace; + } + + private BlockState(BlockState blockState, String withKey, String withValue) { + this.hashed = false; + this.hash = 0; + + Map props = new HashMap<>(blockState.getProperties()); + props.put(withKey, withValue); + + this.id = blockState.getId(); + this.namespace = blockState.getNamespace(); + this.properties = Collections.unmodifiableMap(props); + } + + /** + * The namespace of this blockstate,
+ * this is always "minecraft" in vanilla.
+ */ + public String getNamespace() { + return namespace; + } + + /** + * The id of this blockstate,
+ * also the name of the resource-file without the filetype that represents this block-state (found in mineceraft in assets/minecraft/blockstates).
+ */ + public String getId() { + return id; + } + + /** + * Returns the namespaced id of this blockstate + */ + public String getFullId() { + return getNamespace() + ":" + getId(); + } + + /** + * An immutable map of all properties of this block.
+ *
+ * For Example:
+ * + * facing = east
+ * half = bottom
+ *
+ */ + public Map getProperties() { + return properties; + } + + /** + * Returns a new BlockState with the given property changed + */ + public BlockState with(String property, String value) { + return new BlockState(this, property, value); + } + + public final boolean checkVariantCondition(String condition){ + if (condition.isEmpty() || condition.equals("normal")) return true; + + Map blockProperties = getProperties(); + String[] conditions = condition.split(","); + for (String c : conditions){ + String[] kv = c.split("=", 2); + String key = kv[0]; + String value = kv[1]; + + if (!value.equals(blockProperties.get(key))){ + return false; + } + } + + return true; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof BlockState)) return false; + BlockState b = (BlockState) obj; + if (!Objects.equals(getId(), b.getId())) return false; + if (!Objects.equals(getProperties(), b.getProperties())) return false; + return true; + } + + @Override + public int hashCode() { + if (!hashed){ + hash = Objects.hash( getId(), getProperties() ); + hashed = true; + } + + return hash; + } + + @Override + public String toString() { + StringJoiner sj = new StringJoiner(","); + for (Entry e : getProperties().entrySet()){ + sj.add(e.getKey() + "=" + e.getValue()); + } + + return getId() + "[" + sj.toString() + "]"; + } + + public static BlockState fromString(String serializedBlockState) { + Matcher m = BLOCKSTATE_SERIALIZATION_PATTERN.matcher(serializedBlockState); + m.find(); + + Map pt = new HashMap<>(); + String g2 = m.group(2); + if (g2 != null){ + String[] propertyStrings = g2.trim().split(","); + for (String s : propertyStrings){ + String[] kv = s.split("=", 2); + pt.put(kv[0], kv[1]); + } + } + + String blockId = m.group(1).trim(); + + return new BlockState(blockId, pt); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/CachedBlock.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/CachedBlock.java new file mode 100644 index 00000000..298beeb6 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/CachedBlock.java @@ -0,0 +1,130 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.world; + +import com.flowpowered.math.vector.Vector3i; + +/** + * This class wraps another Block to cache all getters.
+ * The implementation can use this to make sure all underlying getters are only called once and cached-data is used on the second call. + */ +public class CachedBlock extends Block { + + private Block block; + + private BlockState state; + private World world; + private Vector3i position; + private double sunLight, blockLight; + private String biome; + + private boolean isCullingCached; + private boolean isCulling; + + private boolean isOccludingCached; + private boolean isOccluding; + + private CachedBlock(Block block) { + this.block = block; + + this.state = null; + this.world = null; + this.position = null; + this.sunLight = -1; + this.blockLight = -1; + + this.isCullingCached = false; + this.isCulling = false; + + this.isOccludingCached = false; + this.isOccluding = false; + } + + @Override + public BlockState getBlock() { + if (state == null) state = block.getBlock(); + return state; + } + + @Override + public World getWorld() { + if (world == null) world = block.getWorld(); + return world; + } + + @Override + public Vector3i getPosition() { + if (position == null) position = block.getPosition(); + return position; + } + + @Override + public double getSunLightLevel() { + if (sunLight == -1) sunLight = block.getSunLightLevel(); + return sunLight; + } + + @Override + public double getBlockLightLevel() { + if (blockLight == -1) blockLight = block.getBlockLightLevel(); + return blockLight; + } + + @Override + public boolean isCullingNeighborFaces() { + if (!isCullingCached){ + isCulling = block.isCullingNeighborFaces(); + isCullingCached = true; + } + + return isCulling; + } + + @Override + public boolean isOccludingNeighborFaces() { + if (!isOccludingCached){ + isOccluding = block.isOccludingNeighborFaces(); + isOccludingCached = true; + } + + return isOccluding; + } + + @Override + public String getBiome() { + if (biome == null){ + biome = block.getBiome(); + } + + return biome; + } + + public static CachedBlock of(Block block){ + if (block instanceof CachedBlock) return (CachedBlock) block; + + return new CachedBlock(block); + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ChunkNotGeneratedException.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ChunkNotGeneratedException.java new file mode 100644 index 00000000..caf71289 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ChunkNotGeneratedException.java @@ -0,0 +1,43 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.world; + +public class ChunkNotGeneratedException extends Exception { + private static final long serialVersionUID = 0L; + + public ChunkNotGeneratedException() {} + + public ChunkNotGeneratedException(Throwable e) { + super(e); + } + + public ChunkNotGeneratedException(String message){ + super(message); + } + + public ChunkNotGeneratedException(String message, Throwable e) { + super(message, e); + } +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java new file mode 100644 index 00000000..f15d5ae3 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java @@ -0,0 +1,78 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.world; + +import java.util.Collection; +import java.util.UUID; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; + +/** + * Represents a World on the Server
+ *
+ * The implementation of this class has to be thread-save!
+ */ +public interface World extends WorldChunk { + + String getName(); + + UUID getUUID(); + + int getSeaLevel(); + + Vector3i getSpawnPoint(); + + /** + * Returns itself + */ + @Override + default World getWorld() { + return this; + } + + /** + * Always returns false + */ + @Override + default boolean isGenerated() { + return false; + } + + /** + * Returns a collection of all generated chunks.
+ * (Be aware that the collection is not cached and recollected each time from the world-files!) + */ + public default Collection getChunkList(){ + return getChunkList(0); + } + + /** + * Returns a collection of all chunks that have been modified at or after the specified timestamp.
+ * (Be aware that the collection is not cached and recollected each time from the world-files!) + */ + public Collection getChunkList(long modifiedSince); + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/WorldChunk.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/WorldChunk.java new file mode 100644 index 00000000..17b587b3 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/WorldChunk.java @@ -0,0 +1,85 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.core.world; + +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.util.AABB; + +/** + * Represents a chunk of a world.
+ *
+ * The implementation of this class has to be thread-save!
+ */ +public interface WorldChunk { + + /** + * Returns the top-level World of this WorldChunk, + * If this WorldChunk is already a World, the method returns the same instance (return this;). + */ + World getWorld(); + + /** + * Returns the Block on the specified position.
+ *
+ * (The implementation should not invoke the generation of new Terrain, it should rather throw a {@link ChunkNotGeneratedException} if a not generated block is requested)
+ */ + Block getBlock(Vector3i pos) throws ChunkNotGeneratedException; + + /** + * Returns the Block on the specified position.
+ *
+ * (The implementation should not invoke the generation of new Terrain, it should rather throw a {@link ChunkNotGeneratedException} if a not generated block is requested)
+ */ + default Block getBlock(int x, int y, int z) throws ChunkNotGeneratedException { + return getBlock(new Vector3i(x, y, z)); + } + + /** + * Returns true if this WorldChunk contains the given position. + */ + default boolean containsBlock(Vector3i pos){ + return getBoundaries().contains(pos); + } + + /** + * Returns the boundaries of the WorldChunk.
+ */ + AABB getBoundaries(); + + /** + * Returns a smaller part of this WorldChunk
+ *
+ * This is used to give the implementation an easy way to optimize thread-save access to this world-chunk.
+ * The {@link #getBlock} method is and should be used in favour to {@link World#getBlock}.
+ */ + WorldChunk getWorldChunk(AABB boundaries); + + /** + * Returns true if the complete WorldChunk is generated and populated by Minecraft.
+ */ + boolean isGenerated(); + +} diff --git a/BlueMapCore/src/main/resources/DefaultResources.zip b/BlueMapCore/src/main/resources/DefaultResources.zip new file mode 100644 index 0000000000000000000000000000000000000000..8ba93d77f9712d7d6a272c59f57432c959b46a5a GIT binary patch literal 1028645 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%0A`ukE>>`8Tj_s99#(!$j*q)%I2=Q%a< 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%0ASfMr(Y;x%0(Wof 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 z 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
  • 7P|F% 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 z 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�|yjQA3tiun7*}n#4^)MQ*S_7e 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
    + + + + + diff --git a/BlueMapCore/src/main/webroot/js/libs/bluemap.js b/BlueMapCore/src/main/webroot/js/libs/bluemap.js new file mode 100644 index 00000000..f846d529 --- /dev/null +++ b/BlueMapCore/src/main/webroot/js/libs/bluemap.js @@ -0,0 +1,1201 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +BlueMap = function (element, dataRoot) { + this.element = element; + this.dataRoot = dataRoot; + + this.loadingNoticeElement = $('
    loading...
    ').appendTo($(this.element)); + + this.fileLoader = new THREE.FileLoader(); + this.blobLoader = new THREE.FileLoader(); + this.blobLoader.setResponseType("blob"); + this.bufferGeometryLoader = new THREE.BufferGeometryLoader(); + + this.initStage(); + this.locationHash = ""; + this.controls = new BlueMap.Controls(this.camera, this.element, this.hiresScene); + + this.loadSettings(function () { + this.lowresTileManager = new BlueMap.TileManager( + this, + this.settings[this.map]["lowres"]["viewDistance"], + this.loadLowresTile, + this.lowresScene, + this.settings[this.map]["lowres"]["tileSize"], + {x: 0, z: 0} + ); + + this.hiresTileManager = new BlueMap.TileManager( + this, + this.settings[this.map]["hires"]["viewDistance"], + this.loadHiresTile, + this.hiresScene, + this.settings[this.map]["hires"]["tileSize"], + {x: 0, z: 0} + ); + + this.loadHiresMaterial(function () { + this.loadLowresMaterial(function () { + this.initModules(); + this.start(); + }); + }); + }); +}; + +BlueMap.prototype.initModules = function () { + this.modules = {}; + + this.modules.compass = new BlueMap.Module.Compass(this); + this.modules.position = new BlueMap.Module.Position(this); + this.modules.mapMenu = new BlueMap.Module.MapMenu(this); + this.modules.info = new BlueMap.Module.Info(this); + this.modules.settings = new BlueMap.Module.Settings(this); +}; + +BlueMap.prototype.changeMap = function (map) { + this.hiresTileManager.close(); + this.lowresTileManager.close(); + + this.map = map; + this.controls.resetPosition(); + + this.lowresTileManager = new BlueMap.TileManager( + this, + this.settings[this.map]["lowres"]["viewDistance"], + this.loadLowresTile, + this.lowresScene, + this.settings[this.map]["lowres"]["tileSize"], + {x: 0, z: 0} + ); + + this.hiresTileManager = new BlueMap.TileManager( + this, + this.settings[this.map]["hires"]["viewDistance"], + this.loadHiresTile, + this.hiresScene, + this.settings[this.map]["hires"]["tileSize"], + {x: 0, z: 0} + ); + + this.lowresTileManager.update(); + this.hiresTileManager.update(); + + document.dispatchEvent(new Event("bluemap-map-change")); +}; + +BlueMap.prototype.loadLocationHash = function(){ + let hashVars = window.location.hash.substring(1).split(":"); + if (hashVars.length >= 1){ + if (this.settings[hashVars[0]] !== undefined && this.map !== hashVars[0]){ + this.changeMap(hashVars[0]); + } + } + if (hashVars.length >= 3){ + let x = parseInt(hashVars[1]); + let z = parseInt(hashVars[2]); + if (!isNaN(x) && !isNaN(z)){ + this.controls.targetPosition.x = x + 0.5; + this.controls.targetPosition.z = z + 0.5; + } + } + if (hashVars.length >= 6){ + let dir = parseFloat(hashVars[3]); + let dist = parseFloat(hashVars[4]); + let angle = parseFloat(hashVars[5]); + if (!isNaN(dir)) this.controls.targetDirection = dir; + if (!isNaN(dist)) this.controls.targetDistance = dist; + if (!isNaN(angle)) this.controls.targetAngle = angle; + this.controls.direction = this.controls.targetDirection; + this.controls.distance = this.controls.targetDistance; + this.controls.angle = this.controls.targetAngle; + this.controls.targetPosition.y = this.controls.minHeight; + this.controls.position.copy(this.controls.targetPosition); + } + if (hashVars.length >= 7){ + let height = parseInt(hashVars[6]); + if (!isNaN(height)){ + this.controls.minHeight = height; + this.controls.targetPosition.y = height; + this.controls.position.copy(this.controls.targetPosition); + } + } +}; + +BlueMap.prototype.start = function () { + let scope = this; + + this.loadingNoticeElement.remove(); + + this.loadLocationHash(); + + $(window).on("hashchange", function(evt){ + if (scope.locationHash === window.location.hash) return; + scope.loadLocationHash(); + }); + + this.update(); + this.render(); + + this.lowresTileManager.update(); + this.hiresTileManager.update(); +}; + +BlueMap.prototype.update = function () { + let scope = this; + setTimeout(function () { + scope.update() + }, 1000); + + this.lowresTileManager.setPosition(this.controls.targetPosition); + this.hiresTileManager.setPosition(this.controls.targetPosition); + + this.locationHash = + "#" + this.map + + ":" + Math.floor(this.controls.targetPosition.x) + + ":" + Math.floor(this.controls.targetPosition.z) + + ":" + Math.round(this.controls.targetDirection * 100) / 100 + + ":" + Math.round(this.controls.targetDistance * 100) / 100 + + ":" + Math.ceil(this.controls.targetAngle * 100) / 100 + + ":" + Math.floor(this.controls.targetPosition.y); + history.replaceState(undefined, undefined, this.locationHash); +}; + +BlueMap.prototype.render = function () { + let scope = this; + requestAnimationFrame(function () { + scope.render() + }); + + if (this.controls.update()) this.updateFrame = true; + + if (!this.updateFrame) return; + this.updateFrame = false; + + document.dispatchEvent(new Event("bluemap-update-frame")); + + this.skyboxCamera.rotation.copy(this.camera.rotation); + this.skyboxCamera.updateProjectionMatrix(); + + + this.renderer.clear(); + this.renderer.render(this.skyboxScene, this.skyboxCamera, this.renderer.getRenderTarget(), false); + this.renderer.clearDepth(); + this.renderer.render(this.lowresScene, this.camera, this.renderer.getRenderTarget(), false); + if (this.camera.position.y < 400) { + this.renderer.clearDepth(); + this.renderer.render(this.hiresScene, this.camera, this.renderer.getRenderTarget(), false); + } +}; + +BlueMap.prototype.handleContainerResize = function () { + this.camera.aspect = this.element.clientWidth / this.element.clientHeight; + this.camera.updateProjectionMatrix(); + + this.skyboxCamera.aspect = this.element.clientWidth / this.element.clientHeight; + this.skyboxCamera.updateProjectionMatrix(); + + this.renderer.setSize(this.element.clientWidth * this.quality, this.element.clientHeight * this.quality); + $(this.renderer.domElement) + .css("width", this.element.clientWidth) + .css("height", this.element.clientHeight); + + this.updateFrame = true; +}; + +BlueMap.prototype.loadSettings = function (callback) { + let scope = this; + + this.fileLoader.load(this.dataRoot + "settings.json", function (settings) { + scope.settings = JSON.parse(settings); + + scope.maps = []; + for (map in scope.settings){ + if (scope.settings.hasOwnProperty(map)){ + scope.maps.push(map); + } + } + + scope.map = scope.maps[0]; + + callback.call(scope); + }); +}; + +BlueMap.prototype.initStage = function () { + let scope = this; + + this.updateFrame = true; + this.quality = 1; + + this.renderer = new THREE.WebGLRenderer({ + alpha: true, + antialias: true, + sortObjects: false, + preserveDrawingBuffer: true, + logarithmicDepthBuffer: true, + }); + this.renderer.autoClear = false; + + this.camera = new THREE.PerspectiveCamera(75, this.element.scrollWidth / this.element.scrollHeight, 0.1, 10000); + this.camera.updateProjectionMatrix(); + + this.skyboxCamera = this.camera.clone(); + this.skyboxCamera.updateProjectionMatrix(); + + this.skyboxScene = new THREE.Scene(); + this.skyboxScene.ambient = new THREE.AmbientLight(0xffffff, 1); + this.skyboxScene.add(this.skyboxScene.ambient); + this.skyboxScene.add(this.createSkybox()); + + this.lowresScene = new THREE.Scene(); + this.lowresScene.ambient = new THREE.AmbientLight(0xffffff, 0.6); + this.lowresScene.add(this.lowresScene.ambient); + this.lowresScene.sunLight = new THREE.DirectionalLight(0xccccbb, 0.7); + this.lowresScene.sunLight.position.set(1, 5, 3); + this.lowresScene.add(this.lowresScene.sunLight); + + this.hiresScene = new THREE.Scene(); + this.hiresScene.ambient = new THREE.AmbientLight(0xffffff, 1); + this.hiresScene.add(this.hiresScene.ambient); + this.hiresScene.sunLight = new THREE.DirectionalLight(0xccccbb, 0.2); + this.hiresScene.sunLight.position.set(1, 5, 3); + this.hiresScene.add(this.hiresScene.sunLight); + + this.element.append(this.renderer.domElement); + this.handleContainerResize(); + + $(window).resize(function () { + scope.handleContainerResize() + }); +}; + +BlueMap.prototype.createSkybox = function(){ + let geometry = new THREE.CubeGeometry(10, 10, 10); + let material = [ + new THREE.MeshBasicMaterial({ + map: new THREE.TextureLoader().load('assets/skybox/south.png'), + side: THREE.BackSide + }), + new THREE.MeshBasicMaterial({ + map: new THREE.TextureLoader().load('assets/skybox/north.png'), + side: THREE.BackSide + }), + new THREE.MeshBasicMaterial({ + map: new THREE.TextureLoader().load('assets/skybox/up.png'), + side: THREE.BackSide + }), + new THREE.MeshBasicMaterial({ + map: new THREE.TextureLoader().load('assets/skybox/down.png'), + side: THREE.BackSide + }), + new THREE.MeshBasicMaterial({ + map: new THREE.TextureLoader().load('assets/skybox/east.png'), + side: THREE.BackSide + }), + new THREE.MeshBasicMaterial({ + map: new THREE.TextureLoader().load('assets/skybox/west.png'), + side: THREE.BackSide + }) + ]; + return new THREE.Mesh(geometry, material); +}; + +BlueMap.prototype.loadHiresMaterial = function (callback) { + let scope = this; + + this.fileLoader.load(this.dataRoot + "textures.json", function (textures) { + textures = JSON.parse(textures); + + let materials = []; + for (let i = 0; i < textures["textures"].length; i++) { + let t = textures["textures"][i]; + + let material = new THREE.MeshLambertMaterial({ + transparent: t["transparent"], + alphaTest: 0.01, + depthWrite: true, + depthTest: true, + blending: THREE.NormalBlending, + vertexColors: THREE.VertexColors, + side: THREE.FrontSide, + wireframe: false + }); + + let texture = new THREE.Texture(); + texture.image = BlueMap.utils.stringToImage(t["texture"]); + + texture.premultiplyAlpha = false; + texture.generateMipmaps = false; + texture.magFilter = THREE.NearestFilter; + texture.minFilter = THREE.NearestFilter; + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + texture.flipY = false; + texture.needsUpdate = true; + texture.flatShading = true; + + material.map = texture; + material.needsUpdate = true; + + materials[i] = material; + } + + scope.hiresMaterial = materials; + + callback.call(scope); + }); +}; + +BlueMap.prototype.loadLowresMaterial = function (callback) { + this.lowresMaterial = new THREE.MeshLambertMaterial({ + transparent: false, + depthWrite: true, + depthTest: true, + vertexColors: THREE.VertexColors, + side: THREE.FrontSide, + wireframe: false + }); + + callback.call(this); +}; + +BlueMap.prototype.loadHiresTile = function (tileX, tileZ, callback, onError) { + let scope = this; + + let path = this.dataRoot + "hires/" + this.map + "/"; + path += BlueMap.utils.pathFromCoords(tileX, tileZ); + path += ".json"; + + + this.bufferGeometryLoader.load(path, function (geometry) { + let object = new THREE.Mesh(geometry, scope.hiresMaterial); + + let tileSize = scope.settings[scope.map]["hires"]["tileSize"]; + let translate = scope.settings[scope.map]["hires"]["translate"]; + let scale = scope.settings[scope.map]["hires"]["scale"]; + object.position.set(tileX * tileSize.x + translate.x, 0, tileZ * tileSize.z + translate.z); + object.scale.set(scale.x, 1, scale.z); + + callback.call(scope, object); + }, function () { + + }, function (error) { + onError.call(scope, error); + }); +}; + +BlueMap.prototype.loadLowresTile = function (tileX, tileZ, callback, onError) { + let scope = this; + + let path = this.dataRoot + "lowres/" + this.map + "/"; + path += BlueMap.utils.pathFromCoords(tileX, tileZ); + path += ".json"; + + this.bufferGeometryLoader.load(path, function (geometry) { + let object = new THREE.Mesh(geometry, scope.lowresMaterial); + + let tileSize = scope.settings[scope.map]["lowres"]["tileSize"]; + let translate = scope.settings[scope.map]["lowres"]["translate"]; + let scale = scope.settings[scope.map]["lowres"]["scale"]; + object.position.set(tileX * tileSize.x + translate.x, 0, tileZ * tileSize.z + translate.z); + object.scale.set(scale.x, 1, scale.z); + + callback.call(scope, object); + }, function () { + + }, function (error) { + onError.call(scope, error); + }); +}; + + +// ###### UI ###### + +BlueMap.prototype.alert = function (content) { + let alertBox = $('#alert-box'); + if (alertBox.length === 0){ + alertBox = $('
    ').appendTo(this.element); + } + + let displayAlert = function(){ + let alert = $('').appendTo(alertBox); + alert.find('.alert-close-button').click(function(){ + alert.fadeOut(200, function(){ + alert.remove(); + }); + }); + alert.fadeIn(200); + }; + + let oldAlerts = alertBox.find('.alert'); + if (oldAlerts.length > 0){ + alertBox.fadeOut(200, function () { + alertBox.html(''); + alertBox.show(); + displayAlert(); + }) + } else { + displayAlert(); + } +}; + +// ###### TileManager ###### +BlueMap.TileManager = function (blueMap, viewDistance, tileLoader, scene, tileSize, position) { + this.blueMap = blueMap; + this.viewDistance = viewDistance; + this.tileLoader = tileLoader; + this.scene = scene; + this.tileSize = new THREE.Vector2(tileSize.x, tileSize.z); + + this.tile = new THREE.Vector2(position.x, position.z); + this.lastTile = this.tile.clone(); + + this.closed = false; + this.currentlyLoading = 0; + this.updateTimeout = null; + + this.tiles = {}; +}; + +BlueMap.TileManager.prototype.setPosition = function (center) { + this.tile.set(center.x, center.z).divide(this.tileSize).floor(); + + if (!this.tile.equals(this.lastTile) && !this.closed) { + this.update(); + this.lastTile.copy(this.tile); + } +}; + +BlueMap.TileManager.prototype.update = function () { + if (this.closed) return; + + //free a loader so if there was an error loading a tile we don't get stuck forever with the blocked loading process + this.currentlyLoading--; + if (this.currentlyLoading < 0) this.currentlyLoading = 0; + + this.removeFarTiles(); + this.loadCloseTiles(); +}; + +BlueMap.TileManager.prototype.removeFarTiles = function () { + let keys = Object.keys(this.tiles); + for (let i = 0; i < keys.length; i++) { + if (!this.tiles.hasOwnProperty(keys[i])) continue; + + let tile = this.tiles[keys[i]]; + + let vd = this.viewDistance; + + if ( + tile.x + vd < this.tile.x || + tile.x - vd > this.tile.x || + tile.z + vd < this.tile.y || + tile.z - vd > this.tile.y + ) { + tile.disposeModel(); + delete this.tiles[keys[i]]; + } + } +}; + +BlueMap.TileManager.prototype.removeAllTiles = function () { + let keys = Object.keys(this.tiles); + for (let i = 0; i < keys.length; i++) { + if (!this.tiles.hasOwnProperty(keys[i])) continue; + + let tile = this.tiles[keys[i]]; + tile.disposeModel(); + delete this.tiles[keys[i]]; + } +}; + +BlueMap.TileManager.prototype.close = function () { + this.closed = true; + this.removeAllTiles(); +}; + +BlueMap.TileManager.prototype.loadCloseTiles = function () { + if (this.closed) return; + + let scope = this; + + if (this.currentlyLoading < 8) { + if (!this.loadNextTile()) return; + } + + if (this.updateTimeout) clearTimeout(this.updateTimeout); + this.updateTimeout = setTimeout(function () { + scope.loadCloseTiles() + }, 0); +}; + +BlueMap.TileManager.prototype.loadNextTile = function () { + let x = 0; + let z = 0; + let d = 1; + let m = 1; + + while (m < this.viewDistance * 2) { + while (2 * x * d < m) { + if (this.tryLoadTile(this.tile.x + x, this.tile.y + z)) return true; + x = x + d; + } + while (2 * z * d < m) { + if (this.tryLoadTile(this.tile.x + x, this.tile.y + z)) return true; + z = z + d; + } + d = -1 * d; + m = m + 1; + } + + return false; +}; + +BlueMap.TileManager.prototype.tryLoadTile = function (x, z) { + if (this.closed) return; + + let scope = this; + + let tileHash = BlueMap.utils.hashTile(x, z); + + let tile = this.tiles[tileHash]; + if (tile !== undefined) return false; + + tile = new BlueMap.Tile(this.scene, x, z); + tile.isLoading = true; + + this.currentlyLoading++; + + this.tiles[tileHash] = tile; + + this.tileLoader.call(this.blueMap, x, z, function (model) { + tile.isLoading = false; + + if (tile.disposed || scope.closed) { + model.geometry.dispose(); + tile.disposeModel(); + delete scope.tiles[tileHash]; + return; + } + + scope.tiles[tileHash] = tile; + tile.setModel(model); + + scope.blueMap.updateFrame = true; + + scope.currentlyLoading--; + if (scope.currentlyLoading < 0) scope.currentlyLoading = 0; + }, function (error) { + tile.isLoading = false; + tile.disposeModel(); + + scope.currentlyLoading--; + + //console.log("Failed to load tile: ", x, z); + }); + + return true; +}; + + +// ###### Tile ###### +BlueMap.Tile = function (scene, x, z) { + this.scene = scene; + this.x = x; + this.z = z; + + this.isLoading = false; + this.disposed = false; + + this.model = null; +}; + +BlueMap.Tile.prototype.setModel = function (model) { + this.disposeModel(); + + if (model) { + this.model = model; + this.scene.add(model); + + //console.log("Added tile:", this.x, this.z); + } +}; + +BlueMap.Tile.prototype.disposeModel = function () { + this.disposed = true; + + if (this.model) { + this.scene.remove(this.model); + this.model.geometry.dispose(); + delete this.model; + + //console.log("Removed tile:", this.x, this.z); + } +}; + + +// ###### Controls ###### + +/** + * targetHeightScene and cameraHeightScene are scenes of objects that are checked via raycasting for a height for the target and the camera + */ +BlueMap.Controls = function (camera, element, heightScene) { + let scope = this; + + this.settings = { + zoom: { + min: 10, + max: 2000, + speed: 1.5, + smooth: 0.2, + }, + move: { + speed: 1.75, + smooth: 0.3, + smoothY: 0.075, + }, + tilt: { + max: Math.PI / 2.1, + speed: 1.5, + smooth: 0.3, + }, + rotate: { + speed: 1.5, + smooth: 0.3, + } + }; + + this.camera = camera; + this.element = element; + this.heightScene = heightScene; + this.minHeight = 0; + + this.raycaster = new THREE.Raycaster(); + this.rayDirection = new THREE.Vector3(0, -1, 0); + + this.resetPosition(); + + this.mouse = new THREE.Vector2(0, 0); + this.lastMouse = new THREE.Vector2(0, 0); + this.deltaMouse = new THREE.Vector2(0, 0); + + //variables used to calculate with (to prevent object creation every update) + this.orbitRot = new THREE.Euler(0, 0, 0, "YXZ"); + this.cameraPosDelta = new THREE.Vector3(0, 0, 0); + this.moveDelta = new THREE.Vector2(0, 0); + + this.keyStates = {}; + + this.KEYS = { + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + ORBIT: THREE.MOUSE.RIGHT, + MOVE: THREE.MOUSE.LEFT + }; + this.STATES = { + NONE: -1, + ORBIT: 0, + MOVE: 1, + }; + + this.state = this.STATES.NONE; + + let canvas = $(this.element).find("canvas").get(0); + window.addEventListener('contextmenu', function (e) { + e.preventDefault(); + }, false); + canvas.addEventListener('mousedown', function (e) { + scope.onMouseDown(e); + }, false); + window.addEventListener('mousemove', function (e) { + scope.onMouseMove(e); + }, false); + window.addEventListener('mouseup', function (e) { + scope.onMouseUp(e); + }, false); + canvas.addEventListener('wheel', function (e) { + scope.onMouseWheel(e); + }, false); + window.addEventListener('keydown', function (e) { + scope.onKeyDown(e); + }, false); + window.addEventListener('keyup', function (e) { + scope.onKeyUp(e); + }, false); + + this.camera.position.set(0, 1000, 0); + this.camera.lookAt(this.position); + this.camera.updateProjectionMatrix(); +}; + +BlueMap.Controls.prototype.resetPosition = function () { + this.position = new THREE.Vector3(0, 70, 0); + this.targetPosition = new THREE.Vector3(0, 70, 0); + + this.distance = 5000; + this.targetDistance = 1000; + + this.direction = 0; + this.targetDirection = 0; + + this.angle = 0; + this.targetAngle = 0; +}; + +BlueMap.Controls.prototype.update = function () { + this.updateMouseMoves(); + + let changed = false; + + let zoomLerp = (this.distance - 100) / 200; + if (zoomLerp < 0) zoomLerp = 0; + if (zoomLerp > 1) zoomLerp = 1; + this.targetPosition.y = 300 * zoomLerp + this.minHeight * (1 - zoomLerp); + + this.position.x += (this.targetPosition.x - this.position.x) * this.settings.move.smooth; + this.position.y += (this.targetPosition.y - this.position.y) * this.settings.move.smoothY; + this.position.z += (this.targetPosition.z - this.position.z) * this.settings.move.smooth; + + this.distance += (this.targetDistance - this.distance) * this.settings.zoom.smooth; + + let deltaDir = (this.targetDirection - this.direction) * this.settings.rotate.smooth; + this.direction += deltaDir; + changed = changed || Math.abs(deltaDir) > 0.001; + + let max = Math.min(this.settings.tilt.max, this.settings.tilt.max - Math.pow(((this.distance - this.settings.zoom.min) / (this.settings.zoom.max - this.settings.zoom.min)) * Math.pow(this.settings.tilt.max, 4), 1/4)); + if (this.targetAngle > max) this.targetAngle = max; + if (this.targetAngle < 0.01) this.targetAngle = 0.001; + let deltaAngle = (this.targetAngle - this.angle) * this.settings.tilt.smooth; + this.angle += deltaAngle; + changed = changed || Math.abs(deltaAngle) > 0.001; + + let last = this.camera.position.x + this.camera.position.y + this.camera.position.z; + this.orbitRot.set(this.angle, this.direction, 0); + this.cameraPosDelta.set(0, this.distance, 0).applyEuler(this.orbitRot); + + this.camera.position.set(this.position.x + this.cameraPosDelta.x, this.position.y + this.cameraPosDelta.y, this.position.z + this.cameraPosDelta.z); + let move = last - (this.camera.position.x + this.camera.position.y + this.camera.position.z); + + changed = changed || Math.abs(move) > 0.001; + + if (changed) { + this.camera.lookAt(this.position); + this.camera.updateProjectionMatrix(); + + this.updateHeights(); + } + + return changed; +}; + +BlueMap.Controls.prototype.updateHeights = function(){ + //TODO: this can be performance-improved by only intersecting the correct tile? + + let rayStart = new THREE.Vector3(this.targetPosition.x, 300, this.targetPosition.z); + this.raycaster.set(rayStart, this.rayDirection); + this.raycaster.near = 1; + this.raycaster.far = 300; + let intersects = this.raycaster.intersectObjects(this.heightScene.children); + if (intersects.length > 0){ + this.minHeight = intersects[0].point.y; + //this.targetPosition.y = this.minHeight; + } else { + //this.targetPosition.y = 0; + } + + rayStart.set(this.camera.position.x, 300, this.camera.position.z); + this.raycaster.set(rayStart, this.rayDirection); + intersects.length = 0; + intersects = this.raycaster.intersectObjects(this.heightScene.children); + if (intersects.length > 0){ + if (intersects[0].point.y > this.minHeight){ + this.minHeight = intersects[0].point.y; + } + } +}; + +BlueMap.Controls.prototype.updateMouseMoves = function (e) { + this.deltaMouse.set(this.lastMouse.x - this.mouse.x, this.lastMouse.y - this.mouse.y); + + this.moveDelta.x = 0; + this.moveDelta.y = 0; + + if (this.keyStates[this.KEYS.UP]){ + this.moveDelta.y -= 20; + } + if (this.keyStates[this.KEYS.DOWN]){ + this.moveDelta.y += 20; + } + if (this.keyStates[this.KEYS.LEFT]){ + this.moveDelta.x -= 20; + } + if (this.keyStates[this.KEYS.RIGHT]){ + this.moveDelta.x += 20; + } + + if (this.state === this.STATES.MOVE) { + if (this.deltaMouse.x === 0 && this.deltaMouse.y === 0) return; + this.moveDelta.copy(this.deltaMouse); + } + + if (this.moveDelta.x !== 0 || this.moveDelta.y !== 0) { + this.moveDelta.rotateAround(BlueMap.utils.Vector2.ZERO, -this.direction); + this.targetPosition.set( + this.targetPosition.x + (this.moveDelta.x * this.distance / this.element.clientHeight * this.settings.move.speed), + this.targetPosition.y, + this.targetPosition.z + (this.moveDelta.y * this.distance / this.element.clientHeight * this.settings.move.speed) + ); + } + + if (this.state === this.STATES.ORBIT) { + this.targetDirection += (this.deltaMouse.x / this.element.clientHeight * Math.PI); + this.targetAngle += (this.deltaMouse.y / this.element.clientHeight * Math.PI); + } + + this.lastMouse.copy(this.mouse); +}; + +BlueMap.Controls.prototype.onMouseWheel = function (e) { + if (e.deltaY > 0) { + this.targetDistance *= this.settings.zoom.speed; + } else if (e.deltaY < 0) { + this.targetDistance /= this.settings.zoom.speed; + } + + if (this.targetDistance < this.settings.zoom.min) this.targetDistance = this.settings.zoom.min; + if (this.targetDistance > this.settings.zoom.max) this.targetDistance = this.settings.zoom.max; +}; + +BlueMap.Controls.prototype.onMouseMove = function (e) { + this.mouse.set(e.clientX, e.clientY); + + if (this.state !== this.STATES.NONE){ + e.preventDefault(); + } +}; + +BlueMap.Controls.prototype.onMouseDown = function (e) { + if (this.state !== this.STATES.NONE) return; + + switch (e.button) { + case this.KEYS.MOVE : + this.state = this.STATES.MOVE; + e.preventDefault(); + break; + case this.KEYS.ORBIT : + this.state = this.STATES.ORBIT; + e.preventDefault(); + break; + } +}; + +BlueMap.Controls.prototype.onMouseUp = function (e) { + if (this.state === this.STATES.NONE) return; + + switch (e.button) { + case this.KEYS.MOVE : + if (this.state === this.STATES.MOVE) this.state = this.STATES.NONE; + break; + case this.KEYS.ORBIT : + if (this.state === this.STATES.ORBIT) this.state = this.STATES.NONE; + break; + } +}; + +BlueMap.Controls.prototype.onKeyDown = function (e) { + this.keyStates[e.keyCode] = true; +}; + +BlueMap.Controls.prototype.onKeyUp = function (e) { + this.keyStates[e.keyCode] = false; +}; + +// ###### Modules ###### +BlueMap.Module = { + getTopRightElement: function(blueMap){ + let element = $("#bluemap-topright"); + + if (element.length === 0){ + element = $('
    ').appendTo(blueMap.element); + } + + return element; + }, + + getTopLeftElement: function(blueMap){ + let element = $("#bluemap-topleft"); + + if (element.length === 0){ + element = $('
    ').appendTo(blueMap.element); + } + + return element; + } +}; + +// ###### Modules.MapMenu ###### +BlueMap.Module.MapMenu = function (blueMap) { + let scope = this; + + this.bluemap = blueMap; + let maps = this.bluemap.settings; + + $("#bluemap-mapmenu").remove(); + this.element = $('').appendTo(BlueMap.Module.getTopLeftElement(blueMap)); + + let dropdown = $('').appendTo(this.element); + this.maplist = $('
      ').appendTo(dropdown); + + for (mapId in maps) { + if (!maps.hasOwnProperty(mapId)) continue; + + let map = maps[mapId]; + $('

      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�PFh?183Ne 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%0DNBFl_k(YV`&E)zIr*rQN1$*bpr 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 literal 0 HcmV?d00001 diff --git a/BlueMapCore/src/main/resources/biomes.json b/BlueMapCore/src/main/resources/biomes.json new file mode 100644 index 00000000..946c0b47 --- /dev/null +++ b/BlueMapCore/src/main/resources/biomes.json @@ -0,0 +1,452 @@ +{ + "ocean": { + "id": 0, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "plains": { + "id": 1, + "humidity": 0.4, + "temp": 0.8, + "watercolor": 4159204 + }, + "desert": { + "id": 2, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "mountains": { + "id": 3, + "humidity": 0.3, + "temp": 0.2, + "watercolor": 4159204 + }, + "forest": { + "id": 4, + "humidity": 0.8, + "temp": 0.7, + "watercolor": 4159204 + }, + "taiga": { + "id": 5, + "humidity": 0.8, + "temp": 0.25, + "watercolor": 4159204 + }, + "swamp": { + "id": 6, + "humidity": 0.9, + "temp": 0.8, + "watercolor": 6388580 + }, + "river": { + "id": 7, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "nether": { + "id": 8, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "the_end": { + "id": 9, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "frozen_ocean": { + "id": 10, + "humidity": 0.5, + "temp": 0.0, + "watercolor": 3750089 + }, + "frozen_river": { + "id": 11, + "humidity": 0.5, + "temp": 0.0, + "watercolor": 3750089 + }, + "snowy_tundra": { + "id": 12, + "humidity": 0.5, + "temp": 0.0, + "watercolor": 4159204 + }, + "snowy_mountains": { + "id": 13, + "humidity": 0.5, + "temp": 0.0, + "watercolor": 4159204 + }, + "mushroom_fields": { + "id": 14, + "humidity": 1.0, + "temp": 0.9, + "watercolor": 4159204 + }, + "mushroom_field_shore": { + "id": 15, + "humidity": 1.0, + "temp": 0.9, + "watercolor": 4159204 + }, + "beach": { + "id": 16, + "humidity": 0.4, + "temp": 0.8, + "watercolor": 4159204 + }, + "desert_hills": { + "id": 17, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "wooded_hills": { + "id": 18, + "humidity": 0.8, + "temp": 0.7, + "watercolor": 4159204 + }, + "taiga_hills": { + "id": 19, + "humidity": 0.8, + "temp": 0.25, + "watercolor": 4159204 + }, + "mountain_edge": { + "id": 20, + "humidity": 0.3, + "temp": 0.2, + "watercolor": 4159204 + }, + "jungle": { + "id": 21, + "humidity": 0.9, + "temp": 0.95, + "watercolor": 4159204 + }, + "jungle_hills": { + "id": 22, + "humidity": 0.9, + "temp": 0.95, + "watercolor": 4159204 + }, + "jungle_edge": { + "id": 23, + "humidity": 0.8, + "temp": 0.95, + "watercolor": 4159204 + }, + "deep_ocean": { + "id": 24, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "stone_shore": { + "id": 25, + "humidity": 0.3, + "temp": 0.2, + "watercolor": 4159204 + }, + "snowy_beach": { + "id": 26, + "humidity": 0.3, + "temp": 0.05, + "watercolor": 4020182 + }, + "birch_forest": { + "id": 27, + "humidity": 0.6, + "temp": 0.6, + "watercolor": 4159204 + }, + "birch_forest_hills": { + "id": 28, + "humidity": 0.6, + "temp": 0.6, + "watercolor": 4159204 + }, + "dark_forest": { + "id": 29, + "humidity": 0.8, + "temp": 0.7, + "watercolor": 4159204 + }, + "snowy_taiga": { + "id": 30, + "humidity": 0.4, + "temp": -0.5, + "watercolor": 4020182 + }, + "snowy_taiga_hills": { + "id": 31, + "humidity": 0.4, + "temp": -0.5, + "watercolor": 4020182 + }, + "giant_tree_taiga": { + "id": 32, + "humidity": 0.8, + "temp": 0.3, + "watercolor": 4159204 + }, + "giant_tree_taiga_hills": { + "id": 33, + "humidity": 0.8, + "temp": 0.3, + "watercolor": 4159204 + }, + "wooded_mountains": { + "id": 34, + "humidity": 0.3, + "temp": 0.2, + "watercolor": 4159204 + }, + "savanna": { + "id": 35, + "humidity": 0.0, + "temp": 1.2, + "watercolor": 4159204 + }, + "savanna_plateau": { + "id": 36, + "humidity": 0.0, + "temp": 1.0, + "watercolor": 4159204 + }, + "badlands": { + "id": 37, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "wooded_badlands_plateau": { + "id": 38, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "badlands_plateau": { + "id": 39, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "small_end_islands": { + "id": 40, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "end_midlands": { + "id": 41, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "end_highlands": { + "id": 42, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "end_barrens": { + "id": 43, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "warm_ocean": { + "id": 44, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4445678 + }, + "lukewarm_ocean": { + "id": 45, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4566514 + }, + "cold_ocean": { + "id": 46, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4020182 + }, + "deep_warm_ocean": { + "id": 47, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4445678 + }, + "deep_lukewarm_ocean": { + "id": 48, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4566514 + }, + "deep_cold_ocean": { + "id": 49, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4020182 + }, + "deep_frozen_ocean": { + "id": 50, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 3750089 + }, + "the_void": { + "id": 127, + "humidity": 0.5, + "temp": 0.5, + "watercolor": 4159204 + }, + "sunflower_plains": { + "id": 129, + "humidity": 0.4, + "temp": 0.8, + "watercolor": 4159204 + }, + "desert_lakes": { + "id": 130, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "gravelly_mountains": { + "id": 131, + "humidity": 0.3, + "temp": 0.2, + "watercolor": 4159204 + }, + "flower_forest": { + "id": 132, + "humidity": 0.8, + "temp": 0.7, + "watercolor": 4159204 + }, + "taiga_mountains": { + "id": 133, + "humidity": 0.8, + "temp": 0.25, + "watercolor": 4159204 + }, + "swamp_hills": { + "id": 134, + "humidity": 0.9, + "temp": 0.8, + "watercolor": 6388580 + }, + "ice_spikes": { + "id": 140, + "humidity": 0.5, + "temp": 0.0, + "watercolor": 4159204 + }, + "modified_jungle": { + "id": 149, + "humidity": 0.9, + "temp": 0.95, + "watercolor": 4159204 + }, + "modified_jungle_edge": { + "id": 151, + "humidity": 0.8, + "temp": 0.95, + "watercolor": 4159204 + }, + "tall_birch_forest": { + "id": 155, + "humidity": 0.6, + "temp": 0.6, + "watercolor": 4159204 + }, + "tall_birch_hills": { + "id": 156, + "humidity": 0.6, + "temp": 0.6, + "watercolor": 4159204 + }, + "dark_forest_hills": { + "id": 157, + "humidity": 0.8, + "temp": 0.7, + "watercolor": 4159204 + }, + "snowy_taiga_mountains": { + "id": 158, + "humidity": 0.4, + "temp": -0.5, + "watercolor": 4020182 + }, + "giant_spruce_taiga": { + "id": 160, + "humidity": 0.8, + "temp": 0.25, + "watercolor": 4159204 + }, + "giant_spruce_taiga_hills": { + "id": 161, + "humidity": 0.8, + "temp": 0.25, + "watercolor": 4159204 + }, + "modified_gravelly_mountains": { + "id": 162, + "humidity": 0.3, + "temp": 0.2, + "watercolor": 4159204 + }, + "shattered_savanna": { + "id": 163, + "humidity": 0.0, + "temp": 1.1, + "watercolor": 4159204 + }, + "shattered_savanna_plateau": { + "id": 164, + "humidity": 0.0, + "temp": 1.0, + "watercolor": 4159204 + }, + "eroded_badlands": { + "id": 165, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "modified_wooded_badlands_plateau": { + "id": 166, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "modified_badlands_plateau": { + "id": 167, + "humidity": 0.0, + "temp": 2.0, + "watercolor": 4159204 + }, + "bamboo_jungle": { + "id": 168, + "humidity": 0.9, + "temp": 0.95, + "watercolor": 4159204 + }, + "bamboo_jungle_hills": { + "id": 169, + "humidity": 0.9, + "temp": 0.95, + "watercolor": 4159204 + } +} diff --git a/BlueMapCore/src/main/resources/blockColors.json b/BlueMapCore/src/main/resources/blockColors.json new file mode 100644 index 00000000..b2a2e945 --- /dev/null +++ b/BlueMapCore/src/main/resources/blockColors.json @@ -0,0 +1,11 @@ +{ + "default": "#foliage", + "grass_block" : "#grass", + "grass" : "#grass", + "tall_grass" : "#grass", + "fern" : "#grass", + "large_fern" : "#grass", + "redstone_wire" : "ff0000", + "birch_leaves" : "86a863", + "spruce_leaves" : "51946b" +} \ No newline at end of file diff --git a/BlueMapCore/src/main/resources/blockIdMappings.json b/BlueMapCore/src/main/resources/blockIdMappings.json new file mode 100644 index 00000000..232db251 --- /dev/null +++ b/BlueMapCore/src/main/resources/blockIdMappings.json @@ -0,0 +1,1487 @@ +{ + "1:0": "minecraft:stone", + "1:1": "minecraft:granite", + "1:2": "minecraft:polished_granite", + "1:3": "minecraft:diorite", + "1:4": "minecraft:polished_diorite", + "1:5": "minecraft:andesite", + "1:6": "minecraft:polished_andesite", + "2:0": "minecraft:grass_block[snowy=false]", + "3:0": "minecraft:dirt", + "3:1": "minecraft:coarse_dirt", + "3:2": "minecraft:podzol[snowy=false]", + "4:0": "minecraft:cobblestone", + "5:0": "minecraft:oak_planks", + "5:1": "minecraft:spruce_planks", + "5:2": "minecraft:birch_planks", + "5:3": "minecraft:jungle_planks", + "5:4": "minecraft:acacia_planks", + "5:5": "minecraft:dark_oak_planks", + "6:0": "minecraft:oak_sapling[stage=0]", + "6:1": "minecraft:spruce_sapling[stage=0]", + "6:2": "minecraft:birch_sapling[stage=0]", + "6:3": "minecraft:jungle_sapling[stage=0]", + "6:4": "minecraft:acacia_sapling[stage=0]", + "6:5": "minecraft:dark_oak_sapling[stage=0]", + "6:8": "minecraft:oak_sapling[stage=1]", + "6:9": "minecraft:spruce_sapling[stage=1]", + "6:10": "minecraft:birch_sapling[stage=1]", + "6:11": "minecraft:jungle_sapling[stage=1]", + "6:12": "minecraft:acacia_sapling[stage=1]", + "6:13": "minecraft:dark_oak_sapling[stage=1]", + "7:0": "minecraft:bedrock", + "8:0": "minecraft:water[level=0]", + "8:1": "minecraft:water[level=1]", + "8:2": "minecraft:water[level=2]", + "8:3": "minecraft:water[level=3]", + "8:4": "minecraft:water[level=4]", + "8:5": "minecraft:water[level=5]", + "8:6": "minecraft:water[level=6]", + "8:7": "minecraft:water[level=7]", + "8:8": "minecraft:water[level=8]", + "8:9": "minecraft:water[level=9]", + "8:10": "minecraft:water[level=10]", + "8:11": "minecraft:water[level=11]", + "8:12": "minecraft:water[level=12]", + "8:13": "minecraft:water[level=13]", + "8:14": "minecraft:water[level=14]", + "8:15": "minecraft:water[level=15]", + "9:0": "minecraft:water[level=0]", + "9:1": "minecraft:water[level=1]", + "9:2": "minecraft:water[level=2]", + "9:3": "minecraft:water[level=3]", + "9:4": "minecraft:water[level=4]", + "9:5": "minecraft:water[level=5]", + "9:6": "minecraft:water[level=6]", + "9:7": "minecraft:water[level=7]", + "9:8": "minecraft:water[level=8]", + "9:9": "minecraft:water[level=9]", + "9:10": "minecraft:water[level=10]", + "9:11": "minecraft:water[level=11]", + "9:12": "minecraft:water[level=12]", + "9:13": "minecraft:water[level=13]", + "9:14": "minecraft:water[level=14]", + "9:15": "minecraft:water[level=15]", + "10:0": "minecraft:lava[level=0]", + "10:1": "minecraft:lava[level=1]", + "10:2": "minecraft:lava[level=2]", + "10:3": "minecraft:lava[level=3]", + "10:4": "minecraft:lava[level=4]", + "10:5": "minecraft:lava[level=5]", + "10:6": "minecraft:lava[level=6]", + "10:7": "minecraft:lava[level=7]", + "10:8": "minecraft:lava[level=8]", + "10:9": "minecraft:lava[level=9]", + "10:10": "minecraft:lava[level=10]", + "10:11": "minecraft:lava[level=11]", + "10:12": "minecraft:lava[level=12]", + "10:13": "minecraft:lava[level=13]", + "10:14": "minecraft:lava[level=14]", + "10:15": "minecraft:lava[level=15]", + "11:0": "minecraft:lava[level=0]", + "11:1": "minecraft:lava[level=1]", + "11:2": "minecraft:lava[level=2]", + "11:3": "minecraft:lava[level=3]", + "11:4": "minecraft:lava[level=4]", + "11:5": "minecraft:lava[level=5]", + "11:6": "minecraft:lava[level=6]", + "11:7": "minecraft:lava[level=7]", + "11:8": "minecraft:lava[level=8]", + "11:9": "minecraft:lava[level=9]", + "11:10": "minecraft:lava[level=10]", + "11:11": "minecraft:lava[level=11]", + "11:12": "minecraft:lava[level=12]", + "11:13": "minecraft:lava[level=13]", + "11:14": "minecraft:lava[level=14]", + "11:15": "minecraft:lava[level=15]", + "12:0": "minecraft:sand", + "12:1": "minecraft:red_sand", + "13:0": "minecraft:gravel", + "14:0": "minecraft:gold_ore", + "15:0": "minecraft:iron_ore", + "16:0": "minecraft:coal_ore", + "17:0": "minecraft:oak_log[axis=y]", + "17:1": "minecraft:spruce_log[axis=y]", + "17:2": "minecraft:birch_log[axis=y]", + "17:3": "minecraft:jungle_log[axis=y]", + "17:4": "minecraft:oak_log[axis=x]", + "17:5": "minecraft:spruce_log[axis=x]", + "17:6": "minecraft:birch_log[axis=x]", + "17:7": "minecraft:jungle_log[axis=x]", + "17:8": "minecraft:oak_log[axis=z]", + "17:9": "minecraft:spruce_log[axis=z]", + "17:10": "minecraft:birch_log[axis=z]", + "17:11": "minecraft:jungle_log[axis=z]", + "17:12": "minecraft:oak_bark", + "17:13": "minecraft:spruce_bark", + "17:14": "minecraft:birch_bark", + "17:15": "minecraft:jungle_bark", + "18:0": "minecraft:oak_leaves[check_decay=false,decayable=true]", + "18:1": "minecraft:spruce_leaves[check_decay=false,decayable=true]", + "18:2": "minecraft:birch_leaves[check_decay=false,decayable=true]", + "18:3": "minecraft:jungle_leaves[check_decay=false,decayable=true]", + "18:4": "minecraft:oak_leaves[check_decay=false,decayable=false]", + "18:5": "minecraft:spruce_leaves[check_decay=false,decayable=false]", + "18:6": "minecraft:birch_leaves[check_decay=false,decayable=false]", + "18:7": "minecraft:jungle_leaves[check_decay=false,decayable=false]", + "18:8": "minecraft:oak_leaves[check_decay=true,decayable=true]", + "18:9": "minecraft:spruce_leaves[check_decay=true,decayable=true]", + "18:10": "minecraft:birch_leaves[check_decay=true,decayable=true]", + "18:11": "minecraft:jungle_leaves[check_decay=true,decayable=true]", + "18:12": "minecraft:oak_leaves[check_decay=true,decayable=false]", + "18:13": "minecraft:spruce_leaves[check_decay=true,decayable=false]", + "18:14": "minecraft:birch_leaves[check_decay=true,decayable=false]", + "18:15": "minecraft:jungle_leaves[check_decay=true,decayable=false]", + "19:0": "minecraft:sponge", + "19:1": "minecraft:wet_sponge", + "20:0": "minecraft:glass", + "21:0": "minecraft:lapis_ore", + "22:0": "minecraft:lapis_block", + "23:0": "minecraft:dispenser[facing=down,triggered=false]", + "23:1": "minecraft:dispenser[facing=up,triggered=false]", + "23:2": "minecraft:dispenser[facing=north,triggered=false]", + "23:3": "minecraft:dispenser[facing=south,triggered=false]", + "23:4": "minecraft:dispenser[facing=west,triggered=false]", + "23:5": "minecraft:dispenser[facing=east,triggered=false]", + "23:8": "minecraft:dispenser[facing=down,triggered=true]", + "23:9": "minecraft:dispenser[facing=up,triggered=true]", + "23:10": "minecraft:dispenser[facing=north,triggered=true]", + "23:11": "minecraft:dispenser[facing=south,triggered=true]", + "23:12": "minecraft:dispenser[facing=west,triggered=true]", + "23:13": "minecraft:dispenser[facing=east,triggered=true]", + "24:0": "minecraft:sandstone", + "24:1": "minecraft:chiseled_sandstone", + "24:2": "minecraft:cut_sandstone", + "25:0": "minecraft:note_block", + "27:0": "minecraft:powered_rail[powered=false,shape=north_south]", + "27:1": "minecraft:powered_rail[powered=false,shape=east_west]", + "27:2": "minecraft:powered_rail[powered=false,shape=ascending_east]", + "27:3": "minecraft:powered_rail[powered=false,shape=ascending_west]", + "27:4": "minecraft:powered_rail[powered=false,shape=ascending_north]", + "27:5": "minecraft:powered_rail[powered=false,shape=ascending_south]", + "27:8": "minecraft:powered_rail[powered=true,shape=north_south]", + "27:9": "minecraft:powered_rail[powered=true,shape=east_west]", + "27:10": "minecraft:powered_rail[powered=true,shape=ascending_east]", + "27:11": "minecraft:powered_rail[powered=true,shape=ascending_west]", + "27:12": "minecraft:powered_rail[powered=true,shape=ascending_north]", + "27:13": "minecraft:powered_rail[powered=true,shape=ascending_south]", + "28:0": "minecraft:detector_rail[powered=false,shape=north_south]", + "28:1": "minecraft:detector_rail[powered=false,shape=east_west]", + "28:2": "minecraft:detector_rail[powered=false,shape=ascending_east]", + "28:3": "minecraft:detector_rail[powered=false,shape=ascending_west]", + "28:4": "minecraft:detector_rail[powered=false,shape=ascending_north]", + "28:5": "minecraft:detector_rail[powered=false,shape=ascending_south]", + "28:8": "minecraft:detector_rail[powered=true,shape=north_south]", + "28:9": "minecraft:detector_rail[powered=true,shape=east_west]", + "28:10": "minecraft:detector_rail[powered=true,shape=ascending_east]", + "28:11": "minecraft:detector_rail[powered=true,shape=ascending_west]", + "28:12": "minecraft:detector_rail[powered=true,shape=ascending_north]", + "28:13": "minecraft:detector_rail[powered=true,shape=ascending_south]", + "29:0": "minecraft:sticky_piston[facing=down,extended=false]", + "29:1": "minecraft:sticky_piston[facing=up,extended=false]", + "29:2": "minecraft:sticky_piston[facing=north,extended=false]", + "29:3": "minecraft:sticky_piston[facing=south,extended=false]", + "29:4": "minecraft:sticky_piston[facing=west,extended=false]", + "29:5": "minecraft:sticky_piston[facing=east,extended=false]", + "29:8": "minecraft:sticky_piston[facing=down,extended=true]", + "29:9": "minecraft:sticky_piston[facing=up,extended=true]", + "29:10": "minecraft:sticky_piston[facing=north,extended=true]", + "29:11": "minecraft:sticky_piston[facing=south,extended=true]", + "29:12": "minecraft:sticky_piston[facing=west,extended=true]", + "29:13": "minecraft:sticky_piston[facing=east,extended=true]", + "30:0": "minecraft:cobweb", + "31:0": "minecraft:dead_bush", + "31:1": "minecraft:grass", + "31:2": "minecraft:fern", + "32:0": "minecraft:dead_bush", + "33:0": "minecraft:piston[facing=down,extended=false]", + "33:1": "minecraft:piston[facing=up,extended=false]", + "33:2": "minecraft:piston[facing=north,extended=false]", + "33:3": "minecraft:piston[facing=south,extended=false]", + "33:4": "minecraft:piston[facing=west,extended=false]", + "33:5": "minecraft:piston[facing=east,extended=false]", + "33:8": "minecraft:piston[facing=down,extended=true]", + "33:9": "minecraft:piston[facing=up,extended=true]", + "33:10": "minecraft:piston[facing=north,extended=true]", + "33:11": "minecraft:piston[facing=south,extended=true]", + "33:12": "minecraft:piston[facing=west,extended=true]", + "33:13": "minecraft:piston[facing=east,extended=true]", + "34:0": "minecraft:piston_head[facing=down,short=false,type=normal]", + "34:1": "minecraft:piston_head[facing=up,short=false,type=normal]", + "34:2": "minecraft:piston_head[facing=north,short=false,type=normal]", + "34:3": "minecraft:piston_head[facing=south,short=false,type=normal]", + "34:4": "minecraft:piston_head[facing=west,short=false,type=normal]", + "34:5": "minecraft:piston_head[facing=east,short=false,type=normal]", + "34:8": "minecraft:piston_head[facing=down,short=false,type=sticky]", + "34:9": "minecraft:piston_head[facing=up,short=false,type=sticky]", + "34:10": "minecraft:piston_head[facing=north,short=false,type=sticky]", + "34:11": "minecraft:piston_head[facing=south,short=false,type=sticky]", + "34:12": "minecraft:piston_head[facing=west,short=false,type=sticky]", + "34:13": "minecraft:piston_head[facing=east,short=false,type=sticky]", + "35:0": "minecraft:white_wool", + "35:1": "minecraft:orange_wool", + "35:2": "minecraft:magenta_wool", + "35:3": "minecraft:light_blue_wool", + "35:4": "minecraft:yellow_wool", + "35:5": "minecraft:lime_wool", + "35:6": "minecraft:pink_wool", + "35:7": "minecraft:gray_wool", + "35:8": "minecraft:light_gray_wool", + "35:9": "minecraft:cyan_wool", + "35:10": "minecraft:purple_wool", + "35:11": "minecraft:blue_wool", + "35:12": "minecraft:brown_wool", + "35:13": "minecraft:green_wool", + "35:14": "minecraft:red_wool", + "35:15": "minecraft:black_wool", + "37:0": "minecraft:dandelion", + "38:0": "minecraft:poppy", + "38:1": "minecraft:blue_orchid", + "38:2": "minecraft:allium", + "38:3": "minecraft:azure_bluet", + "38:4": "minecraft:red_tulip", + "38:5": "minecraft:orange_tulip", + "38:6": "minecraft:white_tulip", + "38:7": "minecraft:pink_tulip", + "38:8": "minecraft:oxeye_daisy", + "39:0": "minecraft:brown_mushroom", + "40:0": "minecraft:red_mushroom", + "41:0": "minecraft:gold_block", + "42:0": "minecraft:iron_block", + "43:0": "minecraft:stone_slab[type=double]", + "43:1": "minecraft:sandstone_slab[type=double]", + "43:2": "minecraft:petrified_oak_slab[type=double]", + "43:3": "minecraft:cobblestone_slab[type=double]", + "43:4": "minecraft:brick_slab[type=double]", + "43:5": "minecraft:stone_brick_slab[type=double]", + "43:6": "minecraft:nether_brick_slab[type=double]", + "43:7": "minecraft:quartz_slab[type=double]", + "43:8": "minecraft:smooth_stone", + "43:9": "minecraft:smooth_sandstone", + "43:10": "minecraft:petrified_oak_slab[type=double]", + "43:11": "minecraft:cobblestone_slab[type=double]", + "43:12": "minecraft:brick_slab[type=double]", + "43:13": "minecraft:stone_brick_slab[type=double]", + "43:14": "minecraft:nether_brick_slab[type=double]", + "43:15": "minecraft:smooth_quartz", + "44:0": "minecraft:stone_slab[type=bottom]", + "44:1": "minecraft:sandstone_slab[type=bottom]", + "44:2": "minecraft:petrified_oak_slab[type=bottom]", + "44:3": "minecraft:cobblestone_slab[type=bottom]", + "44:4": "minecraft:brick_slab[type=bottom]", + "44:5": "minecraft:stone_brick_slab[type=bottom]", + "44:6": "minecraft:nether_brick_slab[type=bottom]", + "44:7": "minecraft:quartz_slab[type=bottom]", + "44:8": "minecraft:stone_slab[type=top]", + "44:9": "minecraft:sandstone_slab[type=top]", + "44:10": "minecraft:petrified_oak_slab[type=top]", + "44:11": "minecraft:cobblestone_slab[type=top]", + "44:12": "minecraft:brick_slab[type=top]", + "44:13": "minecraft:stone_brick_slab[type=top]", + "44:14": "minecraft:nether_brick_slab[type=top]", + "44:15": "minecraft:quartz_slab[type=top]", + "45:0": "minecraft:bricks", + "46:0": "minecraft:tnt[unstable=false]", + "46:1": "minecraft:tnt[unstable=true]", + "47:0": "minecraft:bookshelf", + "48:0": "minecraft:mossy_cobblestone", + "49:0": "minecraft:obsidian", + "50:1": "minecraft:wall_torch[facing=east]", + "50:2": "minecraft:wall_torch[facing=west]", + "50:3": "minecraft:wall_torch[facing=south]", + "50:4": "minecraft:wall_torch[facing=north]", + "50:5": "minecraft:torch", + "51:0": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=0]", + "51:1": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=1]", + "51:2": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=2]", + "51:3": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=3]", + "51:4": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=4]", + "51:5": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=5]", + "51:6": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=6]", + "51:7": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=7]", + "51:8": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=8]", + "51:9": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=9]", + "51:10": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=10]", + "51:11": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=11]", + "51:12": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=12]", + "51:13": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=13]", + "51:14": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=14]", + "51:15": "minecraft:fire[east=false,south=false,north=false,west=false,up=false,age=15]", + "52:0": "minecraft:mob_spawner", + "53:0": "minecraft:oak_stairs[facing=east,half=bottom,shape=straight]", + "53:1": "minecraft:oak_stairs[facing=west,half=bottom,shape=straight]", + "53:2": "minecraft:oak_stairs[facing=south,half=bottom,shape=straight]", + "53:3": "minecraft:oak_stairs[facing=north,half=bottom,shape=straight]", + "53:4": "minecraft:oak_stairs[facing=east,half=top,shape=straight]", + "53:5": "minecraft:oak_stairs[facing=west,half=top,shape=straight]", + "53:6": "minecraft:oak_stairs[facing=south,half=top,shape=straight]", + "53:7": "minecraft:oak_stairs[facing=north,half=top,shape=straight]", + "55:0": "minecraft:redstone_wire[west=none,east=none,power=0,south=none,north=none]", + "55:1": "minecraft:redstone_wire[west=none,east=none,power=1,south=none,north=none]", + "55:2": "minecraft:redstone_wire[west=none,east=none,power=2,south=none,north=none]", + "55:3": "minecraft:redstone_wire[west=none,east=none,power=3,south=none,north=none]", + "55:4": "minecraft:redstone_wire[west=none,east=none,power=4,south=none,north=none]", + "55:5": "minecraft:redstone_wire[west=none,east=none,power=5,south=none,north=none]", + "55:6": "minecraft:redstone_wire[west=none,east=none,power=6,south=none,north=none]", + "55:7": "minecraft:redstone_wire[west=none,east=none,power=7,south=none,north=none]", + "55:8": "minecraft:redstone_wire[west=none,east=none,power=8,south=none,north=none]", + "55:9": "minecraft:redstone_wire[west=none,east=none,power=9,south=none,north=none]", + "55:10": "minecraft:redstone_wire[west=none,east=none,power=10,south=none,north=none]", + "55:11": "minecraft:redstone_wire[west=none,east=none,power=11,south=none,north=none]", + "55:12": "minecraft:redstone_wire[west=none,east=none,power=12,south=none,north=none]", + "55:13": "minecraft:redstone_wire[west=none,east=none,power=13,south=none,north=none]", + "55:14": "minecraft:redstone_wire[west=none,east=none,power=14,south=none,north=none]", + "55:15": "minecraft:redstone_wire[west=none,east=none,power=15,south=none,north=none]", + "56:0": "minecraft:diamond_ore", + "57:0": "minecraft:diamond_block", + "58:0": "minecraft:crafting_table", + "59:0": "minecraft:wheat[age=0]", + "59:1": "minecraft:wheat[age=1]", + "59:2": "minecraft:wheat[age=2]", + "59:3": "minecraft:wheat[age=3]", + "59:4": "minecraft:wheat[age=4]", + "59:5": "minecraft:wheat[age=5]", + "59:6": "minecraft:wheat[age=6]", + "59:7": "minecraft:wheat[age=7]", + "60:0": "minecraft:farmland[moisture=0]", + "60:1": "minecraft:farmland[moisture=1]", + "60:2": "minecraft:farmland[moisture=2]", + "60:3": "minecraft:farmland[moisture=3]", + "60:4": "minecraft:farmland[moisture=4]", + "60:5": "minecraft:farmland[moisture=5]", + "60:6": "minecraft:farmland[moisture=6]", + "60:7": "minecraft:farmland[moisture=7]", + "61:2": "minecraft:furnace[facing=north,lit=false]", + "61:3": "minecraft:furnace[facing=south,lit=false]", + "61:4": "minecraft:furnace[facing=west,lit=false]", + "61:5": "minecraft:furnace[facing=east,lit=false]", + "62:2": "minecraft:furnace[facing=north,lit=true]", + "62:3": "minecraft:furnace[facing=south,lit=true]", + "62:4": "minecraft:furnace[facing=west,lit=true]", + "62:5": "minecraft:furnace[facing=east,lit=true]", + "64:0": "minecraft:oak_door[hinge=right,facing=east,half=lower,powered=false,open=false]", + "64:1": "minecraft:oak_door[hinge=right,facing=south,half=lower,powered=false,open=false]", + "64:2": "minecraft:oak_door[hinge=right,facing=west,half=lower,powered=false,open=false]", + "64:3": "minecraft:oak_door[hinge=right,facing=north,half=lower,powered=false,open=false]", + "64:4": "minecraft:oak_door[hinge=right,facing=east,half=lower,powered=false,open=true]", + "64:5": "minecraft:oak_door[hinge=right,facing=south,half=lower,powered=false,open=true]", + "64:6": "minecraft:oak_door[hinge=right,facing=west,half=lower,powered=false,open=true]", + "64:7": "minecraft:oak_door[hinge=right,facing=north,half=lower,powered=false,open=true]", + "64:8": "minecraft:oak_door[hinge=left,facing=east,half=upper,powered=false,open=false]", + "64:9": "minecraft:oak_door[hinge=right,facing=east,half=upper,powered=false,open=false]", + "64:10": "minecraft:oak_door[hinge=left,facing=east,half=upper,powered=true,open=false]", + "64:11": "minecraft:oak_door[hinge=right,facing=east,half=upper,powered=true,open=false]", + "65:2": "minecraft:ladder[facing=north]", + "65:3": "minecraft:ladder[facing=south]", + "65:4": "minecraft:ladder[facing=west]", + "65:5": "minecraft:ladder[facing=east]", + "66:0": "minecraft:rail[shape=north_south]", + "66:1": "minecraft:rail[shape=east_west]", + "66:2": "minecraft:rail[shape=ascending_east]", + "66:3": "minecraft:rail[shape=ascending_west]", + "66:4": "minecraft:rail[shape=ascending_north]", + "66:5": "minecraft:rail[shape=ascending_south]", + "66:6": "minecraft:rail[shape=south_east]", + "66:7": "minecraft:rail[shape=south_west]", + "66:8": "minecraft:rail[shape=north_west]", + "66:9": "minecraft:rail[shape=north_east]", + "67:0": "minecraft:cobblestone_stairs[facing=east,half=bottom,shape=straight]", + "67:1": "minecraft:cobblestone_stairs[facing=west,half=bottom,shape=straight]", + "67:2": "minecraft:cobblestone_stairs[facing=south,half=bottom,shape=straight]", + "67:3": "minecraft:cobblestone_stairs[facing=north,half=bottom,shape=straight]", + "67:4": "minecraft:cobblestone_stairs[facing=east,half=top,shape=straight]", + "67:5": "minecraft:cobblestone_stairs[facing=west,half=top,shape=straight]", + "67:6": "minecraft:cobblestone_stairs[facing=south,half=top,shape=straight]", + "67:7": "minecraft:cobblestone_stairs[facing=north,half=top,shape=straight]", + "69:0": "minecraft:lever[facing=west,face=ceiling,powered=false]", + "69:1": "minecraft:lever[facing=east,face=wall,powered=false]", + "69:2": "minecraft:lever[facing=west,face=wall,powered=false]", + "69:3": "minecraft:lever[facing=south,face=wall,powered=false]", + "69:4": "minecraft:lever[facing=north,face=wall,powered=false]", + "69:5": "minecraft:lever[facing=north,face=floor,powered=false]", + "69:6": "minecraft:lever[facing=west,face=floor,powered=false]", + "69:7": "minecraft:lever[facing=north,face=ceiling,powered=false]", + "69:8": "minecraft:lever[facing=west,face=ceiling,powered=true]", + "69:9": "minecraft:lever[facing=east,face=wall,powered=true]", + "69:10": "minecraft:lever[facing=west,face=wall,powered=true]", + "69:11": "minecraft:lever[facing=south,face=wall,powered=true]", + "69:12": "minecraft:lever[facing=north,face=wall,powered=true]", + "69:13": "minecraft:lever[facing=north,face=floor,powered=true]", + "69:14": "minecraft:lever[facing=west,face=floor,powered=true]", + "69:15": "minecraft:lever[facing=north,face=ceiling,powered=true]", + "70:0": "minecraft:stone_pressure_plate[powered=false]", + "70:1": "minecraft:stone_pressure_plate[powered=true]", + "71:0": "minecraft:iron_door[hinge=right,facing=east,half=lower,powered=false,open=false]", + "71:1": "minecraft:iron_door[hinge=right,facing=south,half=lower,powered=false,open=false]", + "71:2": "minecraft:iron_door[hinge=right,facing=west,half=lower,powered=false,open=false]", + "71:3": "minecraft:iron_door[hinge=right,facing=north,half=lower,powered=false,open=false]", + "71:4": "minecraft:iron_door[hinge=right,facing=east,half=lower,powered=false,open=true]", + "71:5": "minecraft:iron_door[hinge=right,facing=south,half=lower,powered=false,open=true]", + "71:6": "minecraft:iron_door[hinge=right,facing=west,half=lower,powered=false,open=true]", + "71:7": "minecraft:iron_door[hinge=right,facing=north,half=lower,powered=false,open=true]", + "71:8": "minecraft:iron_door[hinge=left,facing=east,half=upper,powered=false,open=false]", + "71:9": "minecraft:iron_door[hinge=right,facing=east,half=upper,powered=false,open=false]", + "71:10": "minecraft:iron_door[hinge=left,facing=east,half=upper,powered=true,open=false]", + "71:11": "minecraft:iron_door[hinge=right,facing=east,half=upper,powered=true,open=false]", + "72:0": "minecraft:oak_pressure_plate[powered=false]", + "72:1": "minecraft:oak_pressure_plate[powered=true]", + "73:0": "minecraft:redstone_ore[lit=false]", + "74:0": "minecraft:redstone_ore[lit=true]", + "75:1": "minecraft:redstone_wall_torch[facing=east,lit=false]", + "75:2": "minecraft:redstone_wall_torch[facing=west,lit=false]", + "75:3": "minecraft:redstone_wall_torch[facing=south,lit=false]", + "75:4": "minecraft:redstone_wall_torch[facing=north,lit=false]", + "75:5": "minecraft:redstone_torch[lit=false]", + "76:1": "minecraft:redstone_wall_torch[facing=east,lit=true]", + "76:2": "minecraft:redstone_wall_torch[facing=west,lit=true]", + "76:3": "minecraft:redstone_wall_torch[facing=south,lit=true]", + "76:4": "minecraft:redstone_wall_torch[facing=north,lit=true]", + "76:5": "minecraft:redstone_torch[lit=true]", + "77:0": "minecraft:stone_button[facing=north,face=ceiling,powered=false]", + "77:1": "minecraft:stone_button[facing=east,face=wall,powered=false]", + "77:2": "minecraft:stone_button[facing=west,face=wall,powered=false]", + "77:3": "minecraft:stone_button[facing=south,face=wall,powered=false]", + "77:4": "minecraft:stone_button[facing=north,face=wall,powered=false]", + "77:5": "minecraft:stone_button[facing=north,face=floor,powered=false]", + "77:8": "minecraft:stone_button[facing=north,face=ceiling,powered=true]", + "77:9": "minecraft:stone_button[facing=east,face=wall,powered=true]", + "77:10": "minecraft:stone_button[facing=west,face=wall,powered=true]", + "77:11": "minecraft:stone_button[facing=south,face=wall,powered=true]", + "77:12": "minecraft:stone_button[facing=north,face=wall,powered=true]", + "77:13": "minecraft:stone_button[facing=north,face=floor,powered=true]", + "78:0": "minecraft:snow[layers=1]", + "78:1": "minecraft:snow[layers=2]", + "78:2": "minecraft:snow[layers=3]", + "78:3": "minecraft:snow[layers=4]", + "78:4": "minecraft:snow[layers=5]", + "78:5": "minecraft:snow[layers=6]", + "78:6": "minecraft:snow[layers=7]", + "78:7": "minecraft:snow[layers=8]", + "79:0": "minecraft:ice", + "80:0": "minecraft:snow_block", + "81:0": "minecraft:cactus[age=0]", + "81:1": "minecraft:cactus[age=1]", + "81:2": "minecraft:cactus[age=2]", + "81:3": "minecraft:cactus[age=3]", + "81:4": "minecraft:cactus[age=4]", + "81:5": "minecraft:cactus[age=5]", + "81:6": "minecraft:cactus[age=6]", + "81:7": "minecraft:cactus[age=7]", + "81:8": "minecraft:cactus[age=8]", + "81:9": "minecraft:cactus[age=9]", + "81:10": "minecraft:cactus[age=10]", + "81:11": "minecraft:cactus[age=11]", + "81:12": "minecraft:cactus[age=12]", + "81:13": "minecraft:cactus[age=13]", + "81:14": "minecraft:cactus[age=14]", + "81:15": "minecraft:cactus[age=15]", + "82:0": "minecraft:clay", + "83:0": "minecraft:sugar_cane[age=0]", + "83:1": "minecraft:sugar_cane[age=1]", + "83:2": "minecraft:sugar_cane[age=2]", + "83:3": "minecraft:sugar_cane[age=3]", + "83:4": "minecraft:sugar_cane[age=4]", + "83:5": "minecraft:sugar_cane[age=5]", + "83:6": "minecraft:sugar_cane[age=6]", + "83:7": "minecraft:sugar_cane[age=7]", + "83:8": "minecraft:sugar_cane[age=8]", + "83:9": "minecraft:sugar_cane[age=9]", + "83:10": "minecraft:sugar_cane[age=10]", + "83:11": "minecraft:sugar_cane[age=11]", + "83:12": "minecraft:sugar_cane[age=12]", + "83:13": "minecraft:sugar_cane[age=13]", + "83:14": "minecraft:sugar_cane[age=14]", + "83:15": "minecraft:sugar_cane[age=15]", + "84:0": "minecraft:jukebox[has_record=false]", + "84:1": "minecraft:jukebox[has_record=true]", + "85:0": "minecraft:oak_fence[west=false,east=false,south=false,north=false]", + "86:0": "minecraft:carved_pumpkin[facing=south]", + "86:1": "minecraft:carved_pumpkin[facing=west]", + "86:2": "minecraft:carved_pumpkin[facing=north]", + "86:3": "minecraft:carved_pumpkin[facing=east]", + "87:0": "minecraft:netherrack", + "88:0": "minecraft:soul_sand", + "89:0": "minecraft:glowstone", + "90:1": "minecraft:portal[axis=x]", + "90:2": "minecraft:portal[axis=z]", + "91:0": "minecraft:jack_o_lantern[facing=south]", + "91:1": "minecraft:jack_o_lantern[facing=west]", + "91:2": "minecraft:jack_o_lantern[facing=north]", + "91:3": "minecraft:jack_o_lantern[facing=east]", + "92:0": "minecraft:cake[bites=0]", + "92:1": "minecraft:cake[bites=1]", + "92:2": "minecraft:cake[bites=2]", + "92:3": "minecraft:cake[bites=3]", + "92:4": "minecraft:cake[bites=4]", + "92:5": "minecraft:cake[bites=5]", + "92:6": "minecraft:cake[bites=6]", + "93:0": "minecraft:repeater[facing=south,delay=1,powered=false,locked=false]", + "93:1": "minecraft:repeater[facing=west,delay=1,powered=false,locked=false]", + "93:2": "minecraft:repeater[facing=north,delay=1,powered=false,locked=false]", + "93:3": "minecraft:repeater[facing=east,delay=1,powered=false,locked=false]", + "93:4": "minecraft:repeater[facing=south,delay=2,powered=false,locked=false]", + "93:5": "minecraft:repeater[facing=west,delay=2,powered=false,locked=false]", + "93:6": "minecraft:repeater[facing=north,delay=2,powered=false,locked=false]", + "93:7": "minecraft:repeater[facing=east,delay=2,powered=false,locked=false]", + "93:8": "minecraft:repeater[facing=south,delay=3,powered=false,locked=false]", + "93:9": "minecraft:repeater[facing=west,delay=3,powered=false,locked=false]", + "93:10": "minecraft:repeater[facing=north,delay=3,powered=false,locked=false]", + "93:11": "minecraft:repeater[facing=east,delay=3,powered=false,locked=false]", + "93:12": "minecraft:repeater[facing=south,delay=4,powered=false,locked=false]", + "93:13": "minecraft:repeater[facing=west,delay=4,powered=false,locked=false]", + "93:14": "minecraft:repeater[facing=north,delay=4,powered=false,locked=false]", + "93:15": "minecraft:repeater[facing=east,delay=4,powered=false,locked=false]", + "94:0": "minecraft:repeater[facing=south,delay=1,powered=true,locked=false]", + "94:1": "minecraft:repeater[facing=west,delay=1,powered=true,locked=false]", + "94:2": "minecraft:repeater[facing=north,delay=1,powered=true,locked=false]", + "94:3": "minecraft:repeater[facing=east,delay=1,powered=true,locked=false]", + "94:4": "minecraft:repeater[facing=south,delay=2,powered=true,locked=false]", + "94:5": "minecraft:repeater[facing=west,delay=2,powered=true,locked=false]", + "94:6": "minecraft:repeater[facing=north,delay=2,powered=true,locked=false]", + "94:7": "minecraft:repeater[facing=east,delay=2,powered=true,locked=false]", + "94:8": "minecraft:repeater[facing=south,delay=3,powered=true,locked=false]", + "94:9": "minecraft:repeater[facing=west,delay=3,powered=true,locked=false]", + "94:10": "minecraft:repeater[facing=north,delay=3,powered=true,locked=false]", + "94:11": "minecraft:repeater[facing=east,delay=3,powered=true,locked=false]", + "94:12": "minecraft:repeater[facing=south,delay=4,powered=true,locked=false]", + "94:13": "minecraft:repeater[facing=west,delay=4,powered=true,locked=false]", + "94:14": "minecraft:repeater[facing=north,delay=4,powered=true,locked=false]", + "94:15": "minecraft:repeater[facing=east,delay=4,powered=true,locked=false]", + "95:0": "minecraft:white_stained_glass", + "95:1": "minecraft:orange_stained_glass", + "95:2": "minecraft:magenta_stained_glass", + "95:3": "minecraft:light_blue_stained_glass", + "95:4": "minecraft:yellow_stained_glass", + "95:5": "minecraft:lime_stained_glass", + "95:6": "minecraft:pink_stained_glass", + "95:7": "minecraft:gray_stained_glass", + "95:8": "minecraft:light_gray_stained_glass", + "95:9": "minecraft:cyan_stained_glass", + "95:10": "minecraft:purple_stained_glass", + "95:11": "minecraft:blue_stained_glass", + "95:12": "minecraft:brown_stained_glass", + "95:13": "minecraft:green_stained_glass", + "95:14": "minecraft:red_stained_glass", + "95:15": "minecraft:black_stained_glass", + "96:0": "minecraft:oak_trapdoor[facing=north,half=bottom,open=false]", + "96:1": "minecraft:oak_trapdoor[facing=south,half=bottom,open=false]", + "96:2": "minecraft:oak_trapdoor[facing=west,half=bottom,open=false]", + "96:3": "minecraft:oak_trapdoor[facing=east,half=bottom,open=false]", + "96:4": "minecraft:oak_trapdoor[facing=north,half=bottom,open=true]", + "96:5": "minecraft:oak_trapdoor[facing=south,half=bottom,open=true]", + "96:6": "minecraft:oak_trapdoor[facing=west,half=bottom,open=true]", + "96:7": "minecraft:oak_trapdoor[facing=east,half=bottom,open=true]", + "96:8": "minecraft:oak_trapdoor[facing=north,half=top,open=false]", + "96:9": "minecraft:oak_trapdoor[facing=south,half=top,open=false]", + "96:10": "minecraft:oak_trapdoor[facing=west,half=top,open=false]", + "96:11": "minecraft:oak_trapdoor[facing=east,half=top,open=false]", + "96:12": "minecraft:oak_trapdoor[facing=north,half=top,open=true]", + "96:13": "minecraft:oak_trapdoor[facing=south,half=top,open=true]", + "96:14": "minecraft:oak_trapdoor[facing=west,half=top,open=true]", + "96:15": "minecraft:oak_trapdoor[facing=east,half=top,open=true]", + "97:0": "minecraft:infested_stone", + "97:1": "minecraft:infested_cobblestone", + "97:2": "minecraft:infested_stone_bricks", + "97:3": "minecraft:infested_mossy_stone_bricks", + "97:4": "minecraft:infested_cracked_stone_bricks", + "97:5": "minecraft:infested_chiseled_stone_bricks", + "98:0": "minecraft:stone_bricks", + "98:1": "minecraft:mossy_stone_bricks", + "98:2": "minecraft:cracked_stone_bricks", + "98:3": "minecraft:chiseled_stone_bricks", + "99:0": "minecraft:brown_mushroom_block[east=false,south=false,north=false,west=false,up=false,down=false]", + "99:1": "minecraft:brown_mushroom_block[east=false,south=false,north=true,west=true,up=true,down=false]", + "99:2": "minecraft:brown_mushroom_block[east=false,south=false,north=true,west=false,up=true,down=false]", + "99:3": "minecraft:brown_mushroom_block[east=true,south=false,north=true,west=false,up=true,down=false]", + "99:4": "minecraft:brown_mushroom_block[east=false,south=false,north=false,west=true,up=true,down=false]", + "99:5": "minecraft:brown_mushroom_block[east=false,south=false,north=false,west=false,up=true,down=false]", + "99:6": "minecraft:brown_mushroom_block[east=true,south=false,north=false,west=false,up=true,down=false]", + "99:7": "minecraft:brown_mushroom_block[east=false,south=true,north=false,west=true,up=true,down=false]", + "99:8": "minecraft:brown_mushroom_block[east=false,south=true,north=false,west=false,up=true,down=false]", + "99:9": "minecraft:brown_mushroom_block[east=true,south=true,north=false,west=false,up=true,down=false]", + "99:10": "minecraft:mushroom_stem[east=true,south=true,north=true,west=true,up=false,down=false]", + "99:14": "minecraft:brown_mushroom_block[east=true,south=true,north=true,west=true,up=true,down=true]", + "99:15": "minecraft:mushroom_stem[east=true,south=true,north=true,west=true,up=true,down=true]", + "100:0": "minecraft:red_mushroom_block[east=false,south=false,north=false,west=false,up=false,down=false]", + "100:1": "minecraft:red_mushroom_block[east=false,south=false,north=true,west=true,up=true,down=false]", + "100:2": "minecraft:red_mushroom_block[east=false,south=false,north=true,west=false,up=true,down=false]", + "100:3": "minecraft:red_mushroom_block[east=true,south=false,north=true,west=false,up=true,down=false]", + "100:4": "minecraft:red_mushroom_block[east=false,south=false,north=false,west=true,up=true,down=false]", + "100:5": "minecraft:red_mushroom_block[east=false,south=false,north=false,west=false,up=true,down=false]", + "100:6": "minecraft:red_mushroom_block[east=true,south=false,north=false,west=false,up=true,down=false]", + "100:7": "minecraft:red_mushroom_block[east=false,south=true,north=false,west=true,up=true,down=false]", + "100:8": "minecraft:red_mushroom_block[east=false,south=true,north=false,west=false,up=true,down=false]", + "100:9": "minecraft:red_mushroom_block[east=true,south=true,north=false,west=false,up=true,down=false]", + "100:10": "minecraft:mushroom_stem[east=true,south=true,north=true,west=true,up=false,down=false]", + "100:14": "minecraft:red_mushroom_block[east=true,south=true,north=true,west=true,up=true,down=true]", + "100:15": "minecraft:mushroom_stem[east=true,south=true,north=true,west=true,up=true,down=true]", + "101:0": "minecraft:iron_bars[west=false,east=false,south=false,north=false]", + "102:0": "minecraft:glass_pane[west=false,east=false,south=false,north=false]", + "103:0": "minecraft:melon_block", + "104:0": "minecraft:pumpkin_stem[age=0]", + "104:1": "minecraft:pumpkin_stem[age=1]", + "104:2": "minecraft:pumpkin_stem[age=2]", + "104:3": "minecraft:pumpkin_stem[age=3]", + "104:4": "minecraft:pumpkin_stem[age=4]", + "104:5": "minecraft:pumpkin_stem[age=5]", + "104:6": "minecraft:pumpkin_stem[age=6]", + "104:7": "minecraft:pumpkin_stem[age=7]", + "105:0": "minecraft:melon_stem[age=0]", + "105:1": "minecraft:melon_stem[age=1]", + "105:2": "minecraft:melon_stem[age=2]", + "105:3": "minecraft:melon_stem[age=3]", + "105:4": "minecraft:melon_stem[age=4]", + "105:5": "minecraft:melon_stem[age=5]", + "105:6": "minecraft:melon_stem[age=6]", + "105:7": "minecraft:melon_stem[age=7]", + "106:0": "minecraft:vine[west=false,east=false,up=true,south=false,north=false]", + "106:1": "minecraft:vine[west=false,east=false,up=true,south=true,north=false]", + "106:2": "minecraft:vine[west=true,east=false,up=true,south=false,north=false]", + "106:3": "minecraft:vine[west=true,east=false,up=true,south=true,north=false]", + "106:4": "minecraft:vine[west=false,east=false,up=true,south=false,north=true]", + "106:5": "minecraft:vine[west=false,east=false,up=true,south=true,north=true]", + "106:6": "minecraft:vine[west=true,east=false,up=true,south=false,north=true]", + "106:7": "minecraft:vine[west=true,east=false,up=true,south=true,north=true]", + "106:8": "minecraft:vine[west=false,east=true,up=true,south=false,north=false]", + "106:9": "minecraft:vine[west=false,east=true,up=true,south=true,north=false]", + "106:10": "minecraft:vine[west=true,east=true,up=true,south=false,north=false]", + "106:11": "minecraft:vine[west=true,east=true,up=true,south=true,north=false]", + "106:12": "minecraft:vine[west=false,east=true,up=true,south=false,north=true]", + "106:13": "minecraft:vine[west=false,east=true,up=true,south=true,north=true]", + "106:14": "minecraft:vine[west=true,east=true,up=true,south=false,north=true]", + "106:15": "minecraft:vine[west=true,east=true,up=true,south=true,north=true]", + "107:0": "minecraft:oak_fence_gate[in_wall=false,facing=south,powered=false,open=false]", + "107:1": "minecraft:oak_fence_gate[in_wall=false,facing=west,powered=false,open=false]", + "107:2": "minecraft:oak_fence_gate[in_wall=false,facing=north,powered=false,open=false]", + "107:3": "minecraft:oak_fence_gate[in_wall=false,facing=east,powered=false,open=false]", + "107:4": "minecraft:oak_fence_gate[in_wall=false,facing=south,powered=false,open=true]", + "107:5": "minecraft:oak_fence_gate[in_wall=false,facing=west,powered=false,open=true]", + "107:6": "minecraft:oak_fence_gate[in_wall=false,facing=north,powered=false,open=true]", + "107:7": "minecraft:oak_fence_gate[in_wall=false,facing=east,powered=false,open=true]", + "107:8": "minecraft:oak_fence_gate[in_wall=false,facing=south,powered=true,open=false]", + "107:9": "minecraft:oak_fence_gate[in_wall=false,facing=west,powered=true,open=false]", + "107:10": "minecraft:oak_fence_gate[in_wall=false,facing=north,powered=true,open=false]", + "107:11": "minecraft:oak_fence_gate[in_wall=false,facing=east,powered=true,open=false]", + "107:12": "minecraft:oak_fence_gate[in_wall=false,facing=south,powered=true,open=true]", + "107:13": "minecraft:oak_fence_gate[in_wall=false,facing=west,powered=true,open=true]", + "107:14": "minecraft:oak_fence_gate[in_wall=false,facing=north,powered=true,open=true]", + "107:15": "minecraft:oak_fence_gate[in_wall=false,facing=east,powered=true,open=true]", + "108:0": "minecraft:brick_stairs[facing=east,half=bottom,shape=straight]", + "108:1": "minecraft:brick_stairs[facing=west,half=bottom,shape=straight]", + "108:2": "minecraft:brick_stairs[facing=south,half=bottom,shape=straight]", + "108:3": "minecraft:brick_stairs[facing=north,half=bottom,shape=straight]", + "108:4": "minecraft:brick_stairs[facing=east,half=top,shape=straight]", + "108:5": "minecraft:brick_stairs[facing=west,half=top,shape=straight]", + "108:6": "minecraft:brick_stairs[facing=south,half=top,shape=straight]", + "108:7": "minecraft:brick_stairs[facing=north,half=top,shape=straight]", + "109:0": "minecraft:stone_brick_stairs[facing=east,half=bottom,shape=straight]", + "109:1": "minecraft:stone_brick_stairs[facing=west,half=bottom,shape=straight]", + "109:2": "minecraft:stone_brick_stairs[facing=south,half=bottom,shape=straight]", + "109:3": "minecraft:stone_brick_stairs[facing=north,half=bottom,shape=straight]", + "109:4": "minecraft:stone_brick_stairs[facing=east,half=top,shape=straight]", + "109:5": "minecraft:stone_brick_stairs[facing=west,half=top,shape=straight]", + "109:6": "minecraft:stone_brick_stairs[facing=south,half=top,shape=straight]", + "109:7": "minecraft:stone_brick_stairs[facing=north,half=top,shape=straight]", + "110:0": "minecraft:mycelium[snowy=false]", + "111:0": "minecraft:lily_pad", + "112:0": "minecraft:nether_bricks", + "113:0": "minecraft:nether_brick_fence[west=false,east=false,south=false,north=false]", + "114:0": "minecraft:nether_brick_stairs[facing=east,half=bottom,shape=straight]", + "114:1": "minecraft:nether_brick_stairs[facing=west,half=bottom,shape=straight]", + "114:2": "minecraft:nether_brick_stairs[facing=south,half=bottom,shape=straight]", + "114:3": "minecraft:nether_brick_stairs[facing=north,half=bottom,shape=straight]", + "114:4": "minecraft:nether_brick_stairs[facing=east,half=top,shape=straight]", + "114:5": "minecraft:nether_brick_stairs[facing=west,half=top,shape=straight]", + "114:6": "minecraft:nether_brick_stairs[facing=south,half=top,shape=straight]", + "114:7": "minecraft:nether_brick_stairs[facing=north,half=top,shape=straight]", + "115:0": "minecraft:nether_wart[age=0]", + "115:1": "minecraft:nether_wart[age=1]", + "115:2": "minecraft:nether_wart[age=2]", + "115:3": "minecraft:nether_wart[age=3]", + "116:0": "minecraft:enchanting_table", + "117:0": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", + "117:1": "minecraft:brewing_stand[has_bottle_0=true,has_bottle_1=false,has_bottle_2=false]", + "117:2": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=true,has_bottle_2=false]", + "117:3": "minecraft:brewing_stand[has_bottle_0=true,has_bottle_1=true,has_bottle_2=false]", + "117:4": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=true]", + "117:5": "minecraft:brewing_stand[has_bottle_0=true,has_bottle_1=false,has_bottle_2=true]", + "117:6": "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=true,has_bottle_2=true]", + "117:7": "minecraft:brewing_stand[has_bottle_0=true,has_bottle_1=true,has_bottle_2=true]", + "118:0": "minecraft:cauldron[level=0]", + "118:1": "minecraft:cauldron[level=1]", + "118:2": "minecraft:cauldron[level=2]", + "118:3": "minecraft:cauldron[level=3]", + "120:0": "minecraft:end_portal_frame[eye=false,facing=south]", + "120:1": "minecraft:end_portal_frame[eye=false,facing=west]", + "120:2": "minecraft:end_portal_frame[eye=false,facing=north]", + "120:3": "minecraft:end_portal_frame[eye=false,facing=east]", + "120:4": "minecraft:end_portal_frame[eye=true,facing=south]", + "120:5": "minecraft:end_portal_frame[eye=true,facing=west]", + "120:6": "minecraft:end_portal_frame[eye=true,facing=north]", + "120:7": "minecraft:end_portal_frame[eye=true,facing=east]", + "121:0": "minecraft:end_stone", + "122:0": "minecraft:dragon_egg", + "123:0": "minecraft:redstone_lamp[lit=false]", + "124:0": "minecraft:redstone_lamp[lit=true]", + "125:0": "minecraft:oak_slab[type=double]", + "125:1": "minecraft:spruce_slab[type=double]", + "125:2": "minecraft:birch_slab[type=double]", + "125:3": "minecraft:jungle_slab[type=double]", + "125:4": "minecraft:acacia_slab[type=double]", + "125:5": "minecraft:dark_oak_slab[type=double]", + "126:0": "minecraft:oak_slab[type=bottom]", + "126:1": "minecraft:spruce_slab[type=bottom]", + "126:2": "minecraft:birch_slab[type=bottom]", + "126:3": "minecraft:jungle_slab[type=bottom]", + "126:4": "minecraft:acacia_slab[type=bottom]", + "126:5": "minecraft:dark_oak_slab[type=bottom]", + "126:8": "minecraft:oak_slab[type=top]", + "126:9": "minecraft:spruce_slab[type=top]", + "126:10": "minecraft:birch_slab[type=top]", + "126:11": "minecraft:jungle_slab[type=top]", + "126:12": "minecraft:acacia_slab[type=top]", + "126:13": "minecraft:dark_oak_slab[type=top]", + "127:0": "minecraft:cocoa[facing=south,age=0]", + "127:1": "minecraft:cocoa[facing=west,age=0]", + "127:2": "minecraft:cocoa[facing=north,age=0]", + "127:3": "minecraft:cocoa[facing=east,age=0]", + "127:4": "minecraft:cocoa[facing=south,age=1]", + "127:5": "minecraft:cocoa[facing=west,age=1]", + "127:6": "minecraft:cocoa[facing=north,age=1]", + "127:7": "minecraft:cocoa[facing=east,age=1]", + "127:8": "minecraft:cocoa[facing=south,age=2]", + "127:9": "minecraft:cocoa[facing=west,age=2]", + "127:10": "minecraft:cocoa[facing=north,age=2]", + "127:11": "minecraft:cocoa[facing=east,age=2]", + "128:0": "minecraft:sandstone_stairs[facing=east,half=bottom,shape=straight]", + "128:1": "minecraft:sandstone_stairs[facing=west,half=bottom,shape=straight]", + "128:2": "minecraft:sandstone_stairs[facing=south,half=bottom,shape=straight]", + "128:3": "minecraft:sandstone_stairs[facing=north,half=bottom,shape=straight]", + "128:4": "minecraft:sandstone_stairs[facing=east,half=top,shape=straight]", + "128:5": "minecraft:sandstone_stairs[facing=west,half=top,shape=straight]", + "128:6": "minecraft:sandstone_stairs[facing=south,half=top,shape=straight]", + "128:7": "minecraft:sandstone_stairs[facing=north,half=top,shape=straight]", + "129:0": "minecraft:emerald_ore", + "131:0": "minecraft:tripwire_hook[attached=false,facing=south,powered=false]", + "131:1": "minecraft:tripwire_hook[attached=false,facing=west,powered=false]", + "131:2": "minecraft:tripwire_hook[attached=false,facing=north,powered=false]", + "131:3": "minecraft:tripwire_hook[attached=false,facing=east,powered=false]", + "131:4": "minecraft:tripwire_hook[attached=true,facing=south,powered=false]", + "131:5": "minecraft:tripwire_hook[attached=true,facing=west,powered=false]", + "131:6": "minecraft:tripwire_hook[attached=true,facing=north,powered=false]", + "131:7": "minecraft:tripwire_hook[attached=true,facing=east,powered=false]", + "131:8": "minecraft:tripwire_hook[attached=false,facing=south,powered=true]", + "131:9": "minecraft:tripwire_hook[attached=false,facing=west,powered=true]", + "131:10": "minecraft:tripwire_hook[attached=false,facing=north,powered=true]", + "131:11": "minecraft:tripwire_hook[attached=false,facing=east,powered=true]", + "131:12": "minecraft:tripwire_hook[attached=true,facing=south,powered=true]", + "131:13": "minecraft:tripwire_hook[attached=true,facing=west,powered=true]", + "131:14": "minecraft:tripwire_hook[attached=true,facing=north,powered=true]", + "131:15": "minecraft:tripwire_hook[attached=true,facing=east,powered=true]", + "132:0": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,attached=false,west=false]", + "132:1": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,attached=false,west=false]", + "132:4": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,attached=true,west=false]", + "132:5": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,attached=true,west=false]", + "132:8": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,attached=false,west=false]", + "132:9": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,attached=false,west=false]", + "132:12": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,attached=true,west=false]", + "132:13": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,attached=true,west=false]", + "133:0": "minecraft:emerald_block", + "134:0": "minecraft:spruce_stairs[facing=east,half=bottom,shape=straight]", + "134:1": "minecraft:spruce_stairs[facing=west,half=bottom,shape=straight]", + "134:2": "minecraft:spruce_stairs[facing=south,half=bottom,shape=straight]", + "134:3": "minecraft:spruce_stairs[facing=north,half=bottom,shape=straight]", + "134:4": "minecraft:spruce_stairs[facing=east,half=top,shape=straight]", + "134:5": "minecraft:spruce_stairs[facing=west,half=top,shape=straight]", + "134:6": "minecraft:spruce_stairs[facing=south,half=top,shape=straight]", + "134:7": "minecraft:spruce_stairs[facing=north,half=top,shape=straight]", + "135:0": "minecraft:birch_stairs[facing=east,half=bottom,shape=straight]", + "135:1": "minecraft:birch_stairs[facing=west,half=bottom,shape=straight]", + "135:2": "minecraft:birch_stairs[facing=south,half=bottom,shape=straight]", + "135:3": "minecraft:birch_stairs[facing=north,half=bottom,shape=straight]", + "135:4": "minecraft:birch_stairs[facing=east,half=top,shape=straight]", + "135:5": "minecraft:birch_stairs[facing=west,half=top,shape=straight]", + "135:6": "minecraft:birch_stairs[facing=south,half=top,shape=straight]", + "135:7": "minecraft:birch_stairs[facing=north,half=top,shape=straight]", + "136:0": "minecraft:jungle_stairs[facing=east,half=bottom,shape=straight]", + "136:1": "minecraft:jungle_stairs[facing=west,half=bottom,shape=straight]", + "136:2": "minecraft:jungle_stairs[facing=south,half=bottom,shape=straight]", + "136:3": "minecraft:jungle_stairs[facing=north,half=bottom,shape=straight]", + "136:4": "minecraft:jungle_stairs[facing=east,half=top,shape=straight]", + "136:5": "minecraft:jungle_stairs[facing=west,half=top,shape=straight]", + "136:6": "minecraft:jungle_stairs[facing=south,half=top,shape=straight]", + "136:7": "minecraft:jungle_stairs[facing=north,half=top,shape=straight]", + "137:0": "minecraft:command_block[conditional=false,facing=down]", + "137:1": "minecraft:command_block[conditional=false,facing=up]", + "137:2": "minecraft:command_block[conditional=false,facing=north]", + "137:3": "minecraft:command_block[conditional=false,facing=south]", + "137:4": "minecraft:command_block[conditional=false,facing=west]", + "137:5": "minecraft:command_block[conditional=false,facing=east]", + "137:8": "minecraft:command_block[conditional=true,facing=down]", + "137:9": "minecraft:command_block[conditional=true,facing=up]", + "137:10": "minecraft:command_block[conditional=true,facing=north]", + "137:11": "minecraft:command_block[conditional=true,facing=south]", + "137:12": "minecraft:command_block[conditional=true,facing=west]", + "137:13": "minecraft:command_block[conditional=true,facing=east]", + "138:0": "minecraft:beacon", + "139:0": "minecraft:cobblestone_wall[west=false,east=false,up=false,south=false,north=false]", + "139:1": "minecraft:mossy_cobblestone_wall[west=false,east=false,up=false,south=false,north=false]", + "140:0": "minecraft:potted_cactus", + "140:1": "minecraft:potted_cactus", + "140:2": "minecraft:potted_cactus", + "140:3": "minecraft:potted_cactus", + "140:4": "minecraft:potted_cactus", + "140:5": "minecraft:potted_cactus", + "140:6": "minecraft:potted_cactus", + "140:7": "minecraft:potted_cactus", + "140:8": "minecraft:potted_cactus", + "140:9": "minecraft:potted_cactus", + "140:10": "minecraft:potted_cactus", + "140:11": "minecraft:potted_cactus", + "140:12": "minecraft:potted_cactus", + "140:13": "minecraft:potted_cactus", + "140:14": "minecraft:potted_cactus", + "140:15": "minecraft:potted_cactus", + "141:0": "minecraft:carrots[age=0]", + "141:1": "minecraft:carrots[age=1]", + "141:2": "minecraft:carrots[age=2]", + "141:3": "minecraft:carrots[age=3]", + "141:4": "minecraft:carrots[age=4]", + "141:5": "minecraft:carrots[age=5]", + "141:6": "minecraft:carrots[age=6]", + "141:7": "minecraft:carrots[age=7]", + "142:0": "minecraft:potatoes[age=0]", + "142:1": "minecraft:potatoes[age=1]", + "142:2": "minecraft:potatoes[age=2]", + "142:3": "minecraft:potatoes[age=3]", + "142:4": "minecraft:potatoes[age=4]", + "142:5": "minecraft:potatoes[age=5]", + "142:6": "minecraft:potatoes[age=6]", + "142:7": "minecraft:potatoes[age=7]", + "143:0": "minecraft:oak_button[facing=north,face=ceiling,powered=false]", + "143:1": "minecraft:oak_button[facing=east,face=wall,powered=false]", + "143:2": "minecraft:oak_button[facing=west,face=wall,powered=false]", + "143:3": "minecraft:oak_button[facing=south,face=wall,powered=false]", + "143:4": "minecraft:oak_button[facing=north,face=wall,powered=false]", + "143:5": "minecraft:oak_button[facing=north,face=floor,powered=false]", + "143:8": "minecraft:oak_button[facing=north,face=ceiling,powered=true]", + "143:9": "minecraft:oak_button[facing=east,face=wall,powered=true]", + "143:10": "minecraft:oak_button[facing=west,face=wall,powered=true]", + "143:11": "minecraft:oak_button[facing=south,face=wall,powered=true]", + "143:12": "minecraft:oak_button[facing=north,face=wall,powered=true]", + "143:13": "minecraft:oak_button[facing=north,face=floor,powered=true]", + "145:0": "minecraft:anvil[facing=south]", + "145:1": "minecraft:anvil[facing=west]", + "145:2": "minecraft:anvil[facing=north]", + "145:3": "minecraft:anvil[facing=east]", + "145:4": "minecraft:chipped_anvil[facing=south]", + "145:5": "minecraft:chipped_anvil[facing=west]", + "145:6": "minecraft:chipped_anvil[facing=north]", + "145:7": "minecraft:chipped_anvil[facing=east]", + "145:8": "minecraft:damaged_anvil[facing=south]", + "145:9": "minecraft:damaged_anvil[facing=west]", + "145:10": "minecraft:damaged_anvil[facing=north]", + "145:11": "minecraft:damaged_anvil[facing=east]", + "147:0": "minecraft:light_weighted_pressure_plate[power=0]", + "147:1": "minecraft:light_weighted_pressure_plate[power=1]", + "147:2": "minecraft:light_weighted_pressure_plate[power=2]", + "147:3": "minecraft:light_weighted_pressure_plate[power=3]", + "147:4": "minecraft:light_weighted_pressure_plate[power=4]", + "147:5": "minecraft:light_weighted_pressure_plate[power=5]", + "147:6": "minecraft:light_weighted_pressure_plate[power=6]", + "147:7": "minecraft:light_weighted_pressure_plate[power=7]", + "147:8": "minecraft:light_weighted_pressure_plate[power=8]", + "147:9": "minecraft:light_weighted_pressure_plate[power=9]", + "147:10": "minecraft:light_weighted_pressure_plate[power=10]", + "147:11": "minecraft:light_weighted_pressure_plate[power=11]", + "147:12": "minecraft:light_weighted_pressure_plate[power=12]", + "147:13": "minecraft:light_weighted_pressure_plate[power=13]", + "147:14": "minecraft:light_weighted_pressure_plate[power=14]", + "147:15": "minecraft:light_weighted_pressure_plate[power=15]", + "148:0": "minecraft:heavy_weighted_pressure_plate[power=0]", + "148:1": "minecraft:heavy_weighted_pressure_plate[power=1]", + "148:2": "minecraft:heavy_weighted_pressure_plate[power=2]", + "148:3": "minecraft:heavy_weighted_pressure_plate[power=3]", + "148:4": "minecraft:heavy_weighted_pressure_plate[power=4]", + "148:5": "minecraft:heavy_weighted_pressure_plate[power=5]", + "148:6": "minecraft:heavy_weighted_pressure_plate[power=6]", + "148:7": "minecraft:heavy_weighted_pressure_plate[power=7]", + "148:8": "minecraft:heavy_weighted_pressure_plate[power=8]", + "148:9": "minecraft:heavy_weighted_pressure_plate[power=9]", + "148:10": "minecraft:heavy_weighted_pressure_plate[power=10]", + "148:11": "minecraft:heavy_weighted_pressure_plate[power=11]", + "148:12": "minecraft:heavy_weighted_pressure_plate[power=12]", + "148:13": "minecraft:heavy_weighted_pressure_plate[power=13]", + "148:14": "minecraft:heavy_weighted_pressure_plate[power=14]", + "148:15": "minecraft:heavy_weighted_pressure_plate[power=15]", + "149:0": "minecraft:comparator[mode=compare,facing=south,powered=false]", + "149:1": "minecraft:comparator[mode=compare,facing=west,powered=false]", + "149:2": "minecraft:comparator[mode=compare,facing=north,powered=false]", + "149:3": "minecraft:comparator[mode=compare,facing=east,powered=false]", + "149:4": "minecraft:comparator[mode=subtract,facing=south,powered=false]", + "149:5": "minecraft:comparator[mode=subtract,facing=west,powered=false]", + "149:6": "minecraft:comparator[mode=subtract,facing=north,powered=false]", + "149:7": "minecraft:comparator[mode=subtract,facing=east,powered=false]", + "149:8": "minecraft:comparator[mode=compare,facing=south,powered=true]", + "149:9": "minecraft:comparator[mode=compare,facing=west,powered=true]", + "149:10": "minecraft:comparator[mode=compare,facing=north,powered=true]", + "149:11": "minecraft:comparator[mode=compare,facing=east,powered=true]", + "149:12": "minecraft:comparator[mode=subtract,facing=south,powered=true]", + "149:13": "minecraft:comparator[mode=subtract,facing=west,powered=true]", + "149:14": "minecraft:comparator[mode=subtract,facing=north,powered=true]", + "149:15": "minecraft:comparator[mode=subtract,facing=east,powered=true]", + "150:0": "minecraft:comparator[mode=compare,facing=south,powered=false]", + "150:1": "minecraft:comparator[mode=compare,facing=west,powered=false]", + "150:2": "minecraft:comparator[mode=compare,facing=north,powered=false]", + "150:3": "minecraft:comparator[mode=compare,facing=east,powered=false]", + "150:4": "minecraft:comparator[mode=subtract,facing=south,powered=false]", + "150:5": "minecraft:comparator[mode=subtract,facing=west,powered=false]", + "150:6": "minecraft:comparator[mode=subtract,facing=north,powered=false]", + "150:7": "minecraft:comparator[mode=subtract,facing=east,powered=false]", + "150:8": "minecraft:comparator[mode=compare,facing=south,powered=true]", + "150:9": "minecraft:comparator[mode=compare,facing=west,powered=true]", + "150:10": "minecraft:comparator[mode=compare,facing=north,powered=true]", + "150:11": "minecraft:comparator[mode=compare,facing=east,powered=true]", + "150:12": "minecraft:comparator[mode=subtract,facing=south,powered=true]", + "150:13": "minecraft:comparator[mode=subtract,facing=west,powered=true]", + "150:14": "minecraft:comparator[mode=subtract,facing=north,powered=true]", + "150:15": "minecraft:comparator[mode=subtract,facing=east,powered=true]", + "151:0": "minecraft:daylight_detector[inverted=false,power=0]", + "151:1": "minecraft:daylight_detector[inverted=false,power=1]", + "151:2": "minecraft:daylight_detector[inverted=false,power=2]", + "151:3": "minecraft:daylight_detector[inverted=false,power=3]", + "151:4": "minecraft:daylight_detector[inverted=false,power=4]", + "151:5": "minecraft:daylight_detector[inverted=false,power=5]", + "151:6": "minecraft:daylight_detector[inverted=false,power=6]", + "151:7": "minecraft:daylight_detector[inverted=false,power=7]", + "151:8": "minecraft:daylight_detector[inverted=false,power=8]", + "151:9": "minecraft:daylight_detector[inverted=false,power=9]", + "151:10": "minecraft:daylight_detector[inverted=false,power=10]", + "151:11": "minecraft:daylight_detector[inverted=false,power=11]", + "151:12": "minecraft:daylight_detector[inverted=false,power=12]", + "151:13": "minecraft:daylight_detector[inverted=false,power=13]", + "151:14": "minecraft:daylight_detector[inverted=false,power=14]", + "151:15": "minecraft:daylight_detector[inverted=false,power=15]", + "152:0": "minecraft:redstone_block", + "153:0": "minecraft:nether_quartz_ore", + "154:0": "minecraft:hopper[facing=down,enabled=true]", + "154:2": "minecraft:hopper[facing=north,enabled=true]", + "154:3": "minecraft:hopper[facing=south,enabled=true]", + "154:4": "minecraft:hopper[facing=west,enabled=true]", + "154:5": "minecraft:hopper[facing=east,enabled=true]", + "154:8": "minecraft:hopper[facing=down,enabled=false]", + "154:10": "minecraft:hopper[facing=north,enabled=false]", + "154:11": "minecraft:hopper[facing=south,enabled=false]", + "154:12": "minecraft:hopper[facing=west,enabled=false]", + "154:13": "minecraft:hopper[facing=east,enabled=false]", + "155:0": "minecraft:quartz_block", + "155:1": "minecraft:chiseled_quartz_block", + "155:2": "minecraft:quartz_pillar[axis=y]", + "155:3": "minecraft:quartz_pillar[axis=x]", + "155:4": "minecraft:quartz_pillar[axis=z]", + "156:0": "minecraft:quartz_stairs[facing=east,half=bottom,shape=straight]", + "156:1": "minecraft:quartz_stairs[facing=west,half=bottom,shape=straight]", + "156:2": "minecraft:quartz_stairs[facing=south,half=bottom,shape=straight]", + "156:3": "minecraft:quartz_stairs[facing=north,half=bottom,shape=straight]", + "156:4": "minecraft:quartz_stairs[facing=east,half=top,shape=straight]", + "156:5": "minecraft:quartz_stairs[facing=west,half=top,shape=straight]", + "156:6": "minecraft:quartz_stairs[facing=south,half=top,shape=straight]", + "156:7": "minecraft:quartz_stairs[facing=north,half=top,shape=straight]", + "157:0": "minecraft:activator_rail[powered=false,shape=north_south]", + "157:1": "minecraft:activator_rail[powered=false,shape=east_west]", + "157:2": "minecraft:activator_rail[powered=false,shape=ascending_east]", + "157:3": "minecraft:activator_rail[powered=false,shape=ascending_west]", + "157:4": "minecraft:activator_rail[powered=false,shape=ascending_north]", + "157:5": "minecraft:activator_rail[powered=false,shape=ascending_south]", + "157:8": "minecraft:activator_rail[powered=true,shape=north_south]", + "157:9": "minecraft:activator_rail[powered=true,shape=east_west]", + "157:10": "minecraft:activator_rail[powered=true,shape=ascending_east]", + "157:11": "minecraft:activator_rail[powered=true,shape=ascending_west]", + "157:12": "minecraft:activator_rail[powered=true,shape=ascending_north]", + "157:13": "minecraft:activator_rail[powered=true,shape=ascending_south]", + "158:0": "minecraft:dropper[facing=down,triggered=false]", + "158:1": "minecraft:dropper[facing=up,triggered=false]", + "158:2": "minecraft:dropper[facing=north,triggered=false]", + "158:3": "minecraft:dropper[facing=south,triggered=false]", + "158:4": "minecraft:dropper[facing=west,triggered=false]", + "158:5": "minecraft:dropper[facing=east,triggered=false]", + "158:8": "minecraft:dropper[facing=down,triggered=true]", + "158:9": "minecraft:dropper[facing=up,triggered=true]", + "158:10": "minecraft:dropper[facing=north,triggered=true]", + "158:11": "minecraft:dropper[facing=south,triggered=true]", + "158:12": "minecraft:dropper[facing=west,triggered=true]", + "158:13": "minecraft:dropper[facing=east,triggered=true]", + "159:0": "minecraft:white_terracotta", + "159:1": "minecraft:orange_terracotta", + "159:2": "minecraft:magenta_terracotta", + "159:3": "minecraft:light_blue_terracotta", + "159:4": "minecraft:yellow_terracotta", + "159:5": "minecraft:lime_terracotta", + "159:6": "minecraft:pink_terracotta", + "159:7": "minecraft:gray_terracotta", + "159:8": "minecraft:light_gray_terracotta", + "159:9": "minecraft:cyan_terracotta", + "159:10": "minecraft:purple_terracotta", + "159:11": "minecraft:blue_terracotta", + "159:12": "minecraft:brown_terracotta", + "159:13": "minecraft:green_terracotta", + "159:14": "minecraft:red_terracotta", + "159:15": "minecraft:black_terracotta", + "160:0": "minecraft:white_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:1": "minecraft:orange_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:2": "minecraft:magenta_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:3": "minecraft:light_blue_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:4": "minecraft:yellow_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:5": "minecraft:lime_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:6": "minecraft:pink_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:7": "minecraft:gray_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:8": "minecraft:light_gray_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:9": "minecraft:cyan_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:10": "minecraft:purple_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:11": "minecraft:blue_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:12": "minecraft:brown_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:13": "minecraft:green_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:14": "minecraft:red_stained_glass_pane[west=false,east=false,south=false,north=false]", + "160:15": "minecraft:black_stained_glass_pane[west=false,east=false,south=false,north=false]", + "161:0": "minecraft:acacia_leaves[check_decay=false,decayable=true]", + "161:1": "minecraft:dark_oak_leaves[check_decay=false,decayable=true]", + "161:4": "minecraft:acacia_leaves[check_decay=false,decayable=false]", + "161:5": "minecraft:dark_oak_leaves[check_decay=false,decayable=false]", + "161:8": "minecraft:acacia_leaves[check_decay=true,decayable=true]", + "161:9": "minecraft:dark_oak_leaves[check_decay=true,decayable=true]", + "161:12": "minecraft:acacia_leaves[check_decay=true,decayable=false]", + "161:13": "minecraft:dark_oak_leaves[check_decay=true,decayable=false]", + "162:0": "minecraft:acacia_log[axis=y]", + "162:1": "minecraft:dark_oak_log[axis=y]", + "162:4": "minecraft:acacia_log[axis=x]", + "162:5": "minecraft:dark_oak_log[axis=x]", + "162:8": "minecraft:acacia_log[axis=z]", + "162:9": "minecraft:dark_oak_log[axis=z]", + "162:12": "minecraft:acacia_bark", + "162:13": "minecraft:dark_oak_bark", + "163:0": "minecraft:acacia_stairs[facing=east,half=bottom,shape=straight]", + "163:1": "minecraft:acacia_stairs[facing=west,half=bottom,shape=straight]", + "163:2": "minecraft:acacia_stairs[facing=south,half=bottom,shape=straight]", + "163:3": "minecraft:acacia_stairs[facing=north,half=bottom,shape=straight]", + "163:4": "minecraft:acacia_stairs[facing=east,half=top,shape=straight]", + "163:5": "minecraft:acacia_stairs[facing=west,half=top,shape=straight]", + "163:6": "minecraft:acacia_stairs[facing=south,half=top,shape=straight]", + "163:7": "minecraft:acacia_stairs[facing=north,half=top,shape=straight]", + "164:0": "minecraft:dark_oak_stairs[facing=east,half=bottom,shape=straight]", + "164:1": "minecraft:dark_oak_stairs[facing=west,half=bottom,shape=straight]", + "164:2": "minecraft:dark_oak_stairs[facing=south,half=bottom,shape=straight]", + "164:3": "minecraft:dark_oak_stairs[facing=north,half=bottom,shape=straight]", + "164:4": "minecraft:dark_oak_stairs[facing=east,half=top,shape=straight]", + "164:5": "minecraft:dark_oak_stairs[facing=west,half=top,shape=straight]", + "164:6": "minecraft:dark_oak_stairs[facing=south,half=top,shape=straight]", + "164:7": "minecraft:dark_oak_stairs[facing=north,half=top,shape=straight]", + "165:0": "minecraft:slime_block", + "167:0": "minecraft:iron_trapdoor[facing=north,half=bottom,open=false]", + "167:1": "minecraft:iron_trapdoor[facing=south,half=bottom,open=false]", + "167:2": "minecraft:iron_trapdoor[facing=west,half=bottom,open=false]", + "167:3": "minecraft:iron_trapdoor[facing=east,half=bottom,open=false]", + "167:4": "minecraft:iron_trapdoor[facing=north,half=bottom,open=true]", + "167:5": "minecraft:iron_trapdoor[facing=south,half=bottom,open=true]", + "167:6": "minecraft:iron_trapdoor[facing=west,half=bottom,open=true]", + "167:7": "minecraft:iron_trapdoor[facing=east,half=bottom,open=true]", + "167:8": "minecraft:iron_trapdoor[facing=north,half=top,open=false]", + "167:9": "minecraft:iron_trapdoor[facing=south,half=top,open=false]", + "167:10": "minecraft:iron_trapdoor[facing=west,half=top,open=false]", + "167:11": "minecraft:iron_trapdoor[facing=east,half=top,open=false]", + "167:12": "minecraft:iron_trapdoor[facing=north,half=top,open=true]", + "167:13": "minecraft:iron_trapdoor[facing=south,half=top,open=true]", + "167:14": "minecraft:iron_trapdoor[facing=west,half=top,open=true]", + "167:15": "minecraft:iron_trapdoor[facing=east,half=top,open=true]", + "168:0": "minecraft:prismarine", + "168:1": "minecraft:prismarine_bricks", + "168:2": "minecraft:dark_prismarine", + "169:0": "minecraft:sea_lantern", + "170:0": "minecraft:hay_block[axis=y]", + "170:4": "minecraft:hay_block[axis=x]", + "170:8": "minecraft:hay_block[axis=z]", + "171:0": "minecraft:white_carpet", + "171:1": "minecraft:orange_carpet", + "171:2": "minecraft:magenta_carpet", + "171:3": "minecraft:light_blue_carpet", + "171:4": "minecraft:yellow_carpet", + "171:5": "minecraft:lime_carpet", + "171:6": "minecraft:pink_carpet", + "171:7": "minecraft:gray_carpet", + "171:8": "minecraft:light_gray_carpet", + "171:9": "minecraft:cyan_carpet", + "171:10": "minecraft:purple_carpet", + "171:11": "minecraft:blue_carpet", + "171:12": "minecraft:brown_carpet", + "171:13": "minecraft:green_carpet", + "171:14": "minecraft:red_carpet", + "171:15": "minecraft:black_carpet", + "172:0": "minecraft:terracotta", + "173:0": "minecraft:coal_block", + "174:0": "minecraft:packed_ice", + "175:0": "minecraft:sunflower[half=lower]", + "175:1": "minecraft:lilac[half=lower]", + "175:2": "minecraft:tall_grass[half=lower]", + "175:3": "minecraft:large_fern[half=lower]", + "175:4": "minecraft:rose_bush[half=lower]", + "175:5": "minecraft:peony[half=lower]", + "175:8": "minecraft:peony[half=upper]", + "175:9": "minecraft:peony[half=upper]", + "175:10": "minecraft:peony[half=upper]", + "175:11": "minecraft:peony[half=upper]", + "178:0": "minecraft:daylight_detector[inverted=true,power=0]", + "178:1": "minecraft:daylight_detector[inverted=true,power=1]", + "178:2": "minecraft:daylight_detector[inverted=true,power=2]", + "178:3": "minecraft:daylight_detector[inverted=true,power=3]", + "178:4": "minecraft:daylight_detector[inverted=true,power=4]", + "178:5": "minecraft:daylight_detector[inverted=true,power=5]", + "178:6": "minecraft:daylight_detector[inverted=true,power=6]", + "178:7": "minecraft:daylight_detector[inverted=true,power=7]", + "178:8": "minecraft:daylight_detector[inverted=true,power=8]", + "178:9": "minecraft:daylight_detector[inverted=true,power=9]", + "178:10": "minecraft:daylight_detector[inverted=true,power=10]", + "178:11": "minecraft:daylight_detector[inverted=true,power=11]", + "178:12": "minecraft:daylight_detector[inverted=true,power=12]", + "178:13": "minecraft:daylight_detector[inverted=true,power=13]", + "178:14": "minecraft:daylight_detector[inverted=true,power=14]", + "178:15": "minecraft:daylight_detector[inverted=true,power=15]", + "179:0": "minecraft:red_sandstone", + "179:1": "minecraft:chiseled_red_sandstone", + "179:2": "minecraft:cut_red_sandstone", + "180:0": "minecraft:red_sandstone_stairs[facing=east,half=bottom,shape=straight]", + "180:1": "minecraft:red_sandstone_stairs[facing=west,half=bottom,shape=straight]", + "180:2": "minecraft:red_sandstone_stairs[facing=south,half=bottom,shape=straight]", + "180:3": "minecraft:red_sandstone_stairs[facing=north,half=bottom,shape=straight]", + "180:4": "minecraft:red_sandstone_stairs[facing=east,half=top,shape=straight]", + "180:5": "minecraft:red_sandstone_stairs[facing=west,half=top,shape=straight]", + "180:6": "minecraft:red_sandstone_stairs[facing=south,half=top,shape=straight]", + "180:7": "minecraft:red_sandstone_stairs[facing=north,half=top,shape=straight]", + "181:0": "minecraft:red_sandstone_slab[type=double]", + "181:8": "minecraft:smooth_red_sandstone", + "182:0": "minecraft:red_sandstone_slab[type=bottom]", + "182:8": "minecraft:red_sandstone_slab[type=top]", + "183:0": "minecraft:spruce_fence_gate[in_wall=false,facing=south,powered=false,open=false]", + "183:1": "minecraft:spruce_fence_gate[in_wall=false,facing=west,powered=false,open=false]", + "183:2": "minecraft:spruce_fence_gate[in_wall=false,facing=north,powered=false,open=false]", + "183:3": "minecraft:spruce_fence_gate[in_wall=false,facing=east,powered=false,open=false]", + "183:4": "minecraft:spruce_fence_gate[in_wall=false,facing=south,powered=false,open=true]", + "183:5": "minecraft:spruce_fence_gate[in_wall=false,facing=west,powered=false,open=true]", + "183:6": "minecraft:spruce_fence_gate[in_wall=false,facing=north,powered=false,open=true]", + "183:7": "minecraft:spruce_fence_gate[in_wall=false,facing=east,powered=false,open=true]", + "183:8": "minecraft:spruce_fence_gate[in_wall=false,facing=south,powered=true,open=false]", + "183:9": "minecraft:spruce_fence_gate[in_wall=false,facing=west,powered=true,open=false]", + "183:10": "minecraft:spruce_fence_gate[in_wall=false,facing=north,powered=true,open=false]", + "183:11": "minecraft:spruce_fence_gate[in_wall=false,facing=east,powered=true,open=false]", + "183:12": "minecraft:spruce_fence_gate[in_wall=false,facing=south,powered=true,open=true]", + "183:13": "minecraft:spruce_fence_gate[in_wall=false,facing=west,powered=true,open=true]", + "183:14": "minecraft:spruce_fence_gate[in_wall=false,facing=north,powered=true,open=true]", + "183:15": "minecraft:spruce_fence_gate[in_wall=false,facing=east,powered=true,open=true]", + "184:0": "minecraft:birch_fence_gate[in_wall=false,facing=south,powered=false,open=false]", + "184:1": "minecraft:birch_fence_gate[in_wall=false,facing=west,powered=false,open=false]", + "184:2": "minecraft:birch_fence_gate[in_wall=false,facing=north,powered=false,open=false]", + "184:3": "minecraft:birch_fence_gate[in_wall=false,facing=east,powered=false,open=false]", + "184:4": "minecraft:birch_fence_gate[in_wall=false,facing=south,powered=false,open=true]", + "184:5": "minecraft:birch_fence_gate[in_wall=false,facing=west,powered=false,open=true]", + "184:6": "minecraft:birch_fence_gate[in_wall=false,facing=north,powered=false,open=true]", + "184:7": "minecraft:birch_fence_gate[in_wall=false,facing=east,powered=false,open=true]", + "184:8": "minecraft:birch_fence_gate[in_wall=false,facing=south,powered=true,open=false]", + "184:9": "minecraft:birch_fence_gate[in_wall=false,facing=west,powered=true,open=false]", + "184:10": "minecraft:birch_fence_gate[in_wall=false,facing=north,powered=true,open=false]", + "184:11": "minecraft:birch_fence_gate[in_wall=false,facing=east,powered=true,open=false]", + "184:12": "minecraft:birch_fence_gate[in_wall=false,facing=south,powered=true,open=true]", + "184:13": "minecraft:birch_fence_gate[in_wall=false,facing=west,powered=true,open=true]", + "184:14": "minecraft:birch_fence_gate[in_wall=false,facing=north,powered=true,open=true]", + "184:15": "minecraft:birch_fence_gate[in_wall=false,facing=east,powered=true,open=true]", + "185:0": "minecraft:jungle_fence_gate[in_wall=false,facing=south,powered=false,open=false]", + "185:1": "minecraft:jungle_fence_gate[in_wall=false,facing=west,powered=false,open=false]", + "185:2": "minecraft:jungle_fence_gate[in_wall=false,facing=north,powered=false,open=false]", + "185:3": "minecraft:jungle_fence_gate[in_wall=false,facing=east,powered=false,open=false]", + "185:4": "minecraft:jungle_fence_gate[in_wall=false,facing=south,powered=false,open=true]", + "185:5": "minecraft:jungle_fence_gate[in_wall=false,facing=west,powered=false,open=true]", + "185:6": "minecraft:jungle_fence_gate[in_wall=false,facing=north,powered=false,open=true]", + "185:7": "minecraft:jungle_fence_gate[in_wall=false,facing=east,powered=false,open=true]", + "185:8": "minecraft:jungle_fence_gate[in_wall=false,facing=south,powered=true,open=false]", + "185:9": "minecraft:jungle_fence_gate[in_wall=false,facing=west,powered=true,open=false]", + "185:10": "minecraft:jungle_fence_gate[in_wall=false,facing=north,powered=true,open=false]", + "185:11": "minecraft:jungle_fence_gate[in_wall=false,facing=east,powered=true,open=false]", + "185:12": "minecraft:jungle_fence_gate[in_wall=false,facing=south,powered=true,open=true]", + "185:13": "minecraft:jungle_fence_gate[in_wall=false,facing=west,powered=true,open=true]", + "185:14": "minecraft:jungle_fence_gate[in_wall=false,facing=north,powered=true,open=true]", + "185:15": "minecraft:jungle_fence_gate[in_wall=false,facing=east,powered=true,open=true]", + "186:0": "minecraft:dark_oak_fence_gate[in_wall=false,facing=south,powered=false,open=false]", + "186:1": "minecraft:dark_oak_fence_gate[in_wall=false,facing=west,powered=false,open=false]", + "186:2": "minecraft:dark_oak_fence_gate[in_wall=false,facing=north,powered=false,open=false]", + "186:3": "minecraft:dark_oak_fence_gate[in_wall=false,facing=east,powered=false,open=false]", + "186:4": "minecraft:dark_oak_fence_gate[in_wall=false,facing=south,powered=false,open=true]", + "186:5": "minecraft:dark_oak_fence_gate[in_wall=false,facing=west,powered=false,open=true]", + "186:6": "minecraft:dark_oak_fence_gate[in_wall=false,facing=north,powered=false,open=true]", + "186:7": "minecraft:dark_oak_fence_gate[in_wall=false,facing=east,powered=false,open=true]", + "186:8": "minecraft:dark_oak_fence_gate[in_wall=false,facing=south,powered=true,open=false]", + "186:9": "minecraft:dark_oak_fence_gate[in_wall=false,facing=west,powered=true,open=false]", + "186:10": "minecraft:dark_oak_fence_gate[in_wall=false,facing=north,powered=true,open=false]", + "186:11": "minecraft:dark_oak_fence_gate[in_wall=false,facing=east,powered=true,open=false]", + "186:12": "minecraft:dark_oak_fence_gate[in_wall=false,facing=south,powered=true,open=true]", + "186:13": "minecraft:dark_oak_fence_gate[in_wall=false,facing=west,powered=true,open=true]", + "186:14": "minecraft:dark_oak_fence_gate[in_wall=false,facing=north,powered=true,open=true]", + "186:15": "minecraft:dark_oak_fence_gate[in_wall=false,facing=east,powered=true,open=true]", + "187:0": "minecraft:acacia_fence_gate[in_wall=false,facing=south,powered=false,open=false]", + "187:1": "minecraft:acacia_fence_gate[in_wall=false,facing=west,powered=false,open=false]", + "187:2": "minecraft:acacia_fence_gate[in_wall=false,facing=north,powered=false,open=false]", + "187:3": "minecraft:acacia_fence_gate[in_wall=false,facing=east,powered=false,open=false]", + "187:4": "minecraft:acacia_fence_gate[in_wall=false,facing=south,powered=false,open=true]", + "187:5": "minecraft:acacia_fence_gate[in_wall=false,facing=west,powered=false,open=true]", + "187:6": "minecraft:acacia_fence_gate[in_wall=false,facing=north,powered=false,open=true]", + "187:7": "minecraft:acacia_fence_gate[in_wall=false,facing=east,powered=false,open=true]", + "187:8": "minecraft:acacia_fence_gate[in_wall=false,facing=south,powered=true,open=false]", + "187:9": "minecraft:acacia_fence_gate[in_wall=false,facing=west,powered=true,open=false]", + "187:10": "minecraft:acacia_fence_gate[in_wall=false,facing=north,powered=true,open=false]", + "187:11": "minecraft:acacia_fence_gate[in_wall=false,facing=east,powered=true,open=false]", + "187:12": "minecraft:acacia_fence_gate[in_wall=false,facing=south,powered=true,open=true]", + "187:13": "minecraft:acacia_fence_gate[in_wall=false,facing=west,powered=true,open=true]", + "187:14": "minecraft:acacia_fence_gate[in_wall=false,facing=north,powered=true,open=true]", + "187:15": "minecraft:acacia_fence_gate[in_wall=false,facing=east,powered=true,open=true]", + "188:0": "minecraft:spruce_fence[west=false,east=false,south=false,north=false]", + "189:0": "minecraft:birch_fence[west=false,east=false,south=false,north=false]", + "190:0": "minecraft:jungle_fence[west=false,east=false,south=false,north=false]", + "191:0": "minecraft:dark_oak_fence[west=false,east=false,south=false,north=false]", + "192:0": "minecraft:acacia_fence[west=false,east=false,south=false,north=false]", + "193:0": "minecraft:spruce_door[hinge=right,facing=east,half=lower,powered=false,open=false]", + "193:1": "minecraft:spruce_door[hinge=right,facing=south,half=lower,powered=false,open=false]", + "193:2": "minecraft:spruce_door[hinge=right,facing=west,half=lower,powered=false,open=false]", + "193:3": "minecraft:spruce_door[hinge=right,facing=north,half=lower,powered=false,open=false]", + "193:4": "minecraft:spruce_door[hinge=right,facing=east,half=lower,powered=false,open=true]", + "193:5": "minecraft:spruce_door[hinge=right,facing=south,half=lower,powered=false,open=true]", + "193:6": "minecraft:spruce_door[hinge=right,facing=west,half=lower,powered=false,open=true]", + "193:7": "minecraft:spruce_door[hinge=right,facing=north,half=lower,powered=false,open=true]", + "193:8": "minecraft:spruce_door[hinge=left,facing=east,half=upper,powered=false,open=false]", + "193:9": "minecraft:spruce_door[hinge=right,facing=east,half=upper,powered=false,open=false]", + "193:10": "minecraft:spruce_door[hinge=left,facing=east,half=upper,powered=true,open=false]", + "193:11": "minecraft:spruce_door[hinge=right,facing=east,half=upper,powered=true,open=false]", + "194:0": "minecraft:birch_door[hinge=right,facing=east,half=lower,powered=false,open=false]", + "194:1": "minecraft:birch_door[hinge=right,facing=south,half=lower,powered=false,open=false]", + "194:2": "minecraft:birch_door[hinge=right,facing=west,half=lower,powered=false,open=false]", + "194:3": "minecraft:birch_door[hinge=right,facing=north,half=lower,powered=false,open=false]", + "194:4": "minecraft:birch_door[hinge=right,facing=east,half=lower,powered=false,open=true]", + "194:5": "minecraft:birch_door[hinge=right,facing=south,half=lower,powered=false,open=true]", + "194:6": "minecraft:birch_door[hinge=right,facing=west,half=lower,powered=false,open=true]", + "194:7": "minecraft:birch_door[hinge=right,facing=north,half=lower,powered=false,open=true]", + "194:8": "minecraft:birch_door[hinge=left,facing=east,half=upper,powered=false,open=false]", + "194:9": "minecraft:birch_door[hinge=right,facing=east,half=upper,powered=false,open=false]", + "194:10": "minecraft:birch_door[hinge=left,facing=east,half=upper,powered=true,open=false]", + "194:11": "minecraft:birch_door[hinge=right,facing=east,half=upper,powered=true,open=false]", + "195:0": "minecraft:jungle_door[hinge=right,facing=east,half=lower,powered=false,open=false]", + "195:1": "minecraft:jungle_door[hinge=right,facing=south,half=lower,powered=false,open=false]", + "195:2": "minecraft:jungle_door[hinge=right,facing=west,half=lower,powered=false,open=false]", + "195:3": "minecraft:jungle_door[hinge=right,facing=north,half=lower,powered=false,open=false]", + "195:4": "minecraft:jungle_door[hinge=right,facing=east,half=lower,powered=false,open=true]", + "195:5": "minecraft:jungle_door[hinge=right,facing=south,half=lower,powered=false,open=true]", + "195:6": "minecraft:jungle_door[hinge=right,facing=west,half=lower,powered=false,open=true]", + "195:7": "minecraft:jungle_door[hinge=right,facing=north,half=lower,powered=false,open=true]", + "195:8": "minecraft:jungle_door[hinge=left,facing=east,half=upper,powered=false,open=false]", + "195:9": "minecraft:jungle_door[hinge=right,facing=east,half=upper,powered=false,open=false]", + "195:10": "minecraft:jungle_door[hinge=left,facing=east,half=upper,powered=true,open=false]", + "195:11": "minecraft:jungle_door[hinge=right,facing=east,half=upper,powered=true,open=false]", + "196:0": "minecraft:acacia_door[hinge=right,facing=east,half=lower,powered=false,open=false]", + "196:1": "minecraft:acacia_door[hinge=right,facing=south,half=lower,powered=false,open=false]", + "196:2": "minecraft:acacia_door[hinge=right,facing=west,half=lower,powered=false,open=false]", + "196:3": "minecraft:acacia_door[hinge=right,facing=north,half=lower,powered=false,open=false]", + "196:4": "minecraft:acacia_door[hinge=right,facing=east,half=lower,powered=false,open=true]", + "196:5": "minecraft:acacia_door[hinge=right,facing=south,half=lower,powered=false,open=true]", + "196:6": "minecraft:acacia_door[hinge=right,facing=west,half=lower,powered=false,open=true]", + "196:7": "minecraft:acacia_door[hinge=right,facing=north,half=lower,powered=false,open=true]", + "196:8": "minecraft:acacia_door[hinge=left,facing=east,half=upper,powered=false,open=false]", + "196:9": "minecraft:acacia_door[hinge=right,facing=east,half=upper,powered=false,open=false]", + "196:10": "minecraft:acacia_door[hinge=left,facing=east,half=upper,powered=true,open=false]", + "196:11": "minecraft:acacia_door[hinge=right,facing=east,half=upper,powered=true,open=false]", + "197:0": "minecraft:dark_oak_door[hinge=right,facing=east,half=lower,powered=false,open=false]", + "197:1": "minecraft:dark_oak_door[hinge=right,facing=south,half=lower,powered=false,open=false]", + "197:2": "minecraft:dark_oak_door[hinge=right,facing=west,half=lower,powered=false,open=false]", + "197:3": "minecraft:dark_oak_door[hinge=right,facing=north,half=lower,powered=false,open=false]", + "197:4": "minecraft:dark_oak_door[hinge=right,facing=east,half=lower,powered=false,open=true]", + "197:5": "minecraft:dark_oak_door[hinge=right,facing=south,half=lower,powered=false,open=true]", + "197:6": "minecraft:dark_oak_door[hinge=right,facing=west,half=lower,powered=false,open=true]", + "197:7": "minecraft:dark_oak_door[hinge=right,facing=north,half=lower,powered=false,open=true]", + "197:8": "minecraft:dark_oak_door[hinge=left,facing=east,half=upper,powered=false,open=false]", + "197:9": "minecraft:dark_oak_door[hinge=right,facing=east,half=upper,powered=false,open=false]", + "197:10": "minecraft:dark_oak_door[hinge=left,facing=east,half=upper,powered=true,open=false]", + "197:11": "minecraft:dark_oak_door[hinge=right,facing=east,half=upper,powered=true,open=false]", + "198:0": "minecraft:end_rod[facing=down]", + "198:1": "minecraft:end_rod[facing=up]", + "198:2": "minecraft:end_rod[facing=north]", + "198:3": "minecraft:end_rod[facing=south]", + "198:4": "minecraft:end_rod[facing=west]", + "198:5": "minecraft:end_rod[facing=east]", + "199:0": "minecraft:chorus_plant[east=false,south=false,north=false,west=false,up=false,down=false]", + "200:0": "minecraft:chorus_flower[age=0]", + "200:1": "minecraft:chorus_flower[age=1]", + "200:2": "minecraft:chorus_flower[age=2]", + "200:3": "minecraft:chorus_flower[age=3]", + "200:4": "minecraft:chorus_flower[age=4]", + "200:5": "minecraft:chorus_flower[age=5]", + "201:0": "minecraft:purpur_block", + "202:0": "minecraft:purpur_pillar[axis=y]", + "202:4": "minecraft:purpur_pillar[axis=x]", + "202:8": "minecraft:purpur_pillar[axis=z]", + "203:0": "minecraft:purpur_stairs[facing=east,half=bottom,shape=straight]", + "203:1": "minecraft:purpur_stairs[facing=west,half=bottom,shape=straight]", + "203:2": "minecraft:purpur_stairs[facing=south,half=bottom,shape=straight]", + "203:3": "minecraft:purpur_stairs[facing=north,half=bottom,shape=straight]", + "203:4": "minecraft:purpur_stairs[facing=east,half=top,shape=straight]", + "203:5": "minecraft:purpur_stairs[facing=west,half=top,shape=straight]", + "203:6": "minecraft:purpur_stairs[facing=south,half=top,shape=straight]", + "203:7": "minecraft:purpur_stairs[facing=north,half=top,shape=straight]", + "204:0": "minecraft:purpur_slab[type=double]", + "205:0": "minecraft:purpur_slab[type=bottom]", + "205:8": "minecraft:purpur_slab[type=top]", + "206:0": "minecraft:end_stone_bricks", + "207:0": "minecraft:beetroots[age=0]", + "207:1": "minecraft:beetroots[age=1]", + "207:2": "minecraft:beetroots[age=2]", + "207:3": "minecraft:beetroots[age=3]", + "208:0": "minecraft:grass_path", + "210:0": "minecraft:repeating_command_block[conditional=false,facing=down]", + "210:1": "minecraft:repeating_command_block[conditional=false,facing=up]", + "210:2": "minecraft:repeating_command_block[conditional=false,facing=north]", + "210:3": "minecraft:repeating_command_block[conditional=false,facing=south]", + "210:4": "minecraft:repeating_command_block[conditional=false,facing=west]", + "210:5": "minecraft:repeating_command_block[conditional=false,facing=east]", + "210:8": "minecraft:repeating_command_block[conditional=true,facing=down]", + "210:9": "minecraft:repeating_command_block[conditional=true,facing=up]", + "210:10": "minecraft:repeating_command_block[conditional=true,facing=north]", + "210:11": "minecraft:repeating_command_block[conditional=true,facing=south]", + "210:12": "minecraft:repeating_command_block[conditional=true,facing=west]", + "210:13": "minecraft:repeating_command_block[conditional=true,facing=east]", + "211:0": "minecraft:chain_command_block[conditional=false,facing=down]", + "211:1": "minecraft:chain_command_block[conditional=false,facing=up]", + "211:2": "minecraft:chain_command_block[conditional=false,facing=north]", + "211:3": "minecraft:chain_command_block[conditional=false,facing=south]", + "211:4": "minecraft:chain_command_block[conditional=false,facing=west]", + "211:5": "minecraft:chain_command_block[conditional=false,facing=east]", + "211:8": "minecraft:chain_command_block[conditional=true,facing=down]", + "211:9": "minecraft:chain_command_block[conditional=true,facing=up]", + "211:10": "minecraft:chain_command_block[conditional=true,facing=north]", + "211:11": "minecraft:chain_command_block[conditional=true,facing=south]", + "211:12": "minecraft:chain_command_block[conditional=true,facing=west]", + "211:13": "minecraft:chain_command_block[conditional=true,facing=east]", + "212:0": "minecraft:frosted_ice[age=0]", + "212:1": "minecraft:frosted_ice[age=1]", + "212:2": "minecraft:frosted_ice[age=2]", + "212:3": "minecraft:frosted_ice[age=3]", + "213:0": "minecraft:magma_block", + "214:0": "minecraft:nether_wart_block", + "215:0": "minecraft:red_nether_bricks", + "216:0": "minecraft:bone_block[axis=y]", + "216:4": "minecraft:bone_block[axis=x]", + "216:8": "minecraft:bone_block[axis=z]", + "218:0": "minecraft:observer[powered=false,facing=down]", + "218:1": "minecraft:observer[powered=false,facing=up]", + "218:2": "minecraft:observer[powered=false,facing=north]", + "218:3": "minecraft:observer[powered=false,facing=south]", + "218:4": "minecraft:observer[powered=false,facing=west]", + "218:5": "minecraft:observer[powered=false,facing=east]", + "218:8": "minecraft:observer[powered=true,facing=down]", + "218:9": "minecraft:observer[powered=true,facing=up]", + "218:10": "minecraft:observer[powered=true,facing=north]", + "218:11": "minecraft:observer[powered=true,facing=south]", + "218:12": "minecraft:observer[powered=true,facing=west]", + "218:13": "minecraft:observer[powered=true,facing=east]", + "235:0": "minecraft:white_glazed_terracotta[facing=south]", + "235:1": "minecraft:white_glazed_terracotta[facing=west]", + "235:2": "minecraft:white_glazed_terracotta[facing=north]", + "235:3": "minecraft:white_glazed_terracotta[facing=east]", + "236:0": "minecraft:orange_glazed_terracotta[facing=south]", + "236:1": "minecraft:orange_glazed_terracotta[facing=west]", + "236:2": "minecraft:orange_glazed_terracotta[facing=north]", + "236:3": "minecraft:orange_glazed_terracotta[facing=east]", + "237:0": "minecraft:magenta_glazed_terracotta[facing=south]", + "237:1": "minecraft:magenta_glazed_terracotta[facing=west]", + "237:2": "minecraft:magenta_glazed_terracotta[facing=north]", + "237:3": "minecraft:magenta_glazed_terracotta[facing=east]", + "238:0": "minecraft:light_blue_glazed_terracotta[facing=south]", + "238:1": "minecraft:light_blue_glazed_terracotta[facing=west]", + "238:2": "minecraft:light_blue_glazed_terracotta[facing=north]", + "238:3": "minecraft:light_blue_glazed_terracotta[facing=east]", + "239:0": "minecraft:yellow_glazed_terracotta[facing=south]", + "239:1": "minecraft:yellow_glazed_terracotta[facing=west]", + "239:2": "minecraft:yellow_glazed_terracotta[facing=north]", + "239:3": "minecraft:yellow_glazed_terracotta[facing=east]", + "240:0": "minecraft:lime_glazed_terracotta[facing=south]", + "240:1": "minecraft:lime_glazed_terracotta[facing=west]", + "240:2": "minecraft:lime_glazed_terracotta[facing=north]", + "240:3": "minecraft:lime_glazed_terracotta[facing=east]", + "241:0": "minecraft:pink_glazed_terracotta[facing=south]", + "241:1": "minecraft:pink_glazed_terracotta[facing=west]", + "241:2": "minecraft:pink_glazed_terracotta[facing=north]", + "241:3": "minecraft:pink_glazed_terracotta[facing=east]", + "242:0": "minecraft:gray_glazed_terracotta[facing=south]", + "242:1": "minecraft:gray_glazed_terracotta[facing=west]", + "242:2": "minecraft:gray_glazed_terracotta[facing=north]", + "242:3": "minecraft:gray_glazed_terracotta[facing=east]", + "243:0": "minecraft:light_gray_glazed_terracotta[facing=south]", + "243:1": "minecraft:light_gray_glazed_terracotta[facing=west]", + "243:2": "minecraft:light_gray_glazed_terracotta[facing=north]", + "243:3": "minecraft:light_gray_glazed_terracotta[facing=east]", + "244:0": "minecraft:cyan_glazed_terracotta[facing=south]", + "244:1": "minecraft:cyan_glazed_terracotta[facing=west]", + "244:2": "minecraft:cyan_glazed_terracotta[facing=north]", + "244:3": "minecraft:cyan_glazed_terracotta[facing=east]", + "245:0": "minecraft:purple_glazed_terracotta[facing=south]", + "245:1": "minecraft:purple_glazed_terracotta[facing=west]", + "245:2": "minecraft:purple_glazed_terracotta[facing=north]", + "245:3": "minecraft:purple_glazed_terracotta[facing=east]", + "246:0": "minecraft:blue_glazed_terracotta[facing=south]", + "246:1": "minecraft:blue_glazed_terracotta[facing=west]", + "246:2": "minecraft:blue_glazed_terracotta[facing=north]", + "246:3": "minecraft:blue_glazed_terracotta[facing=east]", + "247:0": "minecraft:brown_glazed_terracotta[facing=south]", + "247:1": "minecraft:brown_glazed_terracotta[facing=west]", + "247:2": "minecraft:brown_glazed_terracotta[facing=north]", + "247:3": "minecraft:brown_glazed_terracotta[facing=east]", + "248:0": "minecraft:green_glazed_terracotta[facing=south]", + "248:1": "minecraft:green_glazed_terracotta[facing=west]", + "248:2": "minecraft:green_glazed_terracotta[facing=north]", + "248:3": "minecraft:green_glazed_terracotta[facing=east]", + "249:0": "minecraft:red_glazed_terracotta[facing=south]", + "249:1": "minecraft:red_glazed_terracotta[facing=west]", + "249:2": "minecraft:red_glazed_terracotta[facing=north]", + "249:3": "minecraft:red_glazed_terracotta[facing=east]", + "250:0": "minecraft:black_glazed_terracotta[facing=south]", + "250:1": "minecraft:black_glazed_terracotta[facing=west]", + "250:2": "minecraft:black_glazed_terracotta[facing=north]", + "250:3": "minecraft:black_glazed_terracotta[facing=east]", + "251:0": "minecraft:white_concrete", + "251:1": "minecraft:orange_concrete", + "251:2": "minecraft:magenta_concrete", + "251:3": "minecraft:light_blue_concrete", + "251:4": "minecraft:yellow_concrete", + "251:5": "minecraft:lime_concrete", + "251:6": "minecraft:pink_concrete", + "251:7": "minecraft:gray_concrete", + "251:8": "minecraft:light_gray_concrete", + "251:9": "minecraft:cyan_concrete", + "251:10": "minecraft:purple_concrete", + "251:11": "minecraft:blue_concrete", + "251:12": "minecraft:brown_concrete", + "251:13": "minecraft:green_concrete", + "251:14": "minecraft:red_concrete", + "251:15": "minecraft:black_concrete", + "252:0": "minecraft:white_concrete_powder", + "252:1": "minecraft:orange_concrete_powder", + "252:2": "minecraft:magenta_concrete_powder", + "252:3": "minecraft:light_blue_concrete_powder", + "252:4": "minecraft:yellow_concrete_powder", + "252:5": "minecraft:lime_concrete_powder", + "252:6": "minecraft:pink_concrete_powder", + "252:7": "minecraft:gray_concrete_powder", + "252:8": "minecraft:light_gray_concrete_powder", + "252:9": "minecraft:cyan_concrete_powder", + "252:10": "minecraft:purple_concrete_powder", + "252:11": "minecraft:blue_concrete_powder", + "252:12": "minecraft:brown_concrete_powder", + "252:13": "minecraft:green_concrete_powder", + "252:14": "minecraft:red_concrete_powder", + "252:15": "minecraft:black_concrete_powder", + "255:0": "minecraft:structure_block[mode=save]", + "255:1": "minecraft:structure_block[mode=load]", + "255:2": "minecraft:structure_block[mode=corner]", + "255:3": "minecraft:structure_block[mode=data]" +} diff --git a/BlueMapCore/src/main/resources/blockProperties.json b/BlueMapCore/src/main/resources/blockProperties.json new file mode 100644 index 00000000..41d46b65 --- /dev/null +++ b/BlueMapCore/src/main/resources/blockProperties.json @@ -0,0 +1,4402 @@ +{ + "minecraft:air": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:granite": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_granite": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:diorite": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_diorite": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:andesite": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_andesite": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:grass_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dirt": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:coarse_dirt": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:podzol": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cobblestone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:oak_planks": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:spruce_planks": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:birch_planks": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:jungle_planks": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:acacia_planks": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:dark_oak_planks": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:oak_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bedrock": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:water": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lava": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sand": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_sand": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:gravel": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:gold_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:iron_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:coal_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:oak_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:spruce_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:birch_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:jungle_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:acacia_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:dark_oak_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_spruce_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_birch_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_jungle_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_acacia_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_dark_oak_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_oak_log": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:oak_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:spruce_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:birch_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:jungle_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:acacia_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:dark_oak_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_oak_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_spruce_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_birch_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_jungle_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_acacia_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stripped_dark_oak_wood": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:oak_leaves": { + "culling": false, + "occluding": true, + "flammable": true + }, + "minecraft:spruce_leaves": { + "culling": false, + "occluding": true, + "flammable": true + }, + "minecraft:birch_leaves": { + "culling": false, + "occluding": true, + "flammable": true + }, + "minecraft:jungle_leaves": { + "culling": false, + "occluding": true, + "flammable": true + }, + "minecraft:acacia_leaves": { + "culling": false, + "occluding": true, + "flammable": true + }, + "minecraft:dark_oak_leaves": { + "culling": false, + "occluding": true, + "flammable": true + }, + "minecraft:sponge": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:wet_sponge": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lapis_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:lapis_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dispenser": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:chiseled_sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cut_sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:note_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:white_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:orange_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:magenta_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_blue_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:yellow_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lime_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:pink_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:gray_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_gray_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cyan_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purple_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:blue_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brown_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:green_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:black_bed": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:powered_rail": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:detector_rail": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sticky_piston[facing=north,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sticky_piston[facing=east,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sticky_piston[facing=south,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sticky_piston[facing=west,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sticky_piston[facing=up,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sticky_piston[facing=down,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sticky_piston[facing=north,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sticky_piston[facing=east,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sticky_piston[facing=south,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sticky_piston[facing=west,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sticky_piston[facing=up,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sticky_piston[facing=down,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cobweb": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:grass": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:fern": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:dead_bush": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:seagrass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:tall_seagrass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:piston[facing=north,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:piston[facing=east,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:piston[facing=south,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:piston[facing=west,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:piston[facing=up,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:piston[facing=down,extended=true]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:piston[facing=north,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:piston[facing=east,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:piston[facing=south,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:piston[facing=west,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:piston[facing=up,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:piston[facing=down,extended=false]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:piston_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:white_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:orange_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:magenta_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:light_blue_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:yellow_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:lime_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:pink_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:gray_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:light_gray_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:cyan_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:purple_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:blue_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:brown_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:green_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:red_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:black_wool": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:moving_piston": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dandelion": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:poppy": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:blue_orchid": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:allium": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:azure_bluet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:red_tulip": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:orange_tulip": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:white_tulip": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:pink_tulip": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:oxeye_daisy": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:cornflower": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:wither_rose": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:lily_of_the_valley": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:brown_mushroom": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_mushroom": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:gold_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:iron_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:tnt": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:bookshelf": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:mossy_cobblestone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:obsidian": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:torch": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:wall_torch": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:fire": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spawner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_stairs": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:chest": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:redstone_wire": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:diamond_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:diamond_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:crafting_table": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:wheat": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:farmland": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:furnace": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:oak_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_door": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:ladder": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:rail": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cobblestone_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_wall_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_wall_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_wall_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_wall_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_wall_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_wall_sign": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lever": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:iron_door": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:redstone_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:redstone_torch": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:redstone_wall_torch": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_button": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=1]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=2]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=3]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=4]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=5]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=6]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=7]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:snow[layers=8]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:ice": { + "culling": false, + "occluding": true, + "flammable": false + }, + "minecraft:snow_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cactus": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:clay": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sugar_cane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jukebox": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:oak_fence": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:pumpkin": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:netherrack": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:soul_sand": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:glowstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:nether_portal": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:carved_pumpkin": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:jack_o_lantern": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cake": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:repeater": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:white_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:orange_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:magenta_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_blue_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:yellow_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lime_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:pink_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:gray_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_gray_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cyan_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purple_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:blue_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brown_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:green_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:black_stained_glass": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_trapdoor": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_trapdoor": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_trapdoor": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_trapdoor": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_trapdoor": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_trapdoor": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:mossy_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cracked_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:chiseled_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:infested_stone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:infested_cobblestone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:infested_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:infested_mossy_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:infested_cracked_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:infested_chiseled_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brown_mushroom_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_mushroom_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:mushroom_stem": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:iron_bars": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:melon": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:attached_pumpkin_stem": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:attached_melon_stem": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:pumpkin_stem": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:melon_stem": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:vine": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:oak_fence_gate": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:brick_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_brick_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mycelium": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:lily_pad": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:nether_brick_fence": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_brick_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_wart": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:enchanting_table": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brewing_stand": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cauldron": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_portal": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_portal_frame": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dragon_egg": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:redstone_lamp": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cocoa": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sandstone_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:emerald_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:ender_chest": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:tripwire_hook": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:tripwire": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:emerald_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:spruce_stairs": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:birch_stairs": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:jungle_stairs": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:command_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:beacon": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cobblestone_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_cobblestone_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:flower_pot": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_oak_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_spruce_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_birch_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_jungle_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_acacia_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_dark_oak_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_fern": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_dandelion": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_poppy": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_blue_orchid": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_allium": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_azure_bluet": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_red_tulip": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_orange_tulip": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_white_tulip": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_pink_tulip": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_oxeye_daisy": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_cornflower": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_lily_of_the_valley": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_wither_rose": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_red_mushroom": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_brown_mushroom": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_dead_bush": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potted_cactus": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:carrots": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:potatoes": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_button": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_button": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_button": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_button": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_button": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_button": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:skeleton_skull": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:skeleton_wall_skull": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:wither_skeleton_skull": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:wither_skeleton_wall_skull": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:zombie_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:zombie_wall_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:player_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:player_wall_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:creeper_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:creeper_wall_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dragon_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dragon_wall_head": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:anvil": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:chipped_anvil": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:damaged_anvil": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:trapped_chest": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_weighted_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:heavy_weighted_pressure_plate": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:comparator": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:daylight_detector": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:redstone_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:nether_quartz_ore": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:hopper": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:quartz_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:chiseled_quartz_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:quartz_pillar": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:quartz_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:activator_rail": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dropper": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:white_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:orange_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:magenta_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_blue_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:yellow_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:lime_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:pink_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:gray_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_gray_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cyan_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purple_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:blue_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brown_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:green_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:black_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:white_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:orange_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:magenta_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_blue_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:yellow_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lime_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:pink_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:gray_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_gray_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cyan_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purple_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:blue_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brown_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:green_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:black_stained_glass_pane": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_stairs": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:dark_oak_stairs": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:slime_block": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:barrier": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:iron_trapdoor": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:prismarine_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dark_prismarine": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:prismarine_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_brick_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_prismarine_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:prismarine_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:prismarine_brick_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_brick_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_brick_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_brick_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_brick_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:prismarine_brick_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dark_prismarine_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_prismarine_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_prismarine_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_prismarine_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_prismarine_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dark_prismarine_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sea_lantern": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:hay_block": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:white_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:orange_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:magenta_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:light_blue_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:yellow_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:lime_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:pink_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:gray_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:light_gray_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:cyan_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:purple_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:blue_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:brown_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:green_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:red_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:black_carpet": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:coal_block": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:packed_ice": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sunflower": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:lilac": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:rose_bush": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:peony": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:tall_grass": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:large_fern": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:white_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:orange_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:magenta_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_blue_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:yellow_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lime_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:pink_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:gray_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_gray_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cyan_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purple_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:blue_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brown_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:green_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:black_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:white_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:orange_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:magenta_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_blue_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:yellow_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lime_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:pink_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:gray_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_gray_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cyan_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purple_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:blue_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brown_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:green_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:black_wall_banner": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:chiseled_red_sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cut_red_sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_sandstone_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:oak_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:oak_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:oak_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:oak_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:spruce_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:spruce_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:spruce_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:spruce_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:spruce_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:birch_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:birch_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:birch_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:birch_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:jungle_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:jungle_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:jungle_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:jungle_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:acacia_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:acacia_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:acacia_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:acacia_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:dark_oak_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:dark_oak_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:dark_oak_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dark_oak_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:stone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:stone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_stone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_stone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_stone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_stone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_stone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_stone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sandstone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sandstone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sandstone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sandstone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sandstone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:sandstone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cut_sandstone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_sandstone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_sandstone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_sandstone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_sandstone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cut_sandstone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:petrified_oak_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:petrified_oak_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:petrified_oak_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:petrified_oak_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:petrified_oak_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:petrified_oak_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cobblestone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cobblestone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cobblestone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cobblestone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cobblestone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cobblestone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brick_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brick_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brick_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brick_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brick_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brick_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:stone_brick_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_brick_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_brick_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_brick_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_brick_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:stone_brick_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:nether_brick_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_brick_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_brick_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_brick_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_brick_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:nether_brick_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:quartz_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:quartz_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:quartz_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:quartz_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:quartz_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:quartz_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_sandstone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_sandstone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_sandstone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_sandstone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_sandstone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_sandstone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cut_red_sandstone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_red_sandstone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_red_sandstone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_red_sandstone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cut_red_sandstone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cut_red_sandstone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purpur_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purpur_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purpur_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purpur_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purpur_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purpur_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_stone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_quartz": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_red_sandstone": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:spruce_fence_gate": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:birch_fence_gate": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:jungle_fence_gate": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:acacia_fence_gate": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:dark_oak_fence_gate": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:spruce_fence": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:birch_fence": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:jungle_fence": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:acacia_fence": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:dark_oak_fence": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:spruce_door": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:birch_door": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:jungle_door": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:acacia_door": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dark_oak_door": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_rod": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:chorus_plant": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:chorus_flower": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purpur_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purpur_pillar": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purpur_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:beetroots": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:grass_path": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_gateway": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:repeating_command_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:chain_command_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:frosted_ice": { + "culling": false, + "occluding": true, + "flammable": false + }, + "minecraft:magma_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:nether_wart_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_nether_bricks": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:bone_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:structure_void": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:observer": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:white_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:orange_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:magenta_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_blue_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:yellow_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lime_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:pink_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:gray_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:light_gray_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cyan_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:purple_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:blue_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brown_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:green_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:black_shulker_box": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:white_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:orange_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:magenta_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_blue_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:yellow_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:lime_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:pink_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:gray_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_gray_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cyan_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purple_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:blue_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brown_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:green_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:black_glazed_terracotta": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:white_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:orange_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:magenta_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_blue_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:yellow_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:lime_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:pink_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:gray_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_gray_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cyan_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purple_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:blue_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brown_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:green_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:black_concrete": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:white_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:orange_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:magenta_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_blue_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:yellow_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:lime_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:pink_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:gray_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:light_gray_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cyan_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:purple_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:blue_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brown_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:green_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:black_concrete_powder": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:kelp": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:kelp_plant": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dried_kelp_block": { + "culling": true, + "occluding": true, + "flammable": true + }, + "minecraft:turtle_egg": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_tube_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dead_brain_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dead_bubble_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dead_fire_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dead_horn_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:tube_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brain_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:bubble_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:fire_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:horn_coral_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:dead_tube_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_brain_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_bubble_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_fire_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_horn_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:tube_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brain_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bubble_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:fire_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:horn_coral": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_tube_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_brain_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_bubble_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_fire_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_horn_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:tube_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brain_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bubble_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:fire_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:horn_coral_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_tube_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_brain_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_bubble_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_fire_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:dead_horn_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:tube_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:brain_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bubble_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:fire_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:horn_coral_wall_fan": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sea_pickle": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:blue_ice": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:conduit": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bamboo_sapling": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bamboo": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:potted_bamboo": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:void_air": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:cave_air": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bubble_column": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_granite_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_red_sandstone_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_stone_brick_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_diorite_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_cobblestone_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone_brick_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_sandstone_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_quartz_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:granite_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:andesite_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_nether_brick_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_andesite_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:diorite_stairs": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_granite_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_granite_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_granite_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_granite_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_granite_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_granite_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_red_sandstone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_red_sandstone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_red_sandstone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_red_sandstone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_red_sandstone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_red_sandstone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:mossy_stone_brick_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_stone_brick_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_stone_brick_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_stone_brick_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_stone_brick_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:mossy_stone_brick_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_diorite_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_diorite_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_diorite_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_diorite_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_diorite_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_diorite_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:mossy_cobblestone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_cobblestone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_cobblestone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_cobblestone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_cobblestone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:mossy_cobblestone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:end_stone_brick_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone_brick_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone_brick_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone_brick_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone_brick_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:end_stone_brick_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_sandstone_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_sandstone_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_sandstone_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_sandstone_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_sandstone_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_sandstone_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_quartz_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_quartz_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_quartz_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_quartz_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:smooth_quartz_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smooth_quartz_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:granite_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:granite_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:granite_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:granite_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:granite_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:granite_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:andesite_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:andesite_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:andesite_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:andesite_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:andesite_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:andesite_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_nether_brick_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_nether_brick_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_nether_brick_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_nether_brick_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_nether_brick_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:red_nether_brick_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_andesite_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_andesite_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_andesite_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_andesite_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:polished_andesite_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:polished_andesite_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:diorite_slab[waterlogged=true,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:diorite_slab[waterlogged=false,type=top]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:diorite_slab[waterlogged=true,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:diorite_slab[waterlogged=false,type=bottom]": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:diorite_slab[waterlogged=true,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:diorite_slab[waterlogged=false,type=double]": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:brick_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:prismarine_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_sandstone_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:mossy_stone_brick_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:granite_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:stone_brick_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:nether_brick_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:andesite_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:red_nether_brick_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sandstone_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:end_stone_brick_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:diorite_wall": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:scaffolding": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:loom": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:barrel": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:smoker": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:blast_furnace": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:cartography_table": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:fletching_table": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:grindstone": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lectern": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:smithing_table": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:stonecutter": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:bell": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:lantern": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:campfire": { + "culling": false, + "occluding": false, + "flammable": false + }, + "minecraft:sweet_berry_bush": { + "culling": false, + "occluding": false, + "flammable": true + }, + "minecraft:structure_block": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:jigsaw": { + "culling": true, + "occluding": true, + "flammable": false + }, + "minecraft:composter": { + "culling": false, + "occluding": false, + "flammable": true + } +} diff --git a/BlueMapCore/src/main/resources/webroot.zip b/BlueMapCore/src/main/resources/webroot.zip new file mode 100644 index 0000000000000000000000000000000000000000..c9412339f3f5a0bbfcc8e57ab0a3191ef413e9c5 GIT binary patch literal 203135 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 w`D2a=5kdY@=lmV>_d4e + + + + + + + + + + + + + diff --git a/BlueMapCore/src/main/webroot/assets/gear.svg b/BlueMapCore/src/main/webroot/assets/gear.svg new file mode 100644 index 00000000..d5695e40 --- /dev/null +++ b/BlueMapCore/src/main/webroot/assets/gear.svg @@ -0,0 +1,19 @@ + + + + + + diff --git a/BlueMapCore/src/main/webroot/assets/skybox/down.png b/BlueMapCore/src/main/webroot/assets/skybox/down.png new file mode 100644 index 0000000000000000000000000000000000000000..77290fc56ce8cc849d1412ddd56bee9bd6984c0f GIT binary patch literal 4533 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 literal 0 HcmV?d00001 diff --git a/BlueMapCore/src/main/webroot/assets/skybox/east.png b/BlueMapCore/src/main/webroot/assets/skybox/east.png new file mode 100644 index 0000000000000000000000000000000000000000..f10f641d8ec163b214c566db7dc5a7a4d87beb45 GIT binary patch literal 4605 zcmeHJX*ksF8h<7-cCt&nBWuFgWgjz^v4@e7%5F$PDO)sl(o2%P5tV(ZsL_NPONfk+ zbu8Hu!pRb4JM*3|opYV@p7*@(hjTuh_rw3X@9Y2E>+k+O&vhrBv@~X8KFkaNU^77* z*Z^>VrXB!{3^cJG{Qf&lF!`e$E(5^A{mTadId=sBV7Br`p-!Ik@(c94?B(YVGeMzX z{+Ikby)SqG5IjP##bIpc`E)kN*O6uk_&a8PHoS~58)OomCsk5Ll!?4uUS zSu@be)~a~cQl!YC57BKct&=nIh)8B}f56FD<1Tu6R}2ESBDA%SA0l^q5Fj(0?PA^E8Q#_f?{0KBw7Mfa&2h5)Mocs$KoG{BG?P%yFgM1#k*fK1_J zsRoR!K*2g8_86cK1J3PYV!H>=x0e@@ zrkL;_=TUPx;F5!oZwkp4REkvL_^|dCfc#WmTDNPv!4&o?3PmlM$nGS!@QPvosH^Mr z-fVZdKLUWsz=)nbS$NH1ycPrAckjN$GQHP1mi#N5NuJdlh-V;we#Cyw{}*fw3vQ8y zhi7MIhD=+KjxHVc;d{6yC$jzSg>MnsJDVFHUQUTeDxHlqrr-L|^mg66@JRPX0a&f`YkV)wNQd`|p6m|VU(wq&&X)jqPm|jL0Gu-rm&bI} z=(RBdV2~dv^H^VKy-`4x%y6Xf;AkVuj)!Z?b#NuH(<~-Gwo)QMx{oiC({*k=sRdBmv@j11pxy$e$g%CEAFl z=SmWXy-DD)K5CY#idM9_fq~hfg;#Yh9ngqBWAq|bs~sps?Znj^E8dB$w$^#i`V2)X zQ9m4Gbf4v&d!S-Y3SWNiyGu_G>)cc;n0r_5#W9kii)vFKe-eNyw_H$=Z*4|CIU&oG z=GOV-Xa#F|>*2?zD(LDGH{80P1krOv8j_jR=!1|j7ZH6l)*Nd&gf4*{5mz}h!lceb z7h~Ndbu_KS?5X67L*H5iT$L2#v1nPb0j?BoIA>S_szqI#D-oq6MY?ss9j?Xfe2ndTYg8KD``RYzumDzUclN!V^TwYtKhdoRv9iVSMziNrG({ z1$D*6thsECY(G1!3{mD9Z)yi~x@o#(x{wSUQ(9J3HeSYJw`SLgNhv*N8(w8(r))c2 z%Je>?+^&ppa?w`E7FViO5?_WZ@x$mnjBwaZWN>IUZ?-}`w9bFxG+o~cV{sF#36>T0 zVJnZj5~@*( z8{<4H$EJ=66{(n$6g|%Plx1XQV9U|v*5$^F4Qf?O#e|{;!#aoUNOt`;Q>imj#< zLBgEvuh|5ne@o1jX z9M7TLUDgYKy`C`-$6>oUyN8sgiQJvXTD%FixqZesejMp?^jbnvqFGd@e5S5^u2Ab( zd&7)r;6}jN$nLT*iN(^3ib(X!gI_j3H`y|*g&j^#NhUw+rzj{0Cd+oQ*FFI~ZB zq9VcyWfh5gHYWymgQwb84nD3e3@Y1nS>f0Hs(b0)wC=RF`nb}#gVS4ea&3EUr&Y6G zo>S}u>blsz`+n$t4=Bbj6 zZLAdaYX5wzQgm}Ji;_z5W{*7?@oC^4)a9c~QgZ~WRBU{#eVkshe**S!k7A~3P|qmp z@`S;6gA9Z5T%4kn#v?gXRTMvAY=(WmwI=t=260jy0%#LWt%T%ddyzp{j zXK5{diZI189mbypZ$IlFQb1{1k1ggamFJSx%s`kYSf04^7ky5d626-ftK2~n$;=^5 z!cDlN@E*0Egdx-!84=4>w2VdQ?a!(8sv+X9l?!EONikBTx9ZK=%*S#y^Z0VE!hDr< zG#eD7Z>Qc0K$eMGq!DooxR0J!J1ab5tM^`COsa*8q(k5M)ZD5#=pe^TL>7I*oR%Jx zfmY)@>^)y~C3a|Jl;<7qT6$a4LA|AZcjeyx5?2$~%2KVIE@EG2bz2%e`aI zTn4u;_ACp9)qhp_+)s6^-`v%G^O9-@v9sv+?DyC<*{<2tt4b`J-^$qbJzHt%8?e+y z*Gsnx6=Nq3lHT_V_v&D5QU;DM8nd_k^m31|5+ui_#%A~P-PS2Fe}j;j`Aw#YO%XQD zk*hbuDkhP)>)44ZSKOq}QNTY145IN58spERdcuSGet`aE#8nmWsE z|J*+3k*1UHLg0e-URs}3TixBdoGQ{8AJTGY!?Q5Y&3U0bb;{U!L&z7t{ek{G4V|%u zwNSs!*P9y?d}9%pq;@Htb;ChY%a!$3^-k-ECH-O4SbV>pbuo>AjX zhS=!tz0{2q4%ESv?3B(pwz$Q-6S^82Q+k(n=XZ)x-R|9zdHj3#_d2Wi`QQ;-{fmQ? zo~)jN%+<`aSH9N@cNfTuf{&=JO|2p?-vlcwo?Ab)z0?>q8YH~(V1mPH<{Ip}^uE`( zCmXi!inr4Q)6(|o>9W>#+?3_0w0#rihPJT)AXEYXd^7;x_Gxk+fGY|BEI0$8nFRp9 z-)*PYMgTyiO$_ug!6To?>e!kPoQ6FP?gnfvPd|M3O3;*!YQHVUnJA0^Xfr|faSe(3 zPv>W>w46fW0MG4beL96!<1;EoBf7I}M5dI%D3VvhUzlJa);0FIEjs80( zIE$g|Y7c;i2gxhjPyQx-8XO^@_rQk+-AVwwAqo>!rvUybz>1{t0+_j0p3x%+K#UwD zE7PuAFht-hlpg>z3%*Q}HVHVm#>@$Nw`jk94{iQ|Z2##!{-?phXte!91Vqpr|H~JJ q*72VJ{l+8nCqRI>3I$+)pAHyL38S0Gi$rNm1tx};231JssJ{Z8#GWhw literal 0 HcmV?d00001 diff --git a/BlueMapCore/src/main/webroot/assets/skybox/north.png b/BlueMapCore/src/main/webroot/assets/skybox/north.png new file mode 100644 index 0000000000000000000000000000000000000000..f10f641d8ec163b214c566db7dc5a7a4d87beb45 GIT binary patch literal 4605 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 literal 0 HcmV?d00001 diff --git a/BlueMapCore/src/main/webroot/assets/skybox/south.png b/BlueMapCore/src/main/webroot/assets/skybox/south.png new file mode 100644 index 0000000000000000000000000000000000000000..f10f641d8ec163b214c566db7dc5a7a4d87beb45 GIT binary patch literal 4605 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 literal 0 HcmV?d00001 diff --git a/BlueMapCore/src/main/webroot/assets/skybox/up.png b/BlueMapCore/src/main/webroot/assets/skybox/up.png new file mode 100644 index 0000000000000000000000000000000000000000..db5cb63178ad193b3f9a7c1bf36c316bde605b64 GIT binary patch literal 4536 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 literal 0 HcmV?d00001 diff --git a/BlueMapCore/src/main/webroot/index.html b/BlueMapCore/src/main/webroot/index.html new file mode 100644 index 00000000..4f13a002 --- /dev/null +++ b/BlueMapCore/src/main/webroot/index.html @@ -0,0 +1,22 @@ + + + + + + BlueMap + + + + + + + + + + +

    • ' + map.name + '
    • ').appendTo(this.maplist); + } + + this.maplist.find('li[map=' + this.bluemap.map + ']').hide(); + this.maplist.find('li[map]').click(function (e) { + let map = $(this).attr('map'); + scope.bluemap.changeMap(map); + }); + + $(document).on('bluemap-map-change', function(){ + scope.maplist.find('li').show(); + scope.maplist.find('li[map=' + scope.bluemap.map + ']').hide(); + + scope.element.find(".selection").html(scope.bluemap.settings[scope.bluemap.map].name); + }); +}; + +// ###### Modules.Compass ###### +BlueMap.Module.Compass = function (blueMap) { + let scope = this; + + this.blueMap = blueMap; + + $("#bluemap-compass").remove(); + this.element = $('
      ').appendTo(BlueMap.Module.getTopLeftElement(blueMap)); + this.needle = $('#bluemap-compass-needle'); + + $(document).on('bluemap-update-frame', function (){ + scope.needle.css("transform", "rotate(" + scope.blueMap.controls.direction + "rad)"); + }); + + $(this.element).click(function(){ + scope.blueMap.controls.targetDirection = 0; + scope.blueMap.controls.direction = scope.blueMap.controls.direction % (Math.PI * 2); + if (scope.blueMap.controls.direction < -Math.PI) scope.blueMap.controls.direction += Math.PI * 2; + if (scope.blueMap.controls.direction > Math.PI) scope.blueMap.controls.direction -= Math.PI * 2; + }); +}; + +// ###### Modules.Position ###### +BlueMap.Module.Position = function (blueMap) { + let scope = this; + + this.blueMap = blueMap; + + let parent = BlueMap.Module.getTopLeftElement(blueMap); + + $(".bluemap-position").remove(); + this.elementX = $('
      0
      ').appendTo(parent); + //this.elementY = $('
      0
      ').appendTo(parent); + this.elementZ = $('
      0
      ').appendTo(parent); + + $(document).on('bluemap-update-frame', function (){ + scope.elementX.html(Math.floor(scope.blueMap.controls.targetPosition.x)); + //scope.elementY.html(scope.blueMap.controls.targetPosition.y === 0 ? "-" : Math.floor(scope.blueMap.controls.targetPosition.y)); + scope.elementZ.html(Math.floor(scope.blueMap.controls.targetPosition.z)); + }); +}; + +// ###### Modules.Settings ###### +BlueMap.Module.Settings = function (blueMap) { + let scope = this; + + this.blueMap = blueMap; + + let parent = BlueMap.Module.getTopRightElement(blueMap); + + $("#bluemap-settings").remove(); + this.elementMenu = $('').appendTo(parent); + this.elementSettings = $('
      ').appendTo(parent); + this.elementSettings.click(function(){ + if (scope.elementMenu.css('display') === "none"){ + scope.elementSettings.addClass("active"); + } else { + scope.elementSettings.removeClass("active"); + } + + scope.elementMenu.animate({ + width: "toggle" + }, 200); + }); + + + /* Quality */ + + this.elementQuality = $( + '' + ).prependTo(this.elementMenu); + + this.elementQuality.find("li[quality]").click(function(){ + let desc = $(this).html(); + scope.blueMap.quality = parseFloat($(this).attr("quality")); + + scope.elementQuality.find('li').show(); + scope.elementQuality.find('li[quality=\'' + scope.blueMap.quality + '\']').hide(); + + scope.elementQuality.find('.selection > span').html(desc); + + scope.blueMap.handleContainerResize(); + }); + + + /* Render Distance */ + + this.pctToRenderDistance = function ( value , defaultValue ) { + let max = defaultValue * 5; + if (max > 20) max = 20; + + return THREE.Math.mapLinear(value, 0, 100, 1, max); + }; + + this.renderDistanceToPct = function ( value , defaultValue ) { + let max = defaultValue * 5; + if (max > 20) max = 20; + + return THREE.Math.mapLinear(value, 1, max, 0, 100); + }; + + this.init = function(){ + scope.defaultHighRes = scope.blueMap.hiresTileManager.viewDistance; + scope.defaultLowRes = scope.blueMap.lowresTileManager.viewDistance; + + scope.elementRenderDistance.html( + 'View Distance: ' + scope.blueMap.hiresTileManager.viewDistance + '' + + '' + ); + + let slider = scope.elementRenderDistance.find("input"); + slider.on('change input', function(e){ + scope.blueMap.hiresTileManager.viewDistance = scope.pctToRenderDistance(parseFloat(slider.val()), scope.defaultHighRes); + scope.blueMap.lowresTileManager.viewDistance = scope.pctToRenderDistance(parseFloat(slider.val()), scope.defaultLowRes); + scope.elementRenderDistance.find(".selection > span").html(Math.round(scope.blueMap.hiresTileManager.viewDistance * 10) / 10); + + scope.blueMap.lowresTileManager.update(); + scope.blueMap.hiresTileManager.update(); + }); + }; + + this.elementRenderDistance = $( + '' + ).prependTo(this.elementMenu); + + scope.init(); + + $(document).on('bluemap-map-change', this.init); +}; + +// ###### Modules.Info ###### +BlueMap.Module.Info = function (blueMap) { + let scope = this; + + this.blueMap = blueMap; + + let parent = BlueMap.Module.getTopRightElement(blueMap); + + $("#bluemap-info").remove(); + this.elementInfo = $('
      ').appendTo(parent); + + this.elementInfo.click(function(){ + scope.blueMap.alert( + '

      Info

      ' + + 'Visit BlueMap on
      GitHub!
      ' + + 'BlueMap works best with Chrome.
      ' + + '

      Controls

      ' + + 'Leftclick-drag with your mouse or use the arrow-keys to navigate.
      ' + + 'Rightclick-drag with your mouse to rotate your view.
      ' + + 'Scroll to zoom.
      ' + ); + }); +}; + +// ###### Utils ###### +BlueMap.utils = {}; + +BlueMap.utils.stringToImage = function (string) { + let image = document.createElementNS('http://www.w3.org/1999/xhtml', 'img'); + image.src = string; + return image; +}; + +BlueMap.utils.pathFromCoords = function (x, z) { + let path = "x"; + path += BlueMap.utils.splitNumberToPath(x); + + path += "z"; + path += BlueMap.utils.splitNumberToPath(z); + + path = path.substring(0, path.length - 1); + + return path; +}; + +BlueMap.utils.splitNumberToPath = function (num) { + let path = ""; + + if (num < 0) { + num = -num; + path += "-"; + } + + let s = num.toString(); + + for (let i = 0; i < s.length; i++) { + path += s.charAt(i) + "/"; + } + + return path; +}; + +BlueMap.utils.hashTile = function (x, z) { + return "x" + x + "z" + z; +}; + +BlueMap.utils.Vector2 = {}; +BlueMap.utils.Vector2.ZERO = new THREE.Vector2(0, 0); +BlueMap.utils.Vector3 = {}; +BlueMap.utils.Vector3.ZERO = new THREE.Vector3(0, 0); diff --git a/BlueMapCore/src/main/webroot/js/libs/jquery.min.js b/BlueMapCore/src/main/webroot/js/libs/jquery.min.js new file mode 100644 index 00000000..63174a0d --- /dev/null +++ b/BlueMapCore/src/main/webroot/js/libs/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
      a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
      t
      ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
      ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
      ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

      ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
      ","
      "],thead:[1,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],col:[2,"","
      "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
      ","
      "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
      ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/BlueMapCore/src/main/webroot/js/libs/three.min.js b/BlueMapCore/src/main/webroot/js/libs/three.min.js new file mode 100644 index 00000000..ea5b0c34 --- /dev/null +++ b/BlueMapCore/src/main/webroot/js/libs/three.min.js @@ -0,0 +1,946 @@ +// threejs.org/license +(function(k,za){"object"===typeof exports&&"undefined"!==typeof module?za(exports):"function"===typeof define&&define.amd?define(["exports"],za):za(k.THREE={})})(this,function(k){function za(){}function B(a,b){this.x=a||0;this.y=b||0}function R(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];0b&&(b=a[c]);return b}function D(){Object.defineProperty(this,"id",{value:Jf+=2});this.uuid=J.generateUUID();this.name="";this.type="BufferGeometry";this.index=null;this.attributes={};this.morphAttributes={};this.groups=[];this.boundingSphere=this.boundingBox=null;this.drawRange={start:0,count:Infinity};this.userData={}}function Nb(a,b,c,d,e,f){P.call(this);this.type="BoxGeometry";this.parameters={width:a,height:b,depth:c,widthSegments:d,heightSegments:e, +depthSegments:f};this.fromBufferGeometry(new pb(a,b,c,d,e,f));this.mergeVertices()}function pb(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,k,Q,M,Ob){var r=f/Q,u=g/M,O=f/2,y=g/2,x=k/2;g=Q+1;var w=M+1,C=f=0,A,B,z=new p;for(B=0;Bm;m++){if(n=d[m])if(h=n[0],l=n[1]){v&&e.addAttribute("morphTarget"+m,v[h]);f&&e.addAttribute("morphNormal"+m,f[h]);c[m]=l;continue}c[m]=0}g.getUniforms().setValue(a,"morphTargetInfluences",c)}}}function Vf(a,b){var c={};return{update:function(d){var e=b.render.frame,f=d.geometry,g=a.get(d,f);c[g.id]!==e&&(f.isGeometry&&g.updateFromObject(d), +a.update(g),c[g.id]=e);return g},dispose:function(){c={}}}}function Za(a,b,c,d,e,f,g,h,l,m){a=void 0!==a?a:[];ea.call(this,a,void 0!==b?b:301,c,d,e,f,g,h,l,m);this.flipY=!1}function Rb(a,b,c){var d=a[0];if(0>=d||0/gm,function(a,c){a=S[c];if(void 0===a)throw Error("Can not resolve #include <"+c+ +">");return Zd(a)})}function Ze(a){return a.replace(/#pragma unroll_loop[\s]+?for \( int i = (\d+); i < (\d+); i \+\+ \) \{([\s\S]+?)(?=\})\}/g,function(a,c,d,e){a="";for(c=parseInt(c);c 0 ) {\n\t\tfloat fogFactor = 0.0;\n\t\tif ( fogType == 1 ) {\n\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t\t} else {\n\t\t\tconst float LOG2 = 1.442695;\n\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );\n\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n\t\t}\n\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n\t}\n}"].join("\n")); +b.compileShader(Ca);b.compileShader(G);b.attachShader(sa,Ca);b.attachShader(sa,G);b.linkProgram(sa);U=sa;O=b.getAttribLocation(U,"position");Q=b.getAttribLocation(U,"uv");f=b.getUniformLocation(U,"uvOffset");g=b.getUniformLocation(U,"uvScale");h=b.getUniformLocation(U,"rotation");l=b.getUniformLocation(U,"center");m=b.getUniformLocation(U,"scale");v=b.getUniformLocation(U,"color");n=b.getUniformLocation(U,"map");t=b.getUniformLocation(U,"opacity");q=b.getUniformLocation(U,"modelViewMatrix");r=b.getUniformLocation(U, +"projectionMatrix");k=b.getUniformLocation(U,"fogType");y=b.getUniformLocation(U,"fogDensity");w=b.getUniformLocation(U,"fogNear");x=b.getUniformLocation(U,"fogFar");A=b.getUniformLocation(U,"fogColor");b.getUniformLocation(U,"fogDepth");C=b.getUniformLocation(U,"alphaTest");sa=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");sa.width=8;sa.height=8;Ca=sa.getContext("2d");Ca.fillStyle="white";Ca.fillRect(0,0,8,8);z=new Sb(sa)}c.useProgram(U);c.initAttributes();c.enableAttribute(O); +c.enableAttribute(Q);c.disableUnusedAttributes();c.disable(b.CULL_FACE);c.enable(b.BLEND);b.bindBuffer(b.ARRAY_BUFFER,B);b.vertexAttribPointer(O,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(Q,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,qb);b.uniformMatrix4fv(r,!1,Ob.projectionMatrix.elements);c.activeTexture(b.TEXTURE0);b.uniform1i(n,0);Ca=sa=0;(G=p.fog)?(b.uniform3f(A,G.color.r,G.color.g,G.color.b),G.isFog?(b.uniform1f(w,G.near),b.uniform1f(x,G.far),b.uniform1i(k,1),Ca=sa=1):G.isFogExp2&& +(b.uniform1f(y,G.density),b.uniform1i(k,2),Ca=sa=2)):(b.uniform1i(k,0),Ca=sa=0);G=0;for(var K=u.length;Gb||a.height>b){if("data"in a){console.warn("THREE.WebGLRenderer: image in DataTexture is too big ("+a.width+"x"+a.height+").");return}b/=Math.max(a.width,a.height);var c=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");c.width=Math.floor(a.width*b);c.height=Math.floor(a.height*b);c.getContext("2d").drawImage(a,0,0,a.width,a.height,0,0,c.width,c.height);console.warn("THREE.WebGLRenderer: image is too big ("+a.width+"x"+a.height+"). Resized to "+c.width+ +"x"+c.height,a);return c}return a}function l(a){return J.isPowerOfTwo(a.width)&&J.isPowerOfTwo(a.height)}function m(a,b){return a.generateMipmaps&&b&&1003!==a.minFilter&&1006!==a.minFilter}function v(b,c,e,f){a.generateMipmap(b);d.get(c).__maxMipLevel=Math.log(Math.max(e,f))*Math.LOG2E}function n(b){return 1003===b||1004===b||1005===b?a.NEAREST:a.LINEAR}function t(b){b=b.target;b.removeEventListener("dispose",t);a:{var c=d.get(b);if(b.image&&c.__image__webglTextureCube)a.deleteTexture(c.__image__webglTextureCube); +else{if(void 0===c.__webglInit)break a;a.deleteTexture(c.__webglTexture)}d.remove(b)}b.isVideoTexture&&delete A[b.id];g.memory.textures--}function q(b){b=b.target;b.removeEventListener("dispose",q);var c=d.get(b),e=d.get(b.texture);if(b){void 0!==e.__webglTexture&&a.deleteTexture(e.__webglTexture);b.depthTexture&&b.depthTexture.dispose();if(b.isWebGLRenderTargetCube)for(e=0;6>e;e++)a.deleteFramebuffer(c.__webglFramebuffer[e]),c.__webglDepthbuffer&&a.deleteRenderbuffer(c.__webglDepthbuffer[e]);else a.deleteFramebuffer(c.__webglFramebuffer), +c.__webglDepthbuffer&&a.deleteRenderbuffer(c.__webglDepthbuffer);d.remove(b.texture);d.remove(b)}g.memory.textures--}function k(b,n){var q=d.get(b);if(b.isVideoTexture){var k=b.id,r=g.render.frame;A[k]!==r&&(A[k]=r,b.update())}if(0p;p++)r[p]=n||k?k?b.image[p].image:b.image[p]:h(b.image[p],e.maxCubemapSize);var x=r[0],y=l(x),C=f.convert(b.format),w=f.convert(b.type);u(a.TEXTURE_CUBE_MAP,b,y);for(p=0;6>p;p++)if(n)for(var O,Q=r[p].mipmaps,A=0,B=Q.length;At;t++)e.__webglFramebuffer[t]=a.createFramebuffer()}else e.__webglFramebuffer= +a.createFramebuffer();if(h){c.bindTexture(a.TEXTURE_CUBE_MAP,f.__webglTexture);u(a.TEXTURE_CUBE_MAP,b.texture,n);for(t=0;6>t;t++)p(e.__webglFramebuffer[t],b,a.COLOR_ATTACHMENT0,a.TEXTURE_CUBE_MAP_POSITIVE_X+t);m(b.texture,n)&&v(a.TEXTURE_CUBE_MAP,b.texture,b.width,b.height);c.bindTexture(a.TEXTURE_CUBE_MAP,null)}else c.bindTexture(a.TEXTURE_2D,f.__webglTexture),u(a.TEXTURE_2D,b.texture,n),p(e.__webglFramebuffer,b,a.COLOR_ATTACHMENT0,a.TEXTURE_2D),m(b.texture,n)&&v(a.TEXTURE_2D,b.texture,b.width,b.height), +c.bindTexture(a.TEXTURE_2D,null);if(b.depthBuffer){e=d.get(b);f=!0===b.isWebGLRenderTargetCube;if(b.depthTexture){if(f)throw Error("target.depthTexture not supported in Cube render targets");if(b&&b.isWebGLRenderTargetCube)throw Error("Depth Texture with cube render targets is not supported");a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer);if(!b.depthTexture||!b.depthTexture.isDepthTexture)throw Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");d.get(b.depthTexture).__webglTexture&& +b.depthTexture.image.width===b.width&&b.depthTexture.image.height===b.height||(b.depthTexture.image.width=b.width,b.depthTexture.image.height=b.height,b.depthTexture.needsUpdate=!0);k(b.depthTexture,0);e=d.get(b.depthTexture).__webglTexture;if(1026===b.depthTexture.format)a.framebufferTexture2D(a.FRAMEBUFFER,a.DEPTH_ATTACHMENT,a.TEXTURE_2D,e,0);else if(1027===b.depthTexture.format)a.framebufferTexture2D(a.FRAMEBUFFER,a.DEPTH_STENCIL_ATTACHMENT,a.TEXTURE_2D,e,0);else throw Error("Unknown depthTexture format"); +}else if(f)for(e.__webglDepthbuffer=[],f=0;6>f;f++)a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer[f]),e.__webglDepthbuffer[f]=a.createRenderbuffer(),w(e.__webglDepthbuffer[f],b);else a.bindFramebuffer(a.FRAMEBUFFER,e.__webglFramebuffer),e.__webglDepthbuffer=a.createRenderbuffer(),w(e.__webglDepthbuffer,b);a.bindFramebuffer(a.FRAMEBUFFER,null)}};this.updateRenderTargetMipmap=function(b){var e=b.texture,f=l(b);if(m(e,f)){f=b.isWebGLRenderTargetCube?a.TEXTURE_CUBE_MAP:a.TEXTURE_2D;var g=d.get(e).__webglTexture; +c.bindTexture(f,g);v(f,e,b.width,b.height);c.bindTexture(f,null)}}}function af(a,b){return{convert:function(c){if(1E3===c)return a.REPEAT;if(1001===c)return a.CLAMP_TO_EDGE;if(1002===c)return a.MIRRORED_REPEAT;if(1003===c)return a.NEAREST;if(1004===c)return a.NEAREST_MIPMAP_NEAREST;if(1005===c)return a.NEAREST_MIPMAP_LINEAR;if(1006===c)return a.LINEAR;if(1007===c)return a.LINEAR_MIPMAP_NEAREST;if(1008===c)return a.LINEAR_MIPMAP_LINEAR;if(1009===c)return a.UNSIGNED_BYTE;if(1017===c)return a.UNSIGNED_SHORT_4_4_4_4; +if(1018===c)return a.UNSIGNED_SHORT_5_5_5_1;if(1019===c)return a.UNSIGNED_SHORT_5_6_5;if(1010===c)return a.BYTE;if(1011===c)return a.SHORT;if(1012===c)return a.UNSIGNED_SHORT;if(1013===c)return a.INT;if(1014===c)return a.UNSIGNED_INT;if(1015===c)return a.FLOAT;if(1016===c){var d=b.get("OES_texture_half_float");if(null!==d)return d.HALF_FLOAT_OES}if(1021===c)return a.ALPHA;if(1022===c)return a.RGB;if(1023===c)return a.RGBA;if(1024===c)return a.LUMINANCE;if(1025===c)return a.LUMINANCE_ALPHA;if(1026=== +c)return a.DEPTH_COMPONENT;if(1027===c)return a.DEPTH_STENCIL;if(100===c)return a.FUNC_ADD;if(101===c)return a.FUNC_SUBTRACT;if(102===c)return a.FUNC_REVERSE_SUBTRACT;if(200===c)return a.ZERO;if(201===c)return a.ONE;if(202===c)return a.SRC_COLOR;if(203===c)return a.ONE_MINUS_SRC_COLOR;if(204===c)return a.SRC_ALPHA;if(205===c)return a.ONE_MINUS_SRC_ALPHA;if(206===c)return a.DST_ALPHA;if(207===c)return a.ONE_MINUS_DST_ALPHA;if(208===c)return a.DST_COLOR;if(209===c)return a.ONE_MINUS_DST_COLOR;if(210=== +c)return a.SRC_ALPHA_SATURATE;if(33776===c||33777===c||33778===c||33779===c)if(d=b.get("WEBGL_compressed_texture_s3tc"),null!==d){if(33776===c)return d.COMPRESSED_RGB_S3TC_DXT1_EXT;if(33777===c)return d.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(33778===c)return d.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(33779===c)return d.COMPRESSED_RGBA_S3TC_DXT5_EXT}if(35840===c||35841===c||35842===c||35843===c)if(d=b.get("WEBGL_compressed_texture_pvrtc"),null!==d){if(35840===c)return d.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(35841=== +c)return d.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(35842===c)return d.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(35843===c)return d.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(36196===c&&(d=b.get("WEBGL_compressed_texture_etc1"),null!==d))return d.COMPRESSED_RGB_ETC1_WEBGL;if(37808===c||37809===c||37810===c||37811===c||37812===c||37813===c||37814===c||37815===c||37816===c||37817===c||37818===c||37819===c||37820===c||37821===c)if(d=b.get("WEBGL_compressed_texture_astc"),null!==d)return c;if(103===c||104===c)if(d=b.get("EXT_blend_minmax"), +null!==d){if(103===c)return d.MIN_EXT;if(104===c)return d.MAX_EXT}return 1020===c&&(d=b.get("WEBGL_depth_texture"),null!==d)?d.UNSIGNED_INT_24_8_WEBGL:0}}}function Ub(){H.call(this);this.type="Group"}function Z(a,b,c,d){Ra.call(this);this.type="PerspectiveCamera";this.fov=void 0!==a?a:50;this.zoom=1;this.near=void 0!==c?c:.1;this.far=void 0!==d?d:2E3;this.focus=10;this.aspect=void 0!==b?b:1;this.view=null;this.filmGauge=35;this.filmOffset=0;this.updateProjectionMatrix()}function Hc(a){Z.call(this); +this.cameras=a||[]}function bf(a){function b(){return null!==e&&!0===e.isPresenting}function c(){if(b()){var c=e.getEyeParameters("left"),f=c.renderWidth;c=c.renderHeight;w=a.getPixelRatio();y=a.getSize();a.setDrawingBufferSize(2*f,c,1);A.start()}else d.enabled&&(a.setDrawingBufferSize(y.width,y.height,w),A.stop())}var d=this,e=null,f=null,g=null,h=[],l=new R,m=new R;"undefined"!==typeof window&&"VRFrameData"in window&&(f=new window.VRFrameData,window.addEventListener("vrdisplaypresentchange",c,!1)); +var v=new R,n=new ca,t=new p,q=new Z;q.bounds=new W(0,0,.5,1);q.layers.enable(1);var k=new Z;k.bounds=new W(.5,0,.5,1);k.layers.enable(2);var u=new Hc([q,k]);u.layers.enable(1);u.layers.enable(2);var y,w,x=!1;this.enabled=!1;this.userHeight=1.6;this.getController=function(a){var b=h[a];void 0===b&&(b=new Ub,b.matrixAutoUpdate=!1,b.visible=!1,h[a]=b);return b};this.getDevice=function(){return e};this.setDevice=function(a){void 0!==a&&(e=a);A.setContext(a)};this.setPoseTarget=function(a){void 0!==a&& +(g=a)};this.getCamera=function(a){if(null===e)return a.position.set(0,d.userHeight,0),a;e.depthNear=a.near;e.depthFar=a.far;e.getFrameData(f);var b=e.stageParameters;b?l.fromArray(b.sittingToStandingTransform):l.makeTranslation(0,d.userHeight,0);b=f.pose;var c=null!==g?g:a;c.matrix.copy(l);c.matrix.decompose(c.position,c.quaternion,c.scale);null!==b.orientation&&(n.fromArray(b.orientation),c.quaternion.multiply(n));null!==b.position&&(n.setFromRotationMatrix(l),t.fromArray(b.position),t.applyQuaternion(n), +c.position.add(t));c.updateMatrixWorld();if(!1===e.isPresenting)return a;q.near=a.near;k.near=a.near;q.far=a.far;k.far=a.far;u.matrixWorld.copy(a.matrixWorld);u.matrixWorldInverse.copy(a.matrixWorldInverse);q.matrixWorldInverse.fromArray(f.leftViewMatrix);k.matrixWorldInverse.fromArray(f.rightViewMatrix);m.getInverse(l);q.matrixWorldInverse.multiply(m);k.matrixWorldInverse.multiply(m);a=c.parent;null!==a&&(v.getInverse(a.matrixWorld),q.matrixWorldInverse.multiply(v),k.matrixWorldInverse.multiply(v)); +q.matrixWorld.getInverse(q.matrixWorldInverse);k.matrixWorld.getInverse(k.matrixWorldInverse);q.projectionMatrix.fromArray(f.leftProjectionMatrix);k.projectionMatrix.fromArray(f.rightProjectionMatrix);u.projectionMatrix.copy(q.projectionMatrix);a=e.getLayers();a.length&&(a=a[0],null!==a.leftBounds&&4===a.leftBounds.length&&q.bounds.fromArray(a.leftBounds),null!==a.rightBounds&&4===a.rightBounds.length&&k.bounds.fromArray(a.rightBounds));a:for(a=0;aa.matrixWorld.determinant();aa.setMaterial(e,h);h=n(c,b.fog,e,a);I="";g(a,h,e)}else U.renderBufferDirect(c,b.fog,d,e,a,f);a.onAfterRender(U,b,c,d,e,f);z=oa.get(b,Pb||c)}function v(a,b,c){var d=Aa.get(a),g=z.state.lights;c=na.getParameters(a,g.state,z.state.shadowsArray,b,X.numPlanes,X.numIntersection,c);var h=na.getProgramCode(a,c),l=d.program,m=!0;if(void 0===l)a.addEventListener("dispose",e);else if(l.code!==h)f(a);else{if(d.lightsHash!==g.state.hash)Aa.update(a,"lightsHash",g.state.hash);else if(void 0!== +c.shaderID)return;m=!1}m&&(c.shaderID?(l=tb[c.shaderID],d.shader={name:a.type,uniforms:Ba.clone(l.uniforms),vertexShader:l.vertexShader,fragmentShader:l.fragmentShader}):d.shader={name:a.type,uniforms:a.uniforms,vertexShader:a.vertexShader,fragmentShader:a.fragmentShader},a.onBeforeCompile(d.shader,U),l=na.acquireProgram(a,d.shader,c,h),d.program=l,a.program=l);c=l.getAttributes();if(a.morphTargets)for(h=a.numSupportedMorphTargets=0;he.matrixWorld.determinant();aa.setMaterial(d,g);var h=n(a,b,d,e);a=c.id+"_"+h.id+"_"+(!0===d.wireframe);var l=!1;a!==I&&(I=a,l=!0);e.morphTargetInfluences&&(va.update(e,c,d,h),l=!0);g=c.index;var m=c.attributes.position;b=1;!0===d.wireframe&&(g=qa.getWireframeAttribute(c),b=2);a=wa;if(null!==g){var v=ja.get(g);a=xa;a.setIndex(v)}if(l){if(c&&c.isInstancedBufferGeometry&&null===ma.get("ANGLE_instanced_arrays"))console.error("THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays."); +else{aa.initAttributes();l=c.attributes;h=h.getAttributes();var t=d.defaultAttributeValues;for(A in h){var q=h[A];if(0<=q){var k=l[A];if(void 0!==k){var r=k.normalized,u=k.itemSize,p=ja.get(k);if(void 0!==p){var y=p.buffer,x=p.type;p=p.bytesPerElement;if(k.isInterleavedBufferAttribute){var w=k.data,C=w.stride;k=k.offset;w&&w.isInstancedInterleavedBuffer?(aa.enableAttributeAndDivisor(q,w.meshPerAttribute),void 0===c.maxInstancedCount&&(c.maxInstancedCount=w.meshPerAttribute*w.count)):aa.enableAttribute(q); +F.bindBuffer(F.ARRAY_BUFFER,y);F.vertexAttribPointer(q,u,x,r,C*p,k*p)}else k.isInstancedBufferAttribute?(aa.enableAttributeAndDivisor(q,k.meshPerAttribute),void 0===c.maxInstancedCount&&(c.maxInstancedCount=k.meshPerAttribute*k.count)):aa.enableAttribute(q),F.bindBuffer(F.ARRAY_BUFFER,y),F.vertexAttribPointer(q,u,x,r,0,0)}}else if(void 0!==t&&(r=t[A],void 0!==r))switch(r.length){case 2:F.vertexAttrib2fv(q,r);break;case 3:F.vertexAttrib3fv(q,r);break;case 4:F.vertexAttrib4fv(q,r);break;default:F.vertexAttrib1fv(q, +r)}}}aa.disableUnusedAttributes()}null!==g&&F.bindBuffer(F.ELEMENT_ARRAY_BUFFER,v.buffer)}v=Infinity;null!==g?v=g.count:void 0!==m&&(v=m.count);g=c.drawRange.start*b;m=null!==f?f.start*b:0;var A=Math.max(g,m);f=Math.max(0,Math.min(v,g+c.drawRange.count*b,m+(null!==f?f.count*b:Infinity))-1-A+1);if(0!==f){if(e.isMesh)if(!0===d.wireframe)aa.setLineWidth(d.wireframeLinewidth*(null===D?V:1)),a.setMode(F.LINES);else switch(e.drawMode){case 0:a.setMode(F.TRIANGLES);break;case 1:a.setMode(F.TRIANGLE_STRIP); +break;case 2:a.setMode(F.TRIANGLE_FAN)}else e.isLine?(d=d.linewidth,void 0===d&&(d=1),aa.setLineWidth(d*(null===D?V:1)),e.isLineSegments?a.setMode(F.LINES):e.isLineLoop?a.setMode(F.LINE_LOOP):a.setMode(F.LINE_STRIP)):e.isPoints&&a.setMode(F.POINTS);c&&c.isInstancedBufferGeometry?0=Sa.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+ +a+" texture units while this GPU supports only "+Sa.maxTextures);$d+=1;return a};this.setTexture2D=function(){var a=!1;return function(b,c){b&&b.isWebGLRenderTarget&&(a||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),a=!0),b=b.texture);Z.setTexture2D(b,c)}}();this.setTexture=function(){var a=!1;return function(b,c){a||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),a=!0);Z.setTexture2D(b, +c)}}();this.setTextureCube=function(){var a=!1;return function(b,c){b&&b.isWebGLRenderTargetCube&&(a||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),a=!0),b=b.texture);b&&b.isCubeTexture||Array.isArray(b.image)&&6===b.image.length?Z.setTextureCube(b,c):Z.setTextureCubeDynamic(b,c)}}();this.setFramebuffer=function(a){H=a};this.getRenderTarget=function(){return D};this.setRenderTarget=function(a){(D=a)&&void 0===Aa.get(a).__webglFramebuffer&& +Z.setupRenderTarget(a);var b=H,c=!1;a?(b=Aa.get(a).__webglFramebuffer,a.isWebGLRenderTargetCube&&(b=b[a.activeCubeFace],c=!0),db.copy(a.viewport),S.copy(a.scissor),T=a.scissorTest):(db.copy(N).multiplyScalar(V),S.copy(ba).multiplyScalar(V),T=ea);E!==b&&(F.bindFramebuffer(F.FRAMEBUFFER,b),E=b);aa.viewport(db);aa.scissor(S);aa.setScissorTest(T);c&&(c=Aa.get(a.texture),F.framebufferTexture2D(F.FRAMEBUFFER,F.COLOR_ATTACHMENT0,F.TEXTURE_CUBE_MAP_POSITIVE_X+a.activeCubeFace,c.__webglTexture,a.activeMipMapLevel))}; +this.readRenderTargetPixels=function(a,b,c,d,e,f){if(a&&a.isWebGLRenderTarget){var g=Aa.get(a).__webglFramebuffer;if(g){var h=!1;g!==E&&(F.bindFramebuffer(F.FRAMEBUFFER,g),h=!0);try{var l=a.texture,m=l.format,n=l.type;1023!==m&&ia.convert(m)!==F.getParameter(F.IMPLEMENTATION_COLOR_READ_FORMAT)?console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format."):1009===n||ia.convert(n)===F.getParameter(F.IMPLEMENTATION_COLOR_READ_TYPE)||1015=== +n&&(ma.get("OES_texture_float")||ma.get("WEBGL_color_buffer_float"))||1016===n&&ma.get("EXT_color_buffer_half_float")?F.checkFramebufferStatus(F.FRAMEBUFFER)===F.FRAMEBUFFER_COMPLETE?0<=b&&b<=a.width-d&&0<=c&&c<=a.height-e&&F.readPixels(b,c,d,e,ia.convert(m),ia.convert(n),f):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete."):console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.")}finally{h&& +F.bindFramebuffer(F.FRAMEBUFFER,E)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")};this.copyFramebufferToTexture=function(a,b,c){var d=b.image.width,e=b.image.height,f=ia.convert(b.format);this.setTexture2D(b,0);F.copyTexImage2D(F.TEXTURE_2D,c||0,f,a.x,a.y,d,e,0)};this.copyTextureToTexture=function(a,b,c,d){var e=b.image.width,f=b.image.height,g=ia.convert(c.format),h=ia.convert(c.type);this.setTexture2D(c,0);b.isDataTexture?F.texSubImage2D(F.TEXTURE_2D, +d||0,a.x,a.y,e,f,g,h,b.image.data):F.texSubImage2D(F.TEXTURE_2D,d||0,a.x,a.y,g,h,b.image)}}function Vb(a,b){this.name="";this.color=new G(a);this.density=void 0!==b?b:2.5E-4}function Wb(a,b,c){this.name="";this.color=new G(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3}function vd(){H.call(this);this.type="Scene";this.overrideMaterial=this.fog=this.background=null;this.autoUpdate=!0}function ib(a){I.call(this);this.type="SpriteMaterial";this.color=new G(16777215);this.map=null;this.rotation= +0;this.lights=this.fog=!1;this.setValues(a)}function Ic(a){H.call(this);this.type="Sprite";this.material=void 0!==a?a:new ib;this.center=new B(.5,.5)}function Jc(){H.call(this);this.type="LOD";Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function Kc(a,b){a=a||[];this.bones=a.slice(0);this.boneMatrices=new Float32Array(16*this.bones.length);if(void 0===b)this.calculateInverses();else if(this.bones.length===b.length)this.boneInverses=b.slice(0);else for(console.warn("THREE.Skeleton boneInverses is the wrong length."), +this.boneInverses=[],a=0,b=this.bones.length;ac;c++){var n=v[h[c]];var t=v[h[(c+1)%3]];f[0]=Math.min(n,t);f[1]=Math.max(n,t);n=f[0]+","+f[1];void 0===g[n]&&(g[n]={index1:f[0],index2:f[1]})}}for(n in g)m=g[n],h=a.vertices[m.index1],b.push(h.x,h.y,h.z),h=a.vertices[m.index2],b.push(h.x,h.y,h.z)}else if(a&&a.isBufferGeometry)if(h=new p,null!==a.index){l=a.attributes.position;v=a.index;var q=a.groups;0===q.length&&(q=[{start:0,count:v.count,materialIndex:0}]);a=0;for(e=q.length;ac;c++)n=v.getX(m+c),t=v.getX(m+(c+1)%3),f[0]=Math.min(n,t),f[1]=Math.max(n,t),n=f[0]+","+f[1],void 0===g[n]&&(g[n]={index1:f[0],index2:f[1]});for(n in g)m=g[n],h.fromBufferAttribute(l,m.index1),b.push(h.x,h.y,h.z),h.fromBufferAttribute(l,m.index2),b.push(h.x,h.y,h.z)}else for(l=a.attributes.position,m=0,d=l.count/3;mc;c++)g=3*m+c,h.fromBufferAttribute(l,g),b.push(h.x,h.y,h.z),g=3*m+(c+1)%3,h.fromBufferAttribute(l,g),b.push(h.x, +h.y,h.z);this.addAttribute("position",new z(b,3))}function Mc(a,b,c){P.call(this);this.type="ParametricGeometry";this.parameters={func:a,slices:b,stacks:c};this.fromBufferGeometry(new $b(a,b,c));this.mergeVertices()}function $b(a,b,c){D.call(this);this.type="ParametricBufferGeometry";this.parameters={func:a,slices:b,stacks:c};var d=[],e=[],f=[],g=[],h=new p,l=new p,m=new p,v=new p,n=new p,t,q;3>a.length&&console.error("THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter."); +var k=b+1;for(t=0;t<=c;t++){var u=t/c;for(q=0;q<=b;q++){var y=q/b;a(y,u,l);e.push(l.x,l.y,l.z);0<=y-1E-5?(a(y-1E-5,u,m),v.subVectors(l,m)):(a(y+1E-5,u,m),v.subVectors(m,l));0<=u-1E-5?(a(y,u-1E-5,m),n.subVectors(l,m)):(a(y,u+1E-5,m),n.subVectors(m,l));h.crossVectors(v,n).normalize();f.push(h.x,h.y,h.z);g.push(y,u)}}for(t=0;td&&1===a.x&&(l[b]=a.x-1);0===c.x&&0===c.z&&(l[b]=d/2/Math.PI+.5)}D.call(this);this.type="PolyhedronBufferGeometry";this.parameters={vertices:a, +indices:b,radius:c,detail:d};c=c||1;d=d||0;var h=[],l=[];(function(a){for(var c=new p,d=new p,g=new p,h=0;he&&(.2>b&&(l[a+0]+=1),.2>c&&(l[a+2]+=1),.2>d&&(l[a+4]+=1))})();this.addAttribute("position",new z(h,3));this.addAttribute("normal",new z(h.slice(),3));this.addAttribute("uv",new z(l,2));0===d?this.computeVertexNormals():this.normalizeNormals()}function Oc(a, +b){P.call(this);this.type="TetrahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new ac(a,b));this.mergeVertices()}function ac(a,b){xa.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],a,b);this.type="TetrahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Pc(a,b){P.call(this);this.type="OctahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new ub(a,b));this.mergeVertices()}function ub(a,b){xa.call(this,[1,0,0, +-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],a,b);this.type="OctahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Qc(a,b){P.call(this);this.type="IcosahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new bc(a,b));this.mergeVertices()}function bc(a,b){var c=(1+Math.sqrt(5))/2;xa.call(this,[-1,c,0,1,c,0,-1,-c,0,1,-c,0,0,-1,c,0,1,c,0,-1,-c,0,1,-c,c,0,-1,c,0,1,-c,0,-1,-c,0,1],[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5, +11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],a,b);this.type="IcosahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Rc(a,b){P.call(this);this.type="DodecahedronGeometry";this.parameters={radius:a,detail:b};this.fromBufferGeometry(new cc(a,b));this.mergeVertices()}function cc(a,b){var c=(1+Math.sqrt(5))/2,d=1/c;xa.call(this,[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-d,-c,0,-d,c,0,d,-c,0,d,c,-d,-c,0,-d,c,0,d,-c,0,d,c, +0,-c,0,-d,c,0,-d,-c,0,d,c,0,d],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],a,b);this.type="DodecahedronBufferGeometry";this.parameters={radius:a,detail:b}}function Sc(a,b,c,d,e,f){P.call(this);this.type="TubeGeometry";this.parameters={path:a,tubularSegments:b,radius:c,radialSegments:d, +closed:e};void 0!==f&&console.warn("THREE.TubeGeometry: taper has been removed.");a=new dc(a,b,c,d,e);this.tangents=a.tangents;this.normals=a.normals;this.binormals=a.binormals;this.fromBufferGeometry(a);this.mergeVertices()}function dc(a,b,c,d,e){function f(e){v=a.getPointAt(e/b,v);var f=g.normals[e];e=g.binormals[e];for(k=0;k<=d;k++){var m=k/d*Math.PI*2,n=Math.sin(m);m=-Math.cos(m);l.x=m*f.x+n*e.x;l.y=m*f.y+n*e.y;l.z=m*f.z+n*e.z;l.normalize();r.push(l.x,l.y,l.z);h.x=v.x+c*l.x;h.y=v.y+c*l.y;h.z= +v.z+c*l.z;q.push(h.x,h.y,h.z)}}D.call(this);this.type="TubeBufferGeometry";this.parameters={path:a,tubularSegments:b,radius:c,radialSegments:d,closed:e};b=b||64;c=c||1;d=d||8;e=e||!1;var g=a.computeFrenetFrames(b,e);this.tangents=g.tangents;this.normals=g.normals;this.binormals=g.binormals;var h=new p,l=new p,m=new B,v=new p,n,k,q=[],r=[],u=[],y=[];for(n=0;n=b;e-=d)f=df(e,a[e],a[e+1],f);f&&vb(f,f.next)&&(Vc(f),f=f.next);return f}function Wc(a,b){if(!a)return a;b||(b=a);do{var c=!1;if(a.steiner||!vb(a,a.next)&&0!==oa(a.prev,a,a.next))a=a.next;else{Vc(a);a=b=a.prev;if(a===a.next)break;c=!0}}while(c||a!==b);return b} +function Xc(a,b,c,d,e,f,g){if(a){if(!g&&f){var h=a,l=h;do null===l.z&&(l.z=ce(l.x,l.y,d,e,f)),l.prevZ=l.prev,l=l.nextZ=l.next;while(l!==h);l.prevZ.nextZ=null;l.prevZ=null;h=l;var m,v,n,k,q=1;do{l=h;var r=h=null;for(v=0;l;){v++;var p=l;for(m=n=0;mn.x?v.x>q.x?v.x:q.x:n.x>q.x?n.x:q.x,A=v.y>n.y?v.y>q.y?v.y:q.y:n.y>q.y?n.y:q.y;m=ce(v.x=m;){if(y!==r.prev&&y!==r.next&&zd(v.x,v.y,n.x,n.y,q.x,q.y,y.x,y.y)&&0<=oa(y.prev,y,y.next)){r=!1;break a}y= +y.prevZ}r=!0}}else a:if(r=a,v=r.prev,n=r,q=r.next,0<=oa(v,n,q))r=!1;else{for(m=r.next.next;m!==r.prev;){if(zd(v.x,v.y,n.x,n.y,q.x,q.y,m.x,m.y)&&0<=oa(m.prev,m,m.next)){r=!1;break a}m=m.next}r=!0}if(r)b.push(l.i/c),b.push(a.i/c),b.push(p.i/c),Vc(a),h=a=p.next;else if(a=p,a===h){if(!g)Xc(Wc(a),b,c,d,e,f,1);else if(1===g){g=b;h=c;l=a;do p=l.prev,r=l.next.next,!vb(p,r)&&ef(p,l,l.next,r)&&Yc(p,r)&&Yc(r,p)&&(g.push(p.i/h),g.push(l.i/h),g.push(r.i/h),Vc(l),Vc(l.next),l=a=r),l=l.next;while(l!==a);a=l;Xc(a, +b,c,d,e,f,2)}else if(2===g)a:{g=a;do{for(h=g.next.next;h!==g.prev;){if(l=g.i!==h.i){l=g;p=h;if(r=l.next.i!==p.i&&l.prev.i!==p.i){b:{r=l;do{if(r.i!==l.i&&r.next.i!==l.i&&r.i!==p.i&&r.next.i!==p.i&&ef(r,r.next,l,p)){r=!0;break b}r=r.next}while(r!==l);r=!1}r=!r}if(r=r&&Yc(l,p)&&Yc(p,l)){r=l;v=!1;n=(l.x+p.x)/2;p=(l.y+p.y)/2;do r.y>p!==r.next.y>p&&r.next.y!==r.y&&n<(r.next.x-r.x)*(p-r.y)/(r.next.y-r.y)+r.x&&(v=!v),r=r.next;while(r!==l);r=v}l=r}if(l){a=ff(g,h);g=Wc(g,g.next);a=Wc(a,a.next);Xc(g,b,c,d,e, +f);Xc(a,b,c,d,e,f);break a}h=h.next}g=g.next}while(g!==a)}break}}}}function Pg(a,b){return a.x-b.x}function Qg(a,b){var c=b,d=a.x,e=a.y,f=-Infinity;do{if(e<=c.y&&e>=c.next.y&&c.next.y!==c.y){var g=c.x+(e-c.y)*(c.next.x-c.x)/(c.next.y-c.y);if(g<=d&&g>f){f=g;if(g===d){if(e===c.y)return c;if(e===c.next.y)return c.next}var h=c.x=c.x&&c.x>=g&&d!==c.x&&zd(eh.x)&&Yc(c,a)&&(h=c,m=v)}c=c.next}return h}function ce(a,b,c,d,e){a=32767*(a-c)*e;b=32767*(b-d)*e;a=(a|a<<8)&16711935;a=(a|a<<4)&252645135;a=(a|a<<2)&858993459;b=(b|b<<8)&16711935;b=(b|b<<4)&252645135;b=(b|b<<2)&858993459;return(a|a<<1)&1431655765|((b|b<<1)&1431655765)<<1}function Rg(a){var b=a,c=a;do b.xoa(a.prev,a,a.next)?0<=oa(a,b,a.next)&&0<=oa(a,a.prev,b):0>oa(a,b,a.prev)||0>oa(a,a.next,b)}function ff(a,b){var c=new de(a.i,a.x,a.y),d=new de(b.i,b.x,b.y),e=a.next,f=b.prev;a.next=b;b.prev=a;c.next=e;e.prev= +c;d.next=c;c.prev=d;f.next=d;d.prev=f;return d}function df(a,b,c,d){a=new de(a,b,c);d?(a.next=d.next,a.prev=d,d.next.prev=a,d.next=a):(a.prev=a,a.next=a);return a}function Vc(a){a.next.prev=a.prev;a.prev.next=a.next;a.prevZ&&(a.prevZ.nextZ=a.nextZ);a.nextZ&&(a.nextZ.prevZ=a.prevZ)}function de(a,b,c){this.i=a;this.x=b;this.y=c;this.nextZ=this.prevZ=this.z=this.next=this.prev=null;this.steiner=!1}function gf(a){var b=a.length;2Number.EPSILON){var l=Math.sqrt(h),m=Math.sqrt(f*f+g*g);h=b.x-e/l;b=b.y+d/l; +g=((c.x-g/m-h)*g-(c.y+f/m-b)*f)/(d*g-e*f);f=h+d*g-a.x;d=b+e*g-a.y;e=f*f+d*d;if(2>=e)return new B(f,d);e=Math.sqrt(e/2)}else a=!1,d>Number.EPSILON?f>Number.EPSILON&&(a=!0):d<-Number.EPSILON?f<-Number.EPSILON&&(a=!0):Math.sign(e)===Math.sign(g)&&(a=!0),a?(f=-e,e=Math.sqrt(h)):(f=d,d=e,e=Math.sqrt(h/2));return new B(f/e,d/e)}function h(a,b){for(N=a.length;0<=--N;){var c=N;var f=N-1;0>f&&(f=a.length-1);var g,h=x+2*M;for(g=0;gk;k++){var n=m[f[k]];var t=m[f[(k+1)%3]];d[0]=Math.min(n,t);d[1]=Math.max(n,t);n=d[0]+","+d[1];void 0===e[n]?e[n]={index1:d[0],index2:d[1],face1:h,face2:void 0}:e[n].face2=h}for(n in e)if(d=e[n],void 0===d.face2||g[d.face1].normal.dot(g[d.face2].normal)<=b)f=a[d.index1], +c.push(f.x,f.y,f.z),f=a[d.index2],c.push(f.x,f.y,f.z);this.addAttribute("position",new z(c,3))}function Ab(a,b,c,d,e,f,g,h){P.call(this);this.type="CylinderGeometry";this.parameters={radiusTop:a,radiusBottom:b,height:c,radialSegments:d,heightSegments:e,openEnded:f,thetaStart:g,thetaLength:h};this.fromBufferGeometry(new ab(a,b,c,d,e,f,g,h));this.mergeVertices()}function ab(a,b,c,d,e,f,g,h){function l(c){var e,f=new B,l=new p,v=0,u=!0===c?a:b,x=!0===c?1:-1;var z=r;for(e=1;e<=d;e++)n.push(0,y*x,0),t.push(0, +x,0),q.push(.5,.5),r++;var G=r;for(e=0;e<=d;e++){var H=e/d*h+g,D=Math.cos(H);H=Math.sin(H);l.x=u*H;l.y=y*x;l.z=u*D;n.push(l.x,l.y,l.z);t.push(0,x,0);f.x=.5*D+.5;f.y=.5*H*x+.5;q.push(f.x,f.y);r++}for(e=0;ethis.duration&&this.resetDuration();this.optimize()}function Pd(a){this.manager=void 0!==a?a:ya;this.textures={}}function ie(a){this.manager=void 0!==a?a: +ya}function pc(){}function je(a){"boolean"===typeof a&&(console.warn("THREE.JSONLoader: showStatus parameter has been removed from constructor."),a=void 0);this.manager=void 0!==a?a:ya;this.withCredentials=!1}function nf(a){this.manager=void 0!==a?a:ya;this.texturePath=""}function ke(a){"undefined"===typeof createImageBitmap&&console.warn("THREE.ImageBitmapLoader: createImageBitmap() not supported.");"undefined"===typeof fetch&&console.warn("THREE.ImageBitmapLoader: fetch() not supported.");this.manager= +void 0!==a?a:ya;this.options=void 0}function le(){this.type="ShapePath";this.color=new G;this.subPaths=[];this.currentPath=null}function me(a){this.type="Font";this.data=a}function of(a){this.manager=void 0!==a?a:ya}function ne(a){this.manager=void 0!==a?a:ya}function pf(){this.type="StereoCamera";this.aspect=1;this.eyeSep=.064;this.cameraL=new Z;this.cameraL.layers.enable(1);this.cameraL.matrixAutoUpdate=!1;this.cameraR=new Z;this.cameraR.layers.enable(2);this.cameraR.matrixAutoUpdate=!1}function kd(a, +b,c){H.call(this);this.type="CubeCamera";var d=new Z(90,1,a,b);d.up.set(0,-1,0);d.lookAt(new p(1,0,0));this.add(d);var e=new Z(90,1,a,b);e.up.set(0,-1,0);e.lookAt(new p(-1,0,0));this.add(e);var f=new Z(90,1,a,b);f.up.set(0,0,1);f.lookAt(new p(0,1,0));this.add(f);var g=new Z(90,1,a,b);g.up.set(0,0,-1);g.lookAt(new p(0,-1,0));this.add(g);var h=new Z(90,1,a,b);h.up.set(0,-1,0);h.lookAt(new p(0,0,1));this.add(h);var l=new Z(90,1,a,b);l.up.set(0,-1,0);l.lookAt(new p(0,0,-1));this.add(l);this.renderTarget= +new Lb(c,c,{format:1022,magFilter:1006,minFilter:1006});this.renderTarget.texture.name="CubeCamera";this.update=function(a,b){null===this.parent&&this.updateMatrixWorld();var c=this.renderTarget,m=c.texture.generateMipmaps;c.texture.generateMipmaps=!1;c.activeCubeFace=0;a.render(b,d,c);c.activeCubeFace=1;a.render(b,e,c);c.activeCubeFace=2;a.render(b,f,c);c.activeCubeFace=3;a.render(b,g,c);c.activeCubeFace=4;a.render(b,h,c);c.texture.generateMipmaps=m;c.activeCubeFace=5;a.render(b,l,c);a.setRenderTarget(null)}; +this.clear=function(a,b,c,d){for(var e=this.renderTarget,f=0;6>f;f++)e.activeCubeFace=f,a.setRenderTarget(e),a.clear(b,c,d);a.setRenderTarget(null)}}function oe(){H.call(this);this.type="AudioListener";this.context=pe.getContext();this.gain=this.context.createGain();this.gain.connect(this.context.destination);this.filter=null}function qc(a){H.call(this);this.type="Audio";this.context=a.context;this.gain=this.context.createGain();this.gain.connect(a.getInput());this.autoplay=!1;this.buffer=null;this.loop= +!1;this.offset=this.startTime=0;this.playbackRate=1;this.isPlaying=!1;this.hasPlaybackControl=!0;this.sourceType="empty";this.filters=[]}function qe(a){qc.call(this,a);this.panner=this.context.createPanner();this.panner.connect(this.gain)}function re(a,b){this.analyser=a.context.createAnalyser();this.analyser.fftSize=void 0!==b?b:2048;this.data=new Uint8Array(this.analyser.frequencyBinCount);a.getOutput().connect(this.analyser)}function se(a,b,c){this.binding=a;this.valueSize=c;a=Float64Array;switch(b){case "quaternion":b= +this._slerp;break;case "string":case "bool":a=Array;b=this._select;break;default:b=this._lerp}this.buffer=new a(4*c);this._mixBufferRegion=b;this.referenceCount=this.useCount=this.cumulativeWeight=0}function qf(a,b,c){c=c||ra.parseTrackName(b);this._targetGroup=a;this._bindings=a.subscribe_(b,c)}function ra(a,b,c){this.path=b;this.parsedPath=c||ra.parseTrackName(b);this.node=ra.findNode(a,this.parsedPath.nodeName)||a;this.rootNode=a}function rf(){this.uuid=J.generateUUID();this._objects=Array.prototype.slice.call(arguments); +this.nCachedObjects_=0;var a={};this._indicesByUUID=a;for(var b=0,c=arguments.length;b!==c;++b)a[arguments[b].uuid]=b;this._paths=[];this._parsedPaths=[];this._bindings=[];this._bindingsIndicesByPath={};var d=this;this.stats={objects:{get total(){return d._objects.length},get inUse(){return this.total-d.nCachedObjects_}},get bindingsPerObject(){return d._bindings.length}}}function sf(a,b,c){this._mixer=a;this._clip=b;this._localRoot=c||null;a=b.tracks;b=a.length;c=Array(b);for(var d={endingStart:2400, +endingEnd:2400},e=0;e!==b;++e){var f=a[e].createInterpolant(null);c[e]=f;f.settings=d}this._interpolantSettings=d;this._interpolants=c;this._propertyBindings=Array(b);this._weightInterpolant=this._timeScaleInterpolant=this._byClipCacheIndex=this._cacheIndex=null;this.loop=2201;this._loopCount=-1;this._startTime=null;this.time=0;this._effectiveWeight=this.weight=this._effectiveTimeScale=this.timeScale=1;this.repetitions=Infinity;this.paused=!1;this.enabled=!0;this.clampWhenFinished=!1;this.zeroSlopeAtEnd= +this.zeroSlopeAtStart=!0}function te(a){this._root=a;this._initMemoryManager();this.time=this._accuIndex=0;this.timeScale=1}function Qd(a,b){"string"===typeof a&&(console.warn("THREE.Uniform: Type parameter is no longer needed."),a=b);this.value=a}function ue(){D.call(this);this.type="InstancedBufferGeometry";this.maxInstancedCount=void 0}function ve(a,b,c,d){this.data=a;this.itemSize=b;this.offset=c;this.normalized=!0===d}function rc(a,b){this.array=a;this.stride=b;this.count=void 0!==a?a.length/ +b:0;this.dynamic=!1;this.updateRange={offset:0,count:-1};this.version=0}function we(a,b,c){rc.call(this,a,b);this.meshPerAttribute=c||1}function xe(a,b,c){L.call(this,a,b);this.meshPerAttribute=c||1}function tf(a,b,c,d){this.ray=new sb(a,b);this.near=c||0;this.far=d||Infinity;this.params={Mesh:{},Line:{},LOD:{},Points:{threshold:1},Sprite:{}};Object.defineProperties(this.params,{PointCloud:{get:function(){console.warn("THREE.Raycaster: params.PointCloud has been renamed to params.Points.");return this.Points}}})} +function uf(a,b){return a.distance-b.distance}function ye(a,b,c,d){if(!1!==a.visible&&(a.raycast(b,c),!0===d)){a=a.children;d=0;for(var e=a.length;dc;c++,d++){var e=c/32*Math.PI*2,f=d/32*Math.PI*2;b.push(Math.cos(e),Math.sin(e),1,Math.cos(f),Math.sin(f),1)}a.addAttribute("position",new z(b,3));b=new T({fog:!1});this.cone=new Y(a,b);this.add(this.cone);this.update()}function yf(a){var b=[];a&&a.isBone&& +b.push(a);for(var c=0;ca?-1:0b;b++)a[b]=(16>b?"0":"")+b.toString(16);return function(){var b=4294967295*Math.random()|0,d=4294967295*Math.random()|0,e=4294967295* +Math.random()|0,f=4294967295*Math.random()|0;return(a[b&255]+a[b>>8&255]+a[b>>16&255]+a[b>>24&255]+"-"+a[d&255]+a[d>>8&255]+"-"+a[d>>16&15|64]+a[d>>24&255]+"-"+a[e&63|128]+a[e>>8&255]+"-"+a[e>>16&255]+a[e>>24&255]+a[f&255]+a[f>>8&255]+a[f>>16&255]+a[f>>24&255]).toUpperCase()}}(),clamp:function(a,b,c){return Math.max(b,Math.min(c,a))},euclideanModulo:function(a,b){return(a%b+b)%b},mapLinear:function(a,b,c,d,e){return d+(a-b)*(e-d)/(c-b)},lerp:function(a,b,c){return(1-c)*a+c*b},smoothstep:function(a, +b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*(3-2*a)},smootherstep:function(a,b,c){if(a<=b)return 0;if(a>=c)return 1;a=(a-b)/(c-b);return a*a*a*(a*(6*a-15)+10)},randInt:function(a,b){return a+Math.floor(Math.random()*(b-a+1))},randFloat:function(a,b){return a+Math.random()*(b-a)},randFloatSpread:function(a){return a*(.5-Math.random())},degToRad:function(a){return a*J.DEG2RAD},radToDeg:function(a){return a*J.RAD2DEG},isPowerOfTwo:function(a){return 0===(a&a-1)&&0!==a},ceilPowerOfTwo:function(a){return Math.pow(2, +Math.ceil(Math.log(a)/Math.LN2))},floorPowerOfTwo:function(a){return Math.pow(2,Math.floor(Math.log(a)/Math.LN2))}};Object.defineProperties(B.prototype,{width:{get:function(){return this.x},set:function(a){this.x=a}},height:{get:function(){return this.y},set:function(a){this.y=a}}});Object.assign(B.prototype,{isVector2:!0,set:function(a,b){this.x=a;this.y=b;return this},setScalar:function(a){this.y=this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this}, +setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;default:throw Error("index is out of range: "+a);}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(a){this.x=a.x;this.y=a.y;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."), +this.addVectors(a,b);this.x+=a.x;this.y+=a.y;return this},addScalar:function(a){this.x+=a;this.y+=a;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addScaledVector:function(a,b){this.x+=a.x*b;this.y+=a.y*b;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;return this},subScalar:function(a){this.x-=a;this.y-=a;return this}, +subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},multiply:function(a){this.x*=a.x;this.y*=a.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this},divide:function(a){this.x/=a.x;this.y/=a.y;return this},divideScalar:function(a){return this.multiplyScalar(1/a)},applyMatrix3:function(a){var b=this.x,c=this.y;a=a.elements;this.x=a[0]*b+a[3]*c+a[6];this.y=a[1]*b+a[4]*c+a[7];return this},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);return this}, +max:function(a){this.x=Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);return this},clamp:function(a,b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y=Math.max(a.y,Math.min(b.y,this.y));return this},clampScalar:function(){var a=new B,b=new B;return function(c,d){a.set(c,c);b.set(d,d);return this.clamp(a,b)}}(),clampLength:function(a,b){var c=this.length();return this.divideScalar(c||1).multiplyScalar(Math.max(a,Math.min(b,c)))},floor:function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y); +return this},ceil:function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this},round:function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this},roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);return this},negate:function(){this.x=-this.x;this.y=-this.y;return this},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x* +this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){var a=Math.atan2(this.y,this.x);0>a&&(a+=2*Math.PI);return a},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x;a=this.y-a.y;return b*b+a*a},manhattanDistanceTo:function(a){return Math.abs(this.x-a.x)+Math.abs(this.y-a.y)},setLength:function(a){return this.normalize().multiplyScalar(a)}, +lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},equals:function(a){return a.x===this.x&&a.y===this.y},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+1];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;return a},fromBufferAttribute:function(a,b,c){void 0!==c&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."); +this.x=a.getX(b);this.y=a.getY(b);return this},rotateAround:function(a,b){var c=Math.cos(b);b=Math.sin(b);var d=this.x-a.x,e=this.y-a.y;this.x=d*c-e*b+a.x;this.y=d*b+e*c+a.y;return this}});Object.assign(R.prototype,{isMatrix4:!0,set:function(a,b,c,d,e,f,g,h,l,m,k,n,t,q,r,p){var v=this.elements;v[0]=a;v[4]=b;v[8]=c;v[12]=d;v[1]=e;v[5]=f;v[9]=g;v[13]=h;v[2]=l;v[6]=m;v[10]=k;v[14]=n;v[3]=t;v[7]=q;v[11]=r;v[15]=p;return this},identity:function(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this}, +clone:function(){return(new R).fromArray(this.elements)},copy:function(a){var b=this.elements;a=a.elements;b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return this},copyPosition:function(a){var b=this.elements;a=a.elements;b[12]=a[12];b[13]=a[13];b[14]=a[14];return this},extractBasis:function(a,b,c){a.setFromMatrixColumn(this,0);b.setFromMatrixColumn(this,1);c.setFromMatrixColumn(this, +2);return this},makeBasis:function(a,b,c){this.set(a.x,b.x,c.x,0,a.y,b.y,c.y,0,a.z,b.z,c.z,0,0,0,0,1);return this},extractRotation:function(){var a=new p;return function(b){var c=this.elements,d=b.elements,e=1/a.setFromMatrixColumn(b,0).length(),f=1/a.setFromMatrixColumn(b,1).length();b=1/a.setFromMatrixColumn(b,2).length();c[0]=d[0]*e;c[1]=d[1]*e;c[2]=d[2]*e;c[3]=0;c[4]=d[4]*f;c[5]=d[5]*f;c[6]=d[6]*f;c[7]=0;c[8]=d[8]*b;c[9]=d[9]*b;c[10]=d[10]*b;c[11]=0;c[12]=0;c[13]=0;c[14]=0;c[15]=1;return this}}(), +makeRotationFromEuler:function(a){a&&a.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var b=this.elements,c=a.x,d=a.y,e=a.z,f=Math.cos(c);c=Math.sin(c);var g=Math.cos(d);d=Math.sin(d);var h=Math.cos(e);e=Math.sin(e);if("XYZ"===a.order){a=f*h;var l=f*e,m=c*h,k=c*e;b[0]=g*h;b[4]=-g*e;b[8]=d;b[1]=l+m*d;b[5]=a-k*d;b[9]=-c*g;b[2]=k-a*d;b[6]=m+l*d;b[10]=f*g}else"YXZ"===a.order?(a=g*h,l=g*e,m=d*h,k=d*e,b[0]=a+k*c,b[4]=m*c-l, +b[8]=f*d,b[1]=f*e,b[5]=f*h,b[9]=-c,b[2]=l*c-m,b[6]=k+a*c,b[10]=f*g):"ZXY"===a.order?(a=g*h,l=g*e,m=d*h,k=d*e,b[0]=a-k*c,b[4]=-f*e,b[8]=m+l*c,b[1]=l+m*c,b[5]=f*h,b[9]=k-a*c,b[2]=-f*d,b[6]=c,b[10]=f*g):"ZYX"===a.order?(a=f*h,l=f*e,m=c*h,k=c*e,b[0]=g*h,b[4]=m*d-l,b[8]=a*d+k,b[1]=g*e,b[5]=k*d+a,b[9]=l*d-m,b[2]=-d,b[6]=c*g,b[10]=f*g):"YZX"===a.order?(a=f*g,l=f*d,m=c*g,k=c*d,b[0]=g*h,b[4]=k-a*e,b[8]=m*e+l,b[1]=e,b[5]=f*h,b[9]=-c*h,b[2]=-d*h,b[6]=l*e+m,b[10]=a-k*e):"XZY"===a.order&&(a=f*g,l=f*d,m=c*g,k= +c*d,b[0]=g*h,b[4]=-e,b[8]=d*h,b[1]=a*e+k,b[5]=f*h,b[9]=l*e-m,b[2]=m*e-l,b[6]=c*h,b[10]=k*e+a);b[3]=0;b[7]=0;b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return this},makeRotationFromQuaternion:function(){var a=new p(0,0,0),b=new p(1,1,1);return function(c){return this.compose(a,c,b)}}(),lookAt:function(){var a=new p,b=new p,c=new p;return function(d,e,f){var g=this.elements;c.subVectors(d,e);0===c.lengthSq()&&(c.z=1);c.normalize();a.crossVectors(f,c);0===a.lengthSq()&&(1===Math.abs(f.z)?c.x+=1E-4:c.z+= +1E-4,c.normalize(),a.crossVectors(f,c));a.normalize();b.crossVectors(c,a);g[0]=a.x;g[4]=b.x;g[8]=c.x;g[1]=a.y;g[5]=b.y;g[9]=c.y;g[2]=a.z;g[6]=b.z;g[10]=c.z;return this}}(),multiply:function(a,b){return void 0!==b?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(a,b)):this.multiplyMatrices(this,a)},premultiply:function(a){return this.multiplyMatrices(a,this)},multiplyMatrices:function(a,b){var c=a.elements,d=b.elements; +b=this.elements;a=c[0];var e=c[4],f=c[8],g=c[12],h=c[1],l=c[5],m=c[9],k=c[13],n=c[2],t=c[6],q=c[10],r=c[14],p=c[3],y=c[7],w=c[11];c=c[15];var x=d[0],A=d[4],C=d[8],O=d[12],Q=d[1],z=d[5],B=d[9],H=d[13],G=d[2],D=d[6],E=d[10],J=d[14],L=d[3],I=d[7],K=d[11];d=d[15];b[0]=a*x+e*Q+f*G+g*L;b[4]=a*A+e*z+f*D+g*I;b[8]=a*C+e*B+f*E+g*K;b[12]=a*O+e*H+f*J+g*d;b[1]=h*x+l*Q+m*G+k*L;b[5]=h*A+l*z+m*D+k*I;b[9]=h*C+l*B+m*E+k*K;b[13]=h*O+l*H+m*J+k*d;b[2]=n*x+t*Q+q*G+r*L;b[6]=n*A+t*z+q*D+r*I;b[10]=n*C+t*B+q*E+r*K;b[14]=n* +O+t*H+q*J+r*d;b[3]=p*x+y*Q+w*G+c*L;b[7]=p*A+y*z+w*D+c*I;b[11]=p*C+y*B+w*E+c*K;b[15]=p*O+y*H+w*J+c*d;return this},multiplyScalar:function(a){var b=this.elements;b[0]*=a;b[4]*=a;b[8]*=a;b[12]*=a;b[1]*=a;b[5]*=a;b[9]*=a;b[13]*=a;b[2]*=a;b[6]*=a;b[10]*=a;b[14]*=a;b[3]*=a;b[7]*=a;b[11]*=a;b[15]*=a;return this},applyToBufferAttribute:function(){var a=new p;return function(b){for(var c=0,d=b.count;cthis.determinant()&&(g=-g);c.x=f[12];c.y=f[13];c.z=f[14];b.copy(this);c=1/g;f=1/h;var m=1/l;b.elements[0]*=c; +b.elements[1]*=c;b.elements[2]*=c;b.elements[4]*=f;b.elements[5]*=f;b.elements[6]*=f;b.elements[8]*=m;b.elements[9]*=m;b.elements[10]*=m;d.setFromRotationMatrix(b);e.x=g;e.y=h;e.z=l;return this}}(),makePerspective:function(a,b,c,d,e,f){void 0===f&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");var g=this.elements;g[0]=2*e/(b-a);g[4]=0;g[8]=(b+a)/(b-a);g[12]=0;g[1]=0;g[5]=2*e/(c-d);g[9]=(c+d)/(c-d);g[13]=0;g[2]=0;g[6]=0;g[10]=-(f+ +e)/(f-e);g[14]=-2*f*e/(f-e);g[3]=0;g[7]=0;g[11]=-1;g[15]=0;return this},makeOrthographic:function(a,b,c,d,e,f){var g=this.elements,h=1/(b-a),l=1/(c-d),m=1/(f-e);g[0]=2*h;g[4]=0;g[8]=0;g[12]=-((b+a)*h);g[1]=0;g[5]=2*l;g[9]=0;g[13]=-((c+d)*l);g[2]=0;g[6]=0;g[10]=-2*m;g[14]=-((f+e)*m);g[3]=0;g[7]=0;g[11]=0;g[15]=1;return this},equals:function(a){var b=this.elements;a=a.elements;for(var c=0;16>c;c++)if(b[c]!==a[c])return!1;return!0},fromArray:function(a,b){void 0===b&&(b=0);for(var c=0;16>c;c++)this.elements[c]= +a[c+b];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);var c=this.elements;a[b]=c[0];a[b+1]=c[1];a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];a[b+9]=c[9];a[b+10]=c[10];a[b+11]=c[11];a[b+12]=c[12];a[b+13]=c[13];a[b+14]=c[14];a[b+15]=c[15];return a}});Object.assign(ca,{slerp:function(a,b,c,d){return c.copy(a).slerp(b,d)},slerpFlat:function(a,b,c,d,e,f,g){var h=c[d+0],l=c[d+1],m=c[d+2];c=c[d+3];d=e[f+0];var k=e[f+1],n=e[f+2];e=e[f+3];if(c!== +e||h!==d||l!==k||m!==n){f=1-g;var t=h*d+l*k+m*n+c*e,q=0<=t?1:-1,p=1-t*t;p>Number.EPSILON&&(p=Math.sqrt(p),t=Math.atan2(p,t*q),f=Math.sin(f*t)/p,g=Math.sin(g*t)/p);q*=g;h=h*f+d*q;l=l*f+k*q;m=m*f+n*q;c=c*f+e*q;f===1-g&&(g=1/Math.sqrt(h*h+l*l+m*m+c*c),h*=g,l*=g,m*=g,c*=g)}a[b]=h;a[b+1]=l;a[b+2]=m;a[b+3]=c}});Object.defineProperties(ca.prototype,{x:{get:function(){return this._x},set:function(a){this._x=a;this.onChangeCallback()}},y:{get:function(){return this._y},set:function(a){this._y=a;this.onChangeCallback()}}, +z:{get:function(){return this._z},set:function(a){this._z=a;this.onChangeCallback()}},w:{get:function(){return this._w},set:function(a){this._w=a;this.onChangeCallback()}}});Object.assign(ca.prototype,{set:function(a,b,c,d){this._x=a;this._y=b;this._z=c;this._w=d;this.onChangeCallback();return this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(a){this._x=a.x;this._y=a.y;this._z=a.z;this._w=a.w;this.onChangeCallback();return this},setFromEuler:function(a, +b){if(!a||!a.isEuler)throw Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var c=a._x,d=a._y,e=a._z;a=a.order;var f=Math.cos,g=Math.sin,h=f(c/2),l=f(d/2);f=f(e/2);c=g(c/2);d=g(d/2);e=g(e/2);"XYZ"===a?(this._x=c*l*f+h*d*e,this._y=h*d*f-c*l*e,this._z=h*l*e+c*d*f,this._w=h*l*f-c*d*e):"YXZ"===a?(this._x=c*l*f+h*d*e,this._y=h*d*f-c*l*e,this._z=h*l*e-c*d*f,this._w=h*l*f+c*d*e):"ZXY"===a?(this._x=c*l*f-h*d*e,this._y=h*d*f+c*l*e,this._z=h*l*e+c*d* +f,this._w=h*l*f-c*d*e):"ZYX"===a?(this._x=c*l*f-h*d*e,this._y=h*d*f+c*l*e,this._z=h*l*e-c*d*f,this._w=h*l*f+c*d*e):"YZX"===a?(this._x=c*l*f+h*d*e,this._y=h*d*f+c*l*e,this._z=h*l*e-c*d*f,this._w=h*l*f-c*d*e):"XZY"===a&&(this._x=c*l*f-h*d*e,this._y=h*d*f-c*l*e,this._z=h*l*e+c*d*f,this._w=h*l*f+c*d*e);if(!1!==b)this.onChangeCallback();return this},setFromAxisAngle:function(a,b){b/=2;var c=Math.sin(b);this._x=a.x*c;this._y=a.y*c;this._z=a.z*c;this._w=Math.cos(b);this.onChangeCallback();return this},setFromRotationMatrix:function(a){var b= +a.elements,c=b[0];a=b[4];var d=b[8],e=b[1],f=b[5],g=b[9],h=b[2],l=b[6];b=b[10];var m=c+f+b;0f&&c>b?(c=2*Math.sqrt(1+c-f-b),this._w=(l-g)/c,this._x=.25*c,this._y=(a+e)/c,this._z=(d+h)/c):f>b?(c=2*Math.sqrt(1+f-c-b),this._w=(d-h)/c,this._x=(a+e)/c,this._y=.25*c,this._z=(g+l)/c):(c=2*Math.sqrt(1+b-c-f),this._w=(e-a)/c,this._x=(d+h)/c,this._y=(g+l)/c,this._z=.25*c);this.onChangeCallback();return this},setFromUnitVectors:function(){var a= +new p,b;return function(c,d){void 0===a&&(a=new p);b=c.dot(d)+1;1E-6>b?(b=0,Math.abs(c.x)>Math.abs(c.z)?a.set(-c.y,c.x,0):a.set(0,-c.z,c.y)):a.crossVectors(c,d);this._x=a.x;this._y=a.y;this._z=a.z;this._w=b;return this.normalize()}}(),inverse:function(){return this.conjugate()},conjugate:function(){this._x*=-1;this._y*=-1;this._z*=-1;this.onChangeCallback();return this},dot:function(a){return this._x*a._x+this._y*a._y+this._z*a._z+this._w*a._w},lengthSq:function(){return this._x*this._x+this._y*this._y+ +this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var a=this.length();0===a?(this._z=this._y=this._x=0,this._w=1):(a=1/a,this._x*=a,this._y*=a,this._z*=a,this._w*=a);this.onChangeCallback();return this},multiply:function(a,b){return void 0!==b?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(a,b)):this.multiplyQuaternions(this, +a)},premultiply:function(a){return this.multiplyQuaternions(a,this)},multiplyQuaternions:function(a,b){var c=a._x,d=a._y,e=a._z;a=a._w;var f=b._x,g=b._y,h=b._z;b=b._w;this._x=c*b+a*f+d*h-e*g;this._y=d*b+a*g+e*f-c*h;this._z=e*b+a*h+c*g-d*f;this._w=a*b-c*f-d*g-e*h;this.onChangeCallback();return this},slerp:function(a,b){if(0===b)return this;if(1===b)return this.copy(a);var c=this._x,d=this._y,e=this._z,f=this._w,g=f*a._w+c*a._x+d*a._y+e*a._z;0>g?(this._w=-a._w,this._x=-a._x,this._y=-a._y,this._z=-a._z, +g=-g):this.copy(a);if(1<=g)return this._w=f,this._x=c,this._y=d,this._z=e,this;a=1-g*g;if(a<=Number.EPSILON)return g=1-b,this._w=g*f+b*this._w,this._x=g*c+b*this._x,this._y=g*d+b*this._y,this._z=g*e+b*this._z,this.normalize();a=Math.sqrt(a);var h=Math.atan2(a,g);g=Math.sin((1-b)*h)/a;b=Math.sin(b*h)/a;this._w=f*g+this._w*b;this._x=c*g+this._x*b;this._y=d*g+this._y*b;this._z=e*g+this._z*b;this.onChangeCallback();return this},equals:function(a){return a._x===this._x&&a._y===this._y&&a._z===this._z&& +a._w===this._w},fromArray:function(a,b){void 0===b&&(b=0);this._x=a[b];this._y=a[b+1];this._z=a[b+2];this._w=a[b+3];this.onChangeCallback();return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this._x;a[b+1]=this._y;a[b+2]=this._z;a[b+3]=this._w;return a},onChange:function(a){this.onChangeCallback=a;return this},onChangeCallback:function(){}});Object.assign(p.prototype,{isVector3:!0,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setScalar:function(a){this.z=this.y= +this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;case 2:this.z=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw Error("index is out of range: "+a);}},clone:function(){return new this.constructor(this.x, +this.y,this.z)},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addScaledVector:function(a,b){this.x+=a.x*b;this.y+=a.y*b;this.z+= +a.z*b;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;return this},subScalar:function(a){this.x-=a;this.y-=a;this.z-=a;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},multiply:function(a,b){if(void 0!==b)return console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."), +this.multiplyVectors(a,b);this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},multiplyVectors:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},applyEuler:function(){var a=new ca;return function(b){b&&b.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.");return this.applyQuaternion(a.setFromEuler(b))}}(),applyAxisAngle:function(){var a=new ca;return function(b, +c){return this.applyQuaternion(a.setFromAxisAngle(b,c))}}(),applyMatrix3:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[3]*c+a[6]*d;this.y=a[1]*b+a[4]*c+a[7]*d;this.z=a[2]*b+a[5]*c+a[8]*d;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z;a=a.elements;var e=1/(a[3]*b+a[7]*c+a[11]*d+a[15]);this.x=(a[0]*b+a[4]*c+a[8]*d+a[12])*e;this.y=(a[1]*b+a[5]*c+a[9]*d+a[13])*e;this.z=(a[2]*b+a[6]*c+a[10]*d+a[14])*e;return this},applyQuaternion:function(a){var b=this.x, +c=this.y,d=this.z,e=a.x,f=a.y,g=a.z;a=a.w;var h=a*b+f*d-g*c,l=a*c+g*b-e*d,m=a*d+e*c-f*b;b=-e*b-f*c-g*d;this.x=h*a+b*-e+l*-g-m*-f;this.y=l*a+b*-f+m*-e-h*-g;this.z=m*a+b*-g+h*-f-l*-e;return this},project:function(){var a=new R;return function(b){a.multiplyMatrices(b.projectionMatrix,a.getInverse(b.matrixWorld));return this.applyMatrix4(a)}}(),unproject:function(){var a=new R;return function(b){a.multiplyMatrices(b.matrixWorld,a.getInverse(b.projectionMatrix));return this.applyMatrix4(a)}}(),transformDirection:function(a){var b= +this.x,c=this.y,d=this.z;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d;this.y=a[1]*b+a[5]*c+a[9]*d;this.z=a[2]*b+a[6]*c+a[10]*d;return this.normalize()},divide:function(a){this.x/=a.x;this.y/=a.y;this.z/=a.z;return this},divideScalar:function(a){return this.multiplyScalar(1/a)},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);this.z=Math.min(this.z,a.z);return this},max:function(a){this.x=Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);this.z=Math.max(this.z,a.z);return this},clamp:function(a, +b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y=Math.max(a.y,Math.min(b.y,this.y));this.z=Math.max(a.z,Math.min(b.z,this.z));return this},clampScalar:function(){var a=new p,b=new p;return function(c,d){a.set(c,c,c);b.set(d,d,d);return this.clamp(a,b)}}(),clampLength:function(a,b){var c=this.length();return this.divideScalar(c||1).multiplyScalar(Math.max(a,Math.min(b,c)))},floor:function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);this.z=Math.floor(this.z);return this},ceil:function(){this.x= +Math.ceil(this.x);this.y=Math.ceil(this.y);this.z=Math.ceil(this.z);return this},round:function(){this.x=Math.round(this.x);this.y=Math.round(this.y);this.z=Math.round(this.z);return this},roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y):Math.floor(this.y);this.z=0>this.z?Math.ceil(this.z):Math.floor(this.z);return this},negate:function(){this.x=-this.x;this.y=-this.y;this.z=-this.z;return this},dot:function(a){return this.x*a.x+this.y* +a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(a){return this.normalize().multiplyScalar(a)},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},lerpVectors:function(a, +b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},cross:function(a,b){return void 0!==b?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(a,b)):this.crossVectors(this,a)},crossVectors:function(a,b){var c=a.x,d=a.y;a=a.z;var e=b.x,f=b.y;b=b.z;this.x=d*b-a*f;this.y=a*e-c*b;this.z=c*f-d*e;return this},projectOnVector:function(a){var b=a.dot(this)/a.lengthSq();return this.copy(a).multiplyScalar(b)},projectOnPlane:function(){var a= +new p;return function(b){a.copy(this).projectOnVector(b);return this.sub(a)}}(),reflect:function(){var a=new p;return function(b){return this.sub(a.copy(b).multiplyScalar(2*this.dot(b)))}}(),angleTo:function(a){a=this.dot(a)/Math.sqrt(this.lengthSq()*a.lengthSq());return Math.acos(J.clamp(a,-1,1))},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,c=this.y-a.y;a=this.z-a.z;return b*b+c*c+a*a},manhattanDistanceTo:function(a){return Math.abs(this.x- +a.x)+Math.abs(this.y-a.y)+Math.abs(this.z-a.z)},setFromSpherical:function(a){var b=Math.sin(a.phi)*a.radius;this.x=b*Math.sin(a.theta);this.y=Math.cos(a.phi)*a.radius;this.z=b*Math.cos(a.theta);return this},setFromCylindrical:function(a){this.x=a.radius*Math.sin(a.theta);this.y=a.y;this.z=a.radius*Math.cos(a.theta);return this},setFromMatrixPosition:function(a){a=a.elements;this.x=a[12];this.y=a[13];this.z=a[14];return this},setFromMatrixScale:function(a){var b=this.setFromMatrixColumn(a,0).length(), +c=this.setFromMatrixColumn(a,1).length();a=this.setFromMatrixColumn(a,2).length();this.x=b;this.y=c;this.z=a;return this},setFromMatrixColumn:function(a,b){return this.fromArray(a.elements,4*b)},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},fromArray:function(a,b){void 0===b&&(b=0);this.x=a[b];this.y=a[b+1];this.z=a[b+2];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;a[b+2]=this.z;return a},fromBufferAttribute:function(a,b,c){void 0!== +c&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);this.z=a.getZ(b);return this}});Object.assign(la.prototype,{isMatrix3:!0,set:function(a,b,c,d,e,f,g,h,l){var m=this.elements;m[0]=a;m[1]=d;m[2]=g;m[3]=b;m[4]=e;m[5]=h;m[6]=c;m[7]=f;m[8]=l;return this},identity:function(){this.set(1,0,0,0,1,0,0,0,1);return this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(a){var b=this.elements;a=a.elements; +b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];return this},setFromMatrix4:function(a){a=a.elements;this.set(a[0],a[4],a[8],a[1],a[5],a[9],a[2],a[6],a[10]);return this},applyToBufferAttribute:function(){var a=new p;return function(b){for(var c=0,d=b.count;cc;c++)if(b[c]!==a[c])return!1;return!0},fromArray:function(a,b){void 0===b&&(b=0);for(var c=0;9>c;c++)this.elements[c]=a[c+b];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);var c=this.elements;a[b]=c[0];a[b+1]=c[1]; +a[b+2]=c[2];a[b+3]=c[3];a[b+4]=c[4];a[b+5]=c[5];a[b+6]=c[6];a[b+7]=c[7];a[b+8]=c[8];return a}});var Ff=0;ea.DEFAULT_IMAGE=void 0;ea.DEFAULT_MAPPING=300;ea.prototype=Object.assign(Object.create(za.prototype),{constructor:ea,isTexture:!0,updateMatrix:function(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.name=a.name;this.image=a.image;this.mipmaps= +a.mipmaps.slice(0);this.mapping=a.mapping;this.wrapS=a.wrapS;this.wrapT=a.wrapT;this.magFilter=a.magFilter;this.minFilter=a.minFilter;this.anisotropy=a.anisotropy;this.format=a.format;this.type=a.type;this.offset.copy(a.offset);this.repeat.copy(a.repeat);this.center.copy(a.center);this.rotation=a.rotation;this.matrixAutoUpdate=a.matrixAutoUpdate;this.matrix.copy(a.matrix);this.generateMipmaps=a.generateMipmaps;this.premultiplyAlpha=a.premultiplyAlpha;this.flipY=a.flipY;this.unpackAlignment=a.unpackAlignment; +this.encoding=a.encoding;return this},toJSON:function(a){function b(a){if(a instanceof HTMLCanvasElement)var b=a;else{b=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");b.width=a.width;b.height=a.height;var c=b.getContext("2d");a instanceof ImageData?c.putImageData(a,0,0):c.drawImage(a,0,0,a.width,a.height)}return 2048a.x||1a.x?0:1;break;case 1002:a.x=1===Math.abs(Math.floor(a.x)%2)?Math.ceil(a.x)-a.x:a.x-Math.floor(a.x)}if(0>a.y||1a.y?0:1;break;case 1002:a.y=1===Math.abs(Math.floor(a.y)%2)?Math.ceil(a.y)-a.y:a.y-Math.floor(a.y)}this.flipY&&(a.y=1-a.y)}}});Object.defineProperty(ea.prototype,"needsUpdate",{set:function(a){!0===a&&this.version++}});Object.assign(W.prototype,{isVector4:!0,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},setScalar:function(a){this.w=this.z=this.y=this.x=a;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this}, +setZ:function(a){this.z=a;return this},setW:function(a){this.w=a;return this},setComponent:function(a,b){switch(a){case 0:this.x=b;break;case 1:this.y=b;break;case 2:this.z=b;break;case 3:this.w=b;break;default:throw Error("index is out of range: "+a);}return this},getComponent:function(a){switch(a){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw Error("index is out of range: "+a);}},clone:function(){return new this.constructor(this.x,this.y,this.z, +this.w)},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},add:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(a,b);this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;this.w+=a;return this},addVectors:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addScaledVector:function(a, +b){this.x+=a.x*b;this.y+=a.y*b;this.z+=a.z*b;this.w+=a.w*b;return this},sub:function(a,b){if(void 0!==b)return console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(a,b);this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;return this},subScalar:function(a){this.x-=a;this.y-=a;this.z-=a;this.w-=a;return this},subVectors:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},multiplyScalar:function(a){this.x*= +a;this.y*=a;this.z*=a;this.w*=a;return this},applyMatrix4:function(a){var b=this.x,c=this.y,d=this.z,e=this.w;a=a.elements;this.x=a[0]*b+a[4]*c+a[8]*d+a[12]*e;this.y=a[1]*b+a[5]*c+a[9]*d+a[13]*e;this.z=a[2]*b+a[6]*c+a[10]*d+a[14]*e;this.w=a[3]*b+a[7]*c+a[11]*d+a[15]*e;return this},divideScalar:function(a){return this.multiplyScalar(1/a)},setAxisAngleFromQuaternion:function(a){this.w=2*Math.acos(a.w);var b=Math.sqrt(1-a.w*a.w);1E-4>b?(this.x=1,this.z=this.y=0):(this.x=a.x/b,this.y=a.y/b,this.z=a.z/ +b);return this},setAxisAngleFromRotationMatrix:function(a){a=a.elements;var b=a[0];var c=a[4];var d=a[8],e=a[1],f=a[5],g=a[9];var h=a[2];var l=a[6];var m=a[10];if(.01>Math.abs(c-e)&&.01>Math.abs(d-h)&&.01>Math.abs(g-l)){if(.1>Math.abs(c+e)&&.1>Math.abs(d+h)&&.1>Math.abs(g+l)&&.1>Math.abs(b+f+m-3))return this.set(1,0,0,0),this;a=Math.PI;b=(b+1)/2;f=(f+1)/2;m=(m+1)/2;c=(c+e)/4;d=(d+h)/4;g=(g+l)/4;b>f&&b>m?.01>b?(l=0,c=h=.707106781):(l=Math.sqrt(b),h=c/l,c=d/l):f>m?.01>f?(l=.707106781,h=0,c=.707106781): +(h=Math.sqrt(f),l=c/h,c=g/h):.01>m?(h=l=.707106781,c=0):(c=Math.sqrt(m),l=d/c,h=g/c);this.set(l,h,c,a);return this}a=Math.sqrt((l-g)*(l-g)+(d-h)*(d-h)+(e-c)*(e-c));.001>Math.abs(a)&&(a=1);this.x=(l-g)/a;this.y=(d-h)/a;this.z=(e-c)/a;this.w=Math.acos((b+f+m-1)/2);return this},min:function(a){this.x=Math.min(this.x,a.x);this.y=Math.min(this.y,a.y);this.z=Math.min(this.z,a.z);this.w=Math.min(this.w,a.w);return this},max:function(a){this.x=Math.max(this.x,a.x);this.y=Math.max(this.y,a.y);this.z=Math.max(this.z, +a.z);this.w=Math.max(this.w,a.w);return this},clamp:function(a,b){this.x=Math.max(a.x,Math.min(b.x,this.x));this.y=Math.max(a.y,Math.min(b.y,this.y));this.z=Math.max(a.z,Math.min(b.z,this.z));this.w=Math.max(a.w,Math.min(b.w,this.w));return this},clampScalar:function(){var a,b;return function(c,d){void 0===a&&(a=new W,b=new W);a.set(c,c,c,c);b.set(d,d,d,d);return this.clamp(a,b)}}(),clampLength:function(a,b){var c=this.length();return this.divideScalar(c||1).multiplyScalar(Math.max(a,Math.min(b,c)))}, +floor:function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);this.z=Math.floor(this.z);this.w=Math.floor(this.w);return this},ceil:function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);this.z=Math.ceil(this.z);this.w=Math.ceil(this.w);return this},round:function(){this.x=Math.round(this.x);this.y=Math.round(this.y);this.z=Math.round(this.z);this.w=Math.round(this.w);return this},roundToZero:function(){this.x=0>this.x?Math.ceil(this.x):Math.floor(this.x);this.y=0>this.y?Math.ceil(this.y): +Math.floor(this.y);this.z=0>this.z?Math.ceil(this.z):Math.floor(this.z);this.w=0>this.w?Math.ceil(this.w):Math.floor(this.w);return this},negate:function(){this.x=-this.x;this.y=-this.y;this.z=-this.z;this.w=-this.w;return this},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},manhattanLength:function(){return Math.abs(this.x)+ +Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(a){return this.normalize().multiplyScalar(a)},lerp:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this},lerpVectors:function(a,b,c){return this.subVectors(b,a).multiplyScalar(c).add(a)},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z&&a.w===this.w},fromArray:function(a,b){void 0=== +b&&(b=0);this.x=a[b];this.y=a[b+1];this.z=a[b+2];this.w=a[b+3];return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this.x;a[b+1]=this.y;a[b+2]=this.z;a[b+3]=this.w;return a},fromBufferAttribute:function(a,b,c){void 0!==c&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute().");this.x=a.getX(b);this.y=a.getY(b);this.z=a.getZ(b);this.w=a.getW(b);return this}});kb.prototype=Object.assign(Object.create(za.prototype),{constructor:kb,isWebGLRenderTarget:!0, +setSize:function(a,b){if(this.width!==a||this.height!==b)this.width=a,this.height=b,this.dispose();this.viewport.set(0,0,a,b);this.scissor.set(0,0,a,b)},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.width=a.width;this.height=a.height;this.viewport.copy(a.viewport);this.texture=a.texture.clone();this.depthBuffer=a.depthBuffer;this.stencilBuffer=a.stencilBuffer;this.depthTexture=a.depthTexture;return this},dispose:function(){this.dispatchEvent({type:"dispose"})}}); +Lb.prototype=Object.create(kb.prototype);Lb.prototype.constructor=Lb;Lb.prototype.isWebGLRenderTargetCube=!0;lb.prototype=Object.create(ea.prototype);lb.prototype.constructor=lb;lb.prototype.isDataTexture=!0;Object.assign(Xa.prototype,{isBox3:!0,set:function(a,b){this.min.copy(a);this.max.copy(b);return this},setFromArray:function(a){for(var b=Infinity,c=Infinity,d=Infinity,e=-Infinity,f=-Infinity,g=-Infinity,h=0,l=a.length;h +e&&(e=m);k>f&&(f=k);n>g&&(g=n)}this.min.set(b,c,d);this.max.set(e,f,g);return this},setFromBufferAttribute:function(a){for(var b=Infinity,c=Infinity,d=Infinity,e=-Infinity,f=-Infinity,g=-Infinity,h=0,l=a.count;he&&(e=m);k>f&&(f=k);n>g&&(g=n)}this.min.set(b,c,d);this.max.set(e,f,g);return this},setFromPoints:function(a){this.makeEmpty();for(var b=0,c=a.length;bthis.max.x||a.ythis.max.y||a.zthis.max.z?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<=this.max.y&&this.min.z<=a.min.z&&a.max.z<=this.max.z},getParameter:function(a,b){void 0===b&&(console.warn("THREE.Box3: .getParameter() target is now required"),b=new p);return b.set((a.x-this.min.x)/(this.max.x- +this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y),(a.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(a){return a.max.xthis.max.x||a.max.ythis.max.y||a.max.zthis.max.z?!1:!0},intersectsSphere:function(){var a=new p;return function(b){this.clampPoint(b.center,a);return a.distanceToSquared(b.center)<=b.radius*b.radius}}(),intersectsPlane:function(a){if(0=a.constant},intersectsTriangle:function(){function a(a){var e;var f=0;for(e=a.length-3;f<=e;f+=3){h.fromArray(a,f);var g=m.x*Math.abs(h.x)+m.y*Math.abs(h.y)+m.z*Math.abs(h.z),l=b.dot(h),k=c.dot(h), +n=d.dot(h);if(Math.max(-Math.max(l,k,n),Math.min(l,k,n))>g)return!1}return!0}var b=new p,c=new p,d=new p,e=new p,f=new p,g=new p,h=new p,l=new p,m=new p,k=new p;return function(h){if(this.isEmpty())return!1;this.getCenter(l);m.subVectors(this.max,l);b.subVectors(h.a,l);c.subVectors(h.b,l);d.subVectors(h.c,l);e.subVectors(c,b);f.subVectors(d,c);g.subVectors(b,d);h=[0,-e.z,e.y,0,-f.z,f.y,0,-g.z,g.y,e.z,0,-e.x,f.z,0,-f.x,g.z,0,-g.x,-e.y,e.x,0,-f.y,f.x,0,-g.y,g.x,0];if(!a(h))return!1;h=[1,0,0,0,1,0,0, +0,1];if(!a(h))return!1;k.crossVectors(e,f);h=[k.x,k.y,k.z];return a(h)}}(),clampPoint:function(a,b){void 0===b&&(console.warn("THREE.Box3: .clampPoint() target is now required"),b=new p);return b.copy(a).clamp(this.min,this.max)},distanceToPoint:function(){var a=new p;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),getBoundingSphere:function(){var a=new p;return function(b){void 0===b&&(console.warn("THREE.Box3: .getBoundingSphere() target is now required"),b=new Ha); +this.getCenter(b.center);b.radius=.5*this.getSize(a).length();return b}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);this.isEmpty()&&this.makeEmpty();return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},applyMatrix4:function(a){if(this.isEmpty())return this;a=a.elements;var b=a[0]*this.min.x,c=a[1]*this.min.x,d=a[2]*this.min.x,e=a[0]*this.max.x,f=a[1]*this.max.x,g=a[2]*this.max.x,h=a[4]*this.min.y,l=a[5]*this.min.y,m=a[6]*this.min.y,k=a[4]*this.max.y, +n=a[5]*this.max.y,p=a[6]*this.max.y,q=a[8]*this.min.z,r=a[9]*this.min.z,u=a[10]*this.min.z,y=a[8]*this.max.z,w=a[9]*this.max.z,x=a[10]*this.max.z;this.min.x=Math.min(b,e)+Math.min(h,k)+Math.min(q,y)+a[12];this.min.y=Math.min(c,f)+Math.min(l,n)+Math.min(r,w)+a[13];this.min.z=Math.min(d,g)+Math.min(m,p)+Math.min(u,x)+a[14];this.max.x=Math.max(b,e)+Math.max(h,k)+Math.max(q,y)+a[12];this.max.y=Math.max(c,f)+Math.max(l,n)+Math.max(r,w)+a[13];this.max.z=Math.max(d,g)+Math.max(m,p)+Math.max(u,x)+a[14];return this}, +translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)}});Object.assign(Ha.prototype,{set:function(a,b){this.center.copy(a);this.radius=b;return this},setFromPoints:function(){var a=new Xa;return function(b,c){var d=this.center;void 0!==c?d.copy(c):a.setFromPoints(b).getCenter(d);for(var e=c=0,f=b.length;e=this.radius},containsPoint:function(a){return a.distanceToSquared(this.center)<=this.radius*this.radius},distanceToPoint:function(a){return a.distanceTo(this.center)-this.radius},intersectsSphere:function(a){var b=this.radius+a.radius;return a.center.distanceToSquared(this.center)<=b*b},intersectsBox:function(a){return a.intersectsSphere(this)},intersectsPlane:function(a){return Math.abs(a.distanceToPoint(this.center))<= +this.radius},clampPoint:function(a,b){var c=this.center.distanceToSquared(a);void 0===b&&(console.warn("THREE.Sphere: .clampPoint() target is now required"),b=new p);b.copy(a);c>this.radius*this.radius&&(b.sub(this.center).normalize(),b.multiplyScalar(this.radius).add(this.center));return b},getBoundingBox:function(a){void 0===a&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),a=new Xa);a.set(this.center,this.center);a.expandByScalar(this.radius);return a},applyMatrix4:function(a){this.center.applyMatrix4(a); +this.radius*=a.getMaxScaleOnAxis();return this},translate:function(a){this.center.add(a);return this},equals:function(a){return a.center.equals(this.center)&&a.radius===this.radius}});Object.assign(Ia.prototype,{set:function(a,b){this.normal.copy(a);this.constant=b;return this},setComponents:function(a,b,c,d){this.normal.set(a,b,c);this.constant=d;return this},setFromNormalAndCoplanarPoint:function(a,b){this.normal.copy(a);this.constant=-b.dot(this.normal);return this},setFromCoplanarPoints:function(){var a= +new p,b=new p;return function(c,d,e){d=a.subVectors(e,d).cross(b.subVectors(c,d)).normalize();this.setFromNormalAndCoplanarPoint(d,c);return this}}(),clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.normal.copy(a.normal);this.constant=a.constant;return this},normalize:function(){var a=1/this.normal.length();this.normal.multiplyScalar(a);this.constant*=a;return this},negate:function(){this.constant*=-1;this.normal.negate();return this},distanceToPoint:function(a){return this.normal.dot(a)+ +this.constant},distanceToSphere:function(a){return this.distanceToPoint(a.center)-a.radius},projectPoint:function(a,b){void 0===b&&(console.warn("THREE.Plane: .projectPoint() target is now required"),b=new p);return b.copy(this.normal).multiplyScalar(-this.distanceToPoint(a)).add(a)},intersectLine:function(){var a=new p;return function(b,c){void 0===c&&(console.warn("THREE.Plane: .intersectLine() target is now required"),c=new p);var d=b.delta(a),e=this.normal.dot(d);if(0===e){if(0===this.distanceToPoint(b.start))return c.copy(b.start)}else if(e= +-(b.start.dot(this.normal)+this.constant)/e,!(0>e||1b&&0a&&0c;c++)b[c].copy(a.planes[c]);return this},setFromMatrix:function(a){var b=this.planes,c=a.elements;a=c[0];var d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],l=c[6],m=c[7],k=c[8],n=c[9],p=c[10],q=c[11],r=c[12],u=c[13],y=c[14];c=c[15];b[0].setComponents(f-a,m-g,q-k,c-r).normalize();b[1].setComponents(f+a,m+g,q+k,c+r).normalize();b[2].setComponents(f+d,m+h,q+n,c+u).normalize();b[3].setComponents(f- +d,m-h,q-n,c-u).normalize();b[4].setComponents(f-e,m-l,q-p,c-y).normalize();b[5].setComponents(f+e,m+l,q+p,c+y).normalize();return this},intersectsObject:function(){var a=new Ha;return function(b){var c=b.geometry;null===c.boundingSphere&&c.computeBoundingSphere();a.copy(c.boundingSphere).applyMatrix4(b.matrixWorld);return this.intersectsSphere(a)}}(),intersectsSprite:function(){var a=new Ha;return function(b){a.center.set(0,0,0);a.radius=.7071067811865476;a.applyMatrix4(b.matrixWorld);return this.intersectsSphere(a)}}(), +intersectsSphere:function(a){var b=this.planes,c=a.center;a=-a.radius;for(var d=0;6>d;d++)if(b[d].distanceToPoint(c)e;e++){var f=d[e];a.x=0 +g&&0>f)return!1}return!0}}(),containsPoint:function(a){for(var b=this.planes,c=0;6>c;c++)if(0>b[c].distanceToPoint(a))return!1;return!0}});var S={alphamap_fragment:"#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n",alphamap_pars_fragment:"#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n",alphatest_fragment:"#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n",aomap_fragment:"#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n", +aomap_pars_fragment:"#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif",begin_vertex:"\nvec3 transformed = vec3( position );\n",beginnormal_vertex:"\nvec3 objectNormal = vec3( normal );\n",bsdfs:"float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n", +bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n", +clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n", +clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n", +color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n", +cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n", +defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n", +emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n", +envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n", +envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n", +envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n", +fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n", +gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n", +lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n", +lights_pars_begin:"uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n", +lights_pars_maps:"#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n", +lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n", +lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n", +lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n", +lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearCoatRadiance = vec3( 0.0 );\n#endif\n", +lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif\n", +lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n", +logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n", +map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n", +metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif", +morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n", +normal_fragment_begin:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n",normal_fragment_maps:"#ifdef USE_NORMALMAP\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t#ifdef FLIP_SIDED\n\t\t\tnormal = - normal;\n\t\t#endif\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\tnormal = normalize( normalMatrix * normal );\n\t#else\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n", +normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tuniform mat3 normalMatrix;\n\t#else\n\t\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\t\tvec2 st0 = dFdx( vUv.st );\n\t\t\tvec2 st1 = dFdy( vUv.st );\n\t\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\t\tvec3 N = normalize( surf_norm );\n\t\t\tmat3 tsn = mat3( S, T, N );\n\t\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t\tmapN.xy *= normalScale;\n\t\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\treturn normalize( tsn * mapN );\n\t\t}\n\t#endif\n#endif\n", +packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n", +premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n", +roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n", +shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n", +shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n", +shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n", +skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n", +skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n", +specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n", +uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n", +uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif", +uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n", +cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\n",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n", +depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n", +distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}\n", +equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\n", +linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\n", +meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +meshphysical_vert:"#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}\n", +normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n", +normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n", +points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}\n", +shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"}, +Ba={merge:function(a){for(var b={},c=0;c>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},setRGB:function(a,b,c){this.r=a;this.g=b;this.b=c;return this},setHSL:function(){function a(a,c,d){0>d&&(d+=1);1d?c:d<2/3?a+6*(c-a)*(2/3-d):a}return function(b, +c,d){b=J.euclideanModulo(b,1);c=J.clamp(c,0,1);d=J.clamp(d,0,1);0===c?this.r=this.g=this.b=d:(c=.5>=d?d*(1+c):d+c-d*c,d=2*d-c,this.r=a(d,c,b+1/3),this.g=a(d,c,b),this.b=a(d,c,b-1/3));return this}}(),setStyle:function(a){function b(b){void 0!==b&&1>parseFloat(b)&&console.warn("THREE.Color: Alpha component of "+a+" will be ignored.")}var c;if(c=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(a)){var d=c[2];switch(c[1]){case "rgb":case "rgba":if(c=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d))return this.r= +Math.min(255,parseInt(c[1],10))/255,this.g=Math.min(255,parseInt(c[2],10))/255,this.b=Math.min(255,parseInt(c[3],10))/255,b(c[5]),this;if(c=/^(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d))return this.r=Math.min(100,parseInt(c[1],10))/100,this.g=Math.min(100,parseInt(c[2],10))/100,this.b=Math.min(100,parseInt(c[3],10))/100,b(c[5]),this;break;case "hsl":case "hsla":if(c=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(d)){d=parseFloat(c[1])/ +360;var e=parseInt(c[2],10)/100,f=parseInt(c[3],10)/100;b(c[5]);return this.setHSL(d,e,f)}}}else if(c=/^#([A-Fa-f0-9]+)$/.exec(a)){c=c[1];d=c.length;if(3===d)return this.r=parseInt(c.charAt(0)+c.charAt(0),16)/255,this.g=parseInt(c.charAt(1)+c.charAt(1),16)/255,this.b=parseInt(c.charAt(2)+c.charAt(2),16)/255,this;if(6===d)return this.r=parseInt(c.charAt(0)+c.charAt(1),16)/255,this.g=parseInt(c.charAt(2)+c.charAt(3),16)/255,this.b=parseInt(c.charAt(4)+c.charAt(5),16)/255,this}a&&0a?.0773993808*a:Math.pow(.9478672986*a+.0521327014,2.4)}return function(b){this.r=a(b.r);this.g=a(b.g);this.b=a(b.b);return this}}(),copyLinearToSRGB:function(){function a(a){return.0031308>a?12.92*a:1.055*Math.pow(a,.41666)-.055}return function(b){this.r=a(b.r);this.g=a(b.g);this.b=a(b.b);return this}}(),convertSRGBToLinear:function(){this.copySRGBToLinear(this); +return this},convertLinearToSRGB:function(){this.copyLinearToSRGB(this);return this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(a){void 0===a&&(console.warn("THREE.Color: .getHSL() target is now required"),a={h:0,s:0,l:0});var b=this.r,c=this.g,d=this.b,e=Math.max(b,c,d),f=Math.min(b,c,d),g,h=(f+e)/2;if(f===e)f=g=0;else{var l=e-f;f=.5>=h?l/(e+f):l/(2-e-f);switch(e){case b:g=(c- +d)/l+(cMath.abs(g)?(this._x=Math.atan2(-m,e),this._z=Math.atan2(-f,a)):(this._x=Math.atan2(n,l),this._z=0)):"YXZ"===b?(this._x=Math.asin(-d(m,-1,1)),.99999>Math.abs(m)?(this._y=Math.atan2(g,e),this._z=Math.atan2(h,l)):(this._y=Math.atan2(-k,a),this._z=0)):"ZXY"===b?(this._x=Math.asin(d(n,-1,1)),.99999>Math.abs(n)? +(this._y=Math.atan2(-k,e),this._z=Math.atan2(-f,l)):(this._y=0,this._z=Math.atan2(h,a))):"ZYX"===b?(this._y=Math.asin(-d(k,-1,1)),.99999>Math.abs(k)?(this._x=Math.atan2(n,e),this._z=Math.atan2(h,a)):(this._x=0,this._z=Math.atan2(-f,l))):"YZX"===b?(this._z=Math.asin(d(h,-1,1)),.99999>Math.abs(h)?(this._x=Math.atan2(-m,l),this._y=Math.atan2(-k,a)):(this._x=0,this._y=Math.atan2(g,e))):"XZY"===b?(this._z=Math.asin(-d(f,-1,1)),.99999>Math.abs(f)?(this._x=Math.atan2(n,l),this._y=Math.atan2(g,a)):(this._x= +Math.atan2(-m,e),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+b);this._order=b;if(!1!==c)this.onChangeCallback();return this},setFromQuaternion:function(){var a=new R;return function(b,c,d){a.makeRotationFromQuaternion(b);return this.setFromRotationMatrix(a,c,d)}}(),setFromVector3:function(a,b){return this.set(a.x,a.y,a.z,b||this._order)},reorder:function(){var a=new ca;return function(b){a.setFromEuler(this);return this.setFromQuaternion(a,b)}}(),equals:function(a){return a._x=== +this._x&&a._y===this._y&&a._z===this._z&&a._order===this._order},fromArray:function(a){this._x=a[0];this._y=a[1];this._z=a[2];void 0!==a[3]&&(this._order=a[3]);this.onChangeCallback();return this},toArray:function(a,b){void 0===a&&(a=[]);void 0===b&&(b=0);a[b]=this._x;a[b+1]=this._y;a[b+2]=this._z;a[b+3]=this._order;return a},toVector3:function(a){return a?a.set(this._x,this._y,this._z):new p(this._x,this._y,this._z)},onChange:function(a){this.onChangeCallback=a;return this},onChangeCallback:function(){}}); +Object.assign(Wd.prototype,{set:function(a){this.mask=1<g;g++)if(d[g]===d[(g+1)%3]){a.push(f);break}for(f=a.length-1;0<=f;f--)for(d=a[f],this.faces.splice(d,1),c=0,e=this.faceVertexUvs.length;cthis.opacity&&(d.opacity=this.opacity);!0===this.transparent&&(d.transparent=this.transparent);d.depthFunc=this.depthFunc;d.depthTest=this.depthTest;d.depthWrite=this.depthWrite;0!==this.rotation&&(d.rotation=this.rotation);1!==this.linewidth&&(d.linewidth=this.linewidth);void 0!==this.dashSize&&(d.dashSize= +this.dashSize);void 0!==this.gapSize&&(d.gapSize=this.gapSize);void 0!==this.scale&&(d.scale=this.scale);!0===this.dithering&&(d.dithering=!0);0a?b.copy(this.origin):b.copy(this.direction).multiplyScalar(a).add(this.origin)},distanceToPoint:function(a){return Math.sqrt(this.distanceSqToPoint(a))},distanceSqToPoint:function(){var a=new p;return function(b){var c=a.subVectors(b,this.origin).dot(this.direction);if(0>c)return this.origin.distanceToSquared(b); +a.copy(this.direction).multiplyScalar(c).add(this.origin);return a.distanceToSquared(b)}}(),distanceSqToSegment:function(){var a=new p,b=new p,c=new p;return function(d,e,f,g){a.copy(d).add(e).multiplyScalar(.5);b.copy(e).sub(d).normalize();c.copy(this.origin).sub(a);var h=.5*d.distanceTo(e),l=-this.direction.dot(b),m=c.dot(this.direction),k=-c.dot(b),n=c.lengthSq(),p=Math.abs(1-l*l);if(0=-q?e<=q?(h=1/p,d*=h,e*=h,l=d*(d+l*e+2*m)+e*(l*d+e+2*k)+n):(e=h,d=Math.max(0, +-(l*e+m)),l=-d*d+e*(e+2*k)+n):(e=-h,d=Math.max(0,-(l*e+m)),l=-d*d+e*(e+2*k)+n):e<=-q?(d=Math.max(0,-(-l*h+m)),e=0b)return null;b=Math.sqrt(b-e);e=d-b;d+=b;return 0>e&&0>d?null:0>e?this.at(d,c):this.at(e,c)}}(),intersectsSphere:function(a){return this.distanceToPoint(a.center)<=a.radius},distanceToPlane:function(a){var b=a.normal.dot(this.direction);if(0===b)return 0===a.distanceToPoint(this.origin)?0:null;a=-(this.origin.dot(a.normal)+a.constant)/b;return 0<=a?a:null},intersectPlane:function(a, +b){a=this.distanceToPlane(a);return null===a?null:this.at(a,b)},intersectsPlane:function(a){var b=a.distanceToPoint(this.origin);return 0===b||0>a.normal.dot(this.direction)*b?!0:!1},intersectBox:function(a,b){var c=1/this.direction.x;var d=1/this.direction.y;var e=1/this.direction.z,f=this.origin;if(0<=c){var g=(a.min.x-f.x)*c;c*=a.max.x-f.x}else g=(a.max.x-f.x)*c,c*=a.min.x-f.x;if(0<=d){var h=(a.min.y-f.y)*d;d*=a.max.y-f.y}else h=(a.max.y-f.y)*d,d*=a.min.y-f.y;if(g>d||h>c)return null;if(h>g||g!== +g)g=h;if(da||h>c)return null;if(h>g||g!==g)g=h;if(ac?null:this.at(0<=g?g:c,b)},intersectsBox:function(){var a=new p;return function(b){return null!==this.intersectBox(b,a)}}(),intersectTriangle:function(){var a=new p,b=new p,c=new p,d=new p;return function(e,f,g,h,l){b.subVectors(f,e);c.subVectors(g,e);d.crossVectors(b,c);f=this.direction.dot(d);if(0 +f)h=-1,f=-f;else return null;a.subVectors(this.origin,e);e=h*this.direction.dot(c.crossVectors(a,c));if(0>e)return null;g=h*this.direction.dot(b.cross(a));if(0>g||e+g>f)return null;e=-h*a.dot(d);return 0>e?null:this.at(e/f,l)}}(),applyMatrix4:function(a){this.origin.applyMatrix4(a);this.direction.transformDirection(a);return this},equals:function(a){return a.origin.equals(this.origin)&&a.direction.equals(this.direction)}});Object.assign(Qb.prototype,{set:function(a,b){this.start.copy(a);this.end.copy(b); +return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.start.copy(a.start);this.end.copy(a.end);return this},getCenter:function(a){void 0===a&&(console.warn("THREE.Line3: .getCenter() target is now required"),a=new p);return a.addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(a){void 0===a&&(console.warn("THREE.Line3: .delta() target is now required"),a=new p);return a.subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)}, +distance:function(){return this.start.distanceTo(this.end)},at:function(a,b){void 0===b&&(console.warn("THREE.Line3: .at() target is now required"),b=new p);return this.delta(b).multiplyScalar(a).add(this.start)},closestPointToPointParameter:function(){var a=new p,b=new p;return function(c,d){a.subVectors(c,this.start);b.subVectors(this.end,this.start);c=b.dot(b);c=b.dot(a)/c;d&&(c=J.clamp(c,0,1));return c}}(),closestPointToPoint:function(a,b,c){a=this.closestPointToPointParameter(a,b);void 0===c&& +(console.warn("THREE.Line3: .closestPointToPoint() target is now required"),c=new p);return this.delta(c).multiplyScalar(a).add(this.start)},applyMatrix4:function(a){this.start.applyMatrix4(a);this.end.applyMatrix4(a);return this},equals:function(a){return a.start.equals(this.start)&&a.end.equals(this.end)}});Object.assign(ta,{getNormal:function(){var a=new p;return function(b,c,d,e){void 0===e&&(console.warn("THREE.Triangle: .getNormal() target is now required"),e=new p);e.subVectors(d,c);a.subVectors(b, +c);e.cross(a);b=e.lengthSq();return 0=a.x+a.y}}()});Object.assign(ta.prototype,{set:function(a,b,c){this.a.copy(a);this.b.copy(b);this.c.copy(c);return this},setFromPointsAndIndices:function(a,b,c,d){this.a.copy(a[b]);this.b.copy(a[c]);this.c.copy(a[d]);return this},clone:function(){return(new this.constructor).copy(this)},copy:function(a){this.a.copy(a.a);this.b.copy(a.b);this.c.copy(a.c);return this},getArea:function(){var a=new p,b=new p;return function(){a.subVectors(this.c, +this.b);b.subVectors(this.a,this.b);return.5*a.cross(b).length()}}(),getMidpoint:function(a){void 0===a&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),a=new p);return a.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},getNormal:function(a){return ta.getNormal(this.a,this.b,this.c,a)},getPlane:function(a){void 0===a&&(console.warn("THREE.Triangle: .getPlane() target is now required"),a=new p);return a.setFromCoplanarPoints(this.a,this.b,this.c)},getBarycoord:function(a, +b){return ta.getBarycoord(a,this.a,this.b,this.c,b)},containsPoint:function(a){return ta.containsPoint(a,this.a,this.b,this.c)},intersectsBox:function(a){return a.intersectsTriangle(this)},closestPointToPoint:function(){var a=new Ia,b=[new Qb,new Qb,new Qb],c=new p,d=new p;return function(e,f){void 0===f&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),f=new p);var g=Infinity;a.setFromCoplanarPoints(this.a,this.b,this.c);a.projectPoint(e,c);if(!0===this.containsPoint(c))f.copy(c); +else for(b[0].set(this.a,this.b),b[1].set(this.b,this.c),b[2].set(this.c,this.a),e=0;ec.far?null:{distance:b,point:w.clone(),object:a}}function c(c,d,e,f,m,k,n,p,v){g.fromBufferAttribute(m,n);h.fromBufferAttribute(m,p);l.fromBufferAttribute(m,v);if(c=b(c,d,e,f,g,h,l,y))k&&(t.fromBufferAttribute(k,n),q.fromBufferAttribute(k,p),r.fromBufferAttribute(k,v),c.uv=a(y,g,h,l,t,q,r)),k=new Ya(n,p,v),ta.getNormal(g,h,l,k.normal),c.face=k;return c}var d=new R,e=new sb,f=new Ha, +g=new p,h=new p,l=new p,m=new p,k=new p,n=new p,t=new B,q=new B,r=new B,u=new p,y=new p,w=new p;return function(p,v){var u=this.geometry,x=this.material,w=this.matrixWorld;if(void 0!==x&&(null===u.boundingSphere&&u.computeBoundingSphere(),f.copy(u.boundingSphere),f.applyMatrix4(w),!1!==p.ray.intersectsSphere(f)&&(d.getInverse(w),e.copy(p.ray).applyMatrix4(d),null===u.boundingBox||!1!==e.intersectsBox(u.boundingBox))))if(u.isBufferGeometry){var A=u.index,z=u.attributes.position,B=u.attributes.uv,H= +u.groups;u=u.drawRange;var G;if(null!==A)if(Array.isArray(x)){var D=0;for(G=H.length;De.far||f.push({distance:p,point:b.clone(),face:null,object:this})}}(),clone:function(){return(new this.constructor(this.material)).copy(this)},copy:function(a){H.prototype.copy.call(this,a);void 0!==a.center&&this.center.copy(a.center);return this}});Jc.prototype=Object.assign(Object.create(H.prototype),{constructor:Jc,copy:function(a){H.prototype.copy.call(this,a,!1);a=a.levels;for(var b=0,c=a.length;b=d[e].distance)d[e-1].object.visible=!1,d[e].object.visible=!0;else break;for(;ef||(k.applyMatrix4(this.matrixWorld),u=d.ray.origin.distanceTo(k),ud.far||e.push({distance:u,point:h.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}}else for(g=0,r=q.length/3-1;gf||(k.applyMatrix4(this.matrixWorld),u=d.ray.origin.distanceTo(k),ud.far||e.push({distance:u,point:h.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}else if(g.isGeometry)for(l=g.vertices,m=l.length,g=0;gf||(k.applyMatrix4(this.matrixWorld),u=d.ray.origin.distanceTo(k),ud.far||e.push({distance:u,point:h.clone().applyMatrix4(this.matrixWorld),index:g, +face:null,faceIndex:null,object:this}))}}}(),clone:function(){return(new this.constructor(this.geometry,this.material)).copy(this)}});Y.prototype=Object.assign(Object.create(wa.prototype),{constructor:Y,isLineSegments:!0,computeLineDistances:function(){var a=new p,b=new p;return function(){var c=this.geometry;if(c.isBufferGeometry)if(null===c.index){for(var d=c.attributes.position,e=[],f=0,g=d.count;fd.far|| +e.push({distance:a,distanceToRay:Math.sqrt(f),point:n.clone(),index:c,face:null,object:g}))}var g=this,h=this.geometry,l=this.matrixWorld,m=d.params.Points.threshold;null===h.boundingSphere&&h.computeBoundingSphere();c.copy(h.boundingSphere);c.applyMatrix4(l);c.radius+=m;if(!1!==d.ray.intersectsSphere(c)){a.getInverse(l);b.copy(d.ray).applyMatrix4(a);m/=(this.scale.x+this.scale.y+this.scale.z)/3;var k=m*m;m=new p;var n=new p;if(h.isBufferGeometry){var t=h.index;h=h.attributes.position.array;if(null!== +t){var q=t.array;t=0;for(var r=q.length;t=a.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}});Yb.prototype=Object.create(ea.prototype); +Yb.prototype.constructor=Yb;Yb.prototype.isCompressedTexture=!0;Lc.prototype=Object.create(ea.prototype);Lc.prototype.constructor=Lc;Lc.prototype.isDepthTexture=!0;Zb.prototype=Object.create(D.prototype);Zb.prototype.constructor=Zb;Mc.prototype=Object.create(P.prototype);Mc.prototype.constructor=Mc;$b.prototype=Object.create(D.prototype);$b.prototype.constructor=$b;Nc.prototype=Object.create(P.prototype);Nc.prototype.constructor=Nc;xa.prototype=Object.create(D.prototype);xa.prototype.constructor= +xa;Oc.prototype=Object.create(P.prototype);Oc.prototype.constructor=Oc;ac.prototype=Object.create(xa.prototype);ac.prototype.constructor=ac;Pc.prototype=Object.create(P.prototype);Pc.prototype.constructor=Pc;ub.prototype=Object.create(xa.prototype);ub.prototype.constructor=ub;Qc.prototype=Object.create(P.prototype);Qc.prototype.constructor=Qc;bc.prototype=Object.create(xa.prototype);bc.prototype.constructor=bc;Rc.prototype=Object.create(P.prototype);Rc.prototype.constructor=Rc;cc.prototype=Object.create(xa.prototype); +cc.prototype.constructor=cc;Sc.prototype=Object.create(P.prototype);Sc.prototype.constructor=Sc;dc.prototype=Object.create(D.prototype);dc.prototype.constructor=dc;Tc.prototype=Object.create(P.prototype);Tc.prototype.constructor=Tc;ec.prototype=Object.create(D.prototype);ec.prototype.constructor=ec;Uc.prototype=Object.create(P.prototype);Uc.prototype.constructor=Uc;fc.prototype=Object.create(D.prototype);fc.prototype.constructor=fc;var Ug={triangulate:function(a,b,c){c=c||2;var d=b&&b.length,e=d? +b[0]*c:a.length,f=cf(a,0,e,c,!0),g=[];if(!f)return g;var h;if(d){var l=c;d=[];var m;var k=0;for(m=b.length;k80*c){var q=h=a[0];var r=d=a[1];for(l=c;lh&&(h=k),b>d&&(d=b);h=Math.max(h-q,d-r);h=0!==h?1/h:0}Xc(f,g,c,q,r,h);return g}},$a={area:function(a){for(var b= +a.length,c=0,d=b-1,e=0;e$a.area(a)},triangulateShape:function(a,b){var c=[],d=[],e=[];gf(a);hf(c,a);var f=a.length;b.forEach(gf);for(a=0;aMath.abs(g-l)?[new B(a,1-c),new B(h,1-d),new B(m,1-e),new B(n,1-b)]:[new B(g,1-c),new B(l,1-d),new B(k,1-e),new B(p,1-b)]}};Zc.prototype=Object.create(P.prototype);Zc.prototype.constructor=Zc;gc.prototype=Object.create(Ta.prototype);gc.prototype.constructor=gc;$c.prototype=Object.create(P.prototype);$c.prototype.constructor=$c;xb.prototype=Object.create(D.prototype);xb.prototype.constructor=xb;ad.prototype=Object.create(P.prototype);ad.prototype.constructor= +ad;hc.prototype=Object.create(D.prototype);hc.prototype.constructor=hc;bd.prototype=Object.create(P.prototype);bd.prototype.constructor=bd;ic.prototype=Object.create(D.prototype);ic.prototype.constructor=ic;yb.prototype=Object.create(P.prototype);yb.prototype.constructor=yb;yb.prototype.toJSON=function(){var a=P.prototype.toJSON.call(this);return kf(this.parameters.shapes,a)};zb.prototype=Object.create(D.prototype);zb.prototype.constructor=zb;zb.prototype.toJSON=function(){var a=D.prototype.toJSON.call(this); +return kf(this.parameters.shapes,a)};jc.prototype=Object.create(D.prototype);jc.prototype.constructor=jc;Ab.prototype=Object.create(P.prototype);Ab.prototype.constructor=Ab;ab.prototype=Object.create(D.prototype);ab.prototype.constructor=ab;cd.prototype=Object.create(Ab.prototype);cd.prototype.constructor=cd;dd.prototype=Object.create(ab.prototype);dd.prototype.constructor=dd;ed.prototype=Object.create(P.prototype);ed.prototype.constructor=ed;kc.prototype=Object.create(D.prototype);kc.prototype.constructor= +kc;var ka=Object.freeze({WireframeGeometry:Zb,ParametricGeometry:Mc,ParametricBufferGeometry:$b,TetrahedronGeometry:Oc,TetrahedronBufferGeometry:ac,OctahedronGeometry:Pc,OctahedronBufferGeometry:ub,IcosahedronGeometry:Qc,IcosahedronBufferGeometry:bc,DodecahedronGeometry:Rc,DodecahedronBufferGeometry:cc,PolyhedronGeometry:Nc,PolyhedronBufferGeometry:xa,TubeGeometry:Sc,TubeBufferGeometry:dc,TorusKnotGeometry:Tc,TorusKnotBufferGeometry:ec,TorusGeometry:Uc,TorusBufferGeometry:fc,TextGeometry:Zc,TextBufferGeometry:gc, +SphereGeometry:$c,SphereBufferGeometry:xb,RingGeometry:ad,RingBufferGeometry:hc,PlaneGeometry:Fc,PlaneBufferGeometry:rb,LatheGeometry:bd,LatheBufferGeometry:ic,ShapeGeometry:yb,ShapeBufferGeometry:zb,ExtrudeGeometry:wb,ExtrudeBufferGeometry:Ta,EdgesGeometry:jc,ConeGeometry:cd,ConeBufferGeometry:dd,CylinderGeometry:Ab,CylinderBufferGeometry:ab,CircleGeometry:ed,CircleBufferGeometry:kc,BoxGeometry:Nb,BoxBufferGeometry:pb});Bb.prototype=Object.create(I.prototype);Bb.prototype.constructor=Bb;Bb.prototype.isShadowMaterial= +!0;Bb.prototype.copy=function(a){I.prototype.copy.call(this,a);this.color.copy(a.color);return this};lc.prototype=Object.create(Fa.prototype);lc.prototype.constructor=lc;lc.prototype.isRawShaderMaterial=!0;Ua.prototype=Object.create(I.prototype);Ua.prototype.constructor=Ua;Ua.prototype.isMeshStandardMaterial=!0;Ua.prototype.copy=function(a){I.prototype.copy.call(this,a);this.defines={STANDARD:""};this.color.copy(a.color);this.roughness=a.roughness;this.metalness=a.metalness;this.map=a.map;this.lightMap= +a.lightMap;this.lightMapIntensity=a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalMapType=a.normalMapType;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias;this.roughnessMap= +a.roughnessMap;this.metalnessMap=a.metalnessMap;this.alphaMap=a.alphaMap;this.envMap=a.envMap;this.envMapIntensity=a.envMapIntensity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};Cb.prototype=Object.create(Ua.prototype);Cb.prototype.constructor=Cb; +Cb.prototype.isMeshPhysicalMaterial=!0;Cb.prototype.copy=function(a){Ua.prototype.copy.call(this,a);this.defines={PHYSICAL:""};this.reflectivity=a.reflectivity;this.clearCoat=a.clearCoat;this.clearCoatRoughness=a.clearCoatRoughness;return this};Ka.prototype=Object.create(I.prototype);Ka.prototype.constructor=Ka;Ka.prototype.isMeshPhongMaterial=!0;Ka.prototype.copy=function(a){I.prototype.copy.call(this,a);this.color.copy(a.color);this.specular.copy(a.specular);this.shininess=a.shininess;this.map= +a.map;this.lightMap=a.lightMap;this.lightMapIntensity=a.lightMapIntensity;this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalMapType=a.normalMapType;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale=a.displacementScale;this.displacementBias=a.displacementBias; +this.specularMap=a.specularMap;this.alphaMap=a.alphaMap;this.envMap=a.envMap;this.combine=a.combine;this.reflectivity=a.reflectivity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};Db.prototype=Object.create(Ka.prototype);Db.prototype.constructor=Db; +Db.prototype.isMeshToonMaterial=!0;Db.prototype.copy=function(a){Ka.prototype.copy.call(this,a);this.gradientMap=a.gradientMap;return this};Eb.prototype=Object.create(I.prototype);Eb.prototype.constructor=Eb;Eb.prototype.isMeshNormalMaterial=!0;Eb.prototype.copy=function(a){I.prototype.copy.call(this,a);this.bumpMap=a.bumpMap;this.bumpScale=a.bumpScale;this.normalMap=a.normalMap;this.normalMapType=a.normalMapType;this.normalScale.copy(a.normalScale);this.displacementMap=a.displacementMap;this.displacementScale= +a.displacementScale;this.displacementBias=a.displacementBias;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.skinning=a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};Fb.prototype=Object.create(I.prototype);Fb.prototype.constructor=Fb;Fb.prototype.isMeshLambertMaterial=!0;Fb.prototype.copy=function(a){I.prototype.copy.call(this,a);this.color.copy(a.color);this.map=a.map;this.lightMap=a.lightMap;this.lightMapIntensity=a.lightMapIntensity; +this.aoMap=a.aoMap;this.aoMapIntensity=a.aoMapIntensity;this.emissive.copy(a.emissive);this.emissiveMap=a.emissiveMap;this.emissiveIntensity=a.emissiveIntensity;this.specularMap=a.specularMap;this.alphaMap=a.alphaMap;this.envMap=a.envMap;this.combine=a.combine;this.reflectivity=a.reflectivity;this.refractionRatio=a.refractionRatio;this.wireframe=a.wireframe;this.wireframeLinewidth=a.wireframeLinewidth;this.wireframeLinecap=a.wireframeLinecap;this.wireframeLinejoin=a.wireframeLinejoin;this.skinning= +a.skinning;this.morphTargets=a.morphTargets;this.morphNormals=a.morphNormals;return this};Gb.prototype=Object.create(T.prototype);Gb.prototype.constructor=Gb;Gb.prototype.isLineDashedMaterial=!0;Gb.prototype.copy=function(a){T.prototype.copy.call(this,a);this.scale=a.scale;this.dashSize=a.dashSize;this.gapSize=a.gapSize;return this};var Vg=Object.freeze({ShadowMaterial:Bb,SpriteMaterial:ib,RawShaderMaterial:lc,ShaderMaterial:Fa,PointsMaterial:Ja,MeshPhysicalMaterial:Cb,MeshStandardMaterial:Ua,MeshPhongMaterial:Ka, +MeshToonMaterial:Db,MeshNormalMaterial:Eb,MeshLambertMaterial:Fb,MeshDepthMaterial:fb,MeshDistanceMaterial:gb,MeshBasicMaterial:ua,LineDashedMaterial:Gb,LineBasicMaterial:T,Material:I}),Kb={enabled:!1,files:{},add:function(a,b){!1!==this.enabled&&(this.files[a]=b)},get:function(a){if(!1!==this.enabled)return this.files[a]},remove:function(a){delete this.files[a]},clear:function(){this.files={}}},ya=new ee,cb={};Object.assign(La.prototype,{load:function(a,b,c,d){void 0===a&&(a="");void 0!==this.path&& +(a=this.path+a);a=this.manager.resolveURL(a);var e=this,f=Kb.get(a);if(void 0!==f)return e.manager.itemStart(a),setTimeout(function(){b&&b(f);e.manager.itemEnd(a)},0),f;if(void 0!==cb[a])cb[a].push({onLoad:b,onProgress:c,onError:d});else{var g=a.match(/^data:(.*?)(;base64)?,(.*)$/);if(g){c=g[1];var h=!!g[2];g=g[3];g=window.decodeURIComponent(g);h&&(g=window.atob(g));try{var l=(this.responseType||"").toLowerCase();switch(l){case "arraybuffer":case "blob":var m=new Uint8Array(g.length);for(h=0;hg)e=a+1;else if(0b&&(b=0);1Number.EPSILON&&(g.normalize(), +c=Math.acos(J.clamp(d[l-1].dot(d[l]),-1,1)),e[l].applyMatrix4(h.makeRotationAxis(g,c))),f[l].crossVectors(d[l],e[l]);if(!0===b)for(c=Math.acos(J.clamp(e[0].dot(e[a]),-1,1)),c/=a,0d;)d+=c;for(;d>c;)d-=c;de&&(e=1);1E-4>d&&(d=e);1E-4>l&&(l=e);Ce.initNonuniformCatmullRom(f.x,g.x,h.x, +c.x,d,e,l);De.initNonuniformCatmullRom(f.y,g.y,h.y,c.y,d,e,l);Ee.initNonuniformCatmullRom(f.z,g.z,h.z,c.z,d,e,l)}else"catmullrom"===this.curveType&&(Ce.initCatmullRom(f.x,g.x,h.x,c.x,this.tension),De.initCatmullRom(f.y,g.y,h.y,c.y,this.tension),Ee.initCatmullRom(f.z,g.z,h.z,c.z,this.tension));b.set(Ce.calc(a),De.calc(a),Ee.calc(a));return b};pa.prototype.copy=function(a){E.prototype.copy.call(this,a);this.points=[];for(var b=0,c=a.points.length;bc.length- +2?c.length-1:a+1];c=c[a>c.length-3?c.length-1:a+2];b.set(mf(d,e.x,f.x,g.x,c.x),mf(d,e.y,f.y,g.y,c.y));return b};Pa.prototype.copy=function(a){E.prototype.copy.call(this,a);this.points=[];for(var b=0,c=a.points.length;b=b)return b=c[a]-b,a=this.curves[a],c=a.getLength(),a.getPointAt(0===c?0:1-b/c);a++}return null},getLength:function(){var a=this.getCurveLengths();return a[a.length-1]},updateArcLengths:function(){this.needsUpdate=!0;this.cacheLengths=null;this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths; +for(var a=[],b=0,c=0,d=this.curves.length;c=e)break a;else{f=b[1];a=e)break b}d=c;c=0}}for(;c>>1,ab;)--f;++f;if(0!==e||f!==d)e>=f&&(f=Math.max(f,1),e=f-1),a=this.getValueSize(),this.times=na.arraySlice(c,e,f),this.values=na.arraySlice(this.values,e*a,f*a);return this},validate:function(){var a=!0,b=this.getValueSize();0!==b-Math.floor(b)&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),a=!1);var c=this.times;b=this.values; +var d=c.length;0===d&&(console.error("THREE.KeyframeTrack: Track is empty.",this),a=!1);for(var e=null,f=0;f!==d;f++){var g=c[f];if("number"===typeof g&&isNaN(g)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,f,g);a=!1;break}if(null!==e&&e>g){console.error("THREE.KeyframeTrack: Out of order keys.",this,f,g,e);a=!1;break}e=g}if(void 0!==b&&na.isTypedArray(b))for(f=0,c=b.length;f!==c;++f)if(d=b[f],isNaN(d)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this, +f,d);a=!1;break}return a},optimize:function(){for(var a=this.times,b=this.values,c=this.getValueSize(),d=2302===this.getInterpolation(),e=1,f=a.length-1,g=1;gk.opacity&&(k.transparent=!0);d.setTextures(l);return d.parse(k)}}()});var Fe={decodeText:function(a){if("undefined"!==typeof TextDecoder)return(new TextDecoder).decode(a);for(var b="",c=0,d=a.length;cf;f++){var C=h[q++];var z=A[2*C];C=A[2*C+1];z=new B(z,C);2!==f&&c.faceVertexUvs[e][u].push(z);0!==f&&c.faceVertexUvs[e][u+1].push(z)}}y&&(y=3*h[q++],r.normal.set(k[y++],k[y++],k[y]),x.normal.copy(r.normal)); +if(w)for(e=0;4>e;e++)y=3*h[q++],w=new p(k[y++],k[y++],k[y]),2!==e&&r.vertexNormals.push(w),0!==e&&x.vertexNormals.push(w);n&&(n=h[q++],n=v[n],r.color.setHex(n),x.color.setHex(n));if(l)for(e=0;4>e;e++)n=h[q++],n=v[n],2!==e&&r.vertexColors.push(new G(n)),0!==e&&x.vertexColors.push(new G(n));c.faces.push(r);c.faces.push(x)}else{r=new Ya;r.a=h[q++];r.b=h[q++];r.c=h[q++];u&&(u=h[q++],r.materialIndex=u);u=c.faces.length;if(e)for(e=0;ef;f++)C=h[q++],z= +A[2*C],C=A[2*C+1],z=new B(z,C),c.faceVertexUvs[e][u].push(z);y&&(y=3*h[q++],r.normal.set(k[y++],k[y++],k[y]));if(w)for(e=0;3>e;e++)y=3*h[q++],w=new p(k[y++],k[y++],k[y]),r.vertexNormals.push(w);n&&(n=h[q++],r.color.setHex(v[n]));if(l)for(e=0;3>e;e++)n=h[q++],r.vertexColors.push(new G(v[n]));c.faces.push(r)}}d=a;q=void 0!==d.influencesPerVertex?d.influencesPerVertex:2;if(d.skinWeights)for(g=0,h=d.skinWeights.length;g +Number.EPSILON){if(0>k&&(g=b[f],l=-l,h=b[e],k=-k),!(a.yh.y))if(a.y===g.y){if(a.x===g.x)return!0}else{e=k*(a.x-g.x)-l*(a.y-g.y);if(0===e)return!0;0>e||(d=!d)}}else if(a.y===g.y&&(h.x<=a.x&&a.x<=g.x||g.x<=a.x&&a.x<=h.x))return!0}return d}var e=$a.isClockWise,f=this.subPaths;if(0===f.length)return[];if(!0===b)return c(f);b=[];if(1===f.length){var g=f[0];var h=new jb;h.curves=g.curves;b.push(h);return b}var l=!e(f[0].getPoints());l=a?!l:l;h=[];var k=[],p=[],n=0;k[n]=void 0;p[n]=[];for(var t= +0,q=f.length;td&&this._mixBufferRegion(c,a,3*b,1-d,b);d=b;for(var f=b+b;d!==f;++d)if(c[d]!==c[d+b]){e.setValue(c,a);break}},saveOriginalState:function(){var a=this.buffer,b=this.valueSize,c=3*b;this.binding.getValue(a,c);for(var d=b;d!==c;++d)a[d]=a[c+d%b];this.cumulativeWeight= +0},restoreOriginalState:function(){this.binding.setValue(this.buffer,3*this.valueSize)},_select:function(a,b,c,d,e){if(.5<=d)for(d=0;d!==e;++d)a[b+d]=a[c+d]},_slerp:function(a,b,c,d){ca.slerpFlat(a,b,a,b,a,c,d)},_lerp:function(a,b,c,d,e){for(var f=1-d,g=0;g!==e;++g){var h=b+g;a[h]=a[h]*f+a[c+g]*d}}});Object.assign(qf.prototype,{getValue:function(a,b){this.bind();var c=this._bindings[this._targetGroup.nCachedObjects_];void 0!==c&&c.getValue(a,b)},setValue:function(a,b){for(var c=this._bindings,d=this._targetGroup.nCachedObjects_, +e=c.length;d!==e;++d)c[d].setValue(a,b)},bind:function(){for(var a=this._bindings,b=this._targetGroup.nCachedObjects_,c=a.length;b!==c;++b)a[b].bind()},unbind:function(){for(var a=this._bindings,b=this._targetGroup.nCachedObjects_,c=a.length;b!==c;++b)a[b].unbind()}});Object.assign(ra,{Composite:qf,create:function(a,b,c){return a&&a.isAnimationObjectGroup?new ra.Composite(a,b,c):new ra(a,b,c)},sanitizeNodeName:function(){var a=/[\[\]\.:\/]/g;return function(b){return b.replace(/\s/g,"_").replace(a, +"")}}(),parseTrackName:function(){var a="[^"+"\\[\\]\\.:\\/".replace("\\.","")+"]",b=/((?:WC+[\/:])*)/.source.replace("WC","[^\\[\\]\\.:\\/]");a=/(WCOD+)?/.source.replace("WCOD",a);var c=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC","[^\\[\\]\\.:\\/]"),d=/\.(WC+)(?:\[(.+)\])?/.source.replace("WC","[^\\[\\]\\.:\\/]"),e=new RegExp("^"+b+a+c+d+"$"),f=["material","materials","bones"];return function(a){var b=e.exec(a);if(!b)throw Error("PropertyBinding: Cannot parse trackName: "+a);b={nodeName:b[2], +objectName:b[3],objectIndex:b[4],propertyName:b[5],propertyIndex:b[6]};var c=b.nodeName&&b.nodeName.lastIndexOf(".");if(void 0!==c&&-1!==c){var d=b.nodeName.substring(c+1);-1!==f.indexOf(d)&&(b.nodeName=b.nodeName.substring(0,c),b.objectName=d)}if(null===b.propertyName||0===b.propertyName.length)throw Error("PropertyBinding: can not parse propertyName from trackName: "+a);return b}}(),findNode:function(a,b){if(!b||""===b||"root"===b||"."===b||-1===b||b===a.name||b===a.uuid)return a;if(a.skeleton){var c= +a.skeleton.getBoneByName(b);if(void 0!==c)return c}if(a.children){var d=function(a){for(var c=0;c=b){var p=b++,n=a[p];c[n.uuid]=k;a[k]=n;c[l]=p;a[p]=h;h=0;for(l=e;h!==l;++h){n=d[h];var t=n[k];n[k]=n[p];n[p]=t}}}this.nCachedObjects_=b},uncache:function(){for(var a=this._objects,b=a.length,c=this.nCachedObjects_,d=this._indicesByUUID,e=this._bindings,f=e.length,g=0,h=arguments.length;g!==h;++g){var l= +arguments[g].uuid,k=d[l];if(void 0!==k)if(delete d[l],kb||0===c)return;this._startTime=null;b*=c}b*=this._updateTimeScale(a);c=this._updateTime(b);a=this._updateWeight(a);if(0c.parameterPositions[1]&&(this.stopFading(),0===d&&(this.enabled=!1))}}return this._effectiveWeight=b},_updateTimeScale:function(a){var b=0;if(!this.paused){b=this.timeScale;var c=this._timeScaleInterpolant;if(null!==c){var d=c.evaluate(a)[0];b*=d;a>c.parameterPositions[1]&&(this.stopWarping(),0===b?this.paused=!0:this.timeScale=b)}}return this._effectiveTimeScale=b},_updateTime:function(a){var b=this.time+a;if(0===a)return b;var c=this._clip.duration,d=this.loop,e=this._loopCount;if(2200=== +d)a:{if(-1===e&&(this._loopCount=0,this._setEndings(!0,!0,!1)),b>=c)b=c;else if(0>b)b=0;else break a;this.clampWhenFinished?this.paused=!0:this.enabled=!1;this._mixer.dispatchEvent({type:"finished",action:this,direction:0>a?-1:1})}else{d=2202===d;-1===e&&(0<=a?(e=0,this._setEndings(!0,0===this.repetitions,d)):this._setEndings(0===this.repetitions,!0,d));if(b>=c||0>b){var f=Math.floor(b/c);b-=c*f;e+=Math.abs(f);var g=this.repetitions-e;0>=g?(this.clampWhenFinished?this.paused=!0:this.enabled=!1,b= +0a,this._setEndings(a,!a,d)):this._setEndings(!1,!1,d),this._loopCount=e,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:f}))}if(d&&1===(e&1))return this.time=b,c-b}return this.time=b},_setEndings:function(a,b,c){var d=this._interpolantSettings;c?(d.endingStart=2401,d.endingEnd=2401):(d.endingStart=a?this.zeroSlopeAtStart?2401:2400:2402,d.endingEnd=b?this.zeroSlopeAtEnd?2401:2400:2402)},_scheduleFading:function(a, +b,c){var d=this._mixer,e=d.time,f=this._weightInterpolant;null===f&&(this._weightInterpolant=f=d._lendControlInterpolant());d=f.parameterPositions;f=f.sampleValues;d[0]=e;f[0]=b;d[1]=e+a;f[1]=c;return this}});te.prototype=Object.assign(Object.create(za.prototype),{constructor:te,_bindAction:function(a,b){var c=a._localRoot||this._root,d=a._clip.tracks,e=d.length,f=a._propertyBindings;a=a._interpolants;var g=c.uuid,h=this._bindingsByRootAndName,k=h[g];void 0===k&&(k={},h[g]=k);for(h=0;h!==e;++h){var m= +d[h],p=m.name,n=k[p];if(void 0===n){n=f[h];if(void 0!==n){null===n._cacheIndex&&(++n.referenceCount,this._addInactiveBinding(n,g,p));continue}n=new se(ra.create(c,p,b&&b._propertyBindings[h].binding.parsedPath),m.ValueTypeName,m.getValueSize());++n.referenceCount;this._addInactiveBinding(n,g,p)}f[h]=n;a[h].resultBuffer=n.buffer}},_activateAction:function(a){if(!this._isActiveAction(a)){if(null===a._cacheIndex){var b=(a._localRoot||this._root).uuid,c=a._clip.uuid,d=this._actionsByClip[c];this._bindAction(a, +d&&d.knownActions[0]);this._addInactiveAction(a,c,b)}b=a._propertyBindings;c=0;for(d=b.length;c!==d;++c){var e=b[c];0===e.useCount++&&(this._lendBinding(e),e.saveOriginalState())}this._lendAction(a)}},_deactivateAction:function(a){if(this._isActiveAction(a)){for(var b=a._propertyBindings,c=0,d=b.length;c!==d;++c){var e=b[c];0===--e.useCount&&(e.restoreOriginalState(),this._takeBackBinding(e))}this._takeBackAction(a)}},_initMemoryManager:function(){this._actions=[];this._nActiveActions=0;this._actionsByClip= +{};this._bindings=[];this._nActiveBindings=0;this._bindingsByRootAndName={};this._controlInterpolants=[];this._nActiveControlInterpolants=0;var a=this;this.stats={actions:{get total(){return a._actions.length},get inUse(){return a._nActiveActions}},bindings:{get total(){return a._bindings.length},get inUse(){return a._nActiveBindings}},controlInterpolants:{get total(){return a._controlInterpolants.length},get inUse(){return a._nActiveControlInterpolants}}}},_isActiveAction:function(a){a=a._cacheIndex; +return null!==a&&athis.max.x||a.ythis.max.y?!1:!0},containsBox:function(a){return this.min.x<=a.min.x&&a.max.x<=this.max.x&&this.min.y<=a.min.y&&a.max.y<= +this.max.y},getParameter:function(a,b){void 0===b&&(console.warn("THREE.Box2: .getParameter() target is now required"),b=new B);return b.set((a.x-this.min.x)/(this.max.x-this.min.x),(a.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(a){return a.max.xthis.max.x||a.max.ythis.max.y?!1:!0},clampPoint:function(a,b){void 0===b&&(console.warn("THREE.Box2: .clampPoint() target is now required"),b=new B);return b.copy(a).clamp(this.min,this.max)},distanceToPoint:function(){var a= +new B;return function(b){return a.copy(b).clamp(this.min,this.max).sub(b).length()}}(),intersect:function(a){this.min.max(a.min);this.max.min(a.max);return this},union:function(a){this.min.min(a.min);this.max.max(a.max);return this},translate:function(a){this.min.add(a);this.max.add(a);return this},equals:function(a){return a.min.equals(this.min)&&a.max.equals(this.max)}});ld.prototype=Object.create(H.prototype);ld.prototype.constructor=ld;ld.prototype.isImmediateRenderObject=!0;md.prototype=Object.create(Y.prototype); +md.prototype.constructor=md;md.prototype.update=function(){var a=new p,b=new p,c=new la;return function(){var d=["a","b","c"];this.object.updateMatrixWorld(!0);c.getNormalMatrix(this.object.matrixWorld);var e=this.object.matrixWorld,f=this.geometry.attributes.position,g=this.object.geometry;if(g&&g.isGeometry)for(var h=g.vertices,k=g.faces,m=g=0,p=k.length;mMath.abs(b)&&(b=1E-8);this.scale.set(.5*this.size,.5*this.size,b);this.children[0].material.side=0>b?1:0;this.lookAt(this.plane.normal);H.prototype.updateMatrixWorld.call(this,a)};var Sd,Ae;Jb.prototype=Object.create(H.prototype);Jb.prototype.constructor=Jb;Jb.prototype.setDirection= +function(){var a=new p,b;return function(c){.99999c.y?this.quaternion.set(1,0,0,0):(a.set(c.z,0,-c.x).normalize(),b=Math.acos(c.y),this.quaternion.setFromAxisAngle(a,b))}}();Jb.prototype.setLength=function(a,b,c){void 0===b&&(b=.2*a);void 0===c&&(c=.2*b);this.line.scale.set(1,Math.max(0,a-b),1);this.line.updateMatrix();this.cone.scale.set(c,b,c);this.cone.position.y=a;this.cone.updateMatrix()};Jb.prototype.setColor=function(a){this.line.material.color.copy(a); +this.cone.material.color.copy(a)};sd.prototype=Object.create(Y.prototype);sd.prototype.constructor=sd;E.create=function(a,b){console.log("THREE.Curve.create() has been deprecated");a.prototype=Object.create(E.prototype);a.prototype.constructor=a;a.prototype.getPoint=b;return a};Object.assign(bb.prototype,{createPointsGeometry:function(a){console.warn("THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");a=this.getPoints(a);return this.createGeometry(a)}, +createSpacedPointsGeometry:function(a){console.warn("THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");a=this.getSpacedPoints(a);return this.createGeometry(a)},createGeometry:function(a){console.warn("THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.");for(var b=new P,c=0,d=a.length;c .dropdown { + position: absolute; + background-color: white; + color: #333333; + width: 100%; + + overflow: hidden; + + transition: all 0.3s; + max-height: 0px; +} + +.dropdown-container:hover > .dropdown { + max-height: 200px; + border-color: #ddddddFF; +} + +.dropdown-container > .dropdown > ul { + margin: 0; + padding: 0; + list-style: none; +} + +.dropdown-container > .dropdown > ul > li { + cursor: pointer; +} + +.dropdown-container > .dropdown > ul > li:hover { + color: #dddddd; + background-color: #333333; +} + +#alert-box { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-content: center; + justify-content: center; + flex-wrap: wrap; + flex-direction: column; + pointer-events: none; +} + +#alert-box h1 { + font-size: 1.4rem; + font-weight: bold; + + margin: 0; + padding: 15px; + text-align: center; +} + +#alert-box h2 { + font-size: 1.2rem; + font-weight: bold; + + margin: 0; + padding: 15px 0 5px 0; + text-align: left; +} + +#alert-box a { + color: #333333; + text-decoration: underline; +} + +#alert-box a:hover { + color: #888888; +} + +#alert-box .alert { + position: relative; + pointer-events: all; + margin: 10px; + padding: 10px; +} + +#alert-box .alert .alert-close-button { + /*position: absolute; + top: 5px; + right: 5px; + */ + margin: -10px -10px 0px 0px; + padding: 0 0 5px 5px; + float: right; + width: 15px; + height: 15px; + line-height: 15px; + font-weight: bold; + font-size: 15px; + color: #333333; +} + +#alert-box .alert .alert-close-button::after { + content: 'x'; +} + +#alert-box .alert .alert-close-button:hover { + color: #dd3333; +} + +#map-container { + position: absolute; + width: 100%; + height: 100%; + background-color: black; + overflow: hidden; +} + +#map-container canvas { + width: 100%; + height: 100%; +} + +#bluemap-loading { + position: absolute; + width: 200px; + line-height: 20px; + padding: 20px 0; + top: calc(50% - 31px); + left: calc(50% - 101px); + text-align: center; +} + +#bluemap-topright { + position: absolute; + top: 10px; + right: 10px; + + line-height: 30px; + + display: flex; +} + +#bluemap-topright > *:not(:last-child) { + border-right: solid 1px #dddddd; +} + +#bluemap-topleft { + position: absolute; + top: 10px; + left: 10px; + + line-height: 30px; + + display: flex; +} + +#bluemap-topleft > *:not(:last-child) { + border-right: solid 1px #dddddd; +} + +#bluemap-mapmenu { + width: 200px; +} + +#bluemap-mapmenu .selection, #bluemap-mapmenu .dropdown li { + padding-left: 10px; +} + +#bluemap-compass { + width: 30px; + height: 30px; +} + +#bluemap-compass:hover #bluemap-compass-needle { + filter: invert(1); +} + +.bluemap-position { + position: relative; + + width: 60px; + height: 30px; + padding: 0 5px 0 25px; +} + +.bluemap-position::before { + position: absolute; + left: 7px; + color: #888888; +} + +.bluemap-position.pos-x::before { + content: "x:"; +} + +.bluemap-position.pos-y::before { + content: "y:"; +} + +.bluemap-position.pos-z::before { + content: "z:"; +} + +#bluemap-settings { + width: 30px; + height: 30px; +} + +#bluemap-settings.active:not(:hover) { + background-color: #dddddd; +} + +#bluemap-settings:hover > img { + filter: invert(1); +} + +#bluemap-settings-container { + display: flex; + white-space: nowrap; +} + +#bluemap-settings-quality { + width: 150px; + height: 30px; + +} + +#bluemap-settings-quality .selection, #bluemap-settings-quality .dropdown li { + padding-left: 10px; +} + +#bluemap-settings-render-distance { + width: 180px; +} + +#bluemap-settings-render-distance .selection { + padding-left: 10px; +} + +#bluemap-settings-render-distance input { + width: calc(100% - 20px); + margin: 10px; + padding: 0; +} + +#bluemap-info { + width: 30px; + height: 30px; + text-align: center; + +} + +#bluemap-info::after { + content: 'i'; + font-weight: bold; +} diff --git a/BlueMapSponge/build.gradle b/BlueMapSponge/build.gradle new file mode 100644 index 00000000..078fd8be --- /dev/null +++ b/BlueMapSponge/build.gradle @@ -0,0 +1,4 @@ +dependencies { + shadow "org.spongepowered:spongeapi:7.2.0-SNAPSHOT" + compile project(':BlueMapCore') +} diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java new file mode 100644 index 00000000..0333f8f0 --- /dev/null +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Slf4jLogger.java @@ -0,0 +1,59 @@ +/* + * This file is part of BlueMapSponge, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.sponge; + +import org.slf4j.Logger; + +import de.bluecolored.bluemap.core.logger.AbstractLogger; + +public class Slf4jLogger extends AbstractLogger { + + private Logger out; + + public Slf4jLogger(Logger out) { + this.out = out; + } + + @Override + public void logError(String message, Throwable throwable) { + out.error(message, throwable); + } + + @Override + public void logWarning(String message) { + out.warn(message); + } + + @Override + public void logInfo(String message) { + out.info(message); + } + + @Override + public void logDebug(String message) { + out.debug(message); + } + +} diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java new file mode 100644 index 00000000..bcf2033c --- /dev/null +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java @@ -0,0 +1,70 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * 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. + */ +package de.bluecolored.bluemap.sponge; + +import java.nio.file.Path; + +import javax.inject.Inject; + +import org.spongepowered.api.config.ConfigDir; +import org.spongepowered.api.plugin.Plugin; + +import de.bluecolored.bluemap.core.logger.Logger; + +@Plugin( + id = SpongePlugin.PLUGIN_ID, + name = SpongePlugin.PLUGIN_NAME, + authors = { "Blue (Lukas Rieger)" }, + description = "This plugin provides a fully 3D map of your world for your browser!", + version = SpongePlugin.PLUGIN_VERSION + ) +public class SpongePlugin { + + public static final String PLUGIN_ID = "bluemap"; + public static final String PLUGIN_NAME = "BlueMap"; + public static final String PLUGIN_VERSION = "0.0.0"; + + private static Object plugin; + + @Inject + @ConfigDir(sharedRoot = false) + private Path configurationDir; + + @Inject + public SpongePlugin(org.slf4j.Logger logger) { + plugin = this; + + Logger.global = new Slf4jLogger(logger); + } + + public Path getConfigPath(){ + return configurationDir; + } + + public static Object getPlugin() { + return plugin; + } + +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..0a98021f --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) Blue +Copyright (c) contributors + +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. diff --git a/README.md b/README.md new file mode 100644 index 00000000..2bfea8d3 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# BlueMap +**Currently not stable or finished!** + +A minecraft mapping tool that creates 3D models of your Minecraft worlds and displays them in a [web viewer](https://bluecolored.de/bluemap/). + +## Clone +Easy: + +`git clone https://github.com/BlueMap-Minecraft/BlueMap.git` + +## Build +In order to build BlueMap you simply need to run the `./gradlew shadowJar` command. +You can find the compiled JAR file in `./build/libs` + +## Contributing +You are welcome to contribute! +Just create a pull request with your changes :) diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..4faa73ab --- /dev/null +++ b/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'com.github.johnrengelman.shadow' version '5.1.0' + id 'java' +} + +allprojects { + repositories { + mavenCentral() + maven { + url 'https://jitpack.io' + } + maven { + name 'sponge' + url 'http://repo.spongepowered.org/maven' + } + } + + compileJava.options.compilerArgs.add '-parameters' + compileTestJava.options.compilerArgs.add '-parameters' + + apply plugin: 'java' + apply plugin: 'com.github.johnrengelman.shadow' +} + +dependencies { + compile project(':BlueMapCore') + compile project(':BlueMapCLI') + compile project(':BlueMapSponge') +} + +shadowJar { + baseName = 'BlueMap' + version = '0.0.1' + classifier = null +} + +jar { + manifest { + attributes 'Main-Class' : "de.bluecolored.bluemap.cli.BlueMapCLI" + } +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c2d1cf016b3885f6930543d57b744ea8c220a1a GIT binary patch literal 55616 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..9618d8d9 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..1a85cd28 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,8 @@ +rootProject.name = 'BlueMap' +include ':BlueMapCore' +include ':BlueMapCLI' +include ':BlueMapSponge' + +project(':BlueMapCore').projectDir = "$rootDir/BlueMapCore" as File +project(':BlueMapCLI').projectDir = "$rootDir/BlueMapCLI" as File +project(':BlueMapSponge').projectDir = "$rootDir/BlueMapSponge" as File \ No newline at end of file