Rewrite of the render-engine and big performance improvements
- changed most immutable vectors with mutable ones - dropped 1.12.2 support - improved caching and block/chunk access - much more smaller tweaks
This commit is contained in:
parent
8838bd6f32
commit
e178f935aa
|
@ -30,7 +30,6 @@ import de.bluecolored.bluemap.common.web.WebSettings;
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||||
import de.bluecolored.bluemap.core.config.*;
|
import de.bluecolored.bluemap.core.config.*;
|
||||||
import de.bluecolored.bluemap.core.debug.DebugDump;
|
import de.bluecolored.bluemap.core.debug.DebugDump;
|
||||||
import de.bluecolored.bluemap.core.debug.OneBlockWorld;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.map.BmMap;
|
import de.bluecolored.bluemap.core.map.BmMap;
|
||||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
|
@ -136,9 +135,6 @@ public class BlueMapService {
|
||||||
maps = new HashMap<>();
|
maps = new HashMap<>();
|
||||||
worlds = new HashMap<>();
|
worlds = new HashMap<>();
|
||||||
|
|
||||||
ConfigManager configManager = getConfigManager();
|
|
||||||
configManager.loadResourceConfigs(configFolder, getResourcePack());
|
|
||||||
|
|
||||||
for (MapConfig mapConfig : getRenderConfig().getMapConfigs()) {
|
for (MapConfig mapConfig : getRenderConfig().getMapConfigs()) {
|
||||||
String id = mapConfig.getId();
|
String id = mapConfig.getId();
|
||||||
String name = mapConfig.getName();
|
String name = mapConfig.getName();
|
||||||
|
@ -160,7 +156,7 @@ public class BlueMapService {
|
||||||
World world = worlds.get(worldUUID);
|
World world = worlds.get(worldUUID);
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
try {
|
try {
|
||||||
world = MCAWorld.load(worldFolder.toPath(), worldUUID, minecraftVersion, configManager.getBlockIdConfig(), configManager.getBlockPropertiesConfig(), configManager.getBiomeConfig(), worldNameProvider.apply(worldUUID), mapConfig.isIgnoreMissingLightData());
|
world = MCAWorld.load(worldFolder.toPath(), worldUUID, worldNameProvider.apply(worldUUID), mapConfig.isIgnoreMissingLightData());
|
||||||
worlds.put(worldUUID, world);
|
worlds.put(worldUUID, world);
|
||||||
} catch (MissingResourcesException e) {
|
} catch (MissingResourcesException e) {
|
||||||
throw e; // rethrow this to stop loading and display resource-missing message
|
throw e; // rethrow this to stop loading and display resource-missing message
|
||||||
|
@ -230,7 +226,10 @@ public class BlueMapService {
|
||||||
|
|
||||||
if (resourceExtensionsFile.exists()) FileUtils.forceDelete(resourceExtensionsFile);
|
if (resourceExtensionsFile.exists()) FileUtils.forceDelete(resourceExtensionsFile);
|
||||||
FileUtils.forceMkdirParent(resourceExtensionsFile);
|
FileUtils.forceMkdirParent(resourceExtensionsFile);
|
||||||
FileUtils.copyURLToFile(Plugin.class.getResource("/de/bluecolored/bluemap/" + minecraftVersion.getResource().getResourcePrefix() + "/resourceExtensions.zip"), resourceExtensionsFile, 10000, 10000);
|
URL resourceExtensionsUrl = Objects.requireNonNull(
|
||||||
|
Plugin.class.getResource("/de/bluecolored/bluemap/" + minecraftVersion.getResource().getResourcePrefix() + "/resourceExtensions.zip")
|
||||||
|
);
|
||||||
|
FileUtils.copyURLToFile(resourceExtensionsUrl, resourceExtensionsFile, 10000, 10000);
|
||||||
|
|
||||||
//find more resource packs
|
//find more resource packs
|
||||||
File[] resourcePacks = resourcePackFolder.listFiles();
|
File[] resourcePacks = resourcePackFolder.listFiles();
|
||||||
|
@ -243,7 +242,7 @@ public class BlueMapService {
|
||||||
resources.add(resourceExtensionsFile);
|
resources.add(resourceExtensionsFile);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
resourcePack = new ResourcePack(minecraftVersion);
|
resourcePack = new ResourcePack();
|
||||||
if (textureExportFile.exists()) resourcePack.loadTextureFile(textureExportFile);
|
if (textureExportFile.exists()) resourcePack.loadTextureFile(textureExportFile);
|
||||||
resourcePack.load(resources);
|
resourcePack.load(resources);
|
||||||
resourcePack.saveTextureFile(textureExportFile);
|
resourcePack.saveTextureFile(textureExportFile);
|
||||||
|
|
|
@ -59,10 +59,8 @@ import de.bluecolored.bluemap.core.debug.StateDumper;
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.map.BmMap;
|
import de.bluecolored.bluemap.core.map.BmMap;
|
||||||
import de.bluecolored.bluemap.core.map.MapRenderState;
|
import de.bluecolored.bluemap.core.map.MapRenderState;
|
||||||
import de.bluecolored.bluemap.core.mca.ChunkAnvil112;
|
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
import de.bluecolored.bluemap.core.world.Block;
|
import de.bluecolored.bluemap.core.world.Block;
|
||||||
import de.bluecolored.bluemap.core.world.Chunk;
|
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -528,24 +526,21 @@ public class Commands<S> {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
// collect and output debug info
|
// collect and output debug info
|
||||||
Vector3i blockPos = position.floor().toInt();
|
Vector3i blockPos = position.floor().toInt();
|
||||||
Block block = world.getBlock(blockPos);
|
Block<?> block = new Block<>(world, blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||||
Block blockBelow = world.getBlock(blockPos.add(0, -1, 0));
|
Block<?> blockBelow = new Block<>(null, 0, 0, 0).copy(block, 0, -1, 0);
|
||||||
|
|
||||||
String blockIdMeta = "";
|
// populate lazy-loaded values
|
||||||
String blockBelowIdMeta = "";
|
block.getBlockState();
|
||||||
|
block.getBiomeId();
|
||||||
|
block.getLightData();
|
||||||
|
|
||||||
Vector2i chunkPos = world.getChunkGrid().getCell(blockPos.toVector2(true));
|
blockBelow.getBlockState();
|
||||||
Chunk chunk = world.getChunk(chunkPos.getX(), chunkPos.getY());
|
blockBelow.getBiomeId();
|
||||||
|
blockBelow.getLightData();
|
||||||
|
|
||||||
if (chunk instanceof ChunkAnvil112) {
|
|
||||||
blockIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(blockPos) + ")";
|
|
||||||
blockBelowIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(blockPos.add(0, -1, 0)) + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
source.sendMessages(Arrays.asList(
|
source.sendMessages(Arrays.asList(
|
||||||
Text.of(TextColor.GOLD, "Block at you: ", TextColor.WHITE, block, TextColor.GRAY, blockIdMeta),
|
Text.of(TextColor.GOLD, "Block at you: ", TextColor.WHITE, block),
|
||||||
Text.of(TextColor.GOLD, "Block below you: ", TextColor.WHITE, blockBelow, TextColor.GRAY, blockBelowIdMeta),
|
Text.of(TextColor.GOLD, "Block below you: ", TextColor.WHITE, blockBelow)
|
||||||
Text.of(TextColor.GOLD, "Chunk: ", TextColor.WHITE, chunk)
|
|
||||||
));
|
));
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.config;
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
|
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
|
||||||
import org.spongepowered.configurate.loader.ConfigurationLoader;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
public class BiomeConfig implements BiomeMapper {
|
|
||||||
|
|
||||||
private final ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader;
|
|
||||||
private final Map<Integer, Biome> biomes;
|
|
||||||
|
|
||||||
public BiomeConfig(ConfigurationNode node) {
|
|
||||||
this(node, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BiomeConfig(ConfigurationNode node, ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader) {
|
|
||||||
this.autopoulationConfigLoader = autopoulationConfigLoader;
|
|
||||||
|
|
||||||
biomes = new ConcurrentHashMap<>(200, 0.5f, 8);
|
|
||||||
|
|
||||||
for (Entry<Object, ? extends ConfigurationNode> e : node.childrenMap().entrySet()){
|
|
||||||
String id = e.getKey().toString();
|
|
||||||
Biome biome = Biome.create(id, e.getValue());
|
|
||||||
biomes.put(biome.getNumeralId(), biome);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Biome get(int id) {
|
|
||||||
Biome biome = biomes.get(id);
|
|
||||||
|
|
||||||
if (biome == null) {
|
|
||||||
if (autopoulationConfigLoader != null) {
|
|
||||||
biomes.put(id, Biome.DEFAULT);
|
|
||||||
|
|
||||||
synchronized (autopoulationConfigLoader) {
|
|
||||||
try {
|
|
||||||
ConfigurationNode node = autopoulationConfigLoader.load();
|
|
||||||
node.node("unknown:" + id).node("id").set(id);
|
|
||||||
autopoulationConfigLoader.save(node);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.global.noFloodError("biomeconf-autopopulate-ioex", "Failed to auto-populate BiomeConfig!", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Biome.DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return biome;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,252 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.config;
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
|
||||||
import org.spongepowered.configurate.loader.ConfigurationLoader;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
|
|
||||||
public class BlockIdConfig implements BlockIdMapper {
|
|
||||||
|
|
||||||
private final ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader;
|
|
||||||
private final Map<BlockNumeralIDMeta, BlockState> numeralMappings;
|
|
||||||
private final Map<BlockIDMeta, BlockState> idMappings;
|
|
||||||
|
|
||||||
private final ReentrantReadWriteLock lock;
|
|
||||||
|
|
||||||
public BlockIdConfig(ConfigurationNode node) {
|
|
||||||
this(node, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockIdConfig(ConfigurationNode node, ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader) {
|
|
||||||
this.autopoulationConfigLoader = autopoulationConfigLoader;
|
|
||||||
|
|
||||||
this.numeralMappings = new ConcurrentHashMap<>(200, 0.5f, 8);
|
|
||||||
this.idMappings = new ConcurrentHashMap<>(200, 0.5f, 8);
|
|
||||||
|
|
||||||
this.lock = new ReentrantReadWriteLock();
|
|
||||||
|
|
||||||
for (Entry<Object, ? extends ConfigurationNode> e : node.childrenMap().entrySet()){
|
|
||||||
String key = e.getKey().toString();
|
|
||||||
String value = e.getValue().getString();
|
|
||||||
|
|
||||||
try {
|
|
||||||
int splitIndex = key.lastIndexOf(':');
|
|
||||||
|
|
||||||
if (splitIndex <= 0 || splitIndex >= key.length() - 1) {
|
|
||||||
Logger.global.logWarning("Loading BlockIdConfig: Failed to parse blockid:meta from key '" + key + "'");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String blockId = key.substring(0, splitIndex);
|
|
||||||
int blockNumeralId;
|
|
||||||
try {
|
|
||||||
blockNumeralId = Integer.parseInt(blockId);
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
blockNumeralId = -1;
|
|
||||||
}
|
|
||||||
int blockMeta = Integer.parseInt(key.substring(splitIndex + 1));
|
|
||||||
BlockState state = BlockState.fromString(MinecraftVersion.EARLIEST_SUPPORTED, value);
|
|
||||||
|
|
||||||
if (blockNumeralId >= 0) {
|
|
||||||
BlockNumeralIDMeta idmeta = new BlockNumeralIDMeta(blockNumeralId, blockMeta);
|
|
||||||
if (blockNumeralId == 0) state = BlockState.AIR; //use the static field to increase render speed (== comparison)
|
|
||||||
numeralMappings.put(idmeta, state);
|
|
||||||
} else {
|
|
||||||
BlockIDMeta idmeta = new BlockIDMeta(blockId, blockMeta);
|
|
||||||
idMappings.put(idmeta, state);
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
Logger.global.logWarning("Loading BlockIdConfig: Failed to parse blockid:meta from key '" + key + "'");
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
Logger.global.logWarning("Loading BlockIdConfig: Failed to parse BlockState from value '" + value + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState get(int numeralId, int meta) {
|
|
||||||
if (numeralId == 0) return BlockState.AIR;
|
|
||||||
|
|
||||||
BlockNumeralIDMeta numidmeta;
|
|
||||||
BlockState state;
|
|
||||||
|
|
||||||
try { lock.readLock().lock();
|
|
||||||
|
|
||||||
numidmeta = new BlockNumeralIDMeta(numeralId, meta);
|
|
||||||
state = numeralMappings.get(numidmeta);
|
|
||||||
|
|
||||||
} finally { lock.readLock().unlock(); }
|
|
||||||
|
|
||||||
if (state == null) {
|
|
||||||
|
|
||||||
try { lock.writeLock().lock();
|
|
||||||
|
|
||||||
state = numeralMappings.getOrDefault(new BlockNumeralIDMeta(numeralId, 0), BlockState.MISSING); //meta-fallback
|
|
||||||
numeralMappings.put(numidmeta, state);
|
|
||||||
|
|
||||||
if (autopoulationConfigLoader != null) {
|
|
||||||
try {
|
|
||||||
ConfigurationNode node = autopoulationConfigLoader.load();
|
|
||||||
node.node(numeralId + ":" + meta).set(state.toString());
|
|
||||||
autopoulationConfigLoader.save(node);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.global.noFloodError("blockidconf-autopopulate-ioex", "Failed to auto-populate BlockIdConfig!", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally { lock.writeLock().unlock(); }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState get(String id, int numeralId, int meta) {
|
|
||||||
if (numeralId == 0) return BlockState.AIR;
|
|
||||||
|
|
||||||
BlockNumeralIDMeta numidmeta;
|
|
||||||
BlockState state;
|
|
||||||
BlockIDMeta idmeta = null;
|
|
||||||
|
|
||||||
try { lock.readLock().lock();
|
|
||||||
|
|
||||||
numidmeta = new BlockNumeralIDMeta(numeralId, meta);
|
|
||||||
state = numeralMappings.get(numidmeta);
|
|
||||||
|
|
||||||
if (state == null) {
|
|
||||||
idmeta = new BlockIDMeta(id, meta);
|
|
||||||
state = idMappings.get(idmeta);
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally { lock.readLock().unlock(); }
|
|
||||||
|
|
||||||
if (state == null) {
|
|
||||||
|
|
||||||
try { lock.writeLock().lock();
|
|
||||||
|
|
||||||
state = idMappings.get(new BlockIDMeta(id, 0));
|
|
||||||
if (state == null) {
|
|
||||||
state = numeralMappings.get(new BlockNumeralIDMeta(numeralId, 0));
|
|
||||||
if (state == null) state = new BlockState(MinecraftVersion.EARLIEST_SUPPORTED, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
idMappings.put(idmeta, state);
|
|
||||||
|
|
||||||
if (autopoulationConfigLoader != null) {
|
|
||||||
try {
|
|
||||||
ConfigurationNode node = autopoulationConfigLoader.load();
|
|
||||||
node.node(id + ":" + meta).set(state.toString());
|
|
||||||
autopoulationConfigLoader.save(node);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.global.noFloodError("blockidconf-autopopulate-ioex", "Failed to auto-populate BlockIdConfig!", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally { lock.writeLock().unlock(); }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BlockNumeralIDMeta {
|
|
||||||
private final int id;
|
|
||||||
private final int meta;
|
|
||||||
|
|
||||||
public BlockNumeralIDMeta(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 * 16 + meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj instanceof BlockNumeralIDMeta) {
|
|
||||||
BlockNumeralIDMeta other = (BlockNumeralIDMeta) obj;
|
|
||||||
return other.id == id && other.meta == meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BlockIDMeta {
|
|
||||||
private final String id;
|
|
||||||
private final int meta;
|
|
||||||
|
|
||||||
public BlockIDMeta(String id, int meta) {
|
|
||||||
this.id = id;
|
|
||||||
this.meta = meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMeta() {
|
|
||||||
return meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return id.hashCode() * 16 + meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj instanceof BlockIDMeta) {
|
|
||||||
BlockIDMeta other = (BlockIDMeta) obj;
|
|
||||||
return other.id.equals(id) && other.meta == meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,141 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.config;
|
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
|
||||||
import de.bluecolored.bluemap.core.BlueMap;
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
|
||||||
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
|
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
|
||||||
import de.bluecolored.bluemap.core.resourcepack.TransformedBlockModelResource;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockProperties;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
|
||||||
import org.spongepowered.configurate.loader.ConfigurationLoader;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
public class BlockPropertiesConfig implements BlockPropertiesMapper {
|
|
||||||
|
|
||||||
private final ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader;
|
|
||||||
|
|
||||||
private final Map<String, List<BlockStateMapping<BlockProperties>>> mappings;
|
|
||||||
private final LoadingCache<BlockState, BlockProperties> mappingCache;
|
|
||||||
|
|
||||||
private final ResourcePack resourcePack;
|
|
||||||
|
|
||||||
public BlockPropertiesConfig(ConfigurationNode node, ResourcePack resourcePack) {
|
|
||||||
this(node, resourcePack, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockPropertiesConfig(ConfigurationNode node, ResourcePack resourcePack, ConfigurationLoader<? extends ConfigurationNode> autopoulationConfigLoader) {
|
|
||||||
this.resourcePack = resourcePack;
|
|
||||||
this.autopoulationConfigLoader = autopoulationConfigLoader;
|
|
||||||
|
|
||||||
mappings = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
for (Entry<Object, ? extends ConfigurationNode> e : node.childrenMap().entrySet()){
|
|
||||||
String key = e.getKey().toString();
|
|
||||||
try {
|
|
||||||
BlockState bsKey = BlockState.fromString(resourcePack.getMinecraftVersion(), key);
|
|
||||||
BlockProperties bsValue = new BlockProperties(
|
|
||||||
e.getValue().node("culling").getBoolean(true),
|
|
||||||
e.getValue().node("occluding").getBoolean(true),
|
|
||||||
e.getValue().node("flammable").getBoolean(false)
|
|
||||||
);
|
|
||||||
BlockStateMapping<BlockProperties> mapping = new BlockStateMapping<>(bsKey, bsValue);
|
|
||||||
mappings.computeIfAbsent(bsKey.getFullId(), k -> new ArrayList<>()).add(mapping);
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
Logger.global.logWarning("Loading BlockPropertiesConfig: Failed to parse BlockState from key '" + key + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mappingCache = Caffeine.newBuilder()
|
|
||||||
.executor(BlueMap.THREAD_POOL)
|
|
||||||
.maximumSize(10000)
|
|
||||||
.build(this::mapNoCache);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockProperties get(BlockState from){
|
|
||||||
return mappingCache.get(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BlockProperties mapNoCache(BlockState bs){
|
|
||||||
for (BlockStateMapping<BlockProperties> bm : mappings.getOrDefault(bs.getFullId(), Collections.emptyList())){
|
|
||||||
if (bm.fitsTo(bs)){
|
|
||||||
return bm.getMapping();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockProperties generated = BlockProperties.SOLID;
|
|
||||||
MinecraftVersion version = MinecraftVersion.LATEST_SUPPORTED;
|
|
||||||
|
|
||||||
if (resourcePack != null) {
|
|
||||||
try {
|
|
||||||
boolean culling = false;
|
|
||||||
boolean occluding = false;
|
|
||||||
|
|
||||||
for(TransformedBlockModelResource model : resourcePack.getBlockStateResource(bs).getModels(bs, new ArrayList<>(10))) {
|
|
||||||
culling = culling || model.getModel().isCulling();
|
|
||||||
occluding = occluding || model.getModel().isOccluding();
|
|
||||||
if (culling && occluding) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
generated = new BlockProperties(culling, occluding, generated.isFlammable());
|
|
||||||
} catch (NoSuchResourceException ignore) {} //ignoring this because it will be logged later again if we try to render that block
|
|
||||||
|
|
||||||
version = resourcePack.getMinecraftVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
mappings.computeIfAbsent(bs.getFullId(), k -> new ArrayList<>()).add(new BlockStateMapping<>(new BlockState(version, bs.getFullId()), generated));
|
|
||||||
if (autopoulationConfigLoader != null) {
|
|
||||||
synchronized (autopoulationConfigLoader) {
|
|
||||||
try {
|
|
||||||
ConfigurationNode node = autopoulationConfigLoader.load();
|
|
||||||
ConfigurationNode bpNode = node.node(bs.getFullId());
|
|
||||||
bpNode.node("culling").set(generated.isCulling());
|
|
||||||
bpNode.node("occluding").set(generated.isOccluding());
|
|
||||||
bpNode.node("flammable").set(generated.isFlammable());
|
|
||||||
autopoulationConfigLoader.save(node);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.global.noFloodError("blockpropsconf-autopopulate-ioex", "Failed to auto-populate BlockPropertiesConfig!", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return generated;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -26,16 +26,16 @@ package de.bluecolored.bluemap.core.config;
|
||||||
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.BlueMap;
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack.Resource;
|
|
||||||
import de.bluecolored.bluemap.core.util.FileUtils;
|
import de.bluecolored.bluemap.core.util.FileUtils;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||||
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
|
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
|
||||||
import org.spongepowered.configurate.loader.ConfigurationLoader;
|
import org.spongepowered.configurate.loader.ConfigurationLoader;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
@ -53,11 +53,7 @@ public class ConfigManager {
|
||||||
CONFIG_PLACEHOLDERS.add(new Placeholder("version", BlueMap.VERSION));
|
CONFIG_PLACEHOLDERS.add(new Placeholder("version", BlueMap.VERSION));
|
||||||
CONFIG_PLACEHOLDERS.add(new Placeholder("datetime-iso", () -> LocalDateTime.now().withNano(0).toString()));
|
CONFIG_PLACEHOLDERS.add(new Placeholder("datetime-iso", () -> LocalDateTime.now().withNano(0).toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockIdConfig blockIdConfig;
|
|
||||||
private BlockPropertiesConfig blockPropertiesConfig;
|
|
||||||
private BiomeConfig biomeConfig;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads or creates a config file for BlueMap.
|
* Loads or creates a config file for BlueMap.
|
||||||
*
|
*
|
||||||
|
@ -66,8 +62,8 @@ public class ConfigManager {
|
||||||
* @param defaultValues The default values used if a key is not present in the config (can be null)
|
* @param defaultValues The default values used if a key is not present in the config (can be null)
|
||||||
* @param usePlaceholders Whether to replace placeholders from the defaultConfig if it is newly generated
|
* @param usePlaceholders Whether to replace placeholders from the defaultConfig if it is newly generated
|
||||||
* @param generateEmptyConfig Whether to generate an empty config file if no default config is provided
|
* @param generateEmptyConfig Whether to generate an empty config file if no default config is provided
|
||||||
* @return
|
* @return The loaded configuration node
|
||||||
* @throws IOException
|
* @throws IOException if an IOException occurs while loading
|
||||||
*/
|
*/
|
||||||
public ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL defaultValues, boolean usePlaceholders, boolean generateEmptyConfig) throws IOException {
|
public ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL defaultValues, boolean usePlaceholders, boolean generateEmptyConfig) throws IOException {
|
||||||
|
|
||||||
|
@ -116,107 +112,6 @@ public class ConfigManager {
|
||||||
return configNode;
|
return configNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadResourceConfigs(File configFolder, ResourcePack resourcePack) throws IOException {
|
|
||||||
|
|
||||||
//load blockColors.json from resources, config-folder and resourcepack
|
|
||||||
URL blockColorsConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/" + resourcePack.getMinecraftVersion().getResource().getResourcePrefix() + "/blockColors.json");
|
|
||||||
File blockColorsConfigFile = new File(configFolder, "blockColors.json");
|
|
||||||
ConfigurationNode blockColorsConfigNode = loadOrCreate(
|
|
||||||
blockColorsConfigFile,
|
|
||||||
null,
|
|
||||||
blockColorsConfigUrl,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
blockColorsConfigNode = joinFromResourcePack(resourcePack, "blockColors.json", blockColorsConfigNode);
|
|
||||||
resourcePack.getBlockColorCalculatorFactory().loadColorConfig(blockColorsConfigNode);
|
|
||||||
|
|
||||||
//load blockIds.json from resources, config-folder and resourcepack
|
|
||||||
URL blockIdsConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/" + resourcePack.getMinecraftVersion().getResource().getResourcePrefix() + "/blockIds.json");
|
|
||||||
File blockIdsConfigFile = new File(configFolder, "blockIds.json");
|
|
||||||
ConfigurationNode blockIdsConfigNode = loadOrCreate(
|
|
||||||
blockIdsConfigFile,
|
|
||||||
null,
|
|
||||||
blockIdsConfigUrl,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
blockIdsConfigNode = joinFromResourcePack(resourcePack, "blockIds.json", blockIdsConfigNode);
|
|
||||||
blockIdConfig = new BlockIdConfig(
|
|
||||||
blockIdsConfigNode
|
|
||||||
);
|
|
||||||
|
|
||||||
//load blockProperties.json from resources, config-folder and resourcepack
|
|
||||||
URL blockPropertiesConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/" + resourcePack.getMinecraftVersion().getResource().getResourcePrefix() + "/blockProperties.json");
|
|
||||||
File blockPropertiesConfigFile = new File(configFolder, "blockProperties.json");
|
|
||||||
ConfigurationNode blockPropertiesConfigNode = loadOrCreate(
|
|
||||||
blockPropertiesConfigFile,
|
|
||||||
null,
|
|
||||||
blockPropertiesConfigUrl,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
blockPropertiesConfigNode = joinFromResourcePack(resourcePack, "blockProperties.json", blockPropertiesConfigNode);
|
|
||||||
blockPropertiesConfig = new BlockPropertiesConfig(
|
|
||||||
blockPropertiesConfigNode,
|
|
||||||
resourcePack
|
|
||||||
);
|
|
||||||
|
|
||||||
//load biomes.json from resources, config-folder and resourcepack
|
|
||||||
URL biomeConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/" + resourcePack.getMinecraftVersion().getResource().getResourcePrefix() + "/biomes.json");
|
|
||||||
File biomeConfigFile = new File(configFolder, "biomes.json");
|
|
||||||
ConfigurationNode biomeConfigNode = loadOrCreate(
|
|
||||||
biomeConfigFile,
|
|
||||||
null,
|
|
||||||
biomeConfigUrl,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
biomeConfigNode = joinFromResourcePack(resourcePack, "biomes.json", biomeConfigNode);
|
|
||||||
biomeConfig = new BiomeConfig(
|
|
||||||
biomeConfigNode
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockIdConfig getBlockIdConfig() {
|
|
||||||
return blockIdConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockPropertiesConfig getBlockPropertiesConfig() {
|
|
||||||
return blockPropertiesConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BiomeConfig getBiomeConfig() {
|
|
||||||
return biomeConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConfigurationNode joinFromResourcePack(ResourcePack resourcePack, String configFileName, ConfigurationNode defaultConfig) {
|
|
||||||
ConfigurationNode joinedNode = null;
|
|
||||||
for (Resource resource : resourcePack.getConfigAdditions(configFileName)) {
|
|
||||||
try {
|
|
||||||
ConfigurationNode node = getLoader(configFileName, resource.read()).load();
|
|
||||||
if (joinedNode == null) joinedNode = node;
|
|
||||||
else joinedNode.mergeFrom(node);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.global.logWarning("Failed to load an additional " + configFileName + " from the resource-pack! " + ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (joinedNode == null) return defaultConfig;
|
|
||||||
|
|
||||||
joinedNode.mergeFrom(defaultConfig);
|
|
||||||
|
|
||||||
return joinedNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConfigurationLoader<? extends ConfigurationNode> getLoader(String filename, InputStream is){
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
|
||||||
|
|
||||||
if (filename.endsWith(".json")) return GsonConfigurationLoader.builder().source(() -> reader).build();
|
|
||||||
else return HoconConfigurationLoader.builder().source(() -> reader).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConfigurationLoader<? extends ConfigurationNode> getLoader(URL url){
|
private ConfigurationLoader<? extends ConfigurationNode> getLoader(URL url){
|
||||||
if (url.getFile().endsWith(".json")) return GsonConfigurationLoader.builder().url(url).build();
|
if (url.getFile().endsWith(".json")) return GsonConfigurationLoader.builder().url(url).build();
|
||||||
else return HoconConfigurationLoader.builder().url(url).build();
|
else return HoconConfigurationLoader.builder().url(url).build();
|
||||||
|
|
|
@ -1,9 +1,35 @@
|
||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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;
|
package de.bluecolored.bluemap.core.debug;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
import com.flowpowered.math.vector.Vector2i;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
import de.bluecolored.bluemap.core.world.Chunk;
|
||||||
import de.bluecolored.bluemap.core.world.*;
|
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.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -62,22 +88,6 @@ public class OneBlockWorld implements World {
|
||||||
return delegate.getRegionGrid();
|
return delegate.getRegionGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Biome getBiome(int x, int y, int z) {
|
|
||||||
return Biome.DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState getBlockState(int x, int y, int z) {
|
|
||||||
if (x == 0 && z == 0 && y == 70) return BlockState.MISSING;
|
|
||||||
return BlockState.AIR;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockProperties getBlockProperties(BlockState blockState) {
|
|
||||||
return delegate.getBlockProperties(blockState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunkAtBlock(int x, int y, int z) {
|
public Chunk getChunkAtBlock(int x, int y, int z) {
|
||||||
return delegate.getChunkAtBlock(x, y, z);
|
return delegate.getChunkAtBlock(x, y, z);
|
||||||
|
@ -113,9 +123,4 @@ public class OneBlockWorld implements World {
|
||||||
delegate.cleanUpChunkCache();
|
delegate.cleanUpChunkCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockPropertiesMapper getBlockPropertiesMapper() {
|
|
||||||
return delegate.getBlockPropertiesMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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.map.hires;
|
package de.bluecolored.bluemap.core.map.hires;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
||||||
|
|
|
@ -29,7 +29,7 @@ import de.bluecolored.bluemap.core.map.hires.blockmodel.BlockStateModelFactory;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
|
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
import de.bluecolored.bluemap.core.world.Block;
|
import de.bluecolored.bluemap.core.world.BlockNeighborhood;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
|
|
||||||
|
@ -54,9 +54,8 @@ public class HiresModelRenderer {
|
||||||
BlockStateModelFactory modelFactory = new BlockStateModelFactory(resourcePack, renderSettings);
|
BlockStateModelFactory modelFactory = new BlockStateModelFactory(resourcePack, renderSettings);
|
||||||
|
|
||||||
int maxHeight, minY, maxY;
|
int maxHeight, minY, maxY;
|
||||||
float dx, dz;
|
|
||||||
Color columnColor = new Color(), blockColor = new Color();
|
Color columnColor = new Color(), blockColor = new Color();
|
||||||
Block block = new Block(world, 0, 0, 0);
|
BlockNeighborhood<?> block = new BlockNeighborhood<>(resourcePack, world, 0, 0, 0);
|
||||||
BlockModelView blockModel = new BlockModelView(model);
|
BlockModelView blockModel = new BlockModelView(model);
|
||||||
|
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
|
@ -96,13 +95,6 @@ public class HiresModelRenderer {
|
||||||
maxHeight = y;
|
maxHeight = y;
|
||||||
columnColor.overlay(blockColor);
|
columnColor.overlay(blockColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
//random offset
|
|
||||||
if (block.getBlockState().isRandomOffset){
|
|
||||||
dx = (hashToFloat(x, z, 123984) - 0.5f) * 0.75f;
|
|
||||||
dz = (hashToFloat(x, z, 345542) - 0.5f) * 0.75f;
|
|
||||||
blockModel.translate(dx, 0, dz);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tileMeta.setHeight(x, z, maxHeight);
|
tileMeta.setHeight(x, z, maxHeight);
|
||||||
|
@ -113,20 +105,4 @@ public class HiresModelRenderer {
|
||||||
|
|
||||||
return tileMeta;
|
return tileMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashes the provided position to a random float between 0 and 1.<br>
|
|
||||||
* <br>
|
|
||||||
* <i>(Implementation adapted from https://github.com/SpongePowered/SpongeAPI/blob/ecd761a70219e467dea47a09fc310e8238e9911f/src/main/java/org/spongepowered/api/extra/skylands/SkylandsUtil.java)</i>
|
|
||||||
*
|
|
||||||
* @param x The x component of the position
|
|
||||||
* @param z The z component of the position
|
|
||||||
* @param seed A seed for the hashing
|
|
||||||
* @return The hashed value between 0 and 1
|
|
||||||
*/
|
|
||||||
public static float hashToFloat(int x, int z, long seed) {
|
|
||||||
final long hash = x * 73428767 ^ z * 4382893 ^ seed * 457;
|
|
||||||
return (hash * (hash + 456149) & 0x00ffffff) / (float) 0x01000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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.map.hires;
|
package de.bluecolored.bluemap.core.map.hires;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
|
@ -37,7 +61,7 @@ public class HiresTileMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setColor(int x, int z, float r, float g, float b, float a) {
|
private void setColor(int x, int z, float r, float g, float b, float a) {
|
||||||
int index = (x - minX) * sizeZ + (z - minZ) * 4;
|
int index = ((x - minX) * sizeZ + (z - minZ)) * 4;
|
||||||
colors[index ] = r;
|
colors[index ] = r;
|
||||||
colors[index + 1] = g;
|
colors[index + 1] = g;
|
||||||
colors[index + 2] = b;
|
colors[index + 2] = b;
|
||||||
|
@ -45,7 +69,7 @@ public class HiresTileMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getColor(int x, int z, Color target) {
|
public Color getColor(int x, int z, Color target) {
|
||||||
int index = (x - minX) * sizeZ + (z - minZ) * 4;
|
int index = ((x - minX) * sizeZ + (z - minZ)) * 4;
|
||||||
return target.set(
|
return target.set(
|
||||||
colors[index ],
|
colors[index ],
|
||||||
colors[index + 1],
|
colors[index + 1],
|
||||||
|
|
|
@ -24,12 +24,14 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
||||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.*;
|
import de.bluecolored.bluemap.core.resourcepack.blockstate.BlockStateResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.TransformedBlockModelResource;
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
import de.bluecolored.bluemap.core.world.Block;
|
import de.bluecolored.bluemap.core.world.BlockNeighborhood;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -46,25 +48,20 @@ public class BlockStateModelFactory {
|
||||||
public BlockStateModelFactory(ResourcePack resourcePack, RenderSettings renderSettings) {
|
public BlockStateModelFactory(ResourcePack resourcePack, RenderSettings renderSettings) {
|
||||||
this.resourcePack = resourcePack;
|
this.resourcePack = resourcePack;
|
||||||
|
|
||||||
Block[] neighborCache = new Block[3 * 3 * 3];
|
this.resourceModelBuilder = new ResourceModelBuilder(resourcePack, renderSettings);
|
||||||
for (int i = 0; i < neighborCache.length; i++) {
|
this.liquidModelBuilder = new LiquidModelBuilder(resourcePack, renderSettings);
|
||||||
neighborCache[i] = new Block(null, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.resourceModelBuilder = new ResourceModelBuilder(resourcePack, renderSettings, neighborCache);
|
|
||||||
this.liquidModelBuilder = new LiquidModelBuilder(resourcePack, renderSettings, neighborCache);
|
|
||||||
|
|
||||||
this.bmrs = new ArrayList<>();
|
this.bmrs = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(Block block, BlockModelView blockModel, Color blockColor) throws NoSuchResourceException {
|
public void render(BlockNeighborhood<?> block, BlockModelView blockModel, Color blockColor) throws NoSuchResourceException {
|
||||||
render(block, block.getBlockState(), blockModel, blockColor);
|
render(block, block.getBlockState(), blockModel, blockColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(Block block, BlockState blockState, BlockModelView blockModel, Color blockColor) throws NoSuchResourceException {
|
public void render(BlockNeighborhood<?> block, BlockState blockState, BlockModelView blockModel, Color blockColor) throws NoSuchResourceException {
|
||||||
|
|
||||||
//shortcut for air
|
//shortcut for air
|
||||||
if (blockState.isAir) return;
|
if (blockState.isAir()) return;
|
||||||
|
|
||||||
int modelStart = blockModel.getStart();
|
int modelStart = blockModel.getStart();
|
||||||
|
|
||||||
|
@ -72,15 +69,14 @@ public class BlockStateModelFactory {
|
||||||
renderModel(block, blockState, blockModel.initialize(), blockColor);
|
renderModel(block, blockState, blockModel.initialize(), blockColor);
|
||||||
|
|
||||||
// add water if block is waterlogged
|
// add water if block is waterlogged
|
||||||
if (blockState.isWaterlogged) {
|
if (blockState.isWaterlogged() || block.getProperties().isAlwaysWaterlogged()) {
|
||||||
renderModel(block, WATERLOGGED_BLOCKSTATE, blockModel.initialize(), blockColor);
|
renderModel(block, WATERLOGGED_BLOCKSTATE, blockModel.initialize(), blockColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
blockModel.initialize(modelStart);
|
blockModel.initialize(modelStart);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderModel(Block block, BlockState blockState, BlockModelView blockModel, Color blockColor) throws NoSuchResourceException {
|
private void renderModel(BlockNeighborhood<?> block, BlockState blockState, BlockModelView blockModel, Color blockColor) throws NoSuchResourceException {
|
||||||
int modelStart = blockModel.getStart();
|
int modelStart = blockModel.getStart();
|
||||||
|
|
||||||
BlockStateResource resource = resourcePack.getBlockStateResource(blockState);
|
BlockStateResource resource = resourcePack.getBlockStateResource(blockState);
|
||||||
|
@ -97,7 +93,7 @@ public class BlockStateModelFactory {
|
||||||
|
|
||||||
blockModel.initialize(modelStart);
|
blockModel.initialize(modelStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static BlockState WATERLOGGED_BLOCKSTATE = new BlockState(MinecraftVersion.LATEST_SUPPORTED, "minecraft:water");
|
private final static BlockState WATERLOGGED_BLOCKSTATE = new BlockState("minecraft:water");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,22 +26,21 @@ package de.bluecolored.bluemap.core.map.hires.blockmodel;
|
||||||
|
|
||||||
import com.flowpowered.math.TrigMath;
|
import com.flowpowered.math.TrigMath;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
|
||||||
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
||||||
import de.bluecolored.bluemap.core.map.hires.HiresTileModel;
|
import de.bluecolored.bluemap.core.map.hires.HiresTileModel;
|
||||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.BlockColorCalculatorFactory;
|
import de.bluecolored.bluemap.core.resourcepack.BlockColorCalculatorFactory;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.Texture;
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.TransformedBlockModelResource;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.TransformedBlockModelResource;
|
import de.bluecolored.bluemap.core.resourcepack.texture.Texture;
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
import de.bluecolored.bluemap.core.util.Direction;
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
||||||
import de.bluecolored.bluemap.core.util.math.VectorM2f;
|
import de.bluecolored.bluemap.core.util.math.VectorM2f;
|
||||||
import de.bluecolored.bluemap.core.util.math.VectorM3f;
|
import de.bluecolored.bluemap.core.util.math.VectorM3f;
|
||||||
import de.bluecolored.bluemap.core.world.Block;
|
import de.bluecolored.bluemap.core.world.BlockNeighborhood;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
import de.bluecolored.bluemap.core.world.ResourcePackBlock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A model builder for all liquid blocks
|
* A model builder for all liquid blocks
|
||||||
|
@ -57,24 +56,19 @@ public class LiquidModelBuilder {
|
||||||
private final BlockColorCalculatorFactory.BlockColorCalculator blockColorCalculator;
|
private final BlockColorCalculatorFactory.BlockColorCalculator blockColorCalculator;
|
||||||
private final RenderSettings renderSettings;
|
private final RenderSettings renderSettings;
|
||||||
|
|
||||||
private final boolean useWaterColorMap;
|
|
||||||
|
|
||||||
private final VectorM3f[] corners;
|
private final VectorM3f[] corners;
|
||||||
private final Block[] blocksAround;
|
|
||||||
private final VectorM2f[] uvs = new VectorM2f[4];
|
private final VectorM2f[] uvs = new VectorM2f[4];
|
||||||
|
|
||||||
private Block block;
|
private BlockNeighborhood<?> block;
|
||||||
private BlockState blockState;
|
private BlockState blockState;
|
||||||
private TransformedBlockModelResource blockModelResource;
|
private TransformedBlockModelResource blockModelResource;
|
||||||
private BlockModelView blockModel;
|
private BlockModelView blockModel;
|
||||||
private Color blockColor;
|
private Color blockColor;
|
||||||
|
|
||||||
public LiquidModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings, Block[] neighborCache) {
|
public LiquidModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings) {
|
||||||
this.blockColorCalculator = resourcePack.getBlockColorCalculatorFactory().createCalculator();
|
this.blockColorCalculator = resourcePack.getBlockColorCalculatorFactory().createCalculator();
|
||||||
this.renderSettings = renderSettings;
|
this.renderSettings = renderSettings;
|
||||||
|
|
||||||
this.useWaterColorMap = resourcePack.getMinecraftVersion().isAtLeast(new MinecraftVersion(1, 13));
|
|
||||||
|
|
||||||
corners = new VectorM3f[]{
|
corners = new VectorM3f[]{
|
||||||
new VectorM3f( 0, 0, 0 ),
|
new VectorM3f( 0, 0, 0 ),
|
||||||
new VectorM3f( 0, 0, 16 ),
|
new VectorM3f( 0, 0, 16 ),
|
||||||
|
@ -86,12 +80,10 @@ public class LiquidModelBuilder {
|
||||||
new VectorM3f( 16, 16, 16 ),
|
new VectorM3f( 16, 16, 16 ),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.blocksAround = neighborCache;
|
|
||||||
|
|
||||||
for (int i = 0; i < uvs.length; i++) uvs[i] = new VectorM2f(0, 0);
|
for (int i = 0; i < uvs.length; i++) uvs[i] = new VectorM2f(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(Block block, BlockState blockState, TransformedBlockModelResource bmr, BlockModelView blockModel, Color color) {
|
public void build(BlockNeighborhood<?> block, BlockState blockState, TransformedBlockModelResource bmr, BlockModelView blockModel, Color color) {
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.blockState = blockState;
|
this.blockState = blockState;
|
||||||
this.blockModelResource = bmr;
|
this.blockModelResource = bmr;
|
||||||
|
@ -107,7 +99,7 @@ public class LiquidModelBuilder {
|
||||||
|
|
||||||
int level = getLiquidLevel(blockState);
|
int level = getLiquidLevel(blockState);
|
||||||
|
|
||||||
if (level < 8 && !(level == 0 && isSameLiquid(getNeighborBlock(0, 1, 0).getBlockState()))){
|
if (level < 8 && !(level == 0 && isSameLiquid(block.getNeighborBlock(0, 1, 0)))){
|
||||||
corners[4].y = getLiquidCornerHeight(-1, -1);
|
corners[4].y = getLiquidCornerHeight(-1, -1);
|
||||||
corners[5].y = getLiquidCornerHeight(-1, 0);
|
corners[5].y = getLiquidCornerHeight(-1, 0);
|
||||||
corners[6].y = getLiquidCornerHeight(0, -1);
|
corners[6].y = getLiquidCornerHeight(0, -1);
|
||||||
|
@ -126,7 +118,7 @@ public class LiquidModelBuilder {
|
||||||
int flowTextureId = flowTexture.getId();
|
int flowTextureId = flowTexture.getId();
|
||||||
|
|
||||||
tintcolor.set(1f, 1f, 1f, 1f, true);
|
tintcolor.set(1f, 1f, 1f, 1f, true);
|
||||||
if (useWaterColorMap && blockState.isWater) {
|
if (blockState.isWater()) {
|
||||||
blockColorCalculator.getWaterAverageColor(block, tintcolor);
|
blockColorCalculator.getWaterAverageColor(block, tintcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +158,7 @@ public class LiquidModelBuilder {
|
||||||
|
|
||||||
for (ix = x; ix <= x+1; ix++){
|
for (ix = x; ix <= x+1; ix++){
|
||||||
for (iz = z; iz<= z+1; iz++){
|
for (iz = z; iz<= z+1; iz++){
|
||||||
if (isSameLiquid(getNeighborBlock(ix, 1, iz).getBlockState())){
|
if (isSameLiquid(block.getNeighborBlock(ix, 1, iz))){
|
||||||
return 16f;
|
return 16f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,12 +166,14 @@ public class LiquidModelBuilder {
|
||||||
|
|
||||||
float sumHeight = 0f;
|
float sumHeight = 0f;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
ResourcePackBlock<?> neighbor;
|
||||||
BlockState neighborBlockState;
|
BlockState neighborBlockState;
|
||||||
|
|
||||||
for (ix = x; ix <= x+1; ix++){
|
for (ix = x; ix <= x+1; ix++){
|
||||||
for (iz = z; iz<= z+1; iz++){
|
for (iz = z; iz<= z+1; iz++){
|
||||||
neighborBlockState = getNeighborBlock(ix, 0, iz).getBlockState();
|
neighbor = block.getNeighborBlock(ix, 0, iz);
|
||||||
if (isSameLiquid(neighborBlockState)){
|
neighborBlockState = neighbor.getBlockState();
|
||||||
|
if (isSameLiquid(neighbor)){
|
||||||
if (getLiquidLevel(neighborBlockState) == 0) return 14f;
|
if (getLiquidLevel(neighborBlockState) == 0) return 14f;
|
||||||
|
|
||||||
sumHeight += getLiquidBaseHeight(neighborBlockState);
|
sumHeight += getLiquidBaseHeight(neighborBlockState);
|
||||||
|
@ -203,9 +197,9 @@ public class LiquidModelBuilder {
|
||||||
return !blockState.equals(BlockState.AIR);
|
return !blockState.equals(BlockState.AIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSameLiquid(BlockState blockState){
|
private boolean isSameLiquid(ResourcePackBlock<?> block){
|
||||||
if (blockState.getFullId().equals(this.blockState.getFullId())) return true;
|
if (block.getBlockState().getFullId().equals(this.blockState.getFullId())) return true;
|
||||||
return this.blockState.isWater && blockState.isWaterlogged;
|
return this.blockState.isWater() && (block.getBlockState().isWaterlogged() || block.getProperties().isAlwaysWaterlogged());
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getLiquidBaseHeight(BlockState block){
|
private float getLiquidBaseHeight(BlockState block){
|
||||||
|
@ -223,13 +217,13 @@ public class LiquidModelBuilder {
|
||||||
Vector3i faceDirVector = faceDir.toVector();
|
Vector3i faceDirVector = faceDir.toVector();
|
||||||
|
|
||||||
//face culling
|
//face culling
|
||||||
Block bl = getNeighborBlock(
|
ResourcePackBlock<?> bl = block.getNeighborBlock(
|
||||||
faceDirVector.getX(),
|
faceDirVector.getX(),
|
||||||
faceDirVector.getY(),
|
faceDirVector.getY(),
|
||||||
faceDirVector.getZ()
|
faceDirVector.getZ()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isSameLiquid(bl.getBlockState()) || (faceDir != Direction.UP && bl.isCullingNeighborFaces())) return false;
|
if (isSameLiquid(bl) || (faceDir != Direction.UP && bl.getProperties().isCulling())) return false;
|
||||||
|
|
||||||
// initialize the faces
|
// initialize the faces
|
||||||
blockModel.initialize();
|
blockModel.initialize();
|
||||||
|
@ -327,17 +321,6 @@ public class LiquidModelBuilder {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Block getNeighborBlock(int dx, int dy, int dz) {
|
|
||||||
int i = (dx + 1) * 9 + (dy + 1) * 3 + (dz + 1);
|
|
||||||
if (i == 13) return block;
|
|
||||||
return blocksAround[i].set(
|
|
||||||
block.getWorld(),
|
|
||||||
block.getX() + dx,
|
|
||||||
block.getY() + dy,
|
|
||||||
block.getZ() + dz
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final VectorM2f flowingVector = new VectorM2f(0, 0);
|
private final VectorM2f flowingVector = new VectorM2f(0, 0);
|
||||||
private int getFlowingAngle() {
|
private int getFlowingAngle() {
|
||||||
float own = getLiquidBaseHeight(blockState) * BLOCK_SCALE;
|
float own = getLiquidBaseHeight(blockState) * BLOCK_SCALE;
|
||||||
|
@ -358,11 +341,11 @@ public class LiquidModelBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private float compareLiquidHeights(float ownHeight, int dx, int dz) {
|
private float compareLiquidHeights(float ownHeight, int dx, int dz) {
|
||||||
BlockState state = getNeighborBlock(dx, 0, dz).getBlockState();
|
ResourcePackBlock<?> neighbor = block.getNeighborBlock(dx, 0, dz);
|
||||||
if (state.isAir) return 0;
|
if (neighbor.getBlockState().isAir()) return 0;
|
||||||
if (!isSameLiquid(state)) return 0;
|
if (!isSameLiquid(neighbor)) return 0;
|
||||||
|
|
||||||
float otherHeight = getLiquidBaseHeight(state) * BLOCK_SCALE;
|
float otherHeight = getLiquidBaseHeight(neighbor.getBlockState()) * BLOCK_SCALE;
|
||||||
return otherHeight - ownHeight;
|
return otherHeight - ownHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,13 +32,19 @@ import com.flowpowered.math.vector.Vector4f;
|
||||||
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
||||||
import de.bluecolored.bluemap.core.map.hires.HiresTileModel;
|
import de.bluecolored.bluemap.core.map.hires.HiresTileModel;
|
||||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.*;
|
import de.bluecolored.bluemap.core.resourcepack.BlockColorCalculatorFactory;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.BlockModelResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.TransformedBlockModelResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.texture.Texture;
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
import de.bluecolored.bluemap.core.util.Direction;
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
import de.bluecolored.bluemap.core.util.math.MatrixM4f;
|
import de.bluecolored.bluemap.core.util.math.MatrixM4f;
|
||||||
import de.bluecolored.bluemap.core.util.math.VectorM2f;
|
import de.bluecolored.bluemap.core.util.math.VectorM2f;
|
||||||
import de.bluecolored.bluemap.core.util.math.VectorM3f;
|
import de.bluecolored.bluemap.core.util.math.VectorM3f;
|
||||||
import de.bluecolored.bluemap.core.world.Block;
|
import de.bluecolored.bluemap.core.world.BlockNeighborhood;
|
||||||
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
import de.bluecolored.bluemap.core.world.ResourcePackBlock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This model builder creates a BlockStateModel using the information from parsed resource-pack json files.
|
* This model builder creates a BlockStateModel using the information from parsed resource-pack json files.
|
||||||
|
@ -54,24 +60,22 @@ public class ResourceModelBuilder {
|
||||||
private final VectorM2f[] uvs = new VectorM2f[4];
|
private final VectorM2f[] uvs = new VectorM2f[4];
|
||||||
private final Color tintColor = new Color();
|
private final Color tintColor = new Color();
|
||||||
private final Color mapColor = new Color();
|
private final Color mapColor = new Color();
|
||||||
private final Block[] blocksAround;
|
|
||||||
|
|
||||||
private Block block;
|
private BlockNeighborhood<?> block;
|
||||||
private TransformedBlockModelResource blockModelResource;
|
private TransformedBlockModelResource blockModelResource;
|
||||||
private BlockModelView blockModel;
|
private BlockModelView blockModel;
|
||||||
private Color blockColor;
|
private Color blockColor;
|
||||||
|
|
||||||
public ResourceModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings, Block[] neighborCache) {
|
public ResourceModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings) {
|
||||||
this.blockColorCalculator = resourcePack.getBlockColorCalculatorFactory().createCalculator();
|
this.blockColorCalculator = resourcePack.getBlockColorCalculatorFactory().createCalculator();
|
||||||
this.renderSettings = renderSettings;
|
this.renderSettings = renderSettings;
|
||||||
this.blocksAround = neighborCache;
|
|
||||||
|
|
||||||
for (int i = 0; i < corners.length; i++) corners[i] = new VectorM3f(0, 0, 0);
|
for (int i = 0; i < corners.length; i++) corners[i] = new VectorM3f(0, 0, 0);
|
||||||
for (int i = 0; i < uvs.length; i++) rawUvs[i] = new VectorM2f(0, 0);
|
for (int i = 0; i < uvs.length; i++) rawUvs[i] = new VectorM2f(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MatrixM4f modelTransform = new MatrixM4f();
|
private final MatrixM4f modelTransform = new MatrixM4f();
|
||||||
public void build(Block block, TransformedBlockModelResource bmr, BlockModelView blockModel, Color color) {
|
public void build(BlockNeighborhood<?> block, TransformedBlockModelResource bmr, BlockModelView blockModel, Color color) {
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.blockModel = blockModel;
|
this.blockModel = blockModel;
|
||||||
this.blockColor = color;
|
this.blockColor = color;
|
||||||
|
@ -97,6 +101,13 @@ public class ResourceModelBuilder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//random offset
|
||||||
|
if (block.getProperties().isRandomOffset()){
|
||||||
|
float dx = (hashToFloat(block.getX(), block.getZ(), 123984) - 0.5f) * 0.75f;
|
||||||
|
float dz = (hashToFloat(block.getX(), block.getZ(), 345542) - 0.5f) * 0.75f;
|
||||||
|
blockModel.translate(dx, 0, dz);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MatrixM4f modelElementTransform = new MatrixM4f();
|
private final MatrixM4f modelElementTransform = new MatrixM4f();
|
||||||
|
@ -149,14 +160,17 @@ public class ResourceModelBuilder {
|
||||||
|
|
||||||
// face culling
|
// face culling
|
||||||
if (face.getCullface() != null) {
|
if (face.getCullface() != null) {
|
||||||
Block b = getRotationRelativeBlock(face.getCullface());
|
ResourcePackBlock<?> b = getRotationRelativeBlock(face.getCullface());
|
||||||
if (b.isCullingNeighborFaces()) return;
|
if (b.getProperties().isCulling()) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// light calculation
|
// light calculation
|
||||||
Block facedBlockNeighbor = getRotationRelativeBlock(faceDir);
|
ResourcePackBlock<?> facedBlockNeighbor = getRotationRelativeBlock(faceDir);
|
||||||
int sunLight = facedBlockNeighbor.getPassedSunLight();
|
LightData blockLightData = block.getLightData();
|
||||||
int blockLight = facedBlockNeighbor.getPassedBlockLight();
|
LightData facedLightData = facedBlockNeighbor.getLightData();
|
||||||
|
|
||||||
|
int sunLight = Math.max(blockLightData.getSkyLight(), facedLightData.getSkyLight());
|
||||||
|
int blockLight = Math.max(blockLightData.getBlockLight(), facedLightData.getBlockLight());
|
||||||
|
|
||||||
// filter out faces that are not sun-lighted
|
// filter out faces that are not sun-lighted
|
||||||
if (sunLight == 0f && renderSettings.isExcludeFacesWithoutSunlight()) return;
|
if (sunLight == 0f && renderSettings.isExcludeFacesWithoutSunlight()) return;
|
||||||
|
@ -302,23 +316,11 @@ public class ResourceModelBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Block getNeighborBlock(int dx, int dy, int dz) {
|
private ResourcePackBlock<?> getRotationRelativeBlock(Direction direction){
|
||||||
int i = (dx + 1) * 9 + (dy + 1) * 3 + (dz + 1);
|
|
||||||
if (i == 13) return block;
|
|
||||||
return blocksAround[i].set(
|
|
||||||
block.getWorld(),
|
|
||||||
block.getX() + dx,
|
|
||||||
block.getY() + dy,
|
|
||||||
block.getZ() + dz
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Block getRotationRelativeBlock(Direction direction){
|
|
||||||
return getRotationRelativeBlock(direction.toVector());
|
return getRotationRelativeBlock(direction.toVector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResourcePackBlock<?> getRotationRelativeBlock(Vector3i direction){
|
||||||
private Block getRotationRelativeBlock(Vector3i direction){
|
|
||||||
return getRotationRelativeBlock(
|
return getRotationRelativeBlock(
|
||||||
direction.getX(),
|
direction.getX(),
|
||||||
direction.getY(),
|
direction.getY(),
|
||||||
|
@ -327,11 +329,11 @@ public class ResourceModelBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final VectorM3f rotationRelativeBlockDirection = new VectorM3f(0, 0, 0);
|
private final VectorM3f rotationRelativeBlockDirection = new VectorM3f(0, 0, 0);
|
||||||
private Block getRotationRelativeBlock(int dx, int dy, int dz){
|
private ResourcePackBlock<?> getRotationRelativeBlock(int dx, int dy, int dz){
|
||||||
rotationRelativeBlockDirection.set(dx, dy, dz);
|
rotationRelativeBlockDirection.set(dx, dy, dz);
|
||||||
makeRotationRelative(rotationRelativeBlockDirection);
|
makeRotationRelative(rotationRelativeBlockDirection);
|
||||||
|
|
||||||
return getNeighborBlock(
|
return block.getNeighborBlock(
|
||||||
Math.round(rotationRelativeBlockDirection.x),
|
Math.round(rotationRelativeBlockDirection.x),
|
||||||
Math.round(rotationRelativeBlockDirection.y),
|
Math.round(rotationRelativeBlockDirection.y),
|
||||||
Math.round(rotationRelativeBlockDirection.z)
|
Math.round(rotationRelativeBlockDirection.z)
|
||||||
|
@ -369,23 +371,28 @@ public class ResourceModelBuilder {
|
||||||
|
|
||||||
|
|
||||||
if (x * dirVec.getX() + y * dirVec.getY() > 0){
|
if (x * dirVec.getX() + y * dirVec.getY() > 0){
|
||||||
if (getRotationRelativeBlock(x, y, 0).isOccludingNeighborFaces()) occluding++;
|
if (getRotationRelativeBlock(x, y, 0).getProperties().isOccluding()) occluding++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x * dirVec.getX() + z * dirVec.getZ() > 0){
|
if (x * dirVec.getX() + z * dirVec.getZ() > 0){
|
||||||
if (getRotationRelativeBlock(x, 0, z).isOccludingNeighborFaces()) occluding++;
|
if (getRotationRelativeBlock(x, 0, z).getProperties().isOccluding()) occluding++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y * dirVec.getY() + z * dirVec.getZ() > 0){
|
if (y * dirVec.getY() + z * dirVec.getZ() > 0){
|
||||||
if (getRotationRelativeBlock(0, y, z).isOccludingNeighborFaces()) occluding++;
|
if (getRotationRelativeBlock(0, y, z).getProperties().isOccluding()) occluding++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x * dirVec.getX() + y * dirVec.getY() + z * dirVec.getZ() > 0){
|
if (x * dirVec.getX() + y * dirVec.getY() + z * dirVec.getZ() > 0){
|
||||||
if (getRotationRelativeBlock(x, y, z).isOccludingNeighborFaces()) occluding++;
|
if (getRotationRelativeBlock(x, y, z).getProperties().isOccluding()) occluding++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (occluding > 3) occluding = 3;
|
if (occluding > 3) occluding = 3;
|
||||||
return Math.max(0f, Math.min(1f - occluding * 0.25f, 1f));
|
return Math.max(0f, Math.min(1f - occluding * 0.25f, 1f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static float hashToFloat(int x, int z, long seed) {
|
||||||
|
final long hash = x * 73428767 ^ z * 4382893 ^ seed * 457;
|
||||||
|
return (hash * (hash + 456149) & 0x00ffffff) / (float) 0x01000000;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,233 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.BiomeMapper;
|
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper;
|
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
|
||||||
import net.querz.nbt.CompoundTag;
|
|
||||||
import net.querz.nbt.ListTag;
|
|
||||||
import net.querz.nbt.NumberTag;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.function.IntFunction;
|
|
||||||
|
|
||||||
public class ChunkAnvil112 extends MCAChunk {
|
|
||||||
private final BiomeMapper biomeIdMapper;
|
|
||||||
private final BlockIdMapper blockIdMapper;
|
|
||||||
private final IntFunction<String> forgeBlockIdMapper;
|
|
||||||
|
|
||||||
private boolean isGenerated;
|
|
||||||
private boolean hasLight;
|
|
||||||
private Section[] sections;
|
|
||||||
private byte[] biomes;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public ChunkAnvil112(CompoundTag chunkTag, boolean ignoreMissingLightData, BiomeMapper biomeIdMapper, BlockIdMapper blockIdMapper, IntFunction<String> forgeBlockIdMapper) {
|
|
||||||
super(chunkTag);
|
|
||||||
|
|
||||||
this.blockIdMapper = blockIdMapper;
|
|
||||||
this.biomeIdMapper = biomeIdMapper;
|
|
||||||
this.forgeBlockIdMapper = forgeBlockIdMapper;
|
|
||||||
|
|
||||||
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
|
||||||
|
|
||||||
hasLight = levelData.getBoolean("LightPopulated");
|
|
||||||
|
|
||||||
isGenerated =
|
|
||||||
(hasLight || ignoreMissingLightData) &&
|
|
||||||
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?
|
|
||||||
if (levelData.containsKey("Sections")) {
|
|
||||||
for (CompoundTag sectionTag : ((ListTag<CompoundTag>) levelData.getListTag("Sections"))) {
|
|
||||||
Section section = new Section(sectionTag);
|
|
||||||
if (section.getSectionY() >= 0 && section.getSectionY() < sections.length) sections[section.getSectionY()] = section;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
biomes = levelData.getByteArray("Biomes");
|
|
||||||
|
|
||||||
if (biomes == null || biomes.length == 0) {
|
|
||||||
biomes = new byte[256];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (biomes.length < 256) {
|
|
||||||
biomes = Arrays.copyOf(biomes, 256);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGenerated() {
|
|
||||||
return isGenerated;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState getBlockState(int x, int y, int z) {
|
|
||||||
int sectionY = y >> 4;
|
|
||||||
if (sectionY < 0 || sectionY >= this.sections.length) return BlockState.AIR;
|
|
||||||
|
|
||||||
Section section = this.sections[sectionY];
|
|
||||||
if (section == null) return BlockState.AIR;
|
|
||||||
|
|
||||||
return section.getBlockState(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBlockIdMeta(Vector3i pos) {
|
|
||||||
int sectionY = pos.getY() >> 4;
|
|
||||||
if (sectionY < 0 || sectionY >= this.sections.length) return "0:0";
|
|
||||||
|
|
||||||
Section section = this.sections[sectionY];
|
|
||||||
if (section == null) return "0:0";
|
|
||||||
|
|
||||||
return section.getBlockIdMeta(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LightData getLightData(int x, int y, int z, LightData target) {
|
|
||||||
if (!hasLight) return target.set(15, 0);
|
|
||||||
|
|
||||||
int sectionY = y >> 4;
|
|
||||||
if (sectionY < 0 || sectionY >= this.sections.length)
|
|
||||||
return (y < 0) ? target.set(0, 0) : target.set(15, 0);
|
|
||||||
|
|
||||||
Section section = this.sections[sectionY];
|
|
||||||
if (section == null) return target.set(15, 0);
|
|
||||||
|
|
||||||
return section.getLightData(x, y, z, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Biome getBiome(int x, int y, int z) {
|
|
||||||
x = x & 0xF; // Math.floorMod(pos.getX(), 16)
|
|
||||||
z = z & 0xF;
|
|
||||||
int biomeByteIndex = z * 16 + x;
|
|
||||||
|
|
||||||
if (biomeByteIndex >= this.biomes.length) return Biome.DEFAULT;
|
|
||||||
|
|
||||||
return biomeIdMapper.get(biomes[biomeByteIndex] & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.get("Y", NumberTag.class).asInt();
|
|
||||||
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");
|
|
||||||
|
|
||||||
if (blocks.length < 4096) blocks = Arrays.copyOf(blocks, 4096);
|
|
||||||
if (blockLight.length < 2048) blockLight = Arrays.copyOf(blockLight, 2048);
|
|
||||||
if (skyLight.length < 2048) skyLight = Arrays.copyOf(skyLight, 2048);
|
|
||||||
if (data.length < 2048) data = Arrays.copyOf(data, 2048);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSectionY() {
|
|
||||||
return sectionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockState getBlockState(int x, int y, int z) {
|
|
||||||
x &= 0xF; y &= 0xF; z &= 0xF; // Math.floorMod(pos.getX(), 16)
|
|
||||||
|
|
||||||
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 > blockHalfByteIndex) {
|
|
||||||
blockId = blockId | (getByteHalf(this.add[blockHalfByteIndex], largeHalf) << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
int blockData = getByteHalf(this.data[blockHalfByteIndex], largeHalf);
|
|
||||||
|
|
||||||
String forgeIdMapping = forgeBlockIdMapper.apply(blockId);
|
|
||||||
if (forgeIdMapping != null) {
|
|
||||||
return blockIdMapper.get(forgeIdMapping, blockId, blockData);
|
|
||||||
} else {
|
|
||||||
return blockIdMapper.get(blockId, blockData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBlockIdMeta(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 > blockHalfByteIndex) {
|
|
||||||
blockId = blockId | (getByteHalf(this.add[blockHalfByteIndex], largeHalf) << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
int blockData = getByteHalf(this.data[blockHalfByteIndex], largeHalf);
|
|
||||||
String forgeIdMapping = forgeBlockIdMapper.apply(blockId);
|
|
||||||
|
|
||||||
return blockId + ":" + blockData + " " + forgeIdMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LightData getLightData(int x, int y, int z, LightData target) {
|
|
||||||
x &= 0xF; y &= 0xF; z &= 0xF; // Math.floorMod(pos.getX(), 16)
|
|
||||||
|
|
||||||
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 target.set(skyLight, blockLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the 4 bits of the left (largeHalf = <code>true</code>) or the right (largeHalf = <code>false</code>) side of the byte stored in <code>value</code>.<br>
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -24,9 +24,7 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.mca;
|
package de.bluecolored.bluemap.core.mca;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
|
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
import de.bluecolored.bluemap.core.world.Biome;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
@ -38,21 +36,15 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class ChunkAnvil113 extends MCAChunk {
|
public class ChunkAnvil113 extends MCAChunk {
|
||||||
private static final MinecraftVersion VERSION = new MinecraftVersion(1, 13);
|
|
||||||
|
|
||||||
private BiomeMapper biomeIdMapper;
|
|
||||||
|
|
||||||
private boolean isGenerated;
|
private boolean isGenerated;
|
||||||
private boolean hasLight;
|
private boolean hasLight;
|
||||||
private Section[] sections;
|
private Section[] sections;
|
||||||
private int[] biomes;
|
private int[] biomes;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ChunkAnvil113(CompoundTag chunkTag, boolean ignoreMissingLightData, BiomeMapper biomeIdMapper) {
|
public ChunkAnvil113(CompoundTag chunkTag, boolean ignoreMissingLightData) {
|
||||||
super(chunkTag);
|
super(chunkTag);
|
||||||
|
|
||||||
this.biomeIdMapper = biomeIdMapper;
|
|
||||||
|
|
||||||
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
||||||
|
|
||||||
String status = levelData.getString("Status");
|
String status = levelData.getString("Status");
|
||||||
|
@ -124,14 +116,14 @@ public class ChunkAnvil113 extends MCAChunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getBiome(int x, int y, int z) {
|
public int getBiome(int x, int y, int z) {
|
||||||
x = x & 0xF; // Math.floorMod(pos.getX(), 16)
|
x = x & 0xF; // Math.floorMod(pos.getX(), 16)
|
||||||
z = z & 0xF;
|
z = z & 0xF;
|
||||||
int biomeIntIndex = z * 16 + x;
|
int biomeIntIndex = z * 16 + x;
|
||||||
|
|
||||||
if (biomeIntIndex >= this.biomes.length) return Biome.DEFAULT;
|
if (biomeIntIndex >= this.biomes.length) return Biome.DEFAULT.getNumeralId();
|
||||||
|
|
||||||
return biomeIdMapper.get(biomes[biomeIntIndex]);
|
return biomes[biomeIntIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Section {
|
private class Section {
|
||||||
|
@ -178,7 +170,7 @@ public class ChunkAnvil113 extends MCAChunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
palette[i] = new BlockState(VERSION, id, properties);
|
palette[i] = new BlockState(id, properties);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.palette = new BlockState[0];
|
this.palette = new BlockState[0];
|
||||||
|
|
|
@ -24,9 +24,7 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.mca;
|
package de.bluecolored.bluemap.core.mca;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
|
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
import de.bluecolored.bluemap.core.world.Biome;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
@ -38,21 +36,15 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class ChunkAnvil115 extends MCAChunk {
|
public class ChunkAnvil115 extends MCAChunk {
|
||||||
private static final MinecraftVersion VERSION = new MinecraftVersion(1, 15);
|
|
||||||
|
|
||||||
private BiomeMapper biomeIdMapper;
|
|
||||||
|
|
||||||
private boolean isGenerated;
|
private boolean isGenerated;
|
||||||
private boolean hasLight;
|
private boolean hasLight;
|
||||||
private Section[] sections;
|
private Section[] sections;
|
||||||
private int[] biomes;
|
private int[] biomes;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ChunkAnvil115(CompoundTag chunkTag, boolean ignoreMissingLightData, BiomeMapper biomeIdMapper) {
|
public ChunkAnvil115(CompoundTag chunkTag, boolean ignoreMissingLightData) {
|
||||||
super(chunkTag);
|
super(chunkTag);
|
||||||
|
|
||||||
this.biomeIdMapper = biomeIdMapper;
|
|
||||||
|
|
||||||
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
||||||
|
|
||||||
String status = levelData.getString("Status");
|
String status = levelData.getString("Status");
|
||||||
|
@ -124,16 +116,16 @@ public class ChunkAnvil115 extends MCAChunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getBiome(int x, int y, int z) {
|
public int getBiome(int x, int y, int z) {
|
||||||
x = (x & 0xF) / 4; // Math.floorMod(pos.getX(), 16)
|
x = (x & 0xF) / 4; // Math.floorMod(pos.getX(), 16)
|
||||||
z = (z & 0xF) / 4;
|
z = (z & 0xF) / 4;
|
||||||
y = y / 4;
|
y = y / 4;
|
||||||
int biomeIntIndex = y * 16 + z * 4 + x;
|
int biomeIntIndex = y * 16 + z * 4 + x;
|
||||||
|
|
||||||
if (biomeIntIndex < 0) return Biome.DEFAULT;
|
if (biomeIntIndex < 0) return Biome.DEFAULT.getNumeralId();
|
||||||
if (biomeIntIndex >= this.biomes.length) return Biome.DEFAULT;
|
if (biomeIntIndex >= this.biomes.length) return Biome.DEFAULT.getNumeralId();
|
||||||
|
|
||||||
return biomeIdMapper.get(biomes[biomeIntIndex]);
|
return biomes[biomeIntIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Section {
|
private static class Section {
|
||||||
|
@ -180,7 +172,7 @@ public class ChunkAnvil115 extends MCAChunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
palette[i] = new BlockState(VERSION, id, properties);
|
palette[i] = new BlockState(id, properties);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.palette = new BlockState[0];
|
this.palette = new BlockState[0];
|
||||||
|
|
|
@ -24,9 +24,7 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.mca;
|
package de.bluecolored.bluemap.core.mca;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
|
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
import de.bluecolored.bluemap.core.world.Biome;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
@ -39,10 +37,6 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class ChunkAnvil116 extends MCAChunk {
|
public class ChunkAnvil116 extends MCAChunk {
|
||||||
private static final MinecraftVersion VERSION = new MinecraftVersion(1, 16);
|
|
||||||
|
|
||||||
private BiomeMapper biomeIdMapper;
|
|
||||||
|
|
||||||
private boolean isGenerated;
|
private boolean isGenerated;
|
||||||
private boolean hasLight;
|
private boolean hasLight;
|
||||||
|
|
||||||
|
@ -52,11 +46,9 @@ public class ChunkAnvil116 extends MCAChunk {
|
||||||
private int[] biomes;
|
private int[] biomes;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ChunkAnvil116(CompoundTag chunkTag, boolean ignoreMissingLightData, BiomeMapper biomeIdMapper) {
|
public ChunkAnvil116(CompoundTag chunkTag, boolean ignoreMissingLightData) {
|
||||||
super(chunkTag);
|
super(chunkTag);
|
||||||
|
|
||||||
this.biomeIdMapper = biomeIdMapper;
|
|
||||||
|
|
||||||
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
||||||
|
|
||||||
String status = levelData.getString("Status");
|
String status = levelData.getString("Status");
|
||||||
|
@ -138,8 +130,8 @@ public class ChunkAnvil116 extends MCAChunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getBiome(int x, int y, int z) {
|
public int getBiome(int x, int y, int z) {
|
||||||
if (biomes.length < 16) return Biome.DEFAULT;
|
if (biomes.length < 16) return Biome.DEFAULT.getNumeralId();
|
||||||
|
|
||||||
x = (x & 0xF) / 4; // Math.floorMod(pos.getX(), 16)
|
x = (x & 0xF) / 4; // Math.floorMod(pos.getX(), 16)
|
||||||
z = (z & 0xF) / 4;
|
z = (z & 0xF) / 4;
|
||||||
|
@ -150,7 +142,7 @@ public class ChunkAnvil116 extends MCAChunk {
|
||||||
if (biomeIntIndex >= biomes.length) biomeIntIndex -= (((biomeIntIndex - biomes.length) >> 4) + 1) * 16;
|
if (biomeIntIndex >= biomes.length) biomeIntIndex -= (((biomeIntIndex - biomes.length) >> 4) + 1) * 16;
|
||||||
if (biomeIntIndex < 0) biomeIntIndex -= (biomeIntIndex >> 4) * 16;
|
if (biomeIntIndex < 0) biomeIntIndex -= (biomeIntIndex >> 4) * 16;
|
||||||
|
|
||||||
return biomeIdMapper.get(biomes[biomeIntIndex]);
|
return biomes[biomeIntIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -213,7 +205,7 @@ public class ChunkAnvil116 extends MCAChunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
palette[i] = new BlockState(VERSION, id, properties);
|
palette[i] = new BlockState(id, properties);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.palette = new BlockState[0];
|
this.palette = new BlockState[0];
|
||||||
|
|
|
@ -48,8 +48,8 @@ public class EmptyChunk extends MCAChunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getBiome(int x, int y, int z) {
|
public int getBiome(int x, int y, int z) {
|
||||||
return Biome.DEFAULT;
|
return Biome.DEFAULT.getNumeralId();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.mca;
|
package de.bluecolored.bluemap.core.mca;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.world.Chunk;
|
import de.bluecolored.bluemap.core.world.Chunk;
|
||||||
import de.bluecolored.bluemap.core.world.LightData;
|
import de.bluecolored.bluemap.core.world.LightData;
|
||||||
|
@ -59,7 +58,7 @@ public abstract class MCAChunk implements Chunk {
|
||||||
public abstract LightData getLightData(int x, int y, int z, LightData target);
|
public abstract LightData getLightData(int x, int y, int z, LightData target);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract Biome getBiome(int x, int y, int z);
|
public abstract int getBiome(int x, int y, int z);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxY(int x, int z) {
|
public int getMaxY(int x, int z) {
|
||||||
|
@ -73,11 +72,10 @@ public abstract class MCAChunk implements Chunk {
|
||||||
|
|
||||||
public static MCAChunk create(MCAWorld world, CompoundTag chunkTag, boolean ignoreMissingLightData) throws IOException {
|
public static MCAChunk create(MCAWorld world, CompoundTag chunkTag, boolean ignoreMissingLightData) throws IOException {
|
||||||
int version = chunkTag.getInt("DataVersion");
|
int version = chunkTag.getInt("DataVersion");
|
||||||
|
|
||||||
if (version < 1400) return new ChunkAnvil112(chunkTag, ignoreMissingLightData, world.getBiomeIdMapper(), world.getBlockIdMapper(), world::getForgeBlockIdMapping);
|
if (version < 2200) return new ChunkAnvil113(chunkTag, ignoreMissingLightData);
|
||||||
if (version < 2200) return new ChunkAnvil113(chunkTag, ignoreMissingLightData, world.getBiomeIdMapper());
|
if (version < 2500) return new ChunkAnvil115(chunkTag, ignoreMissingLightData);
|
||||||
if (version < 2500) return new ChunkAnvil115(chunkTag, ignoreMissingLightData, world.getBiomeIdMapper());
|
return new ChunkAnvil116(chunkTag, ignoreMissingLightData);
|
||||||
return new ChunkAnvil116(chunkTag, ignoreMissingLightData, world.getBiomeIdMapper());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MCAChunk empty() {
|
public static MCAChunk empty() {
|
||||||
|
|
|
@ -29,20 +29,13 @@ import com.flowpowered.math.vector.Vector3i;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
import de.bluecolored.bluemap.core.BlueMap;
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.debug.DebugDump;
|
import de.bluecolored.bluemap.core.debug.DebugDump;
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.mca.extensions.*;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
|
import de.bluecolored.bluemap.core.world.Grid;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
|
||||||
import de.bluecolored.bluemap.core.util.ArrayPool;
|
|
||||||
import de.bluecolored.bluemap.core.util.math.VectorM2i;
|
|
||||||
import de.bluecolored.bluemap.core.world.*;
|
|
||||||
import net.querz.nbt.CompoundTag;
|
import net.querz.nbt.CompoundTag;
|
||||||
import net.querz.nbt.ListTag;
|
|
||||||
import net.querz.nbt.NBTUtil;
|
import net.querz.nbt.NBTUtil;
|
||||||
import net.querz.nbt.Tag;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -58,62 +51,28 @@ public class MCAWorld implements World {
|
||||||
|
|
||||||
@DebugDump private final UUID uuid;
|
@DebugDump private final UUID uuid;
|
||||||
@DebugDump private final Path worldFolder;
|
@DebugDump private final Path worldFolder;
|
||||||
private final MinecraftVersion minecraftVersion;
|
|
||||||
@DebugDump private final String name;
|
@DebugDump private final String name;
|
||||||
@DebugDump private final Vector3i spawnPoint;
|
@DebugDump private final Vector3i spawnPoint;
|
||||||
|
|
||||||
|
@DebugDump private final boolean ignoreMissingLightData;
|
||||||
|
|
||||||
private final LoadingCache<Vector2i, MCARegion> regionCache;
|
private final LoadingCache<Vector2i, MCARegion> regionCache;
|
||||||
private final LoadingCache<Vector2i, MCAChunk> chunkCache;
|
private final LoadingCache<Vector2i, MCAChunk> chunkCache;
|
||||||
|
|
||||||
private BlockIdMapper blockIdMapper;
|
|
||||||
private BlockPropertiesMapper blockPropertiesMapper;
|
|
||||||
private BiomeMapper biomeMapper;
|
|
||||||
|
|
||||||
private final Map<String, List<BlockStateExtension>> blockStateExtensions;
|
|
||||||
|
|
||||||
@DebugDump private final boolean ignoreMissingLightData;
|
|
||||||
|
|
||||||
private final Map<Integer, String> forgeBlockMappings;
|
|
||||||
|
|
||||||
private MCAWorld(
|
private MCAWorld(
|
||||||
Path worldFolder,
|
Path worldFolder,
|
||||||
UUID uuid,
|
UUID uuid,
|
||||||
MinecraftVersion minecraftVersion,
|
|
||||||
String name,
|
String name,
|
||||||
Vector3i spawnPoint,
|
Vector3i spawnPoint,
|
||||||
BlockIdMapper blockIdMapper,
|
|
||||||
BlockPropertiesMapper blockPropertiesMapper,
|
|
||||||
BiomeMapper biomeMapper,
|
|
||||||
boolean ignoreMissingLightData
|
boolean ignoreMissingLightData
|
||||||
) {
|
) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.worldFolder = worldFolder;
|
this.worldFolder = worldFolder;
|
||||||
this.minecraftVersion = minecraftVersion;
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.spawnPoint = spawnPoint;
|
this.spawnPoint = spawnPoint;
|
||||||
|
|
||||||
this.blockIdMapper = blockIdMapper;
|
|
||||||
this.blockPropertiesMapper = blockPropertiesMapper;
|
|
||||||
this.biomeMapper = biomeMapper;
|
|
||||||
|
|
||||||
this.ignoreMissingLightData = ignoreMissingLightData;
|
this.ignoreMissingLightData = ignoreMissingLightData;
|
||||||
|
|
||||||
this.forgeBlockMappings = new HashMap<>();
|
|
||||||
|
|
||||||
this.blockStateExtensions = new HashMap<>();
|
|
||||||
registerBlockStateExtension(new SnowyExtension(minecraftVersion));
|
|
||||||
registerBlockStateExtension(new StairShapeExtension());
|
|
||||||
registerBlockStateExtension(new FireExtension());
|
|
||||||
registerBlockStateExtension(new RedstoneExtension());
|
|
||||||
registerBlockStateExtension(new DoorExtension(minecraftVersion));
|
|
||||||
registerBlockStateExtension(new NetherFenceConnectExtension());
|
|
||||||
registerBlockStateExtension(new TripwireConnectExtension());
|
|
||||||
registerBlockStateExtension(new WallConnectExtension());
|
|
||||||
registerBlockStateExtension(new WoodenFenceConnectExtension(minecraftVersion));
|
|
||||||
registerBlockStateExtension(new GlassPaneConnectExtension());
|
|
||||||
registerBlockStateExtension(new DoublePlantExtension(minecraftVersion));
|
|
||||||
registerBlockStateExtension(new DoubleChestExtension());
|
|
||||||
|
|
||||||
this.regionCache = Caffeine.newBuilder()
|
this.regionCache = Caffeine.newBuilder()
|
||||||
.executor(BlueMap.THREAD_POOL)
|
.executor(BlueMap.THREAD_POOL)
|
||||||
.maximumSize(100)
|
.maximumSize(100)
|
||||||
|
@ -130,34 +89,6 @@ public class MCAWorld implements World {
|
||||||
public BlockState getBlockState(Vector3i pos) {
|
public BlockState getBlockState(Vector3i pos) {
|
||||||
return getChunk(pos.getX() >> 4, pos.getZ() >> 4).getBlockState(pos.getX(), pos.getY(), pos.getZ());
|
return getChunk(pos.getX() >> 4, pos.getZ() >> 4).getBlockState(pos.getX(), pos.getY(), pos.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Biome getBiome(int x, int y, int z) {
|
|
||||||
return getChunk(x >> 4, z >> 4).getBiome(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState getBlockState(int x, int y, int z) {
|
|
||||||
MCAChunk chunk = getChunk(x >> 4, z >> 4);
|
|
||||||
BlockState blockState = chunk.getBlockState(x, y, z);
|
|
||||||
|
|
||||||
if (chunk instanceof ChunkAnvil112) { // only use extensions if old format chunk (1.12) in the new format block-states are saved with extensions
|
|
||||||
List<BlockStateExtension> applicableExtensions = blockStateExtensions.getOrDefault(blockState.getFullId(), Collections.emptyList());
|
|
||||||
if (!applicableExtensions.isEmpty()) {
|
|
||||||
Vector3i pos = new Vector3i(x, y, z);
|
|
||||||
for (BlockStateExtension ext : applicableExtensions) {
|
|
||||||
blockState = ext.extend(this, pos, blockState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return blockState;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockProperties getBlockProperties(BlockState blockState) {
|
|
||||||
return blockPropertiesMapper.get(blockState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MCAChunk getChunkAtBlock(int x, int y, int z) {
|
public MCAChunk getChunkAtBlock(int x, int y, int z) {
|
||||||
|
@ -166,19 +97,19 @@ public class MCAWorld implements World {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MCAChunk getChunk(int x, int z) {
|
public MCAChunk getChunk(int x, int z) {
|
||||||
return getChunk(new Vector2i(x, z));
|
return getChunk(vec2i(x, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MCAChunk getChunk(Vector2i pos) {
|
private MCAChunk getChunk(Vector2i pos) {
|
||||||
return chunkCache.get(pos);
|
return chunkCache.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MCARegion getRegion(int x, int z) {
|
public MCARegion getRegion(int x, int z) {
|
||||||
return getRegion(new Vector2i(x, z));
|
return getRegion(vec2i(x, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MCARegion getRegion(Vector2i pos) {
|
private MCARegion getRegion(Vector2i pos) {
|
||||||
return regionCache.get(pos);
|
return regionCache.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,42 +195,10 @@ public class MCAWorld implements World {
|
||||||
public void cleanUpChunkCache() {
|
public void cleanUpChunkCache() {
|
||||||
chunkCache.cleanUp();
|
chunkCache.cleanUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockIdMapper getBlockIdMapper() {
|
|
||||||
return blockIdMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockPropertiesMapper getBlockPropertiesMapper() {
|
|
||||||
return blockPropertiesMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BiomeMapper getBiomeIdMapper() {
|
|
||||||
return biomeMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockIdMapper(BlockIdMapper blockIdMapper) {
|
|
||||||
this.blockIdMapper = blockIdMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockPropertiesMapper(BlockPropertiesMapper blockPropertiesMapper) {
|
|
||||||
this.blockPropertiesMapper = blockPropertiesMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBiomeMapper(BiomeMapper biomeMapper) {
|
|
||||||
this.biomeMapper = biomeMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getWorldFolder() {
|
public Path getWorldFolder() {
|
||||||
return worldFolder;
|
return worldFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getForgeBlockIdMapping(int id) {
|
|
||||||
return forgeBlockMappings.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MinecraftVersion getMinecraftVersion() {
|
|
||||||
return minecraftVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path getRegionFolder() {
|
private Path getRegionFolder() {
|
||||||
return worldFolder.resolve("region");
|
return worldFolder.resolve("region");
|
||||||
|
@ -309,12 +208,6 @@ public class MCAWorld implements World {
|
||||||
return getRegionFolder().resolve("r." + regionX + "." + regionZ + ".mca").toFile();
|
return getRegionFolder().resolve("r." + regionX + "." + regionZ + ".mca").toFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerBlockStateExtension(BlockStateExtension extension) {
|
|
||||||
for (String id : extension.getAffectedBlockIds()) {
|
|
||||||
this.blockStateExtensions.computeIfAbsent(id, t -> new ArrayList<>()).add(extension);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MCARegion loadRegion(Vector2i regionPos) {
|
private MCARegion loadRegion(Vector2i regionPos) {
|
||||||
return loadRegion(regionPos.getX(), regionPos.getY());
|
return loadRegion(regionPos.getX(), regionPos.getY());
|
||||||
}
|
}
|
||||||
|
@ -356,11 +249,11 @@ public class MCAWorld implements World {
|
||||||
return MCAChunk.empty();
|
return MCAChunk.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MCAWorld load(Path worldFolder, UUID uuid, MinecraftVersion version, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper) throws IOException {
|
public static MCAWorld load(Path worldFolder, UUID uuid) throws IOException {
|
||||||
return load(worldFolder, uuid, version, blockIdMapper, blockPropertiesMapper, biomeIdMapper, null, false);
|
return load(worldFolder, uuid, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MCAWorld load(Path worldFolder, UUID uuid, MinecraftVersion version, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper, String name, boolean ignoreMissingLightData) throws IOException {
|
public static MCAWorld load(Path worldFolder, UUID uuid, String name, boolean ignoreMissingLightData) throws IOException {
|
||||||
try {
|
try {
|
||||||
StringBuilder subDimensionName = new StringBuilder();
|
StringBuilder subDimensionName = new StringBuilder();
|
||||||
|
|
||||||
|
@ -392,37 +285,15 @@ public class MCAWorld implements World {
|
||||||
levelData.getInt("SpawnX"),
|
levelData.getInt("SpawnX"),
|
||||||
levelData.getInt("SpawnY"),
|
levelData.getInt("SpawnY"),
|
||||||
levelData.getInt("SpawnZ")
|
levelData.getInt("SpawnZ")
|
||||||
);
|
);
|
||||||
|
|
||||||
MCAWorld world = new MCAWorld(
|
return new MCAWorld(
|
||||||
worldFolder,
|
worldFolder,
|
||||||
uuid,
|
uuid,
|
||||||
version,
|
|
||||||
name,
|
name,
|
||||||
spawnPoint,
|
spawnPoint,
|
||||||
blockIdMapper,
|
|
||||||
blockPropertiesMapper,
|
|
||||||
biomeIdMapper,
|
|
||||||
ignoreMissingLightData
|
ignoreMissingLightData
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
|
||||||
CompoundTag fmlTag = level.getCompoundTag("FML");
|
|
||||||
if (fmlTag == null) fmlTag = level.getCompoundTag("fml");
|
|
||||||
|
|
||||||
ListTag<? extends Tag<?>> blockIdReg = fmlTag.getCompoundTag("Registries").getCompoundTag("minecraft:blocks").getListTag("ids");
|
|
||||||
for (Tag<?> tag : blockIdReg) {
|
|
||||||
if (tag instanceof CompoundTag) {
|
|
||||||
CompoundTag entry = (CompoundTag) tag;
|
|
||||||
String blockId = entry.getString("K");
|
|
||||||
int numeralId = entry.getInt("V");
|
|
||||||
|
|
||||||
world.forgeBlockMappings.put(numeralId, blockId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (NullPointerException ignore) {}
|
|
||||||
|
|
||||||
return world;
|
|
||||||
} catch (ClassCastException | NullPointerException ex) {
|
} catch (ClassCastException | NullPointerException ex) {
|
||||||
throw new IOException("Invaid level.dat format!", ex);
|
throw new IOException("Invaid level.dat format!", ex);
|
||||||
}
|
}
|
||||||
|
@ -437,4 +308,17 @@ public class MCAWorld implements World {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final int VEC_2I_CACHE_SIZE = 0x4000;
|
||||||
|
private static final int VEC_2I_CACHE_MASK = VEC_2I_CACHE_SIZE - 1;
|
||||||
|
private static final Vector2i[] VEC_2I_CACHE = new Vector2i[VEC_2I_CACHE_SIZE];
|
||||||
|
private static Vector2i vec2i(int x, int y) {
|
||||||
|
int cacheIndex = (x * 1456 ^ y * 948375892) & VEC_2I_CACHE_MASK;
|
||||||
|
Vector2i possibleMatch = VEC_2I_CACHE[cacheIndex];
|
||||||
|
|
||||||
|
if (possibleMatch != null && possibleMatch.getX() == x && possibleMatch.getY() == y)
|
||||||
|
return possibleMatch;
|
||||||
|
|
||||||
|
return VEC_2I_CACHE[cacheIndex] = new Vector2i(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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<String> getAffectedBlockIds();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.getBlockPropertiesMapper().get(block).isCulling();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class DoorExtension implements BlockStateExtension {
|
|
||||||
private final Set<String> affectedBlockIds;
|
|
||||||
|
|
||||||
public DoorExtension(MinecraftVersion version) {
|
|
||||||
if (version.isBefore(MinecraftVersion.THE_FLATTENING)) {
|
|
||||||
affectedBlockIds = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:wooden_door",
|
|
||||||
"minecraft:iron_door",
|
|
||||||
"minecraft:spruce_door",
|
|
||||||
"minecraft:birch_door",
|
|
||||||
"minecraft:jungle_door",
|
|
||||||
"minecraft:acacia_door",
|
|
||||||
"minecraft:dark_oak_door"
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
affectedBlockIds = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:oak_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;
|
|
||||||
|
|
||||||
boolean isLower = Objects.equals(state.getProperties().get("half"), "lower");
|
|
||||||
|
|
||||||
if (isLower) {
|
|
||||||
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<String, String> prop : otherDoor.getProperties().entrySet()) {
|
|
||||||
if (
|
|
||||||
!state.getProperties().containsKey(prop.getKey()) ||
|
|
||||||
(isLower && prop.getKey().equals("hinge")) ||
|
|
||||||
(isLower && prop.getKey().equals("powered")) ||
|
|
||||||
(!isLower && prop.getKey().equals("open")) ||
|
|
||||||
(!isLower && prop.getKey().equals("facing"))
|
|
||||||
) {
|
|
||||||
state = state.with(prop.getKey(), prop.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return affectedBlockIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.util.Direction;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class DoubleChestExtension implements BlockStateExtension {
|
|
||||||
|
|
||||||
private static final Set<String> AFFECTED_BLOCK_IDS = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:chest",
|
|
||||||
"minecraft:trapped_chest"
|
|
||||||
));
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
|
|
||||||
Direction dir = Direction.fromString(state.getProperties().getOrDefault("facing", "north"));
|
|
||||||
|
|
||||||
BlockState left = world.getBlockState(pos.add(dir.left().toVector()));
|
|
||||||
if (left.getFullId().equals(state.getFullId())) return state.with("type", "right");
|
|
||||||
|
|
||||||
BlockState right = world.getBlockState(pos.add(dir.right().toVector()));
|
|
||||||
if (right.getFullId().equals(state.getFullId())) return state.with("type", "left");
|
|
||||||
|
|
||||||
return state.with("type", "single");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return AFFECTED_BLOCK_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class DoublePlantExtension implements BlockStateExtension {
|
|
||||||
private final Set<String> affectedBlockIds;
|
|
||||||
|
|
||||||
public DoublePlantExtension(MinecraftVersion version) {
|
|
||||||
if (version.isBefore(MinecraftVersion.THE_FLATTENING)) {
|
|
||||||
affectedBlockIds = new HashSet<>(Collections.singletonList(
|
|
||||||
"minecraft:double_plant"
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
affectedBlockIds = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:sunflower",
|
|
||||||
"minecraft:lilac",
|
|
||||||
"minecraft:tall_grass",
|
|
||||||
"minecraft:large_fern",
|
|
||||||
"minecraft:rose_bush",
|
|
||||||
"minecraft:peony"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
|
|
||||||
if (Objects.equals(state.getProperties().get("half"), "upper")) {
|
|
||||||
BlockState otherPlant = world.getBlockState(pos.add(Direction.DOWN.toVector()));
|
|
||||||
|
|
||||||
return otherPlant.with("half", "upper");
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return affectedBlockIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.util.Direction;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class FireExtension implements BlockStateExtension {
|
|
||||||
|
|
||||||
private static final Set<String> AFFECTED_BLOCK_IDS = new HashSet<>(Collections.singletonList(
|
|
||||||
"minecraft:fire"
|
|
||||||
));
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
|
|
||||||
BlockState below = world.getBlockState(pos.add(0, -1, 0));
|
|
||||||
|
|
||||||
boolean isOnGround = world.getBlockPropertiesMapper().get(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.getBlockPropertiesMapper().get(neighbor).isCulling()));
|
|
||||||
} else {
|
|
||||||
state = state.with(dir.name().toLowerCase(), "false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return AFFECTED_BLOCK_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class GlassPaneConnectExtension extends ConnectSameOrFullBlockExtension {
|
|
||||||
|
|
||||||
private static final HashSet<String> AFFECTED_BLOCK_IDS = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:glass_pane",
|
|
||||||
"minecraft:white_stained_glass_pane",
|
|
||||||
"minecraft:orange_stained_glass_pane",
|
|
||||||
"minecraft:magenta_stained_glass_pane",
|
|
||||||
"minecraft:light_blue_white_stained_glass_pane",
|
|
||||||
"minecraft:yellow_stained_glass_pane",
|
|
||||||
"minecraft:lime_stained_glass_pane",
|
|
||||||
"minecraft:pink_stained_glass_pane",
|
|
||||||
"minecraft:gray_stained_glass_pane",
|
|
||||||
"minecraft:light_gray_stained_glass_pane",
|
|
||||||
"minecraft:cyan_stained_glass_pane",
|
|
||||||
"minecraft:purple_stained_glass_pane",
|
|
||||||
"minecraft:blue_stained_glass_pane",
|
|
||||||
"minecraft:green_stained_glass_pane",
|
|
||||||
"minecraft:red_stained_glass_pane",
|
|
||||||
"minecraft:black_stained_glass_pane",
|
|
||||||
"minecraft:iron_bars"
|
|
||||||
));
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return AFFECTED_BLOCK_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class NetherFenceConnectExtension extends ConnectSameOrFullBlockExtension {
|
|
||||||
|
|
||||||
private static final HashSet<String> AFFECTED_BLOCK_IDS = new HashSet<>(Collections.singletonList(
|
|
||||||
"minecraft:nether_brick_fence"
|
|
||||||
));
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return AFFECTED_BLOCK_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.util.Direction;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class RedstoneExtension implements BlockStateExtension {
|
|
||||||
|
|
||||||
private static final Set<String> AFFECTED_BLOCK_IDS = new HashSet<>(Collections.singletonList(
|
|
||||||
"minecraft:redstone_wire"
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
private static final Set<String> CONNECTIBLE = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:redstone_wire",
|
|
||||||
"minecraft:redstone_wall_torch",
|
|
||||||
"minecraft:redstone_torch",
|
|
||||||
"minecraft:stone_button",
|
|
||||||
"minecraft:oak_button",
|
|
||||||
"minecraft:stone_button",
|
|
||||||
"minecraft:lever",
|
|
||||||
"minecraft:stone_pressure_plate",
|
|
||||||
"minecraft:oak_pressure_plate",
|
|
||||||
"minecraft:light_weighted_pressure_plate",
|
|
||||||
"minecraft:heavy_weighted_pressure_plate"
|
|
||||||
));
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
|
|
||||||
BlockState up = world.getBlockState(pos.add(0, 1, 0));
|
|
||||||
boolean upBlocking = !up.equals(BlockState.AIR);
|
|
||||||
|
|
||||||
state = state
|
|
||||||
.with("north", connection(world, pos, upBlocking, Direction.NORTH))
|
|
||||||
.with("east", connection(world, pos, upBlocking, Direction.EAST))
|
|
||||||
.with("south", connection(world, pos, upBlocking, Direction.SOUTH))
|
|
||||||
.with("west", connection(world, pos, upBlocking, Direction.WEST));
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String connection(MCAWorld world, Vector3i pos, boolean upBlocking, Direction direction) {
|
|
||||||
Vector3i directionVector = direction.toVector();
|
|
||||||
|
|
||||||
BlockState next = world.getBlockState(pos.add(directionVector));
|
|
||||||
if (CONNECTIBLE.contains(next.getFullId())) return "side";
|
|
||||||
|
|
||||||
if (next.equals(BlockState.AIR)) {
|
|
||||||
BlockState nextdown = world.getBlockState(pos.add(directionVector.getX(), directionVector.getY() - 1, directionVector.getZ()));
|
|
||||||
if (nextdown.getFullId().equals("minecraft:redstone_wire")) return "side";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!upBlocking) {
|
|
||||||
BlockState nextup = world.getBlockState(pos.add(directionVector.getX(), directionVector.getY() + 1, directionVector.getZ()));
|
|
||||||
if (nextup.getFullId().equals("minecraft:redstone_wire")) return "up";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return AFFECTED_BLOCK_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class SnowyExtension implements BlockStateExtension {
|
|
||||||
|
|
||||||
private final Set<String> affectedBlockIds;
|
|
||||||
|
|
||||||
private final String snowLayerId;
|
|
||||||
private final String snowBlockId;
|
|
||||||
|
|
||||||
public SnowyExtension(MinecraftVersion version) {
|
|
||||||
if (version.isBefore(MinecraftVersion.THE_FLATTENING)) {
|
|
||||||
affectedBlockIds = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:grass",
|
|
||||||
"minecraft:mycelium"
|
|
||||||
));
|
|
||||||
snowLayerId = "minecraft:snow_layer";
|
|
||||||
snowBlockId = "minecraft:snow";
|
|
||||||
} else {
|
|
||||||
affectedBlockIds = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:grass_block",
|
|
||||||
"minecraft:podzol"
|
|
||||||
));
|
|
||||||
snowLayerId = "minecraft:snow";
|
|
||||||
snowBlockId = "minecraft:snow_block";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
|
|
||||||
BlockState above = world.getBlockState(pos.add(0, 1, 0));
|
|
||||||
|
|
||||||
if (above.getFullId().equals(snowLayerId) || above.getFullId().equals(snowBlockId)) {
|
|
||||||
return state.with("snowy", "true");
|
|
||||||
} else {
|
|
||||||
return state.with("snowy", "false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return affectedBlockIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.util.Direction;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class StairShapeExtension implements BlockStateExtension {
|
|
||||||
|
|
||||||
private static final Set<String> AFFECTED_BLOCK_IDS = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:oak_stairs",
|
|
||||||
"minecraft:cobblestone_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 == facing.left()){
|
|
||||||
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 == facing.left()){
|
|
||||||
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.getFullId());
|
|
||||||
}
|
|
||||||
|
|
||||||
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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return AFFECTED_BLOCK_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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.util.Direction;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class WallConnectExtension extends ConnectSameOrFullBlockExtension {
|
|
||||||
|
|
||||||
private static final HashSet<String> AFFECTED_BLOCK_IDS = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:cobblestone_wall",
|
|
||||||
"minecraft:mossy_cobblestone_wall"
|
|
||||||
));
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState extend(MCAWorld world, Vector3i pos, BlockState state) {
|
|
||||||
state = super.extend(world, pos, state);
|
|
||||||
|
|
||||||
if (
|
|
||||||
Objects.equals(state.getProperties().get("north"), state.getProperties().get("south")) &&
|
|
||||||
Objects.equals(state.getProperties().get("east"), state.getProperties().get("west")) &&
|
|
||||||
!Objects.equals(state.getProperties().get("north"), 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<String> getAffectedBlockIds() {
|
|
||||||
return AFFECTED_BLOCK_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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 de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class WoodenFenceConnectExtension extends ConnectSameOrFullBlockExtension {
|
|
||||||
|
|
||||||
private final Set<String> affectedBlockIds;
|
|
||||||
|
|
||||||
public WoodenFenceConnectExtension(MinecraftVersion version) {
|
|
||||||
if (version.isBefore(MinecraftVersion.THE_FLATTENING)) {
|
|
||||||
affectedBlockIds = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:fence",
|
|
||||||
"minecraft:spruce_fence",
|
|
||||||
"minecraft:birch_fence",
|
|
||||||
"minecraft:jungle_fence",
|
|
||||||
"minecraft:dark_oak_fence",
|
|
||||||
"minecraft:acacia_fence"
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
affectedBlockIds = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:oak_fence",
|
|
||||||
"minecraft:spruce_fence",
|
|
||||||
"minecraft:birch_fence",
|
|
||||||
"minecraft:jungle_fence",
|
|
||||||
"minecraft:dark_oak_fence",
|
|
||||||
"minecraft:acacia_fence"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
|
||||||
return affectedBlockIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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 de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
public interface BlockIdMapper {
|
|
||||||
|
|
||||||
BlockState get(int id, int meta);
|
|
||||||
|
|
||||||
BlockState get(String id, int numeralId, int meta);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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 de.bluecolored.bluemap.core.world.BlockProperties;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface BlockPropertiesMapper {
|
|
||||||
|
|
||||||
BlockProperties get(BlockState blockState);
|
|
||||||
|
|
||||||
}
|
|
|
@ -28,7 +28,6 @@ import com.flowpowered.math.imaginary.Quaternionf;
|
||||||
import com.flowpowered.math.matrix.Matrix3f;
|
import com.flowpowered.math.matrix.Matrix3f;
|
||||||
import com.flowpowered.math.vector.Vector2f;
|
import com.flowpowered.math.vector.Vector2f;
|
||||||
import com.flowpowered.math.vector.Vector3f;
|
import com.flowpowered.math.vector.Vector3f;
|
||||||
import de.bluecolored.bluemap.core.util.MathUtils;
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class Face {
|
public class Face {
|
||||||
|
@ -51,7 +50,7 @@ public class Face {
|
||||||
|
|
||||||
this.materialIndex = materialIndex;
|
this.materialIndex = materialIndex;
|
||||||
|
|
||||||
this.n1 = getFaceNormal();
|
this.n1 = calculateSurfaceNormal(new VectorM3f(0, 0, 0));
|
||||||
this.n2 = new VectorM3f(n1);
|
this.n2 = new VectorM3f(n1);
|
||||||
this.n3 = new VectorM3f(n1);
|
this.n3 = new VectorM3f(n1);
|
||||||
this.normalizedNormals = true;
|
this.normalizedNormals = true;
|
||||||
|
@ -202,10 +201,6 @@ public class Face {
|
||||||
this.materialIndex = materialIndex;
|
this.materialIndex = materialIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private VectorM3f getFaceNormal() {
|
|
||||||
return MathUtils.getSurfaceNormal(p1, p2, p3);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void normalizeNormals() {
|
private void normalizeNormals() {
|
||||||
if (normalizedNormals) return;
|
if (normalizedNormals) return;
|
||||||
|
|
||||||
|
@ -216,4 +211,31 @@ public class Face {
|
||||||
normalizedNormals = true;
|
normalizedNormals = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VectorM3f calculateSurfaceNormal(
|
||||||
|
VectorM3f target
|
||||||
|
){
|
||||||
|
double
|
||||||
|
p1x = p1.x, p1y = p1.y, p1z = p1.z,
|
||||||
|
p2x = p2.x, p2y = p2.y, p2z = p2.z,
|
||||||
|
p3x = p3.x, p3y = p3.y, p3z = p3.z;
|
||||||
|
|
||||||
|
p2x -= p1x; p2y -= p1y; p2z -= p1z;
|
||||||
|
p3x -= p1x; p3y -= p1y; p3z -= p1z;
|
||||||
|
|
||||||
|
p1x = p2y * p3z - p2z * p3y;
|
||||||
|
p1y = p2z * p3x - p2x * p3z;
|
||||||
|
p1z = p2x * p3y - p2y * p3x;
|
||||||
|
|
||||||
|
double length = Math.sqrt(p1x * p1x + p1y * p1y + p1z * p1z);
|
||||||
|
p1x /= length;
|
||||||
|
p1y /= length;
|
||||||
|
p1z /= length;
|
||||||
|
|
||||||
|
target.x = (float) p1x;
|
||||||
|
target.y = (float) p1y;
|
||||||
|
target.z = (float) p1z;
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,52 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.mca.mapping;
|
package de.bluecolored.bluemap.core.resourcepack;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
import de.bluecolored.bluemap.core.world.Biome;
|
||||||
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
|
|
||||||
@FunctionalInterface
|
import java.util.Map.Entry;
|
||||||
public interface BiomeMapper {
|
|
||||||
|
public class BiomeConfig {
|
||||||
|
|
||||||
|
private Biome[] biomes;
|
||||||
|
|
||||||
|
public BiomeConfig() {
|
||||||
|
biomes = new Biome[10];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(ConfigurationNode node) {
|
||||||
|
for (Entry<Object, ? extends ConfigurationNode> e : node.childrenMap().entrySet()){
|
||||||
|
String id = e.getKey().toString();
|
||||||
|
Biome biome = Biome.create(id, e.getValue());
|
||||||
|
|
||||||
|
int numeralId = biome.getNumeralId();
|
||||||
|
ensureAvailability(numeralId);
|
||||||
|
biomes[numeralId] = biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Biome getBiome(int id) {
|
||||||
|
if (id < biomes.length) {
|
||||||
|
Biome biome = biomes[id];
|
||||||
|
return biome != null ? biome : Biome.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Biome.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureAvailability(int id) {
|
||||||
|
if (id >= biomes.length) {
|
||||||
|
int newSize = biomes.length;
|
||||||
|
do {
|
||||||
|
newSize = (int) (newSize * 1.5) + 1;
|
||||||
|
} while (id >= newSize);
|
||||||
|
|
||||||
|
Biome[] newArray = new Biome[newSize];
|
||||||
|
System.arraycopy(biomes, 0, newArray, 0, biomes.length);
|
||||||
|
biomes = newArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Biome get(int id);
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ import de.bluecolored.bluemap.core.debug.DebugDump;
|
||||||
import de.bluecolored.bluemap.core.util.ConfigUtils;
|
import de.bluecolored.bluemap.core.util.ConfigUtils;
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
import de.bluecolored.bluemap.core.world.Biome;
|
import de.bluecolored.bluemap.core.world.Biome;
|
||||||
import de.bluecolored.bluemap.core.world.Block;
|
import de.bluecolored.bluemap.core.world.BlockNeighborhood;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
@ -40,21 +40,16 @@ import java.util.Map.Entry;
|
||||||
@DebugDump
|
@DebugDump
|
||||||
public class BlockColorCalculatorFactory {
|
public class BlockColorCalculatorFactory {
|
||||||
|
|
||||||
private BufferedImage foliageMap;
|
private final int[] foliageMap = new int[65536];
|
||||||
private BufferedImage grassMap;
|
private final int[] grassMap = new int[65536];
|
||||||
|
|
||||||
private final Map<String, ColorFunction> blockColorMap;
|
private final Map<String, ColorFunction> blockColorMap;
|
||||||
|
|
||||||
public BlockColorCalculatorFactory(BufferedImage foliageMap, BufferedImage grassMap) {
|
public BlockColorCalculatorFactory() {
|
||||||
this.foliageMap = foliageMap;
|
|
||||||
this.grassMap = grassMap;
|
|
||||||
|
|
||||||
this.blockColorMap = new HashMap<>();
|
this.blockColorMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadColorConfig(ConfigurationNode colorConfig) {
|
public void load(ConfigurationNode colorConfig) {
|
||||||
blockColorMap.clear();
|
|
||||||
|
|
||||||
for (Entry<Object, ? extends ConfigurationNode> entry : colorConfig.childrenMap().entrySet()){
|
for (Entry<Object, ? extends ConfigurationNode> entry : colorConfig.childrenMap().entrySet()){
|
||||||
String key = entry.getKey().toString();
|
String key = entry.getKey().toString();
|
||||||
String value = entry.getValue().getString("");
|
String value = entry.getValue().getString("");
|
||||||
|
@ -85,19 +80,11 @@ public class BlockColorCalculatorFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFoliageMap(BufferedImage foliageMap) {
|
public void setFoliageMap(BufferedImage foliageMap) {
|
||||||
this.foliageMap = foliageMap;
|
foliageMap.getRGB(0, 0, 256, 256, this.foliageMap, 0, 256);
|
||||||
}
|
|
||||||
|
|
||||||
public BufferedImage getFoliageMap() {
|
|
||||||
return foliageMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGrassMap(BufferedImage grassMap) {
|
public void setGrassMap(BufferedImage grassMap) {
|
||||||
this.grassMap = grassMap;
|
grassMap.getRGB(0, 0, 256, 256, this.grassMap, 0, 256);
|
||||||
}
|
|
||||||
|
|
||||||
public BufferedImage getGrassMap() {
|
|
||||||
return grassMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockColorCalculator createCalculator() {
|
public BlockColorCalculator createCalculator() {
|
||||||
|
@ -106,14 +93,14 @@ public class BlockColorCalculatorFactory {
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
private interface ColorFunction {
|
private interface ColorFunction {
|
||||||
Color invoke(BlockColorCalculator calculator, Block block, Color target);
|
Color invoke(BlockColorCalculator calculator, BlockNeighborhood block, Color target);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlockColorCalculator {
|
public class BlockColorCalculator {
|
||||||
|
|
||||||
private final Color tempColor = new Color();
|
private final Color tempColor = new Color();
|
||||||
|
|
||||||
public Color getBlockColor(Block block, Color target) {
|
public Color getBlockColor(BlockNeighborhood block, Color target) {
|
||||||
String blockId = block.getBlockState().getFullId();
|
String blockId = block.getBlockState().getFullId();
|
||||||
|
|
||||||
ColorFunction colorFunction = blockColorMap.get(blockId);
|
ColorFunction colorFunction = blockColorMap.get(blockId);
|
||||||
|
@ -123,7 +110,7 @@ public class BlockColorCalculatorFactory {
|
||||||
return colorFunction.invoke(this, block, target);
|
return colorFunction.invoke(this, block, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getRedstoneColor(Block block, Color target) {
|
public Color getRedstoneColor(BlockNeighborhood block, Color target) {
|
||||||
String powerString = block.getBlockState().getProperties().get("power");
|
String powerString = block.getBlockState().getProperties().get("power");
|
||||||
|
|
||||||
int power = 15;
|
int power = 15;
|
||||||
|
@ -137,25 +124,23 @@ public class BlockColorCalculatorFactory {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getWaterAverageColor(Block block, Color target) {
|
public Color getWaterAverageColor(BlockNeighborhood block, Color target) {
|
||||||
target.set(0, 0, 0, 0, true);
|
target.set(0, 0, 0, 0, true);
|
||||||
|
|
||||||
int x, y, z,
|
int x, y, z,
|
||||||
minX = block.getX() - 2,
|
minX = - 2,
|
||||||
maxX = block.getX() + 2,
|
maxX = + 2,
|
||||||
minY = block.getY() - 1,
|
minY = - 1,
|
||||||
maxY = block.getY() + 1,
|
maxY = + 1,
|
||||||
minZ = block.getZ() - 2,
|
minZ = - 2,
|
||||||
maxZ = block.getZ() + 2;
|
maxZ = + 2;
|
||||||
|
|
||||||
|
Biome biome;
|
||||||
for (x = minX; x <= maxX; x++) {
|
for (x = minX; x <= maxX; x++) {
|
||||||
for (y = minY; y <= maxY; y++) {
|
for (y = minY; y <= maxY; y++) {
|
||||||
for (z = minZ; z <= maxZ; z++) {
|
for (z = minZ; z <= maxZ; z++) {
|
||||||
target.add(block
|
biome = block.getNeighborBlock(x, y, z).getBiome();
|
||||||
.getWorld()
|
target.add(biome.getWaterColor());
|
||||||
.getBiome(x, y, z)
|
|
||||||
.getWaterColor()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,28 +148,23 @@ public class BlockColorCalculatorFactory {
|
||||||
return target.flatten();
|
return target.flatten();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getFoliageAverageColor(Block block, Color target) {
|
public Color getFoliageAverageColor(BlockNeighborhood block, Color target) {
|
||||||
target.set(0, 0, 0, 0, true);
|
target.set(0, 0, 0, 0, true);
|
||||||
|
|
||||||
int x, y, z,
|
int x, y, z,
|
||||||
minX = block.getX() - 2,
|
minX = - 2,
|
||||||
maxX = block.getX() + 2,
|
maxX = + 2,
|
||||||
minY = block.getY() - 1,
|
minY = - 1,
|
||||||
maxY = block.getY() + 1,
|
maxY = + 1,
|
||||||
minZ = block.getZ() - 2,
|
minZ = - 2,
|
||||||
maxZ = block.getZ() + 2;
|
maxZ = + 2;
|
||||||
|
|
||||||
int seaLevel = block.getWorld().getSeaLevel();
|
|
||||||
int blocksAboveSeaLevel;
|
|
||||||
Biome biome;
|
Biome biome;
|
||||||
|
|
||||||
for (y = minY; y <= maxY; y++) {
|
for (y = minY; y <= maxY; y++) {
|
||||||
blocksAboveSeaLevel = Math.max(block.getY() - seaLevel, 0);
|
|
||||||
|
|
||||||
for (x = minX; x <= maxX; x++) {
|
for (x = minX; x <= maxX; x++) {
|
||||||
for (z = minZ; z <= maxZ; z++) {
|
for (z = minZ; z <= maxZ; z++) {
|
||||||
biome = block.getWorld().getBiome(x, y, z);
|
biome = block.getNeighborBlock(x, y, z).getBiome();
|
||||||
target.add(getFoliageColor(biome, blocksAboveSeaLevel, tempColor));
|
target.add(getFoliageColor(biome, tempColor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,33 +172,28 @@ public class BlockColorCalculatorFactory {
|
||||||
return target.flatten();
|
return target.flatten();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getFoliageColor(Biome biome, int blocksAboveSeaLevel, Color target) {
|
public Color getFoliageColor(Biome biome, Color target) {
|
||||||
getColorFromMap(biome, blocksAboveSeaLevel, foliageMap, target);
|
getColorFromMap(biome, foliageMap, 4764952, target);
|
||||||
return target.overlay(biome.getOverlayFoliageColor());
|
return target.overlay(biome.getOverlayFoliageColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getGrassAverageColor(Block block, Color target) {
|
public Color getGrassAverageColor(BlockNeighborhood block, Color target) {
|
||||||
target.set(0, 0, 0, 0, true);
|
target.set(0, 0, 0, 0, true);
|
||||||
|
|
||||||
int x, y, z,
|
int x, y, z,
|
||||||
minX = block.getX() - 2,
|
minX = - 2,
|
||||||
maxX = block.getX() + 2,
|
maxX = + 2,
|
||||||
minY = block.getY() - 1,
|
minY = - 1,
|
||||||
maxY = block.getY() + 1,
|
maxY = + 1,
|
||||||
minZ = block.getZ() - 2,
|
minZ = - 2,
|
||||||
maxZ = block.getZ() + 2;
|
maxZ = + 2;
|
||||||
|
|
||||||
int seaLevel = block.getWorld().getSeaLevel();
|
|
||||||
int blocksAboveSeaLevel;
|
|
||||||
Biome biome;
|
Biome biome;
|
||||||
|
|
||||||
for (y = minY; y <= maxY; y++) {
|
for (y = minY; y <= maxY; y++) {
|
||||||
blocksAboveSeaLevel = Math.max(block.getY() - seaLevel, 0);
|
|
||||||
|
|
||||||
for (x = minX; x <= maxX; x++) {
|
for (x = minX; x <= maxX; x++) {
|
||||||
for (z = minZ; z <= maxZ; z++) {
|
for (z = minZ; z <= maxZ; z++) {
|
||||||
biome = block.getWorld().getBiome(x, y, z);
|
biome = block.getNeighborBlock(x, y, z).getBiome();
|
||||||
target.add(getGrassColor(biome, blocksAboveSeaLevel, tempColor));
|
target.add(getGrassColor(biome, tempColor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,24 +201,22 @@ public class BlockColorCalculatorFactory {
|
||||||
return target.flatten();
|
return target.flatten();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getGrassColor(Biome biome, int blocksAboveSeaLevel, Color target) {
|
public Color getGrassColor(Biome biome, Color target) {
|
||||||
getColorFromMap(biome, blocksAboveSeaLevel, grassMap, target);
|
getColorFromMap(biome, grassMap, 0xff52952f, target);
|
||||||
return target.overlay(biome.getOverlayGrassColor());
|
return target.overlay(biome.getOverlayGrassColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getColorFromMap(Biome biome, int blocksAboveSeaLevel, BufferedImage map, Color target) {
|
private void getColorFromMap(Biome biome, int[] colorMap, int defaultColor, Color target) {
|
||||||
float adjTemp = (float) GenericMath.clamp(biome.getTemp() - (0.00166667 * blocksAboveSeaLevel), 0, 1);
|
double temperature = GenericMath.clamp(biome.getTemp(), 0, 1);
|
||||||
float adjHumidity = (float) GenericMath.clamp(biome.getHumidity(), 0, 1) * adjTemp;
|
double humidity = GenericMath.clamp(biome.getHumidity(), 0, 1) * temperature;
|
||||||
|
|
||||||
int x = (int) ((1 - adjTemp) * map.getWidth());
|
int x = (int) ((1.0 - temperature) * 255.0);
|
||||||
int y = (int) ((1 - adjHumidity) * map.getHeight());
|
int y = (int) ((1.0 - humidity) * 255.0);
|
||||||
|
|
||||||
int cValue = map.getRGB(
|
int index = y << 8 | x;
|
||||||
GenericMath.clamp(x, 0, map.getWidth() - 1),
|
int color = index >= colorMap.length ? defaultColor : colorMap[index];
|
||||||
GenericMath.clamp(y, 0, map.getHeight() - 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
target.set(cValue);
|
target.set(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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 de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import de.bluecolored.bluemap.core.world.BlockProperties;
|
||||||
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class BlockPropertiesConfig {
|
||||||
|
|
||||||
|
private final Map<String, List<BlockStateMapping<BlockProperties>>> mappings;
|
||||||
|
|
||||||
|
public BlockPropertiesConfig() {
|
||||||
|
mappings = new ConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(ConfigurationNode node) {
|
||||||
|
for (Entry<Object, ? extends ConfigurationNode> e : node.childrenMap().entrySet()){
|
||||||
|
String key = e.getKey().toString();
|
||||||
|
try {
|
||||||
|
BlockState bsKey = BlockState.fromString(key);
|
||||||
|
BlockProperties.Builder bsValueBuilder = BlockProperties.builder();
|
||||||
|
|
||||||
|
readBool(e.getValue().node("culling"), bsValueBuilder::culling);
|
||||||
|
readBool(e.getValue().node("occluding"), bsValueBuilder::occluding);
|
||||||
|
readBool(e.getValue().node("alwaysWaterlogged"), bsValueBuilder::alwaysWaterlogged);
|
||||||
|
readBool(e.getValue().node("randomOffset"), bsValueBuilder::randomOffset);
|
||||||
|
|
||||||
|
BlockStateMapping<BlockProperties> mapping = new BlockStateMapping<>(bsKey, bsValueBuilder.build());
|
||||||
|
mappings.computeIfAbsent(bsKey.getFullId(), k -> new LinkedList<>()).add(0, mapping);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
Logger.global.logWarning("Loading BlockPropertiesConfig: Failed to parse BlockState from key '" + key + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readBool(ConfigurationNode node, Consumer<Boolean> target) {
|
||||||
|
if (!node.virtual()) target.accept(node.getBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockProperties getBlockProperties(BlockState from){
|
||||||
|
for (BlockStateMapping<BlockProperties> bm : mappings.getOrDefault(from.getFullId(), Collections.emptyList())){
|
||||||
|
if (bm.fitsTo(from)){
|
||||||
|
return bm.getMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlockProperties.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,12 +22,12 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.config;
|
package de.bluecolored.bluemap.core.resourcepack;
|
||||||
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
class BlockStateMapping<T> {
|
class BlockStateMapping<T> {
|
||||||
private BlockState blockState;
|
private BlockState blockState;
|
||||||
private T mapping;
|
private T mapping;
|
||||||
|
@ -59,5 +59,5 @@ class BlockStateMapping<T> {
|
||||||
public T getMapping(){
|
public T getMapping(){
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -24,83 +24,64 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
import de.bluecolored.bluemap.core.debug.DebugDump;
|
import de.bluecolored.bluemap.core.debug.DebugDump;
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.BlockStateResource.Builder;
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.BlockModelResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.TransformedBlockModelResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockstate.BlockStateResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockstate.BlockStateResource.Builder;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.BluemapAssetOverrideFileAccess;
|
import de.bluecolored.bluemap.core.resourcepack.fileaccess.BluemapAssetOverrideFileAccess;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.CaseInsensitiveFileAccess;
|
import de.bluecolored.bluemap.core.resourcepack.fileaccess.CaseInsensitiveFileAccess;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.CombinedFileAccess;
|
import de.bluecolored.bluemap.core.resourcepack.fileaccess.CombinedFileAccess;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.texture.Texture;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.texture.TextureGallery;
|
||||||
|
import de.bluecolored.bluemap.core.util.Tristate;
|
||||||
|
import de.bluecolored.bluemap.core.world.Biome;
|
||||||
|
import de.bluecolored.bluemap.core.world.BlockProperties;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
import org.apache.commons.io.output.ByteArrayOutputStream;
|
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||||
|
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents all resources (BlockStates / BlockModels and Textures) that are loaded and used to generate map-models.
|
* Represents all resources (BlockStates / BlockModels and Textures) that are loaded and used to generate map-models.
|
||||||
*/
|
*/
|
||||||
@DebugDump
|
@DebugDump
|
||||||
public class ResourcePack {
|
public class ResourcePack {
|
||||||
|
|
||||||
private static final String[] CONFIG_FILES = {
|
|
||||||
"blockColors.json",
|
|
||||||
"blockIds.json",
|
|
||||||
"blockProperties.json",
|
|
||||||
"biomes.json"
|
|
||||||
};
|
|
||||||
|
|
||||||
private final MinecraftVersion minecraftVersion;
|
|
||||||
|
|
||||||
protected final Map<String, BlockStateResource> blockStateResources;
|
|
||||||
protected final Map<String, BlockModelResource> blockModelResources;
|
|
||||||
protected final TextureGallery textures;
|
|
||||||
|
|
||||||
private final BlockColorCalculatorFactory blockColorCalculatorFactory;
|
|
||||||
|
|
||||||
private final Map<String, List<Resource>> configs;
|
|
||||||
|
|
||||||
private BufferedImage foliageMap;
|
private final Map<String, BlockStateResource> blockStateResources;
|
||||||
private BufferedImage grassMap;
|
private final Map<String, BlockModelResource> blockModelResources;
|
||||||
|
private final TextureGallery textures;
|
||||||
public ResourcePack(MinecraftVersion minecraftVersion) {
|
|
||||||
this.minecraftVersion = minecraftVersion;
|
private final BlockPropertiesConfig blockPropertiesConfig;
|
||||||
|
private final BiomeConfig biomeConfig;
|
||||||
|
private final BlockColorCalculatorFactory blockColorCalculatorFactory;
|
||||||
|
|
||||||
|
private final LoadingCache<BlockState, BlockProperties> blockPropertiesCache;
|
||||||
|
|
||||||
|
public ResourcePack() {
|
||||||
blockStateResources = new HashMap<>();
|
blockStateResources = new HashMap<>();
|
||||||
blockModelResources = new HashMap<>();
|
blockModelResources = new HashMap<>();
|
||||||
textures = new TextureGallery();
|
textures = new TextureGallery();
|
||||||
foliageMap = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
|
|
||||||
foliageMap.setRGB(0, 0, 0xFF00FF00);
|
blockPropertiesConfig = new BlockPropertiesConfig();
|
||||||
grassMap = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
|
biomeConfig = new BiomeConfig();
|
||||||
grassMap.setRGB(0, 0, 0xFF00FF00);
|
blockColorCalculatorFactory = new BlockColorCalculatorFactory();
|
||||||
blockColorCalculatorFactory = new BlockColorCalculatorFactory(foliageMap, grassMap);
|
|
||||||
configs = new HashMap<>();
|
blockPropertiesCache = Caffeine.newBuilder()
|
||||||
}
|
.executor(BlueMap.THREAD_POOL)
|
||||||
|
.maximumSize(10000)
|
||||||
/**
|
.build(this::getBlockPropertiesNoCache);
|
||||||
* Returns all config-files found in the namespaces of the ResourcePack with that filename
|
|
||||||
*/
|
|
||||||
public Collection<Resource> getConfigAdditions(String configFileName){
|
|
||||||
return configs.getOrDefault(configFileName, Collections.emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link TextureGallery#loadTextureFile(File)}
|
|
||||||
* @see TextureGallery#loadTextureFile(File)
|
|
||||||
*/
|
|
||||||
public void loadTextureFile(File file) throws IOException, ParseResourceException {
|
|
||||||
textures.loadTextureFile(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link TextureGallery#saveTextureFile(File)}
|
|
||||||
* @see TextureGallery#saveTextureFile(File)
|
|
||||||
*/
|
|
||||||
public void saveTextureFile(File file) throws IOException {
|
|
||||||
textures.saveTextureFile(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,37 +140,61 @@ public class ResourcePack {
|
||||||
String filename = FileAccess.getFileName(blockstateFile);
|
String filename = FileAccess.getFileName(blockstateFile);
|
||||||
if (!filename.endsWith(".json")) continue;
|
if (!filename.endsWith(".json")) continue;
|
||||||
|
|
||||||
|
String jsonFileName = filename.substring(0, filename.length() - 5);
|
||||||
try {
|
try {
|
||||||
blockStateResources.put(namespace + ":" + filename.substring(0, filename.length() - 5), builder.build(blockstateFile));
|
blockStateResources.put(namespace + ":" + jsonFileName, builder.build(blockstateFile));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.global.logError("Failed to load blockstate: " + namespace + ":" + filename.substring(0, filename.length() - 5), ex);
|
Logger.global.logError("Failed to load blockstate: " + namespace + ":" + jsonFileName, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//load configs
|
//load biomes
|
||||||
for (String configName : CONFIG_FILES) {
|
try {
|
||||||
try {
|
GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
|
||||||
Resource config = new Resource(sourcesAccess.readFile(
|
.source(() -> new BufferedReader(new InputStreamReader(sourcesAccess.readFile(
|
||||||
"assets/" + namespace + "/" + configName));
|
"assets/" + namespace + "/biomes.json"))))
|
||||||
configs.computeIfAbsent(configName, t -> new ArrayList<>()).add(config);
|
.build();
|
||||||
} catch (FileNotFoundException ignore) {
|
biomeConfig.load(loader.load());
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.global.logError("Failed to load config for " + namespace + ": " + configName, ex);
|
Logger.global.logError("Failed to load biomes.conf from: " + namespace, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//load block properties
|
||||||
|
try {
|
||||||
|
GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
|
||||||
|
.source(() -> new BufferedReader(new InputStreamReader(sourcesAccess.readFile(
|
||||||
|
"assets/" + namespace + "/blockProperties.json"))))
|
||||||
|
.build();
|
||||||
|
blockPropertiesConfig.load(loader.load());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logError("Failed to load biomes.conf from: " + namespace, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//load block colors
|
||||||
|
try {
|
||||||
|
GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
|
||||||
|
.source(() -> new BufferedReader(new InputStreamReader(sourcesAccess.readFile(
|
||||||
|
"assets/" + namespace + "/blockColors.json"))))
|
||||||
|
.build();
|
||||||
|
blockColorCalculatorFactory.load(loader.load());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logError("Failed to load biomes.conf from: " + namespace, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
foliageMap = ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/foliage.png"));
|
blockColorCalculatorFactory.setFoliageMap(
|
||||||
blockColorCalculatorFactory.setFoliageMap(foliageMap);
|
ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/foliage.png"))
|
||||||
} catch (IOException ex) {
|
);
|
||||||
|
} catch (IOException | ArrayIndexOutOfBoundsException ex) {
|
||||||
Logger.global.logError("Failed to load foliagemap!", ex);
|
Logger.global.logError("Failed to load foliagemap!", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
grassMap = ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/grass.png"));
|
blockColorCalculatorFactory.setGrassMap(
|
||||||
blockColorCalculatorFactory.setGrassMap(grassMap);
|
ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/grass.png"))
|
||||||
} catch (IOException ex) {
|
);
|
||||||
|
} catch (IOException | ArrayIndexOutOfBoundsException ex) {
|
||||||
Logger.global.logError("Failed to load grassmap!", ex);
|
Logger.global.logError("Failed to load grassmap!", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +202,22 @@ public class ResourcePack {
|
||||||
Logger.global.logError("Failed to close FileAccess!", ex);
|
Logger.global.logError("Failed to close FileAccess!", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link TextureGallery#loadTextureFile(File)}
|
||||||
|
* @see TextureGallery#loadTextureFile(File)
|
||||||
|
*/
|
||||||
|
public void loadTextureFile(File file) throws IOException, ParseResourceException {
|
||||||
|
textures.loadTextureFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link TextureGallery#saveTextureFile(File)}
|
||||||
|
* @see TextureGallery#saveTextureFile(File)
|
||||||
|
*/
|
||||||
|
public void saveTextureFile(File file) throws IOException {
|
||||||
|
textures.saveTextureFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link BlockStateResource} for the given {@link BlockState} if found.
|
* Returns a {@link BlockStateResource} for the given {@link BlockState} if found.
|
||||||
|
@ -209,16 +230,48 @@ public class ResourcePack {
|
||||||
if (resource == null) throw new NoSuchResourceException("No resource for blockstate: " + state.getFullId());
|
if (resource == null) throw new NoSuchResourceException("No resource for blockstate: " + state.getFullId());
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockProperties getBlockProperties(BlockState state) {
|
||||||
|
return blockPropertiesCache.get(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockProperties getBlockPropertiesNoCache(BlockState state) {
|
||||||
|
BlockProperties.Builder props = blockPropertiesConfig.getBlockProperties(state).toBuilder();
|
||||||
|
|
||||||
|
if (props.isOccluding() == Tristate.UNDEFINED || props.isCulling() == Tristate.UNDEFINED) {
|
||||||
|
try {
|
||||||
|
BlockStateResource resource = getBlockStateResource(state);
|
||||||
|
for (TransformedBlockModelResource bmr : resource.getModels(state, new ArrayList<>())) {
|
||||||
|
if (props.isOccluding() == Tristate.UNDEFINED) props.occluding(bmr.getModel().isOccluding());
|
||||||
|
if (props.isCulling() == Tristate.UNDEFINED) props.culling(bmr.getModel().isCulling());
|
||||||
|
}
|
||||||
|
} catch (NoSuchResourceException ignore) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Biome getBiome(int id) {
|
||||||
|
return biomeConfig.getBiome(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, BlockStateResource> getBlockStateResources() {
|
||||||
|
return blockStateResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, BlockModelResource> getBlockModelResources() {
|
||||||
|
return blockModelResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureGallery getTextures() {
|
||||||
|
return textures;
|
||||||
|
}
|
||||||
|
|
||||||
public BlockColorCalculatorFactory getBlockColorCalculatorFactory() {
|
public BlockColorCalculatorFactory getBlockColorCalculatorFactory() {
|
||||||
return blockColorCalculatorFactory;
|
return blockColorCalculatorFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinecraftVersion getMinecraftVersion() {
|
public static String namespacedToAbsoluteResourcePath(String namespacedPath, String resourceTypeFolder) {
|
||||||
return minecraftVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static String namespacedToAbsoluteResourcePath(String namespacedPath, String resourceTypeFolder) {
|
|
||||||
String path = namespacedPath;
|
String path = namespacedPath;
|
||||||
|
|
||||||
resourceTypeFolder = FileAccess.normalize(resourceTypeFolder);
|
resourceTypeFolder = FileAccess.normalize(resourceTypeFolder);
|
||||||
|
@ -246,7 +299,7 @@ public class ResourcePack {
|
||||||
|
|
||||||
private final byte[] data;
|
private final byte[] data;
|
||||||
|
|
||||||
public Resource(InputStream data) throws FileNotFoundException, IOException {
|
public Resource(InputStream data) throws IOException {
|
||||||
try (ByteArrayOutputStream bout = new ByteArrayOutputStream()) {
|
try (ByteArrayOutputStream bout = new ByteArrayOutputStream()) {
|
||||||
bout.write(data);
|
bout.write(data);
|
||||||
this.data = bout.toByteArray();
|
this.data = bout.toByteArray();
|
||||||
|
|
|
@ -22,13 +22,16 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack.blockmodel;
|
||||||
|
|
||||||
import com.flowpowered.math.TrigMath;
|
import com.flowpowered.math.TrigMath;
|
||||||
import com.flowpowered.math.vector.Vector3f;
|
import com.flowpowered.math.vector.Vector3f;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import com.flowpowered.math.vector.Vector4f;
|
import com.flowpowered.math.vector.Vector4f;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.BlockModelResource.Element.Face;
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.texture.Texture;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.BlockModelResource.Element.Face;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
import de.bluecolored.bluemap.core.util.Direction;
|
||||||
import de.bluecolored.bluemap.core.util.math.Axis;
|
import de.bluecolored.bluemap.core.util.math.Axis;
|
||||||
|
@ -45,13 +48,13 @@ public class BlockModelResource {
|
||||||
private static final double FIT_TO_BLOCK_SCALE_MULTIPLIER = 2 - Math.sqrt(2);
|
private static final double FIT_TO_BLOCK_SCALE_MULTIPLIER = 2 - Math.sqrt(2);
|
||||||
|
|
||||||
private ModelType modelType = ModelType.NORMAL;
|
private ModelType modelType = ModelType.NORMAL;
|
||||||
|
|
||||||
private boolean culling = false;
|
private boolean culling = false;
|
||||||
private boolean occluding = false;
|
private boolean occluding = false;
|
||||||
|
|
||||||
private boolean ambientOcclusion = true;
|
private final boolean ambientOcclusion = true; //TODO: wat?
|
||||||
private Collection<Element> elements = new ArrayList<>();
|
private final Collection<Element> elements = new ArrayList<>();
|
||||||
private Map<String, Texture> textures = new HashMap<>();
|
private final Map<String, Texture> textures = new HashMap<>();
|
||||||
|
|
||||||
private BlockModelResource() {}
|
private BlockModelResource() {}
|
||||||
|
|
||||||
|
@ -477,9 +480,9 @@ public class BlockModelResource {
|
||||||
|
|
||||||
Texture texture;
|
Texture texture;
|
||||||
try {
|
try {
|
||||||
texture = resourcePack.textures.get(path);
|
texture = resourcePack.getTextures().get(path);
|
||||||
} catch (NoSuchElementException ex) {
|
} catch (NoSuchElementException ex) {
|
||||||
texture = resourcePack.textures.loadTexture(sourcesAccess, path);
|
texture = resourcePack.getTextures().loadTexture(sourcesAccess, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
|
@ -22,7 +22,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack.blockmodel;
|
||||||
|
|
||||||
public enum ModelType {
|
public enum ModelType {
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack.blockmodel;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2f;
|
import com.flowpowered.math.vector.Vector2f;
|
||||||
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
|
@ -22,19 +22,20 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack.blockstate;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2f;
|
import com.flowpowered.math.vector.Vector2f;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.PropertyCondition.All;
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.BlockModelResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.TransformedBlockModelResource;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockstate.PropertyCondition.All;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
||||||
import de.bluecolored.bluemap.core.util.MathUtils;
|
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -46,8 +47,6 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
public class BlockStateResource {
|
public class BlockStateResource {
|
||||||
|
|
||||||
private static final MinecraftVersion NEW_MODEL_PATH_VERSION = new MinecraftVersion(1, 13);
|
|
||||||
|
|
||||||
private final List<Variant> variants = new ArrayList<>(0);
|
private final List<Variant> variants = new ArrayList<>(0);
|
||||||
private final Collection<Variant> multipart = new ArrayList<>(0);
|
private final Collection<Variant> multipart = new ArrayList<>(0);
|
||||||
|
|
||||||
|
@ -92,53 +91,6 @@ public class BlockStateResource {
|
||||||
return targetCollection;
|
return targetCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Variant {
|
|
||||||
|
|
||||||
private PropertyCondition condition = PropertyCondition.all();
|
|
||||||
private Collection<Weighted<TransformedBlockModelResource>> models = new ArrayList<>();
|
|
||||||
|
|
||||||
private double totalWeight;
|
|
||||||
|
|
||||||
private Variant() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformedBlockModelResource getModel(int x, int y, int z) {
|
|
||||||
if (models.isEmpty()) throw new IllegalStateException("A variant must have at least one model!");
|
|
||||||
|
|
||||||
double selection = MathUtils.hashToFloat(x, y, z, 827364) * totalWeight; // random based on position
|
|
||||||
for (Weighted<TransformedBlockModelResource> w : models) {
|
|
||||||
selection -= w.weight;
|
|
||||||
if (selection <= 0) return w.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException("This line should never be reached!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkValid() throws ParseResourceException {
|
|
||||||
if (models.isEmpty()) throw new ParseResourceException("A variant must have at least one model!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateTotalWeight() {
|
|
||||||
totalWeight = 0d;
|
|
||||||
for (Weighted<?> w : models) {
|
|
||||||
totalWeight += w.weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Weighted<T> {
|
|
||||||
|
|
||||||
private final T value;
|
|
||||||
private final double weight;
|
|
||||||
|
|
||||||
public Weighted(T value, double weight) {
|
|
||||||
this.value = value;
|
|
||||||
this.weight = weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Builder builder(FileAccess sourcesAccess, ResourcePack resourcePack) {
|
public static Builder builder(FileAccess sourcesAccess, ResourcePack resourcePack) {
|
||||||
return new Builder(sourcesAccess, resourcePack);
|
return new Builder(sourcesAccess, resourcePack);
|
||||||
}
|
}
|
||||||
|
@ -241,16 +193,9 @@ public class BlockStateResource {
|
||||||
String namespacedModelPath = node.node("model").getString();
|
String namespacedModelPath = node.node("model").getString();
|
||||||
if (namespacedModelPath == null)
|
if (namespacedModelPath == null)
|
||||||
throw new ParseResourceException("No model defined!");
|
throw new ParseResourceException("No model defined!");
|
||||||
|
|
||||||
|
|
||||||
String modelPath;
|
|
||||||
if (resourcePack.getMinecraftVersion().isBefore(NEW_MODEL_PATH_VERSION)) {
|
|
||||||
modelPath = ResourcePack.namespacedToAbsoluteResourcePath(namespacedModelPath, "models/block") + ".json";
|
|
||||||
}else {
|
|
||||||
modelPath = ResourcePack.namespacedToAbsoluteResourcePath(namespacedModelPath, "models") + ".json";
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockModelResource model = resourcePack.blockModelResources.get(modelPath);
|
String modelPath = ResourcePack.namespacedToAbsoluteResourcePath(namespacedModelPath, "models") + ".json";
|
||||||
|
BlockModelResource model = resourcePack.getBlockModelResources().get(modelPath);
|
||||||
if (model == null) {
|
if (model == null) {
|
||||||
BlockModelResource.Builder builder = BlockModelResource.builder(sourcesAccess, resourcePack);
|
BlockModelResource.Builder builder = BlockModelResource.builder(sourcesAccess, resourcePack);
|
||||||
try {
|
try {
|
||||||
|
@ -260,7 +205,7 @@ public class BlockStateResource {
|
||||||
throw new ParseResourceException("Failed to load model " + modelPath, e);
|
throw new ParseResourceException("Failed to load model " + modelPath, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
resourcePack.blockModelResources.put(modelPath, model);
|
resourcePack.getBlockModelResources().put(modelPath, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2f rotation = new Vector2f(node.node("x").getFloat(0), node.node("y").getFloat(0));
|
Vector2f rotation = new Vector2f(node.node("x").getFloat(0), node.node("y").getFloat(0));
|
|
@ -22,21 +22,24 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.mca.extensions;
|
package de.bluecolored.bluemap.core.resourcepack.blockstate;
|
||||||
|
|
||||||
import java.util.Collections;
|
public class Conditional<T> {
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class TripwireConnectExtension extends ConnectExtension {
|
private final PropertyCondition condition;
|
||||||
|
private final T value;
|
||||||
|
|
||||||
private static final HashSet<String> AFFECTED_BLOCK_IDS = new HashSet<>(Collections.singletonList(
|
public Conditional(PropertyCondition condition, T value) {
|
||||||
"minecraft:tripwire"
|
this.condition = condition;
|
||||||
));
|
this.value = value;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedBlockIds() {
|
public PropertyCondition getCondition() {
|
||||||
return AFFECTED_BLOCK_IDS;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,12 +22,14 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack.blockstate;
|
||||||
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.util.Preconditions;
|
import de.bluecolored.bluemap.core.util.Preconditions;
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
import de.bluecolored.bluemap.core.world.BlockState;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface PropertyCondition {
|
public interface PropertyCondition {
|
||||||
|
|
||||||
|
@ -35,7 +37,7 @@ public interface PropertyCondition {
|
||||||
PropertyCondition MATCH_NONE = new None();
|
PropertyCondition MATCH_NONE = new None();
|
||||||
|
|
||||||
boolean matches(BlockState state);
|
boolean matches(BlockState state);
|
||||||
|
|
||||||
class Property implements PropertyCondition {
|
class Property implements PropertyCondition {
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
|
@ -151,5 +153,18 @@ public interface PropertyCondition {
|
||||||
|
|
||||||
return or(conditions);
|
return or(conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PropertyCondition blockState(BlockState state) {
|
||||||
|
Map<String, String> props = state.getProperties();
|
||||||
|
if (props.isEmpty()) return all();
|
||||||
|
|
||||||
|
PropertyCondition[] conditions = new Property[props.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (Map.Entry<String, String> prop : props.entrySet()) {
|
||||||
|
conditions[i++] = property(prop.getKey(), prop.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return and(conditions);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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.blockstate;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.blockmodel.TransformedBlockModelResource;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class Variant {
|
||||||
|
|
||||||
|
PropertyCondition condition = PropertyCondition.all();
|
||||||
|
Collection<Weighted<TransformedBlockModelResource>> models = new ArrayList<>(0);
|
||||||
|
|
||||||
|
private double totalWeight;
|
||||||
|
|
||||||
|
Variant() {}
|
||||||
|
|
||||||
|
public TransformedBlockModelResource getModel(int x, int y, int z) {
|
||||||
|
if (models.isEmpty()) throw new IllegalStateException("A variant must have at least one model!");
|
||||||
|
|
||||||
|
double selection = hashToFloat(x, y, z) * totalWeight; // random based on position
|
||||||
|
for (Weighted<TransformedBlockModelResource> w : models) {
|
||||||
|
selection -= w.getWeight();
|
||||||
|
if (selection <= 0) return w.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("This line should never be reached!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkValid() throws ParseResourceException {
|
||||||
|
if (models.isEmpty()) throw new ParseResourceException("A variant must have at least one model!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateTotalWeight() {
|
||||||
|
totalWeight = 0d;
|
||||||
|
for (Weighted<?> w : models) {
|
||||||
|
totalWeight += w.getWeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float hashToFloat(int x, int y, int z) {
|
||||||
|
final long hash = x * 73438747 ^ y * 9357269 ^ z * 4335792;
|
||||||
|
return (hash * (hash + 456149) & 0x00ffffff) / (float) 0x01000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,19 +22,24 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.mca.extensions;
|
package de.bluecolored.bluemap.core.resourcepack.blockstate;
|
||||||
|
|
||||||
import java.util.Set;
|
public class Weighted<T> {
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
private final T value;
|
||||||
|
private final double weight;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
public Weighted(T value, double weight) {
|
||||||
import de.bluecolored.bluemap.core.world.BlockState;
|
this.value = value;
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
public interface BlockStateExtension {
|
public double getWeight() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
BlockState extend(MCAWorld world, Vector3i pos, BlockState state);
|
|
||||||
|
|
||||||
Set<String> getAffectedBlockIds();
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack.texture;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
|
|
|
@ -22,10 +22,11 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.resourcepack;
|
package de.bluecolored.bluemap.core.resourcepack.texture;
|
||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
|
import de.bluecolored.bluemap.core.resourcepack.ParseResourceException;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
import de.bluecolored.bluemap.core.resourcepack.fileaccess.FileAccess;
|
||||||
import de.bluecolored.bluemap.core.util.FileUtils;
|
import de.bluecolored.bluemap.core.util.FileUtils;
|
||||||
import de.bluecolored.bluemap.core.util.math.Color;
|
import de.bluecolored.bluemap.core.util.math.Color;
|
||||||
|
@ -37,14 +38,14 @@ import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link TextureGallery} is managing {@link Texture}s and their id's and path's.<br>
|
* A {@link TextureGallery} is managing {@link Texture}s and their id's and path's.<br>
|
||||||
* I can also load and generate the texture.json file, or load new {@link Texture}s from a {@link FileAccess}.
|
* I can also load and generate the texture.json file, or load new {@link Texture}s from a {@link FileAccess}.
|
||||||
*/
|
*/
|
||||||
public class TextureGallery {
|
public class TextureGallery {
|
||||||
|
|
||||||
private static final String EMPTY_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAEUlEQVR42mNkIAAYRxWMJAUAE5gAEdz4t9QAAAAASUVORK5CYII=";
|
private static final String EMPTY_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAEUlEQVR42mNkIAAYRxWMJAUAE5gAEdz4t9QAAAAASUVORK5CYII=";
|
||||||
|
|
||||||
private Map<String, Texture> textureMap;
|
private final Map<String, Texture> textureMap;
|
||||||
private List<Texture> textureList;
|
private final List<Texture> textureList;
|
||||||
|
|
||||||
public TextureGallery() {
|
public TextureGallery() {
|
||||||
textureMap = new HashMap<>();
|
textureMap = new HashMap<>();
|
||||||
|
@ -129,7 +130,7 @@ public class TextureGallery {
|
||||||
* Loads all the {@link Texture}s from the provided texture.json file, removes any existing {@link Texture}s from this gallery.
|
* Loads all the {@link Texture}s from the provided texture.json file, removes any existing {@link Texture}s from this gallery.
|
||||||
* @param file The texture.json file.
|
* @param file The texture.json file.
|
||||||
* @throws IOException If an IOException occurs while reading the file.
|
* @throws IOException If an IOException occurs while reading the file.
|
||||||
* @throws ParseResourceException If the whole file can not be read. Errors with single textures are logged and ignored.
|
* @throws ParseResourceException If the whole file can not be read. Errors with single textures are logged and ignored.
|
||||||
*/
|
*/
|
||||||
public synchronized void loadTextureFile(File file) throws IOException, ParseResourceException {
|
public synchronized void loadTextureFile(File file) throws IOException, ParseResourceException {
|
||||||
textureList.clear();
|
textureList.clear();
|
||||||
|
@ -149,13 +150,11 @@ public class TextureGallery {
|
||||||
String path = texture.get("id").getAsString();
|
String path = texture.get("id").getAsString();
|
||||||
boolean transparent = texture.get("transparent").getAsBoolean();
|
boolean transparent = texture.get("transparent").getAsBoolean();
|
||||||
Color color = readColor(texture.get("color").getAsJsonArray());
|
Color color = readColor(texture.get("color").getAsJsonArray());
|
||||||
textureList.set(i, new Texture(i, path, color, transparent, EMPTY_BASE64));
|
textureList.set(i, new Texture(i, path, color, transparent, texture.get("texture").getAsString()));
|
||||||
} catch (ParseResourceException | RuntimeException ex) {
|
} catch (ParseResourceException | RuntimeException ex) {
|
||||||
Logger.global.logWarning("Failed to load texture with id " + i + " from texture file " + file + "!");
|
Logger.global.logWarning("Failed to load texture with id " + i + " from texture file " + file + "!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
|
||||||
throw ex;
|
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw new ParseResourceException("Invalid texture file format!", ex);
|
throw new ParseResourceException("Invalid texture file format!", ex);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -210,7 +209,7 @@ public class TextureGallery {
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to reload all {@link Texture}s from the given {@link FileAccess}<br>
|
* Tries to reload all {@link Texture}s from the given {@link FileAccess}<br>
|
||||||
* <br>
|
* <br>
|
||||||
|
@ -221,11 +220,7 @@ public class TextureGallery {
|
||||||
for (Texture texture : textureList.toArray(new Texture[textureList.size()])) {
|
for (Texture texture : textureList.toArray(new Texture[textureList.size()])) {
|
||||||
try {
|
try {
|
||||||
loadTexture(fileAccess, texture.getPath());
|
loadTexture(fileAccess, texture.getPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException ignored) {}
|
||||||
Logger.global.noFloodWarning("TextureGallery-uiz78tef5", "Failed to reload texture: " + texture.getPath());
|
|
||||||
Logger.global.noFloodWarning("TextureGallery-89763455h", "This happens if the resource-packs have changed, but you have not deleted your already generated maps. This might result in broken map-models!");
|
|
||||||
Logger.global.noFloodWarning("TextureGallery-re56ugb56", "(Future warnings of this will be suppressed, so more textures might have failed to load after this)");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
package de.bluecolored.bluemap.core.util;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A pool of objects that (lazily) maintains a specific size of objects.
|
|
||||||
* that threads can take, use and return.
|
|
||||||
* It discards excessive objects and creates new ones when needed.
|
|
||||||
*/
|
|
||||||
public class ArrayPool<T> {
|
|
||||||
|
|
||||||
private final Object[] objects;
|
|
||||||
private final int capacity, maxConcurrency;
|
|
||||||
private final Supplier<T> supplier;
|
|
||||||
|
|
||||||
private final AtomicInteger head, tail; // head is excluded, tail included
|
|
||||||
private int size;
|
|
||||||
|
|
||||||
public ArrayPool(int capacity, int maxConcurrency, Supplier<T> supplier) {
|
|
||||||
this.capacity = capacity;
|
|
||||||
this.objects = new Object[capacity + maxConcurrency * 2];
|
|
||||||
this.maxConcurrency = maxConcurrency;
|
|
||||||
this.supplier = supplier;
|
|
||||||
|
|
||||||
this.head = new AtomicInteger(0);
|
|
||||||
this.tail = new AtomicInteger(0);
|
|
||||||
this.size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public T take() {
|
|
||||||
while (size < maxConcurrency) add(supplier.get());
|
|
||||||
|
|
||||||
size --;
|
|
||||||
return (T) objects[tail.getAndUpdate(this::nextPointer)];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void add(T resource) {
|
|
||||||
while (size > capacity + maxConcurrency) take();
|
|
||||||
|
|
||||||
objects[head.getAndUpdate(this::nextPointer)] = resource;
|
|
||||||
size ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int capacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int nextPointer(int prev) {
|
|
||||||
return (prev + 1) % objects.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -28,6 +28,7 @@ import com.flowpowered.math.vector.Vector3d;
|
||||||
import com.flowpowered.math.vector.Vector3f;
|
import com.flowpowered.math.vector.Vector3f;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import com.flowpowered.math.vector.Vector4f;
|
import com.flowpowered.math.vector.Vector4f;
|
||||||
|
import de.bluecolored.bluemap.core.util.math.VectorM3f;
|
||||||
|
|
||||||
@Deprecated //TODO
|
@Deprecated //TODO
|
||||||
public class MathUtils {
|
public class MathUtils {
|
||||||
|
|
|
@ -22,48 +22,51 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.sponge;
|
package de.bluecolored.bluemap.core.util;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.logger.AbstractLogger;
|
public enum Tristate {
|
||||||
|
|
||||||
public class Slf4jLogger extends AbstractLogger {
|
TRUE (true),
|
||||||
|
UNDEFINED (false) {
|
||||||
|
@Override
|
||||||
|
public Tristate getOr(Tristate other) {
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
private Logger out;
|
@Override
|
||||||
|
public boolean getOr(BooleanSupplier other) {
|
||||||
public Slf4jLogger(Logger out) {
|
return other.getAsBoolean();
|
||||||
this.out = out;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void logError(String message, Throwable throwable) {
|
public boolean getOr(boolean defaultValue) {
|
||||||
out.error(message, throwable);
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
FALSE (false);
|
||||||
|
|
||||||
@Override
|
private final boolean value;
|
||||||
public void logWarning(String message) {
|
|
||||||
out.warn(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
Tristate(boolean value ) {
|
||||||
public void logInfo(String message) {
|
this.value = value;
|
||||||
out.info(message);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public Tristate getOr(Tristate other) {
|
||||||
public void logDebug(String message) {
|
return this;
|
||||||
if (out.isDebugEnabled()) out.debug(message);
|
}
|
||||||
}
|
|
||||||
|
public boolean getOr(BooleanSupplier other) {
|
||||||
@Override
|
return value;
|
||||||
public void noFloodDebug(String message) {
|
}
|
||||||
if (out.isDebugEnabled()) super.noFloodDebug(message);
|
|
||||||
}
|
public boolean getOr(boolean defaultValue) {
|
||||||
|
return value;
|
||||||
@Override
|
}
|
||||||
public void noFloodDebug(String key, String message) {
|
|
||||||
if (out.isDebugEnabled()) super.noFloodDebug(key, message);
|
@Override
|
||||||
}
|
public String toString() {
|
||||||
|
return "Tristate." + name();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,27 @@
|
||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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.math;
|
package de.bluecolored.bluemap.core.util.math;
|
||||||
|
|
||||||
public class Color {
|
public class Color {
|
||||||
|
|
|
@ -24,10 +24,7 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.world;
|
package de.bluecolored.bluemap.core.world;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
public class Block<T extends Block<T>> {
|
||||||
import de.bluecolored.bluemap.core.util.Direction;
|
|
||||||
|
|
||||||
public class Block {
|
|
||||||
|
|
||||||
private World world;
|
private World world;
|
||||||
private int x, y, z;
|
private int x, y, z;
|
||||||
|
@ -35,23 +32,19 @@ public class Block {
|
||||||
private Chunk chunk;
|
private Chunk chunk;
|
||||||
|
|
||||||
private BlockState blockState;
|
private BlockState blockState;
|
||||||
private BlockProperties properties;
|
|
||||||
private LightData lightData;
|
private LightData lightData;
|
||||||
private Biome biome;
|
private int biomeId;
|
||||||
|
|
||||||
private int sunLight;
|
|
||||||
private int blockLight;
|
|
||||||
|
|
||||||
private final transient LightData tempLight;
|
|
||||||
|
|
||||||
public Block(World world, int x, int y, int z) {
|
public Block(World world, int x, int y, int z) {
|
||||||
tempLight = new LightData(0, 0);
|
|
||||||
|
|
||||||
set(world, x, y, z);
|
set(world, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block set(World world, int x, int y, int z) {
|
public T set(World world, int x, int y, int z) {
|
||||||
if (this.x == x && this.y == y && this.z == z && this.world == world) return this;
|
if (this.x == x && this.z == z && this.world == world){
|
||||||
|
if (this.y == y) return self();
|
||||||
|
} else {
|
||||||
|
this.chunk = null; //only reset the chunk if x or z have changed
|
||||||
|
}
|
||||||
|
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
|
@ -60,11 +53,15 @@ public class Block {
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block set(int x, int y, int z) {
|
public T set(int x, int y, int z) {
|
||||||
if (this.x == x && this.y == y && this.z == z) return this;
|
if (this.x == x && this.z == z){
|
||||||
|
if (this.y == y) return self();
|
||||||
|
} else {
|
||||||
|
this.chunk = null; //only reset the chunk if x or z have changed
|
||||||
|
}
|
||||||
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
|
@ -72,27 +69,49 @@ public class Block {
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
return this;
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reset() {
|
protected void reset() {
|
||||||
this.chunk = null;
|
|
||||||
|
|
||||||
this.blockState = null;
|
this.blockState = null;
|
||||||
this.properties = null;
|
|
||||||
this.lightData = new LightData(-1, -1);
|
this.lightData = new LightData(-1, -1);
|
||||||
this.biome = null;
|
this.biomeId = -1;
|
||||||
|
|
||||||
this.blockLight = -1;
|
|
||||||
this.sunLight = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block add(int dx, int dy, int dz) {
|
public T add(int dx, int dy, int dz) {
|
||||||
return set(x + dx, y + dy, z + dz);
|
return set(x + dx, y + dy, z + dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block copy(Block source) {
|
public T copy(Block<?> source) {
|
||||||
return set(source.world, source.x, source.y, source.z);
|
this.world = source.world;
|
||||||
|
this.chunk = source.chunk;
|
||||||
|
this.x = source.x;
|
||||||
|
this.y = source.y;
|
||||||
|
this.z = source.z;
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
this.blockState = source.blockState;
|
||||||
|
this.lightData = new LightData(source.lightData.getSkyLight(), source.lightData.getBlockLight());
|
||||||
|
this.biomeId = source.biomeId;
|
||||||
|
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy with offset
|
||||||
|
*/
|
||||||
|
public T copy(Block<?> source, int dx, int dy, int dz) {
|
||||||
|
this.world = source.world;
|
||||||
|
this.x = source.x + dx;
|
||||||
|
this.y = source.y + dy;
|
||||||
|
this.z = source.z + dz;
|
||||||
|
|
||||||
|
this.chunk = null;
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public World getWorld() {
|
public World getWorld() {
|
||||||
|
@ -121,19 +140,14 @@ public class Block {
|
||||||
return blockState;
|
return blockState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockProperties getProperties() {
|
|
||||||
if (properties == null) properties = world.getBlockProperties(getBlockState());
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LightData getLightData() {
|
public LightData getLightData() {
|
||||||
if (lightData.getSkyLight() < 0) getChunk().getLightData(x, y, z, lightData);
|
if (lightData.getSkyLight() < 0) getChunk().getLightData(x, y, z, lightData);
|
||||||
return lightData;
|
return lightData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Biome getBiome() {
|
public int getBiomeId() {
|
||||||
if (biome == null) biome = getChunk().getBiome(x, y, z);
|
if (biomeId == -1) biomeId = getChunk().getBiome(x, y, z);
|
||||||
return biome;
|
return biomeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSunLightLevel() {
|
public int getSunLightLevel() {
|
||||||
|
@ -144,67 +158,32 @@ public class Block {
|
||||||
return getLightData().getBlockLight();
|
return getLightData().getBlockLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCullingNeighborFaces() {
|
@Override
|
||||||
return getProperties().isCulling();
|
public String toString() {
|
||||||
}
|
if (world != null) {
|
||||||
|
return "Block{" +
|
||||||
public boolean isFlammable() {
|
"world=" + world +
|
||||||
return getProperties().isFlammable();
|
", x=" + x +
|
||||||
}
|
", y=" + y +
|
||||||
|
", z=" + z +
|
||||||
public boolean isOccludingNeighborFaces(){
|
", chunk=" + getChunk() +
|
||||||
return getProperties().isOccluding();
|
", blockState=" + getBlockState() +
|
||||||
}
|
", lightData=" + getLightData() +
|
||||||
|
", biomeId=" + getBiomeId() +
|
||||||
/**
|
'}';
|
||||||
* This is internally used for light rendering
|
} else {
|
||||||
* It is basically the sun light that is projected onto adjacent faces
|
return "Block{" +
|
||||||
*/
|
"world=" + world +
|
||||||
public int getPassedSunLight() {
|
", x=" + x +
|
||||||
if (sunLight < 0) calculateLight();
|
", y=" + y +
|
||||||
return sunLight;
|
", z=" + z +
|
||||||
}
|
'}';
|
||||||
|
|
||||||
/**
|
|
||||||
* This is internally used for light rendering
|
|
||||||
* It is basically the block light that is projected onto adjacent faces
|
|
||||||
*/
|
|
||||||
public int getPassedBlockLight() {
|
|
||||||
if (blockLight < 0) calculateLight();
|
|
||||||
return blockLight;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateLight() {
|
|
||||||
sunLight = getSunLightLevel();
|
|
||||||
blockLight = getBlockLightLevel();
|
|
||||||
|
|
||||||
if (blockLight > 0 || sunLight > 0) return;
|
|
||||||
|
|
||||||
Vector3i dirV;
|
|
||||||
int nx, ny, nz;
|
|
||||||
for (Direction direction : Direction.values()) {
|
|
||||||
dirV = direction.toVector();
|
|
||||||
nx = dirV.getX() + x;
|
|
||||||
ny = dirV.getY() + y;
|
|
||||||
nz = dirV.getZ() + z;
|
|
||||||
|
|
||||||
world.getLightData(nx, ny, nz, tempLight);
|
|
||||||
|
|
||||||
sunLight = Math.max(tempLight.getSkyLight(), sunLight);
|
|
||||||
blockLight = Math.max(tempLight.getBlockLight(), blockLight);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@SuppressWarnings("unchecked")
|
||||||
public String toString() {
|
protected T self() {
|
||||||
return "Block{" +
|
return (T) this;
|
||||||
"world=" + world +
|
|
||||||
", x=" + x +
|
|
||||||
", y=" + y +
|
|
||||||
", z=" + z +
|
|
||||||
", sunLight=" + sunLight +
|
|
||||||
", blockLight=" + blockLight +
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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 de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
|
|
||||||
|
public class BlockNeighborhood<T extends BlockNeighborhood<T>> extends ResourcePackBlock<T> {
|
||||||
|
|
||||||
|
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 int thisIndex;
|
||||||
|
|
||||||
|
public BlockNeighborhood(ResourcePackBlock<?> center) {
|
||||||
|
super(center.getResourcePack(), null, 0, 0, 0);
|
||||||
|
copy(center);
|
||||||
|
|
||||||
|
neighborhood = new ResourcePackBlock[DIAMETER * DIAMETER * DIAMETER];
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockNeighborhood(ResourcePack resourcePack, World world, int x, int y, int z) {
|
||||||
|
super(resourcePack, world, x, y, z);
|
||||||
|
|
||||||
|
neighborhood = new ResourcePackBlock[DIAMETER * DIAMETER * DIAMETER];
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void reset() {
|
||||||
|
super.reset();
|
||||||
|
|
||||||
|
this.thisIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
this.thisIndex = -1;
|
||||||
|
for (int i = 0; i < neighborhood.length; i++) {
|
||||||
|
neighborhood[i] = new ResourcePackBlock<>(this.getResourcePack(), null, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourcePackBlock<?> getNeighborBlock(int dx, int dy, int dz) {
|
||||||
|
int i = neighborIndex(dx, dy, dz);
|
||||||
|
if (i == thisIndex()) return this;
|
||||||
|
return neighborhood[i].set(
|
||||||
|
getWorld(),
|
||||||
|
getX() + dx,
|
||||||
|
getY() + dy,
|
||||||
|
getZ() + dz
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int thisIndex() {
|
||||||
|
if (thisIndex == -1) thisIndex = neighborIndex(0, 0, 0);
|
||||||
|
return thisIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int neighborIndex(int dx, int dy, int dz) {
|
||||||
|
return ((getX() + dx) & DIAMETER_MASK) * DIAMETER_SQUARED +
|
||||||
|
((getY() + dy) & DIAMETER_MASK) * DIAMETER +
|
||||||
|
((getZ() + dz) & DIAMETER_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,29 +24,122 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.world;
|
package de.bluecolored.bluemap.core.world;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.util.Tristate;
|
||||||
|
|
||||||
public class BlockProperties {
|
public class BlockProperties {
|
||||||
|
|
||||||
public static final BlockProperties SOLID = new BlockProperties(true, true, false);
|
public static final BlockProperties DEFAULT = new BlockProperties();
|
||||||
public static final BlockProperties TRANSPARENT = new BlockProperties(false, false, false);
|
|
||||||
|
|
||||||
private final boolean culling, occluding, flammable;
|
private Tristate culling, occluding, alwaysWaterlogged, randomOffset;
|
||||||
|
|
||||||
public BlockProperties(boolean culling, boolean occluding, boolean flammable) {
|
public BlockProperties() {
|
||||||
|
this.culling = Tristate.UNDEFINED;
|
||||||
|
this.occluding = Tristate.UNDEFINED;
|
||||||
|
this.alwaysWaterlogged = Tristate.UNDEFINED;
|
||||||
|
this.randomOffset = Tristate.UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockProperties(
|
||||||
|
Tristate culling,
|
||||||
|
Tristate occluding,
|
||||||
|
Tristate alwaysWaterlogged,
|
||||||
|
Tristate randomOffset
|
||||||
|
) {
|
||||||
this.culling = culling;
|
this.culling = culling;
|
||||||
this.occluding = occluding;
|
this.occluding = occluding;
|
||||||
this.flammable = flammable;
|
this.alwaysWaterlogged = alwaysWaterlogged;
|
||||||
|
this.randomOffset = randomOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCulling() {
|
public boolean isCulling() {
|
||||||
return culling;
|
return culling.getOr(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOccluding() {
|
public boolean isOccluding() {
|
||||||
return occluding;
|
return occluding.getOr(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFlammable() {
|
public boolean isAlwaysWaterlogged() {
|
||||||
return flammable;
|
return alwaysWaterlogged.getOr(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRandomOffset() {
|
||||||
|
return randomOffset.getOr(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return new BlockProperties(
|
||||||
|
culling,
|
||||||
|
occluding,
|
||||||
|
alwaysWaterlogged,
|
||||||
|
randomOffset
|
||||||
|
).new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new BlockProperties().new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Builder {
|
||||||
|
|
||||||
|
public Builder culling(boolean culling) {
|
||||||
|
BlockProperties.this.culling = culling ? Tristate.TRUE : Tristate.FALSE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder occluding(boolean occluding) {
|
||||||
|
BlockProperties.this.occluding = occluding ? Tristate.TRUE : Tristate.FALSE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder alwaysWaterlogged(boolean alwaysWaterlogged) {
|
||||||
|
BlockProperties.this.alwaysWaterlogged = alwaysWaterlogged ? Tristate.TRUE : Tristate.FALSE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder randomOffset(boolean randomOffset) {
|
||||||
|
BlockProperties.this.randomOffset = randomOffset ? Tristate.TRUE : Tristate.FALSE;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder from(BlockProperties other) {
|
||||||
|
culling = other.culling.getOr(culling);
|
||||||
|
occluding = other.occluding.getOr(occluding);
|
||||||
|
alwaysWaterlogged = other.alwaysWaterlogged.getOr(alwaysWaterlogged);
|
||||||
|
randomOffset = other.randomOffset.getOr(randomOffset);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockProperties build() {
|
||||||
|
return BlockProperties.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tristate isCulling() {
|
||||||
|
return culling;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tristate isOccluding() {
|
||||||
|
return occluding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tristate isAlwaysWaterlogged() {
|
||||||
|
return alwaysWaterlogged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tristate isRandomOffset() {
|
||||||
|
return randomOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BlockProperties{" +
|
||||||
|
"culling=" + culling +
|
||||||
|
", occluding=" + occluding +
|
||||||
|
", alwaysWaterlogged=" + alwaysWaterlogged +
|
||||||
|
", randomOffset=" + randomOffset +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.world;
|
package de.bluecolored.bluemap.core.world;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -39,46 +37,10 @@ import java.util.regex.Pattern;
|
||||||
*/
|
*/
|
||||||
public class BlockState {
|
public class BlockState {
|
||||||
|
|
||||||
private static final Pattern BLOCKSTATE_SERIALIZATION_PATTERN = Pattern.compile("^(.+?)(?:\\[(.*)\\])?$");
|
private static final Pattern BLOCKSTATE_SERIALIZATION_PATTERN = Pattern.compile("^(.+?)(?:\\[(.*)])?$");
|
||||||
|
|
||||||
private static final HashSet<String> DEFAULT_WATERLOGGED_BLOCK_IDS = new HashSet<>(Arrays.asList(
|
public static final BlockState AIR = new BlockState("minecraft:air");
|
||||||
"minecraft:seagrass",
|
public static final BlockState MISSING = new BlockState("bluemap:missing");
|
||||||
"minecraft:tall_seagrass",
|
|
||||||
"minecraft:kelp",
|
|
||||||
"minecraft:kelp_plant",
|
|
||||||
"minecraft:bubble_column"
|
|
||||||
));
|
|
||||||
|
|
||||||
private static final HashSet<String> OFFSET_BLOCK_IDS = new HashSet<>(Arrays.asList(
|
|
||||||
"minecraft:grass",
|
|
||||||
"minecraft:tall_grass",
|
|
||||||
"minecraft:fern",
|
|
||||||
"minecraft:dandelion",
|
|
||||||
"minecraft:cornflower",
|
|
||||||
"minecraft:poppy",
|
|
||||||
"minecraft:blue_orchid",
|
|
||||||
"minecraft:allium",
|
|
||||||
"minecraft:azure_bluet",
|
|
||||||
"minecraft:red_tulip",
|
|
||||||
"minecraft:orange_tulip",
|
|
||||||
"minecraft:white_tulip",
|
|
||||||
"minecraft:pink_tulip",
|
|
||||||
"minecraft:oxeye_daisy",
|
|
||||||
"minecraft:lily_of_the_valley",
|
|
||||||
"minecraft:wither_rose",
|
|
||||||
"minecraft:crimson_roots",
|
|
||||||
"minecraft:warped_roots",
|
|
||||||
"minecraft:nether_sprouts",
|
|
||||||
"minecraft:rose_bush",
|
|
||||||
"minecraft:peony",
|
|
||||||
"minecraft:lilac",
|
|
||||||
"minecraft:sunflower",
|
|
||||||
"minecraft:hanging_roots",
|
|
||||||
"minecraft:small_dripleaf"
|
|
||||||
));
|
|
||||||
|
|
||||||
public static final BlockState AIR = new BlockState(MinecraftVersion.LATEST_SUPPORTED, "minecraft:air", Collections.emptyMap());
|
|
||||||
public static final BlockState MISSING = new BlockState(MinecraftVersion.LATEST_SUPPORTED, "bluemap:missing", Collections.emptyMap());
|
|
||||||
|
|
||||||
private boolean hashed;
|
private boolean hashed;
|
||||||
private int hash;
|
private int hash;
|
||||||
|
@ -88,14 +50,13 @@ public class BlockState {
|
||||||
private final String fullId;
|
private final String fullId;
|
||||||
private final Map<String, String> properties;
|
private final Map<String, String> properties;
|
||||||
|
|
||||||
// special fast-access properties
|
private final boolean isAir, isWater, isWaterlogged;
|
||||||
public final boolean isAir, isWater, isWaterlogged, isRandomOffset;
|
|
||||||
|
|
||||||
public BlockState(MinecraftVersion version, String id) {
|
public BlockState(String id) {
|
||||||
this(version, id, Collections.emptyMap());
|
this(id, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockState(MinecraftVersion version, String id, Map<String, String> properties) {
|
public BlockState(String id, Map<String, String> properties) {
|
||||||
this.hashed = false;
|
this.hashed = false;
|
||||||
this.hash = 0;
|
this.hash = 0;
|
||||||
|
|
||||||
|
@ -121,38 +82,7 @@ public class BlockState {
|
||||||
"minecraft:void_air".equals(this.fullId);
|
"minecraft:void_air".equals(this.fullId);
|
||||||
|
|
||||||
this.isWater = "minecraft:water".equals(this.fullId);
|
this.isWater = "minecraft:water".equals(this.fullId);
|
||||||
|
this.isWaterlogged = "true".equals(properties.get("waterlogged"));
|
||||||
this.isWaterlogged =
|
|
||||||
DEFAULT_WATERLOGGED_BLOCK_IDS.contains(this.fullId) ||
|
|
||||||
"true".equals(this.properties.get("waterlogged"));
|
|
||||||
|
|
||||||
if (version.isAtLeast(MinecraftVersion.THE_FLATTENING)) {
|
|
||||||
this.isRandomOffset = OFFSET_BLOCK_IDS.contains(this.fullId);
|
|
||||||
} else {
|
|
||||||
this.isRandomOffset =
|
|
||||||
"minecraft:tall_grass".equals(this.fullId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private BlockState(BlockState blockState, String withKey, String withValue) {
|
|
||||||
this.hashed = false;
|
|
||||||
this.hash = 0;
|
|
||||||
|
|
||||||
Map<String, String> props = new HashMap<>(blockState.getProperties());
|
|
||||||
props.put(withKey, withValue);
|
|
||||||
|
|
||||||
this.id = blockState.getId();
|
|
||||||
this.namespace = blockState.getNamespace();
|
|
||||||
this.fullId = namespace + ":" + id;
|
|
||||||
this.properties = props;
|
|
||||||
|
|
||||||
// special fast-access properties
|
|
||||||
this.isAir = blockState.isAir;
|
|
||||||
this.isWater = blockState.isWater;
|
|
||||||
this.isWaterlogged =
|
|
||||||
DEFAULT_WATERLOGGED_BLOCK_IDS.contains(this.fullId) ||
|
|
||||||
"true".equals(this.properties.get("waterlogged"));
|
|
||||||
this.isRandomOffset = blockState.isRandomOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,14 +120,19 @@ public class BlockState {
|
||||||
public Map<String, String> getProperties() {
|
public Map<String, String> getProperties() {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public boolean isAir() {
|
||||||
* Returns a new BlockState with the given property changed
|
return isAir;
|
||||||
*/
|
|
||||||
public BlockState with(String property, String value) {
|
|
||||||
return new BlockState(this, property, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWater() {
|
||||||
|
return isWater;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWaterlogged() {
|
||||||
|
return isWaterlogged;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) return true;
|
if (this == obj) return true;
|
||||||
|
@ -205,8 +140,7 @@ public class BlockState {
|
||||||
if (!(obj instanceof BlockState)) return false;
|
if (!(obj instanceof BlockState)) return false;
|
||||||
BlockState b = (BlockState) obj;
|
BlockState b = (BlockState) obj;
|
||||||
if (!Objects.equals(getFullId(), b.getFullId())) return false;
|
if (!Objects.equals(getFullId(), b.getFullId())) return false;
|
||||||
if (!Objects.equals(getProperties(), b.getProperties())) return false;
|
return Objects.equals(getProperties(), b.getProperties());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -229,10 +163,12 @@ public class BlockState {
|
||||||
return getFullId() + "[" + sj.toString() + "]";
|
return getFullId() + "[" + sj.toString() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlockState fromString(MinecraftVersion version, String serializedBlockState) throws IllegalArgumentException {
|
public static BlockState fromString(String serializedBlockState) throws IllegalArgumentException {
|
||||||
try {
|
try {
|
||||||
Matcher m = BLOCKSTATE_SERIALIZATION_PATTERN.matcher(serializedBlockState);
|
Matcher m = BLOCKSTATE_SERIALIZATION_PATTERN.matcher(serializedBlockState);
|
||||||
m.find();
|
|
||||||
|
if (!m.find())
|
||||||
|
throw new IllegalArgumentException("'" + serializedBlockState + "' could not be parsed to a BlockState!");
|
||||||
|
|
||||||
Map<String, String> pt = new HashMap<>();
|
Map<String, String> pt = new HashMap<>();
|
||||||
String g2 = m.group(2);
|
String g2 = m.group(2);
|
||||||
|
@ -246,7 +182,7 @@ public class BlockState {
|
||||||
|
|
||||||
String blockId = m.group(1).trim();
|
String blockId = m.group(1).trim();
|
||||||
|
|
||||||
return new BlockState(version, blockId, pt);
|
return new BlockState(blockId, pt);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw new IllegalArgumentException("'" + serializedBlockState + "' could not be parsed to a BlockState!");
|
throw new IllegalArgumentException("'" + serializedBlockState + "' could not be parsed to a BlockState!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public interface Chunk {
|
||||||
|
|
||||||
LightData getLightData(int x, int y, int z, LightData target);
|
LightData getLightData(int x, int y, int z, LightData target);
|
||||||
|
|
||||||
Biome getBiome(int x, int y, int z);
|
int getBiome(int x, int y, int z);
|
||||||
|
|
||||||
int getMaxY(int x, int z);
|
int getMaxY(int x, int z);
|
||||||
|
|
||||||
|
|
|
@ -22,36 +22,43 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.sponge;
|
package de.bluecolored.bluemap.core.world;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener;
|
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||||
import de.bluecolored.bluemap.common.plugin.text.Text;
|
|
||||||
import org.spongepowered.api.event.Listener;
|
|
||||||
import org.spongepowered.api.event.Order;
|
|
||||||
import org.spongepowered.api.event.message.MessageChannelEvent;
|
|
||||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
|
||||||
|
|
||||||
public class EventForwarder {
|
import java.util.Objects;
|
||||||
|
|
||||||
private final ServerEventListener listener;
|
public class ResourcePackBlock<T extends ResourcePackBlock<T>> extends Block<T> {
|
||||||
|
|
||||||
public EventForwarder(ServerEventListener listener) {
|
private final ResourcePack resourcePack;
|
||||||
this.listener = listener;
|
private BlockProperties properties;
|
||||||
}
|
private Biome biome;
|
||||||
|
|
||||||
|
public ResourcePackBlock(ResourcePack resourcePack, World world, int x, int y, int z) {
|
||||||
|
super(world, x, y, z);
|
||||||
|
this.resourcePack = Objects.requireNonNull(resourcePack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void reset() {
|
||||||
|
super.reset();
|
||||||
|
|
||||||
|
this.properties = null;
|
||||||
|
this.biome = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockProperties getProperties() {
|
||||||
|
if (properties == null) properties = resourcePack.getBlockProperties(getBlockState());
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Biome getBiome() {
|
||||||
|
if (biome == null) biome = resourcePack.getBiome(getBiomeId());
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourcePack getResourcePack() {
|
||||||
|
return resourcePack;
|
||||||
|
}
|
||||||
|
|
||||||
@Listener(order = Order.POST)
|
|
||||||
public void onPlayerJoin(ClientConnectionEvent.Join evt) {
|
|
||||||
listener.onPlayerJoin(evt.getTargetEntity().getUniqueId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Listener(order = Order.POST)
|
|
||||||
public void onPlayerLeave(ClientConnectionEvent.Disconnect evt) {
|
|
||||||
listener.onPlayerJoin(evt.getTargetEntity().getUniqueId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Listener(order = Order.POST)
|
|
||||||
public void onPlayerChat(MessageChannelEvent.Chat evt) {
|
|
||||||
listener.onChatMessage(Text.of(evt.getMessage().toPlain()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -26,7 +26,6 @@ package de.bluecolored.bluemap.core.world;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
import com.flowpowered.math.vector.Vector2i;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -93,22 +92,6 @@ public class SlicedWorld implements World {
|
||||||
return world.getRegionGrid();
|
return world.getRegionGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Biome getBiome(int x, int y, int z) {
|
|
||||||
return world.getBiome(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockProperties getBlockProperties(BlockState blockState) {
|
|
||||||
return world.getBlockProperties(blockState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState getBlockState(int x, int y, int z) {
|
|
||||||
if (!isInside(x, y, z)) return BlockState.AIR;
|
|
||||||
return world.getBlockState(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getChunk(int x, int z) {
|
public Chunk getChunk(int x, int z) {
|
||||||
return world.getChunk(x, z);
|
return world.getChunk(x, z);
|
||||||
|
@ -153,11 +136,6 @@ public class SlicedWorld implements World {
|
||||||
world.cleanUpChunkCache();
|
world.cleanUpChunkCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockPropertiesMapper getBlockPropertiesMapper() {
|
|
||||||
return world.getBlockPropertiesMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInside(int x, int z) {
|
private boolean isInside(int x, int z) {
|
||||||
return
|
return
|
||||||
x >= min.getX() &&
|
x >= min.getX() &&
|
||||||
|
|
|
@ -26,7 +26,6 @@ package de.bluecolored.bluemap.core.world;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
import com.flowpowered.math.vector.Vector2i;
|
||||||
import com.flowpowered.math.vector.Vector3i;
|
import com.flowpowered.math.vector.Vector3i;
|
||||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -57,21 +56,6 @@ public interface World {
|
||||||
|
|
||||||
Grid getRegionGrid();
|
Grid getRegionGrid();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link Biome} on the specified position or the default biome if the block is not generated yet.
|
|
||||||
*/
|
|
||||||
Biome getBiome(int x, int y, int z);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link BlockState} on the specified position or an air-block if the block is not generated yet.
|
|
||||||
*/
|
|
||||||
BlockState getBlockState(int x, int y, int z);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the BlockProperties for a block-state
|
|
||||||
*/
|
|
||||||
BlockProperties getBlockProperties(BlockState blockState);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link Chunk} on the specified block-position
|
* Returns the {@link Chunk} on the specified block-position
|
||||||
*/
|
*/
|
||||||
|
@ -83,7 +67,7 @@ public interface World {
|
||||||
Chunk getChunk(int x, int z);
|
Chunk getChunk(int x, int z);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Chunk on the specified chunk-position
|
* Returns the {@link Region} on the specified region-position
|
||||||
*/
|
*/
|
||||||
Region getRegion(int x, int z);
|
Region getRegion(int x, int z);
|
||||||
|
|
||||||
|
@ -107,10 +91,5 @@ public interface World {
|
||||||
* Cleans up invalid cache-entries to free up memory
|
* Cleans up invalid cache-entries to free up memory
|
||||||
*/
|
*/
|
||||||
void cleanUpChunkCache();
|
void cleanUpChunkCache();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the block-properties manager used for this world
|
|
||||||
*/
|
|
||||||
BlockPropertiesMapper getBlockPropertiesMapper();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"": { "model": "bluemap:missing" }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent": "block/cube_all",
|
|
||||||
"textures": {
|
|
||||||
"all": "bluemap:blocks/missing"
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB |
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"": { "model": "barrier" }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/black_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/black_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/black_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/black_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/black_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/black_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/black_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/black_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/blue_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/blue_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/blue_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/blue_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/blue_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/blue_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/blue_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/blue_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/brown_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/brown_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/brown_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/brown_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/brown_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/brown_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/brown_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/brown_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"": { "model": "bubble_column" }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"type=single,facing=north": { "model": "chest/normal", "y": 180 },
|
|
||||||
"type=single,facing=east": { "model": "chest/normal", "y": 270 },
|
|
||||||
"type=single,facing=south": { "model": "chest/normal" },
|
|
||||||
"type=single,facing=west": { "model": "chest/normal", "y":90 },
|
|
||||||
"type=right,facing=north": { "model": "chest/normal_double", "y": 180 },
|
|
||||||
"type=right,facing=east": { "model": "chest/normal_double", "y": 270 },
|
|
||||||
"type=right,facing=south": { "model": "chest/normal_double" },
|
|
||||||
"type=right,facing=west": { "model": "chest/normal_double", "y":90 },
|
|
||||||
"type=left": { "model": "chest/left" }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/cyan_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/cyan_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/cyan_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/cyan_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/cyan_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/cyan_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/cyan_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/cyan_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"facing=north": { "model": "chest/ender", "y": 180 },
|
|
||||||
"facing=east": { "model": "chest/ender", "y": 270 },
|
|
||||||
"facing=south": { "model": "chest/ender" },
|
|
||||||
"facing=west": { "model": "chest/ender", "y":90 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/gray_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/gray_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/gray_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/gray_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/gray_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/gray_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/gray_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/gray_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/green_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/green_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/green_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/green_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/green_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/green_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/green_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/green_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"": { "model": "lava" }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/light_blue_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/light_blue_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/light_blue_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/light_blue_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/light_blue_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/light_blue_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/light_blue_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/light_blue_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/light_gray_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/light_gray_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/light_gray_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/light_gray_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/light_gray_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/light_gray_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/light_gray_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/light_gray_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/lime_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/lime_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/lime_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/lime_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/lime_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/lime_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/lime_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/lime_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/magenta_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/magenta_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/magenta_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/magenta_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/magenta_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/magenta_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/magenta_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/magenta_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"rotation=0": { "model": "sign/oak" },
|
|
||||||
"rotation=1": { "model": "sign/oak", "y": 22.5 },
|
|
||||||
"rotation=2": { "model": "sign/oak", "y": 45 },
|
|
||||||
"rotation=3": { "model": "sign/oak", "y": 67.5 },
|
|
||||||
"rotation=4": { "model": "sign/oak", "y": 90 },
|
|
||||||
"rotation=5": { "model": "sign/oak", "y": 112.5 },
|
|
||||||
"rotation=6": { "model": "sign/oak", "y": 135 },
|
|
||||||
"rotation=7": { "model": "sign/oak", "y": 157.5 },
|
|
||||||
"rotation=8": { "model": "sign/oak", "y": 180 },
|
|
||||||
"rotation=9": { "model": "sign/oak", "y": 202.5 },
|
|
||||||
"rotation=10": { "model": "sign/oak", "y": 225 },
|
|
||||||
"rotation=11": { "model": "sign/oak", "y": 247.5 },
|
|
||||||
"rotation=12": { "model": "sign/oak", "y": 270 },
|
|
||||||
"rotation=13": { "model": "sign/oak", "y": 292.5 },
|
|
||||||
"rotation=14": { "model": "sign/oak", "y": 315 },
|
|
||||||
"rotation=15": { "model": "sign/oak", "y": 337.5 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"facing=south": { "model": "sign/wall_oak" },
|
|
||||||
"facing=west": { "model": "sign/wall_oak", "y": 90 },
|
|
||||||
"facing=north": { "model": "sign/wall_oak", "y": 180 },
|
|
||||||
"facing=east": { "model": "sign/wall_oak", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/orange_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/orange_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/orange_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/orange_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/orange_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/orange_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/orange_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/orange_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/pink_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/pink_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/pink_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/pink_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/pink_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/pink_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/pink_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/pink_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/purple_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/purple_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/purple_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/purple_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/purple_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/purple_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/purple_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/purple_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/red_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/red_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/red_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/red_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/red_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/red_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/red_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/red_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"type=single,facing=north": { "model": "chest/trapped", "y": 180 },
|
|
||||||
"type=single,facing=east": { "model": "chest/trapped", "y": 270 },
|
|
||||||
"type=single,facing=south": { "model": "chest/trapped" },
|
|
||||||
"type=single,facing=west": { "model": "chest/trapped", "y":90 },
|
|
||||||
"type=right,facing=north": { "model": "chest/trapped_double", "y": 180 },
|
|
||||||
"type=right,facing=east": { "model": "chest/trapped_double", "y": 270 },
|
|
||||||
"type=right,facing=south": { "model": "chest/trapped_double" },
|
|
||||||
"type=right,facing=west": { "model": "chest/trapped_double", "y":90 },
|
|
||||||
"type=left": { "model": "chest/left" }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"": { "model": "water" }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/white_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/white_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/white_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/white_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/white_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/white_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/white_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/white_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"variants": {
|
|
||||||
"part=head,facing=north": { "model": "bed/yellow_head" },
|
|
||||||
"part=head,facing=east": { "model": "bed/yellow_head", "y": 90 },
|
|
||||||
"part=head,facing=south": { "model": "bed/yellow_head", "y": 180 },
|
|
||||||
"part=head,facing=west": { "model": "bed/yellow_head", "y": 270 },
|
|
||||||
"part=foot,facing=north": { "model": "bed/yellow_foot" },
|
|
||||||
"part=foot,facing=east": { "model": "bed/yellow_foot", "y": 90 },
|
|
||||||
"part=foot,facing=south": { "model": "bed/yellow_foot", "y": 180 },
|
|
||||||
"part=foot,facing=west": { "model": "bed/yellow_foot", "y": 270 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
{}
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"from": [0, 0, 13],
|
|
||||||
"to": [3, 3, 16],
|
|
||||||
"faces": {
|
|
||||||
"north": {"uv": [14.75, 0.75, 15.5, 1.5], "texture": "#bed"},
|
|
||||||
"east": {"uv": [14, 0.75, 14.75, 1.5], "texture": "#bed"},
|
|
||||||
"south": {"uv": [13.25, 0.75, 14, 1.5], "texture": "#bed"},
|
|
||||||
"west": {"uv": [12.5, 0.75, 13.25, 1.5], "texture": "#bed"},
|
|
||||||
"up": {"uv": [13.25, 0, 14, 0.75], "texture": "#bed"},
|
|
||||||
"down": {"uv": [14, 0, 14.75, 0.75], "texture": "#bed"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": [13, 0, 13],
|
|
||||||
"to": [16, 3, 16],
|
|
||||||
"faces": {
|
|
||||||
"north": {"uv": [14, 3.75, 14.75, 4.5], "texture": "#bed"},
|
|
||||||
"east": {"uv": [13.25, 3.75, 14, 4.5], "texture": "#bed"},
|
|
||||||
"south": {"uv": [12.5, 3.75, 13.25, 4.5], "texture": "#bed"},
|
|
||||||
"west": {"uv": [14.75, 3.75, 15.5, 4.5], "texture": "#bed"},
|
|
||||||
"up": {"uv": [13.25, 3, 14, 3.75], "texture": "#bed"},
|
|
||||||
"down": {"uv": [14, 3, 14.75, 3.75], "texture": "#bed"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": [0, 3, 0],
|
|
||||||
"to": [16, 9, 16],
|
|
||||||
"faces": {
|
|
||||||
"east": {"uv": [5.5, 7, 7, 11], "rotation": 90, "texture": "#bed"},
|
|
||||||
"south": {"uv": [5.5, 7, 9.5, 5.5], "texture": "#bed"},
|
|
||||||
"west": {"uv": [0, 7, 1.5, 11], "rotation": 270, "texture": "#bed"},
|
|
||||||
"up": {"uv": [1.5, 7, 5.5, 11], "texture": "#bed"},
|
|
||||||
"down": {"uv": [7, 7, 11, 11], "rotation": 180, "texture": "#bed"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"from": [0, 0, 0],
|
|
||||||
"to": [3, 3, 3],
|
|
||||||
"faces": {
|
|
||||||
"north": {"uv": [12.5, 2.25, 13.25, 3], "texture": "#bed"},
|
|
||||||
"east": {"uv": [14.75, 2.25, 15.5, 3], "texture": "#bed"},
|
|
||||||
"south": {"uv": [14, 2.25, 14.75, 3], "texture": "#bed"},
|
|
||||||
"west": {"uv": [13.25, 2.25, 14, 3], "texture": "#bed"},
|
|
||||||
"up": {"uv": [13.25, 1.5, 14, 2.25], "texture": "#bed"},
|
|
||||||
"down": {"uv": [14, 1.5, 14.75, 2.25], "texture": "#bed"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": [13, 0, 0],
|
|
||||||
"to": [16, 3, 3],
|
|
||||||
"faces": {
|
|
||||||
"north": {"uv": [13.25, 5.25, 14, 6], "texture": "#bed"},
|
|
||||||
"east": {"uv": [12.5, 5.25, 13.25, 6], "texture": "#bed"},
|
|
||||||
"south": {"uv": [14.75, 5.25, 15.5, 6], "texture": "#bed"},
|
|
||||||
"west": {"uv": [14, 5.25, 14.75, 6], "texture": "#bed"},
|
|
||||||
"up": {"uv": [13.25, 4.5, 14, 5.25], "texture": "#bed"},
|
|
||||||
"down": {"uv": [14, 4.5, 14.75, 5.25], "texture": "#bed"}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"from": [0, 3, 0],
|
|
||||||
"to": [16, 9, 16],
|
|
||||||
"faces": {
|
|
||||||
"north": {"uv": [1.5, 1.5, 5.5, 0], "texture": "#bed"},
|
|
||||||
"east": {"uv": [5.5, 1.5, 7, 5.5], "rotation": 90, "texture": "#bed"},
|
|
||||||
"west": {"uv": [0, 1.5, 1.5, 5.5], "rotation": 270, "texture": "#bed"},
|
|
||||||
"up": {"uv": [1.5, 1.5, 5.5, 5.5], "texture": "#bed"},
|
|
||||||
"down": {"uv": [7, 1.5, 11, 5.5], "rotation": 180, "texture": "#bed"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent":"block/bed/bed_foot",
|
|
||||||
"textures": {
|
|
||||||
"bed": "entity/bed/black"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent":"block/bed/bed_head",
|
|
||||||
"textures": {
|
|
||||||
"bed": "entity/bed/black"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent":"block/bed/bed_foot",
|
|
||||||
"textures": {
|
|
||||||
"bed": "entity/bed/blue"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent":"block/bed/bed_head",
|
|
||||||
"textures": {
|
|
||||||
"bed": "entity/bed/blue"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent":"block/bed/bed_foot",
|
|
||||||
"textures": {
|
|
||||||
"bed": "entity/bed/brown"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"parent":"block/bed/bed_head",
|
|
||||||
"textures": {
|
|
||||||
"bed": "entity/bed/brown"
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue