diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java index 6fc63b29..74a0e81e 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java @@ -32,11 +32,9 @@ import de.bluecolored.bluemap.core.debug.DebugDump; import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.map.BmMap; -import de.bluecolored.bluemap.core.map.hires.RenderSettings; import de.bluecolored.bluemap.core.mca.MCAWorld; import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; import de.bluecolored.bluemap.core.resourcepack.ResourcePack; -import de.bluecolored.bluemap.core.world.SlicedWorld; import de.bluecolored.bluemap.core.world.World; import org.apache.commons.io.FileUtils; @@ -156,7 +154,7 @@ private synchronized void loadWorldsAndMaps() throws IOException, InterruptedExc World world = worlds.get(worldUUID); if (world == null) { try { - world = MCAWorld.load(worldFolder.toPath(), worldUUID, worldNameProvider.apply(worldUUID), mapConfig.isIgnoreMissingLightData()); + world = MCAWorld.load(worldFolder.toPath(), worldUUID, worldNameProvider.apply(worldUUID), 15, mapConfig.isIgnoreMissingLightData()); worlds.put(worldUUID, world); } catch (MissingResourcesException e) { throw e; // rethrow this to stop loading and display resource-missing message @@ -165,19 +163,6 @@ private synchronized void loadWorldsAndMaps() throws IOException, InterruptedExc continue; } } - - //slice world if configured - if (!mapConfig.getMin().equals(RenderSettings.DEFAULT_MIN) || !mapConfig.getMax().equals(RenderSettings.DEFAULT_MAX)) { - if (mapConfig.isRenderEdges()) { - world = new SlicedWorld(world, mapConfig.getMin(), mapConfig.getMax()); - } else { - world = new SlicedWorld( - world, - mapConfig.getMin().min(mapConfig.getMin().sub(2, 2, 2)), // protect from int-overflow - mapConfig.getMax().max(mapConfig.getMax().add(2, 2, 2)) // protect from int-overflow - ); - } - } BmMap map = new BmMap( id, diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/MapUpdateTask.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/MapUpdateTask.java index c8f41c37..48df2a71 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/MapUpdateTask.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/MapUpdateTask.java @@ -94,7 +94,7 @@ private static List getRegions(World world) { } private static List getRegions(World world, Vector2i center, int radius) { - if (center == null || radius < 0) return new ArrayList<>(world.listRegions()); + if (center == null || radius < 0) return new ArrayList<>(world.listRegions()); //TODO: remove regions outside render-boundaries List regions = new ArrayList<>(); diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/WorldRegionRenderTask.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/WorldRegionRenderTask.java index f910769e..de179c79 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/WorldRegionRenderTask.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/rendermanager/WorldRegionRenderTask.java @@ -115,7 +115,9 @@ public void doWork() { } //Logger.global.logInfo("Working on " + worldRegion + " - Tile " + tile); - map.renderTile(tile); // <- actual work + if (isAllChunksInTileGenerated(tile)) { + map.renderTile(tile); // <- actual work + } synchronized (this) { this.atWork--; @@ -126,6 +128,22 @@ public void doWork() { } } + private boolean isAllChunksInTileGenerated(Vector2i tile) { + Grid tileGrid = map.getHiresModelManager().getTileGrid(); + Grid chunkGrid = map.getWorld().getChunkGrid(); + + Vector2i minChunk = tileGrid.getCellMin(tile, chunkGrid); + Vector2i maxChunk = tileGrid.getCellMax(tile, chunkGrid); + + for (int x = minChunk.getX(); x <= maxChunk.getX(); x++) { + for (int z = minChunk.getY(); z <= maxChunk.getY(); z++) { + if (!map.getWorld().getChunk(x, z).isGenerated()) return false; + } + } + + return true; + } + private void complete() { map.getRenderState().setRenderTime(worldRegion, startTime); diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MapConfig.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MapConfig.java index 2c27e756..14f1f041 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MapConfig.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MapConfig.java @@ -45,6 +45,7 @@ public class MapConfig implements MapSettings { private Vector2i startPos; private int skyColor; private float ambientLight; + private int worldSkyLight; private boolean renderCaves; @@ -82,6 +83,9 @@ public MapConfig(ConfigurationNode node) throws IOException { //ambientLight this.ambientLight = node.node("ambientLight").getFloat(0f); + + //worldSkyLight + this.worldSkyLight = node.node("worldSkyLight").getInt(15); //renderCaves this.renderCaves = node.node("renderCaves").getBoolean(false); @@ -101,7 +105,7 @@ public MapConfig(ConfigurationNode node) throws IOException { //useCompression this.useGzip = node.node("useCompression").getBoolean(true); - + //ignoreMissingLightData this.ignoreMissingLightData = node.node("ignoreMissingLightData").getBoolean(false); @@ -135,11 +139,17 @@ public Vector2i getStartPos() { public int getSkyColor() { return skyColor; } - + + @Override public float getAmbientLight() { return ambientLight; } + @Override + public int getWorldSkyLight() { + return worldSkyLight; + } + public boolean isRenderCaves() { return renderCaves; } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/debug/OneBlockWorld.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/debug/OneBlockWorld.java deleted file mode 100644 index ceaa470b..00000000 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/debug/OneBlockWorld.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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.debug; - -import com.flowpowered.math.vector.Vector2i; -import com.flowpowered.math.vector.Vector3i; -import de.bluecolored.bluemap.core.world.Chunk; -import de.bluecolored.bluemap.core.world.Grid; -import de.bluecolored.bluemap.core.world.Region; -import de.bluecolored.bluemap.core.world.World; - -import java.nio.file.Path; -import java.util.Collection; -import java.util.UUID; - -public class OneBlockWorld implements World { - - private final World delegate; - - public OneBlockWorld(World delegate) { - this.delegate = delegate; - } - - @Override - public String getName() { - return delegate.getName(); - } - - @Override - public UUID getUUID() { - return delegate.getUUID(); - } - - @Override - public Path getSaveFolder() { - return delegate.getSaveFolder(); - } - - @Override - public int getSeaLevel() { - return 64; - } - - @Override - public Vector3i getSpawnPoint() { - return new Vector3i(0, 70, 0); - } - - @Override - public int getMaxY(int x, int z) { - return 255; - } - - @Override - public int getMinY(int x, int z) { - return 0; - } - - @Override - public Grid getChunkGrid() { - return delegate.getChunkGrid(); - } - - @Override - public Grid getRegionGrid() { - return delegate.getRegionGrid(); - } - - @Override - public Chunk getChunkAtBlock(int x, int y, int z) { - return delegate.getChunkAtBlock(x, y, z); - } - - @Override - public Chunk getChunk(int x, int z) { - return delegate.getChunk(x, z); - } - - @Override - public Region getRegion(int x, int z) { - return delegate.getRegion(x, z); - } - - @Override - public Collection listRegions() { - return delegate.listRegions(); - } - - @Override - public void invalidateChunkCache() { - delegate.invalidateChunkCache(); - } - - @Override - public void invalidateChunkCache(int x, int z) { - delegate.invalidateChunkCache(x, z); - } - - @Override - public void cleanUpChunkCache() { - delegate.cleanUpChunkCache(); - } - -} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java index 1d143185..3ff02900 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/HiresModelRenderer.java @@ -55,7 +55,7 @@ public HiresTileMeta render(World world, Vector3i modelMin, Vector3i modelMax, H int maxHeight, minY, maxY; Color columnColor = new Color(), blockColor = new Color(); - BlockNeighborhood block = new BlockNeighborhood<>(resourcePack, world, 0, 0, 0); + BlockNeighborhood block = new BlockNeighborhood<>(resourcePack, renderSettings, world, 0, 0, 0); BlockModelView blockModel = new BlockModelView(model); int x, y, z; @@ -65,35 +65,39 @@ public HiresTileMeta render(World world, Vector3i modelMin, Vector3i modelMax, H maxHeight = 0; columnColor.set(0, 0, 0, 1, true); - minY = Math.max(min.getY(), world.getMinY(x, z)); - maxY = Math.min(max.getY(), world.getMaxY(x, z)); + if (renderSettings.isInsideRenderBoundaries(x, z)) { + minY = Math.max(min.getY(), world.getMinY(x, z)); + maxY = Math.min(max.getY(), world.getMaxY(x, z)); - for (y = minY; y <= maxY; y++){ - block.set(x, y, z); - blockColor.set(0, 0, 0, 0, true); - blockModel.initialize(); + for (y = minY; y <= maxY; y++) { + block.set(x, y, z); + if (!block.isInsideRenderBounds()) continue; + + blockColor.set(0, 0, 0, 0, true); + blockModel.initialize(); - try { - modelFactory.render(block, blockModel, blockColor); - } catch (NoSuchResourceException e) { try { - modelFactory.render(block, BlockState.MISSING, blockModel.reset(), blockColor); - } catch (NoSuchResourceException e2) { - e.addSuppressed(e2); + modelFactory.render(block, blockModel, blockColor); + } catch (NoSuchResourceException e) { + try { + modelFactory.render(block, BlockState.MISSING, blockModel.reset(), blockColor); + } catch (NoSuchResourceException e2) { + e.addSuppressed(e2); + } + //Logger.global.noFloodDebug(block.getBlockState().getFullId() + "-hiresModelRenderer-blockmodelerr", "Failed to create BlockModel for BlockState: " + block.getBlockState() + " (" + e.toString() + ")"); } - //Logger.global.noFloodDebug(block.getBlockState().getFullId() + "-hiresModelRenderer-blockmodelerr", "Failed to create BlockModel for BlockState: " + block.getBlockState() + " (" + e.toString() + ")"); - } - // skip empty blocks - if (blockModel.getSize() <= 0) continue; + // skip empty blocks + if (blockModel.getSize() <= 0) continue; - // move block-model to correct position - blockModel.translate(x - modelAnchor.getX(), y - modelAnchor.getY(), z - modelAnchor.getZ()); - - //update color and height (only if not 100% translucent) - if (blockColor.a > 0) { - maxHeight = y; - columnColor.overlay(blockColor); + // move block-model to correct position + blockModel.translate(x - modelAnchor.getX(), y - modelAnchor.getY(), z - modelAnchor.getZ()); + + //update color and height (only if not 100% translucent) + if (blockColor.a > 0) { + maxHeight = y; + columnColor.overlay(blockColor); + } } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/RenderSettings.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/RenderSettings.java index d827ee0a..c6754c64 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/RenderSettings.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/RenderSettings.java @@ -52,6 +52,9 @@ default Vector3i getMax() { return DEFAULT_MAX; } + float getAmbientLight(); + + int getWorldSkyLight(); /** * The same as the maximum height, but blocks that are above this value are treated as AIR.
@@ -67,5 +70,29 @@ default boolean isRenderEdges() { default boolean useGzipCompression() { return true; } - + + default boolean isInsideRenderBoundaries(int x, int z) { + Vector3i min = getMin(); + Vector3i max = getMax(); + + return + x >= min.getX() && + x <= max.getX() && + z >= min.getZ() && + z <= max.getZ(); + } + + default boolean isInsideRenderBoundaries(int x, int y, int z) { + Vector3i min = getMin(); + Vector3i max = getMax(); + + return + x >= min.getX() && + x <= max.getX() && + z >= min.getZ() && + z <= max.getZ() && + y >= min.getY() && + y <= max.getY(); + } + } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/LiquidModelBuilder.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/LiquidModelBuilder.java index a5fa0cf3..871dd055 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/LiquidModelBuilder.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/LiquidModelBuilder.java @@ -40,7 +40,7 @@ import de.bluecolored.bluemap.core.util.math.VectorM3f; import de.bluecolored.bluemap.core.world.BlockNeighborhood; import de.bluecolored.bluemap.core.world.BlockState; -import de.bluecolored.bluemap.core.world.ResourcePackBlock; +import de.bluecolored.bluemap.core.world.ExtendedBlock; /** * A model builder for all liquid blocks @@ -144,10 +144,11 @@ private void build() { blockColor.multiply(tintcolor); // apply light - float sl = block.getSunLightLevel() / 16f; - blockColor.r *= sl; - blockColor.g *= sl; - blockColor.b *= sl; + float combinedLight = Math.max(block.getSunLightLevel() / 15f, block.getBlockLightLevel() / 15f); + combinedLight = (renderSettings.getAmbientLight() + combinedLight) / (renderSettings.getAmbientLight() + 1f); + blockColor.r *= combinedLight; + blockColor.g *= combinedLight; + blockColor.b *= combinedLight; } else { blockColor.set(0, 0, 0, 0, true); } @@ -166,7 +167,7 @@ private float getLiquidCornerHeight(int x, int z){ float sumHeight = 0f; int count = 0; - ResourcePackBlock neighbor; + ExtendedBlock neighbor; BlockState neighborBlockState; for (ix = x; ix <= x+1; ix++){ @@ -197,7 +198,7 @@ private boolean isLiquidBlockingBlock(BlockState blockState){ return !blockState.equals(BlockState.AIR); } - private boolean isSameLiquid(ResourcePackBlock block){ + private boolean isSameLiquid(ExtendedBlock block){ if (block.getBlockState().getFullId().equals(this.blockState.getFullId())) return true; return this.blockState.isWater() && (block.getBlockState().isWaterlogged() || block.getProperties().isAlwaysWaterlogged()); } @@ -217,7 +218,7 @@ private boolean createElementFace(Direction faceDir, VectorM3f c0, VectorM3f c1, Vector3i faceDirVector = faceDir.toVector(); //face culling - ResourcePackBlock bl = block.getNeighborBlock( + ExtendedBlock bl = block.getNeighborBlock( faceDirVector.getX(), faceDirVector.getY(), faceDirVector.getZ() @@ -341,7 +342,7 @@ private int getFlowingAngle() { } private float compareLiquidHeights(float ownHeight, int dx, int dz) { - ResourcePackBlock neighbor = block.getNeighborBlock(dx, 0, dz); + ExtendedBlock neighbor = block.getNeighborBlock(dx, 0, dz); if (neighbor.getBlockState().isAir()) return 0; if (!isSameLiquid(neighbor)) return 0; diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/ResourceModelBuilder.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/ResourceModelBuilder.java index 83b3bb39..69e246bf 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/ResourceModelBuilder.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/map/hires/blockmodel/ResourceModelBuilder.java @@ -44,7 +44,7 @@ import de.bluecolored.bluemap.core.util.math.VectorM3f; import de.bluecolored.bluemap.core.world.BlockNeighborhood; import de.bluecolored.bluemap.core.world.LightData; -import de.bluecolored.bluemap.core.world.ResourcePackBlock; +import de.bluecolored.bluemap.core.world.ExtendedBlock; /** * This model builder creates a BlockStateModel using the information from parsed resource-pack json files. @@ -160,12 +160,12 @@ private void createElementFace(BlockModelResource.Element element, Direction fac // face culling if (face.getCullface() != null) { - ResourcePackBlock b = getRotationRelativeBlock(face.getCullface()); + ExtendedBlock b = getRotationRelativeBlock(face.getCullface()); if (b.getProperties().isCulling()) return; } // light calculation - ResourcePackBlock facedBlockNeighbor = getRotationRelativeBlock(faceDir); + ExtendedBlock facedBlockNeighbor = getRotationRelativeBlock(faceDir); LightData blockLightData = block.getLightData(); LightData facedLightData = facedBlockNeighbor.getLightData(); @@ -307,20 +307,21 @@ private void createElementFace(BlockModelResource.Element element, Direction fac } // apply light - float sl = sunLight / 16f; - mapColor.r *= sl; - mapColor.g *= sl; - mapColor.b *= sl; + float combinedLight = Math.max(sunLight / 15f, blockLight / 15f); + combinedLight = (renderSettings.getAmbientLight() + combinedLight) / (renderSettings.getAmbientLight() + 1f); + mapColor.r *= combinedLight; + mapColor.g *= combinedLight; + mapColor.b *= combinedLight; blockColor.add(mapColor); } } - private ResourcePackBlock getRotationRelativeBlock(Direction direction){ + private ExtendedBlock getRotationRelativeBlock(Direction direction){ return getRotationRelativeBlock(direction.toVector()); } - private ResourcePackBlock getRotationRelativeBlock(Vector3i direction){ + private ExtendedBlock getRotationRelativeBlock(Vector3i direction){ return getRotationRelativeBlock( direction.getX(), direction.getY(), @@ -329,7 +330,7 @@ private ResourcePackBlock getRotationRelativeBlock(Vector3i direction){ } private final VectorM3f rotationRelativeBlockDirection = new VectorM3f(0, 0, 0); - private ResourcePackBlock getRotationRelativeBlock(int dx, int dy, int dz){ + private ExtendedBlock getRotationRelativeBlock(int dx, int dy, int dz){ rotationRelativeBlockDirection.set(dx, dy, dz); makeRotationRelative(rotationRelativeBlockDirection); 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 index 809aa525..d022a31a 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil113.java @@ -42,8 +42,8 @@ public class ChunkAnvil113 extends MCAChunk { private int[] biomes; @SuppressWarnings("unchecked") - public ChunkAnvil113(CompoundTag chunkTag, boolean ignoreMissingLightData) { - super(chunkTag); + public ChunkAnvil113(MCAWorld world, CompoundTag chunkTag) { + super(world, chunkTag); CompoundTag levelData = chunkTag.getCompoundTag("Level"); @@ -51,7 +51,7 @@ public ChunkAnvil113(CompoundTag chunkTag, boolean ignoreMissingLightData) { this.isGenerated = status.equals("full"); this.hasLight = isGenerated; - if (!isGenerated && ignoreMissingLightData) { + if (!isGenerated && getWorld().isIgnoreMissingLightData()) { isGenerated = !status.equals("empty"); } @@ -103,14 +103,14 @@ public BlockState getBlockState(int x, int y, int z) { @Override public LightData getLightData(int x, int y, int z, LightData target) { - if (!hasLight) return target.set(15, 0); + if (!hasLight) return target.set(getWorld().getSkyLight(), 0); int sectionY = y >> 4; if (sectionY < 0 || sectionY >= this.sections.length) - return (y < 0) ? target.set(0, 0) : target.set(15, 0); + return (y < 0) ? target.set(0, 0) : target.set(getWorld().getSkyLight(), 0); Section section = this.sections[sectionY]; - if (section == null) return target.set(15, 0); + if (section == null) return target.set(getWorld().getSkyLight(), 0); return section.getLightData(x, y, z, target); } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java index 7f34eb7b..7a7678a8 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil115.java @@ -42,8 +42,8 @@ public class ChunkAnvil115 extends MCAChunk { private int[] biomes; @SuppressWarnings("unchecked") - public ChunkAnvil115(CompoundTag chunkTag, boolean ignoreMissingLightData) { - super(chunkTag); + public ChunkAnvil115(MCAWorld world, CompoundTag chunkTag) { + super(world, chunkTag); CompoundTag levelData = chunkTag.getCompoundTag("Level"); @@ -51,7 +51,7 @@ public ChunkAnvil115(CompoundTag chunkTag, boolean ignoreMissingLightData) { this.isGenerated = status.equals("full"); this.hasLight = isGenerated; - if (!isGenerated && ignoreMissingLightData) { + if (!isGenerated && getWorld().isIgnoreMissingLightData()) { isGenerated = !status.equals("empty"); } @@ -103,14 +103,14 @@ public BlockState getBlockState(int x, int y, int z) { @Override public LightData getLightData(int x, int y, int z, LightData target) { - if (!hasLight) return target.set(15, 0); + if (!hasLight) return target.set(getWorld().getSkyLight(), 0); int sectionY = y >> 4; if (sectionY < 0 || sectionY >= this.sections.length) - return (y < 0) ? target.set(0, 0) : target.set(15, 0); + return (y < 0) ? target.set(0, 0) : target.set(getWorld().getSkyLight(), 0); Section section = this.sections[sectionY]; - if (section == null) return target.set(15, 0); + if (section == null) return target.set(getWorld().getSkyLight(), 0); return section.getLightData(x, y, z, target); } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java index 10e693fb..c90a465c 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/ChunkAnvil116.java @@ -46,8 +46,8 @@ public class ChunkAnvil116 extends MCAChunk { private int[] biomes; @SuppressWarnings("unchecked") - public ChunkAnvil116(CompoundTag chunkTag, boolean ignoreMissingLightData) { - super(chunkTag); + public ChunkAnvil116(MCAWorld world, CompoundTag chunkTag) { + super(world, chunkTag); CompoundTag levelData = chunkTag.getCompoundTag("Level"); @@ -55,7 +55,7 @@ public ChunkAnvil116(CompoundTag chunkTag, boolean ignoreMissingLightData) { this.isGenerated = status.equals("full"); this.hasLight = isGenerated; - if (!isGenerated && ignoreMissingLightData) { + if (!isGenerated && getWorld().isIgnoreMissingLightData()) { isGenerated = !status.equals("empty"); } @@ -119,12 +119,12 @@ public BlockState getBlockState(int x, int y, int z) { @Override public LightData getLightData(int x, int y, int z, LightData target) { - if (!hasLight) return target.set(15, 0); + if (!hasLight) return target.set(getWorld().getSkyLight(), 0); int sectionY = y >> 4; Section section = getSection(sectionY); - if (section == null) return (sectionY < sectionMin) ? target.set(0, 0) : target.set(15, 0); + if (section == null) return (sectionY < sectionMin) ? target.set(0, 0) : target.set(getWorld().getSkyLight(), 0); return section.getLightData(x, y, z, target); } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAChunk.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAChunk.java index a8eacc5d..50f64283 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAChunk.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAChunk.java @@ -33,13 +33,21 @@ public abstract class MCAChunk implements Chunk { + private final MCAWorld world; private final int dataVersion; - + protected MCAChunk() { + this.world = null; + this.dataVersion = -1; + } + + protected MCAChunk(MCAWorld world) { + this.world = world; this.dataVersion = -1; } - protected MCAChunk(CompoundTag chunkTag) { + protected MCAChunk(MCAWorld world, CompoundTag chunkTag) { + this.world = world; dataVersion = chunkTag.getInt("DataVersion"); } @@ -69,13 +77,17 @@ public int getMaxY(int x, int z) { public int getMinY(int x, int z) { return 0; } - - public static MCAChunk create(MCAWorld world, CompoundTag chunkTag, boolean ignoreMissingLightData) throws IOException { + + protected MCAWorld getWorld() { + return world; + } + + public static MCAChunk create(MCAWorld world, CompoundTag chunkTag) throws IOException { int version = chunkTag.getInt("DataVersion"); - if (version < 2200) return new ChunkAnvil113(chunkTag, ignoreMissingLightData); - if (version < 2500) return new ChunkAnvil115(chunkTag, ignoreMissingLightData); - return new ChunkAnvil116(chunkTag, ignoreMissingLightData); + if (version < 2200) return new ChunkAnvil113(world, chunkTag); + if (version < 2500) return new ChunkAnvil115(world, chunkTag); + return new ChunkAnvil116(world, chunkTag); } public static MCAChunk empty() { @@ -85,6 +97,7 @@ public static MCAChunk empty() { @Override public String toString() { return "MCAChunk{" + + "world=" + world + "dataVersion=" + dataVersion + "isGenerated()=" + isGenerated() + '}'; diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCARegion.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCARegion.java index 0cf3a775..47bd3029 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCARegion.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCARegion.java @@ -84,7 +84,7 @@ public MCAChunk loadChunk(int chunkX, int chunkZ, boolean ignoreMissingLightData 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) { - MCAChunk chunk = MCAChunk.create(world, (CompoundTag) tag, ignoreMissingLightData); + MCAChunk chunk = MCAChunk.create(world, (CompoundTag) tag); if (!chunk.isGenerated()) return MCAChunk.empty(); return chunk; } else { 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 index 75fc2a65..c985c9b0 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java @@ -54,6 +54,7 @@ public class MCAWorld implements World { @DebugDump private final String name; @DebugDump private final Vector3i spawnPoint; + @DebugDump private final int skyLight; @DebugDump private final boolean ignoreMissingLightData; private final LoadingCache regionCache; @@ -64,13 +65,15 @@ private MCAWorld( UUID uuid, String name, Vector3i spawnPoint, + int skyLight, boolean ignoreMissingLightData ) { this.uuid = uuid; this.worldFolder = worldFolder; this.name = name; this.spawnPoint = spawnPoint; - + + this.skyLight = skyLight; this.ignoreMissingLightData = ignoreMissingLightData; this.regionCache = Caffeine.newBuilder() @@ -152,8 +155,8 @@ public Path getSaveFolder() { } @Override - public int getSeaLevel() { - return 63; + public int getSkyLight() { + return skyLight; } @Override @@ -203,7 +206,11 @@ public Path getWorldFolder() { private Path getRegionFolder() { return worldFolder.resolve("region"); } - + + public boolean isIgnoreMissingLightData() { + return ignoreMissingLightData; + } + private File getMCAFile(int regionX, int regionZ) { return getRegionFolder().resolve("r." + regionX + "." + regionZ + ".mca").toFile(); } @@ -248,12 +255,8 @@ private MCAChunk loadChunk(int x, int z) { Logger.global.logDebug("Unexpected exception trying to load chunk (x:" + x + ", z:" + z + "):" + loadException); return MCAChunk.empty(); } - - public static MCAWorld load(Path worldFolder, UUID uuid) throws IOException { - return load(worldFolder, uuid, null, false); - } - public static MCAWorld load(Path worldFolder, UUID uuid, String name, boolean ignoreMissingLightData) throws IOException { + public static MCAWorld load(Path worldFolder, UUID uuid, String name, int skyLight, boolean ignoreMissingLightData) throws IOException { try { StringBuilder subDimensionName = new StringBuilder(); @@ -292,6 +295,7 @@ public static MCAWorld load(Path worldFolder, UUID uuid, String name, boolean ig uuid, name, spawnPoint, + skyLight, ignoreMissingLightData ); } catch (ClassCastException | NullPointerException ex) { diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AtomicFileHelper.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AtomicFileHelper.java index cd584b55..6cb47e7d 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AtomicFileHelper.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AtomicFileHelper.java @@ -44,7 +44,7 @@ public static OutputStream createFilepartOutputStream(final Path file) throws IO try { Files.move(partFile, file, StandardCopyOption.ATOMIC_MOVE); - } catch (AtomicMoveNotSupportedException ex) { + } catch (IOException ex) { Files.move(partFile, file); } }); diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockNeighborhood.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockNeighborhood.java index 47dd3aab..7640ab98 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockNeighborhood.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockNeighborhood.java @@ -24,30 +24,31 @@ */ package de.bluecolored.bluemap.core.world; +import de.bluecolored.bluemap.core.map.hires.RenderSettings; import de.bluecolored.bluemap.core.resourcepack.ResourcePack; -public class BlockNeighborhood> extends ResourcePackBlock { +public class BlockNeighborhood> extends ExtendedBlock { private static final int DIAMETER = 8; private static final int DIAMETER_MASK = DIAMETER - 1; private static final int DIAMETER_SQUARED = DIAMETER * DIAMETER; - private final ResourcePackBlock[] neighborhood; + private final ExtendedBlock[] neighborhood; private int thisIndex; - public BlockNeighborhood(ResourcePackBlock center) { - super(center.getResourcePack(), null, 0, 0, 0); + public BlockNeighborhood(ExtendedBlock center) { + super(center.getResourcePack(), center.getRenderSettings(), null, 0, 0, 0); copy(center); - neighborhood = new ResourcePackBlock[DIAMETER * DIAMETER * DIAMETER]; + neighborhood = new ExtendedBlock[DIAMETER * DIAMETER * DIAMETER]; init(); } - public BlockNeighborhood(ResourcePack resourcePack, World world, int x, int y, int z) { - super(resourcePack, world, x, y, z); + public BlockNeighborhood(ResourcePack resourcePack, RenderSettings renderSettings, World world, int x, int y, int z) { + super(resourcePack, renderSettings, world, x, y, z); - neighborhood = new ResourcePackBlock[DIAMETER * DIAMETER * DIAMETER]; + neighborhood = new ExtendedBlock[DIAMETER * DIAMETER * DIAMETER]; init(); } @@ -61,11 +62,11 @@ protected void reset() { private void init() { this.thisIndex = -1; for (int i = 0; i < neighborhood.length; i++) { - neighborhood[i] = new ResourcePackBlock<>(this.getResourcePack(), null, 0, 0, 0); + neighborhood[i] = new ExtendedBlock<>(this.getResourcePack(), this.getRenderSettings(), null, 0, 0, 0); } } - public ResourcePackBlock getNeighborBlock(int dx, int dy, int dz) { + public ExtendedBlock getNeighborBlock(int dx, int dy, int dz) { int i = neighborIndex(dx, dy, dz); if (i == thisIndex()) return this; return neighborhood[i].set( diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ResourcePackBlock.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ExtendedBlock.java similarity index 64% rename from BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ResourcePackBlock.java rename to BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ExtendedBlock.java index e54ff511..acc5728e 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ResourcePackBlock.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/ExtendedBlock.java @@ -24,19 +24,22 @@ */ package de.bluecolored.bluemap.core.world; +import de.bluecolored.bluemap.core.map.hires.RenderSettings; import de.bluecolored.bluemap.core.resourcepack.ResourcePack; import java.util.Objects; -public class ResourcePackBlock> extends Block { - +public class ExtendedBlock> extends Block { private final ResourcePack resourcePack; + private final RenderSettings renderSettings; private BlockProperties properties; private Biome biome; + private Boolean insideRenderBounds; - public ResourcePackBlock(ResourcePack resourcePack, World world, int x, int y, int z) { + public ExtendedBlock(ResourcePack resourcePack, RenderSettings renderSettings, World world, int x, int y, int z) { super(world, x, y, z); this.resourcePack = Objects.requireNonNull(resourcePack); + this.renderSettings = renderSettings; } @Override @@ -45,6 +48,20 @@ protected void reset() { this.properties = null; this.biome = null; + this.insideRenderBounds = null; + } + + @Override + public BlockState getBlockState() { + if (!isInsideRenderBounds() && renderSettings.isRenderEdges()) return BlockState.AIR; + return super.getBlockState(); + } + + @Override + public LightData getLightData() { + LightData ld = super.getLightData(); + if (!isInsideRenderBounds() && renderSettings.isRenderEdges()) ld.set(getWorld().getSkyLight(), ld.getBlockLight()); + return ld; } public BlockProperties getProperties() { @@ -57,6 +74,15 @@ public Biome getBiome() { return biome; } + public RenderSettings getRenderSettings() { + return renderSettings; + } + + public boolean isInsideRenderBounds() { + if (insideRenderBounds == null) insideRenderBounds = renderSettings.isInsideRenderBoundaries(getX(), getY(), getZ()); + return insideRenderBounds; + } + public ResourcePack getResourcePack() { return resourcePack; } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java deleted file mode 100644 index a746be97..00000000 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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.Vector2i; -import com.flowpowered.math.vector.Vector3i; - -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.UUID; - -/** - * A sliced view of a world. Everything outside the defined bounds is seen as "not generated" and "air". - */ -public class SlicedWorld implements World { - - private final World world; - private final Vector3i min; - private final Vector3i max; - - public SlicedWorld(World world, Vector3i min, Vector3i max) { - this.world = world; - this.min = min; - this.max = max; - } - - @Override - public String getName() { - return world.getName(); - } - - @Override - public Path getSaveFolder() { - return world.getSaveFolder(); - } - - @Override - public UUID getUUID() { - return world.getUUID(); - } - - @Override - public int getSeaLevel() { - return world.getSeaLevel(); - } - - @Override - public Vector3i getSpawnPoint() { - return world.getSpawnPoint(); - } - - @Override - public int getMaxY(int x, int z) { - return world.getMaxY(x, z); - } - - @Override - public int getMinY(int x, int z) { - return world.getMinY(x, z); - } - - @Override - public Grid getChunkGrid() { - return world.getChunkGrid(); - } - - @Override - public Grid getRegionGrid() { - return world.getRegionGrid(); - } - - @Override - public Chunk getChunk(int x, int z) { - return world.getChunk(x, z); - } - - @Override - public Chunk getChunkAtBlock(int x, int y, int z) { - return world.getChunkAtBlock(x, y, z); - } - - @Override - public Region getRegion(int x, int z) { - return world.getRegion(x, z); - } - - @Override - public Collection listRegions() { - Grid regionGrid = getRegionGrid(); - Collection regions = new ArrayList<>(); - - for (Vector2i region : world.listRegions()) { - Vector2i min = regionGrid.getCellMin(region); - Vector2i max = regionGrid.getCellMax(region); - if (isInside(min.getX(), min.getY()) || isInside(max.getX(), max.getY())) regions.add(region); - } - - return regions; - } - - @Override - public void invalidateChunkCache() { - world.invalidateChunkCache(); - } - - @Override - public void invalidateChunkCache(int x, int z) { - world.invalidateChunkCache(x, z); - } - - @Override - public void cleanUpChunkCache() { - world.cleanUpChunkCache(); - } - - private boolean isInside(int x, int z) { - return - x >= min.getX() && - x <= max.getX() && - z >= min.getZ() && - z <= max.getZ(); - } - - private boolean isInside(int x, int y, int z) { - return - x >= min.getX() && - x <= max.getX() && - z >= min.getZ() && - z <= max.getZ() && - y >= min.getY() && - y <= max.getY(); - } - -} 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 index 6a7cb24d..6e7b59e3 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java @@ -43,8 +43,8 @@ public interface World { UUID getUUID(); Path getSaveFolder(); - - int getSeaLevel(); + + int getSkyLight(); Vector3i getSpawnPoint(); diff --git a/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongeCommands.java b/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongeCommands.java index c41ff2d2..170235a2 100644 --- a/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongeCommands.java +++ b/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongeCommands.java @@ -68,7 +68,7 @@ public Collection getRootCommands(){ public class SpongeCommandProxy implements Command.Raw { - private String label; + private final String label; protected SpongeCommandProxy(String label) { this.label = label; @@ -88,12 +88,13 @@ public CommandResult process(CommandCause cause, ArgumentReader.Mutable argument try { return CommandResult.builder().result(dispatcher.execute(command, cause)).build(); } catch (CommandSyntaxException ex) { - cause.audience().sendMessage(Component.text(ex.getRawMessage().getString(), NamedTextColor.RED)); + Component errText = Component.text(ex.getRawMessage().getString(), NamedTextColor.RED); String context = ex.getContext(); - if (context != null) cause.audience().sendMessage(Component.text(context, NamedTextColor.GRAY)); + if (context != null) + errText = errText.append(Component.newline()).append(Component.text(context, NamedTextColor.GRAY)); - return CommandResult.empty(); + return CommandResult.error(errText); } } diff --git a/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongePlugin.java b/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongePlugin.java index ff30c930..63e5c637 100644 --- a/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongePlugin.java +++ b/implementations/sponge-8.0.0/src/main/java/de/bluecolored/bluemap/sponge8/SpongePlugin.java @@ -36,9 +36,10 @@ import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; import de.bluecolored.bluemap.sponge8.SpongeCommands.SpongeCommandProxy; -import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.querz.nbt.CompoundTag; import net.querz.nbt.NBTUtil; +import org.apache.maven.artifact.versioning.ArtifactVersion; import org.spongepowered.api.Platform; import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; @@ -65,7 +66,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -@org.spongepowered.plugin.jvm.Plugin(Plugin.PLUGIN_ID) +@org.spongepowered.plugin.builtin.jvm.Plugin(Plugin.PLUGIN_ID) public class SpongePlugin implements ServerInterface { private final PluginContainer pluginContainer; @@ -92,13 +93,12 @@ public SpongePlugin(org.apache.logging.log4j.Logger logger, PluginContainer plug this.onlinePlayerMap = new ConcurrentHashMap<>(); this.onlinePlayerList = Collections.synchronizedList(new ArrayList<>()); - final String versionFromSponge = Sponge.platform().container(Platform.Component.GAME).metadata().version(); - MinecraftVersion version = new MinecraftVersion(1, 16); - try { - version = MinecraftVersion.of(versionFromSponge); - } catch (IllegalArgumentException e) { - Logger.global.logWarning("Failed to find a matching version for version-name '" + versionFromSponge + "'! Using latest known sponge-version: " + version.getVersionString()); - } + final ArtifactVersion versionFromSponge = Sponge.platform().container(Platform.Component.GAME).metadata().version(); + MinecraftVersion version = new MinecraftVersion( + versionFromSponge.getMajorVersion(), + versionFromSponge.getMinorVersion(), + versionFromSponge.getIncrementalVersion() + ); this.pluginInstance = new Plugin(version, "sponge-8.0.0", this); this.commands = new SpongeCommands(pluginInstance); @@ -210,7 +210,7 @@ public String getWorldName(UUID worldUUID) { serverWorld -> serverWorld .properties() .displayName() - .map(PlainComponentSerializer.plain()::serialize) + .map(PlainTextComponentSerializer.plainText()::serialize) ) .orElse(null); }