mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-12-26 10:58:00 +01:00
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.core.MinecraftVersion;
|
||||
import de.bluecolored.bluemap.core.config.*;
|
||||
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.map.BmMap;
|
||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||
@ -136,9 +135,6 @@ private synchronized void loadWorldsAndMaps() throws IOException, InterruptedExc
|
||||
maps = new HashMap<>();
|
||||
worlds = new HashMap<>();
|
||||
|
||||
ConfigManager configManager = getConfigManager();
|
||||
configManager.loadResourceConfigs(configFolder, getResourcePack());
|
||||
|
||||
for (MapConfig mapConfig : getRenderConfig().getMapConfigs()) {
|
||||
String id = mapConfig.getId();
|
||||
String name = mapConfig.getName();
|
||||
@ -160,7 +156,7 @@ private synchronized void loadWorldsAndMaps() throws IOException, InterruptedExc
|
||||
World world = worlds.get(worldUUID);
|
||||
if (world == null) {
|
||||
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);
|
||||
} catch (MissingResourcesException e) {
|
||||
throw e; // rethrow this to stop loading and display resource-missing message
|
||||
@ -230,7 +226,10 @@ public synchronized ResourcePack getResourcePack() throws IOException, Interrupt
|
||||
|
||||
if (resourceExtensionsFile.exists()) FileUtils.forceDelete(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
|
||||
File[] resourcePacks = resourcePackFolder.listFiles();
|
||||
@ -243,7 +242,7 @@ public synchronized ResourcePack getResourcePack() throws IOException, Interrupt
|
||||
resources.add(resourceExtensionsFile);
|
||||
|
||||
try {
|
||||
resourcePack = new ResourcePack(minecraftVersion);
|
||||
resourcePack = new ResourcePack();
|
||||
if (textureExportFile.exists()) resourcePack.loadTextureFile(textureExportFile);
|
||||
resourcePack.load(resources);
|
||||
resourcePack.saveTextureFile(textureExportFile);
|
||||
|
@ -59,10 +59,8 @@
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.map.BmMap;
|
||||
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.world.Block;
|
||||
import de.bluecolored.bluemap.core.world.Chunk;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -528,24 +526,21 @@ public int debugBlockCommand(CommandContext<S> context) {
|
||||
new Thread(() -> {
|
||||
// collect and output debug info
|
||||
Vector3i blockPos = position.floor().toInt();
|
||||
Block block = world.getBlock(blockPos);
|
||||
Block blockBelow = world.getBlock(blockPos.add(0, -1, 0));
|
||||
Block<?> block = new Block<>(world, blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
Block<?> blockBelow = new Block<>(null, 0, 0, 0).copy(block, 0, -1, 0);
|
||||
|
||||
String blockIdMeta = "";
|
||||
String blockBelowIdMeta = "";
|
||||
// populate lazy-loaded values
|
||||
block.getBlockState();
|
||||
block.getBiomeId();
|
||||
block.getLightData();
|
||||
|
||||
Vector2i chunkPos = world.getChunkGrid().getCell(blockPos.toVector2(true));
|
||||
Chunk chunk = world.getChunk(chunkPos.getX(), chunkPos.getY());
|
||||
|
||||
if (chunk instanceof ChunkAnvil112) {
|
||||
blockIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(blockPos) + ")";
|
||||
blockBelowIdMeta = " (" + ((ChunkAnvil112) chunk).getBlockIdMeta(blockPos.add(0, -1, 0)) + ")";
|
||||
}
|
||||
blockBelow.getBlockState();
|
||||
blockBelow.getBiomeId();
|
||||
blockBelow.getLightData();
|
||||
|
||||
source.sendMessages(Arrays.asList(
|
||||
Text.of(TextColor.GOLD, "Block at you: ", TextColor.WHITE, block, TextColor.GRAY, blockIdMeta),
|
||||
Text.of(TextColor.GOLD, "Block below you: ", TextColor.WHITE, blockBelow, TextColor.GRAY, blockBelowIdMeta),
|
||||
Text.of(TextColor.GOLD, "Chunk: ", TextColor.WHITE, chunk)
|
||||
Text.of(TextColor.GOLD, "Block at you: ", TextColor.WHITE, block),
|
||||
Text.of(TextColor.GOLD, "Block below you: ", TextColor.WHITE, blockBelow)
|
||||
));
|
||||
}).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 @@
|
||||
|
||||
|
||||
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 org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
|
||||
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.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@ -54,10 +54,6 @@ public class ConfigManager {
|
||||
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.
|
||||
*
|
||||
@ -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 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
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @return The loaded configuration node
|
||||
* @throws IOException if an IOException occurs while loading
|
||||
*/
|
||||
public ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL defaultValues, boolean usePlaceholders, boolean generateEmptyConfig) throws IOException {
|
||||
|
||||
@ -116,107 +112,6 @@ public ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL de
|
||||
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){
|
||||
if (url.getFile().endsWith(".json")) return GsonConfigurationLoader.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;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
||||
import de.bluecolored.bluemap.core.world.*;
|
||||
import de.bluecolored.bluemap.core.world.Chunk;
|
||||
import de.bluecolored.bluemap.core.world.Grid;
|
||||
import de.bluecolored.bluemap.core.world.Region;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
@ -62,22 +88,6 @@ public Grid 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
|
||||
public Chunk getChunkAtBlock(int x, int y, int z) {
|
||||
return delegate.getChunkAtBlock(x, y, z);
|
||||
@ -113,9 +123,4 @@ public void 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;
|
||||
|
||||
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
||||
|
@ -29,7 +29,7 @@
|
||||
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
|
||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||
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.World;
|
||||
|
||||
@ -54,9 +54,8 @@ public HiresTileMeta render(World world, Vector3i modelMin, Vector3i modelMax, H
|
||||
BlockStateModelFactory modelFactory = new BlockStateModelFactory(resourcePack, renderSettings);
|
||||
|
||||
int maxHeight, minY, maxY;
|
||||
float dx, dz;
|
||||
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);
|
||||
|
||||
int x, y, z;
|
||||
@ -96,13 +95,6 @@ public HiresTileMeta render(World world, Vector3i modelMin, Vector3i modelMax, H
|
||||
maxHeight = y;
|
||||
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);
|
||||
@ -113,20 +105,4 @@ public HiresTileMeta render(World world, Vector3i modelMin, Vector3i modelMax, H
|
||||
|
||||
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;
|
||||
|
||||
import de.bluecolored.bluemap.core.util.math.Color;
|
||||
@ -37,7 +61,7 @@ public void setColor(int x, int z, Color color) {
|
||||
}
|
||||
|
||||
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 + 1] = g;
|
||||
colors[index + 2] = b;
|
||||
@ -45,7 +69,7 @@ private void setColor(int x, int z, float r, float g, float b, float a) {
|
||||
}
|
||||
|
||||
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(
|
||||
colors[index ],
|
||||
colors[index + 1],
|
||||
|
@ -24,12 +24,14 @@
|
||||
*/
|
||||
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.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.world.Block;
|
||||
import de.bluecolored.bluemap.core.world.BlockNeighborhood;
|
||||
import de.bluecolored.bluemap.core.world.BlockState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -46,25 +48,20 @@ public class BlockStateModelFactory {
|
||||
public BlockStateModelFactory(ResourcePack resourcePack, RenderSettings renderSettings) {
|
||||
this.resourcePack = resourcePack;
|
||||
|
||||
Block[] neighborCache = new Block[3 * 3 * 3];
|
||||
for (int i = 0; i < neighborCache.length; i++) {
|
||||
neighborCache[i] = new Block(null, 0, 0, 0);
|
||||
}
|
||||
|
||||
this.resourceModelBuilder = new ResourceModelBuilder(resourcePack, renderSettings, neighborCache);
|
||||
this.liquidModelBuilder = new LiquidModelBuilder(resourcePack, renderSettings, neighborCache);
|
||||
this.resourceModelBuilder = new ResourceModelBuilder(resourcePack, renderSettings);
|
||||
this.liquidModelBuilder = new LiquidModelBuilder(resourcePack, renderSettings);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
if (blockState.isAir) return;
|
||||
if (blockState.isAir()) return;
|
||||
|
||||
int modelStart = blockModel.getStart();
|
||||
|
||||
@ -72,15 +69,14 @@ public void render(Block block, BlockState blockState, BlockModelView blockModel
|
||||
renderModel(block, blockState, blockModel.initialize(), blockColor);
|
||||
|
||||
// add water if block is waterlogged
|
||||
if (blockState.isWaterlogged) {
|
||||
if (blockState.isWaterlogged() || block.getProperties().isAlwaysWaterlogged()) {
|
||||
renderModel(block, WATERLOGGED_BLOCKSTATE, blockModel.initialize(), blockColor);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
BlockStateResource resource = resourcePack.getBlockStateResource(blockState);
|
||||
@ -98,6 +94,6 @@ private void renderModel(Block block, BlockState blockState, BlockModelView bloc
|
||||
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 @@
|
||||
|
||||
import com.flowpowered.math.TrigMath;
|
||||
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.HiresTileModel;
|
||||
import de.bluecolored.bluemap.core.map.hires.RenderSettings;
|
||||
import de.bluecolored.bluemap.core.resourcepack.BlockColorCalculatorFactory;
|
||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||
import de.bluecolored.bluemap.core.resourcepack.Texture;
|
||||
import de.bluecolored.bluemap.core.resourcepack.TransformedBlockModelResource;
|
||||
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.math.Color;
|
||||
import de.bluecolored.bluemap.core.util.math.MatrixM3f;
|
||||
import de.bluecolored.bluemap.core.util.math.VectorM2f;
|
||||
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.ResourcePackBlock;
|
||||
|
||||
/**
|
||||
* A model builder for all liquid blocks
|
||||
@ -57,24 +56,19 @@ public class LiquidModelBuilder {
|
||||
private final BlockColorCalculatorFactory.BlockColorCalculator blockColorCalculator;
|
||||
private final RenderSettings renderSettings;
|
||||
|
||||
private final boolean useWaterColorMap;
|
||||
|
||||
private final VectorM3f[] corners;
|
||||
private final Block[] blocksAround;
|
||||
private final VectorM2f[] uvs = new VectorM2f[4];
|
||||
|
||||
private Block block;
|
||||
private BlockNeighborhood<?> block;
|
||||
private BlockState blockState;
|
||||
private TransformedBlockModelResource blockModelResource;
|
||||
private BlockModelView blockModel;
|
||||
private Color blockColor;
|
||||
|
||||
public LiquidModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings, Block[] neighborCache) {
|
||||
public LiquidModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings) {
|
||||
this.blockColorCalculator = resourcePack.getBlockColorCalculatorFactory().createCalculator();
|
||||
this.renderSettings = renderSettings;
|
||||
|
||||
this.useWaterColorMap = resourcePack.getMinecraftVersion().isAtLeast(new MinecraftVersion(1, 13));
|
||||
|
||||
corners = new VectorM3f[]{
|
||||
new VectorM3f( 0, 0, 0 ),
|
||||
new VectorM3f( 0, 0, 16 ),
|
||||
@ -86,12 +80,10 @@ public LiquidModelBuilder(ResourcePack resourcePack, RenderSettings renderSettin
|
||||
new VectorM3f( 16, 16, 16 ),
|
||||
};
|
||||
|
||||
this.blocksAround = neighborCache;
|
||||
|
||||
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.blockState = blockState;
|
||||
this.blockModelResource = bmr;
|
||||
@ -107,7 +99,7 @@ private void build() {
|
||||
|
||||
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[5].y = getLiquidCornerHeight(-1, 0);
|
||||
corners[6].y = getLiquidCornerHeight(0, -1);
|
||||
@ -126,7 +118,7 @@ private void build() {
|
||||
int flowTextureId = flowTexture.getId();
|
||||
|
||||
tintcolor.set(1f, 1f, 1f, 1f, true);
|
||||
if (useWaterColorMap && blockState.isWater) {
|
||||
if (blockState.isWater()) {
|
||||
blockColorCalculator.getWaterAverageColor(block, tintcolor);
|
||||
}
|
||||
|
||||
@ -166,7 +158,7 @@ private float getLiquidCornerHeight(int x, int z){
|
||||
|
||||
for (ix = x; ix <= x+1; ix++){
|
||||
for (iz = z; iz<= z+1; iz++){
|
||||
if (isSameLiquid(getNeighborBlock(ix, 1, iz).getBlockState())){
|
||||
if (isSameLiquid(block.getNeighborBlock(ix, 1, iz))){
|
||||
return 16f;
|
||||
}
|
||||
}
|
||||
@ -174,12 +166,14 @@ private float getLiquidCornerHeight(int x, int z){
|
||||
|
||||
float sumHeight = 0f;
|
||||
int count = 0;
|
||||
ResourcePackBlock<?> neighbor;
|
||||
BlockState neighborBlockState;
|
||||
|
||||
for (ix = x; ix <= x+1; ix++){
|
||||
for (iz = z; iz<= z+1; iz++){
|
||||
neighborBlockState = getNeighborBlock(ix, 0, iz).getBlockState();
|
||||
if (isSameLiquid(neighborBlockState)){
|
||||
neighbor = block.getNeighborBlock(ix, 0, iz);
|
||||
neighborBlockState = neighbor.getBlockState();
|
||||
if (isSameLiquid(neighbor)){
|
||||
if (getLiquidLevel(neighborBlockState) == 0) return 14f;
|
||||
|
||||
sumHeight += getLiquidBaseHeight(neighborBlockState);
|
||||
@ -203,9 +197,9 @@ private boolean isLiquidBlockingBlock(BlockState blockState){
|
||||
return !blockState.equals(BlockState.AIR);
|
||||
}
|
||||
|
||||
private boolean isSameLiquid(BlockState blockState){
|
||||
if (blockState.getFullId().equals(this.blockState.getFullId())) return true;
|
||||
return this.blockState.isWater && blockState.isWaterlogged;
|
||||
private boolean isSameLiquid(ResourcePackBlock<?> block){
|
||||
if (block.getBlockState().getFullId().equals(this.blockState.getFullId())) return true;
|
||||
return this.blockState.isWater() && (block.getBlockState().isWaterlogged() || block.getProperties().isAlwaysWaterlogged());
|
||||
}
|
||||
|
||||
private float getLiquidBaseHeight(BlockState block){
|
||||
@ -223,13 +217,13 @@ private boolean createElementFace(Direction faceDir, VectorM3f c0, VectorM3f c1,
|
||||
Vector3i faceDirVector = faceDir.toVector();
|
||||
|
||||
//face culling
|
||||
Block bl = getNeighborBlock(
|
||||
ResourcePackBlock<?> bl = block.getNeighborBlock(
|
||||
faceDirVector.getX(),
|
||||
faceDirVector.getY(),
|
||||
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
|
||||
blockModel.initialize();
|
||||
@ -327,17 +321,6 @@ private boolean createElementFace(Direction faceDir, VectorM3f c0, VectorM3f c1,
|
||||
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 int getFlowingAngle() {
|
||||
float own = getLiquidBaseHeight(blockState) * BLOCK_SCALE;
|
||||
@ -358,11 +341,11 @@ private int getFlowingAngle() {
|
||||
}
|
||||
|
||||
private float compareLiquidHeights(float ownHeight, int dx, int dz) {
|
||||
BlockState state = getNeighborBlock(dx, 0, dz).getBlockState();
|
||||
if (state.isAir) return 0;
|
||||
if (!isSameLiquid(state)) return 0;
|
||||
ResourcePackBlock<?> neighbor = block.getNeighborBlock(dx, 0, dz);
|
||||
if (neighbor.getBlockState().isAir()) return 0;
|
||||
if (!isSameLiquid(neighbor)) return 0;
|
||||
|
||||
float otherHeight = getLiquidBaseHeight(state) * BLOCK_SCALE;
|
||||
float otherHeight = getLiquidBaseHeight(neighbor.getBlockState()) * BLOCK_SCALE;
|
||||
return otherHeight - ownHeight;
|
||||
}
|
||||
|
||||
|
@ -32,13 +32,19 @@
|
||||
import de.bluecolored.bluemap.core.map.hires.BlockModelView;
|
||||
import de.bluecolored.bluemap.core.map.hires.HiresTileModel;
|
||||
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.math.Color;
|
||||
import de.bluecolored.bluemap.core.util.math.MatrixM4f;
|
||||
import de.bluecolored.bluemap.core.util.math.VectorM2f;
|
||||
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.
|
||||
@ -54,24 +60,22 @@ public class ResourceModelBuilder {
|
||||
private final VectorM2f[] uvs = new VectorM2f[4];
|
||||
private final Color tintColor = new Color();
|
||||
private final Color mapColor = new Color();
|
||||
private final Block[] blocksAround;
|
||||
|
||||
private Block block;
|
||||
private BlockNeighborhood<?> block;
|
||||
private TransformedBlockModelResource blockModelResource;
|
||||
private BlockModelView blockModel;
|
||||
private Color blockColor;
|
||||
|
||||
public ResourceModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings, Block[] neighborCache) {
|
||||
public ResourceModelBuilder(ResourcePack resourcePack, RenderSettings renderSettings) {
|
||||
this.blockColorCalculator = resourcePack.getBlockColorCalculatorFactory().createCalculator();
|
||||
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 < uvs.length; i++) rawUvs[i] = new VectorM2f(0, 0);
|
||||
}
|
||||
|
||||
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.blockModel = blockModel;
|
||||
this.blockColor = color;
|
||||
@ -97,6 +101,13 @@ public void build(Block block, TransformedBlockModelResource bmr, BlockModelView
|
||||
);
|
||||
}
|
||||
|
||||
//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();
|
||||
@ -149,14 +160,17 @@ private void createElementFace(BlockModelResource.Element element, Direction fac
|
||||
|
||||
// face culling
|
||||
if (face.getCullface() != null) {
|
||||
Block b = getRotationRelativeBlock(face.getCullface());
|
||||
if (b.isCullingNeighborFaces()) return;
|
||||
ResourcePackBlock<?> b = getRotationRelativeBlock(face.getCullface());
|
||||
if (b.getProperties().isCulling()) return;
|
||||
}
|
||||
|
||||
// light calculation
|
||||
Block facedBlockNeighbor = getRotationRelativeBlock(faceDir);
|
||||
int sunLight = facedBlockNeighbor.getPassedSunLight();
|
||||
int blockLight = facedBlockNeighbor.getPassedBlockLight();
|
||||
ResourcePackBlock<?> facedBlockNeighbor = getRotationRelativeBlock(faceDir);
|
||||
LightData blockLightData = block.getLightData();
|
||||
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
|
||||
if (sunLight == 0f && renderSettings.isExcludeFacesWithoutSunlight()) return;
|
||||
@ -302,23 +316,11 @@ private void createElementFace(BlockModelResource.Element element, Direction fac
|
||||
}
|
||||
}
|
||||
|
||||
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 Block getRotationRelativeBlock(Direction direction){
|
||||
private ResourcePackBlock<?> getRotationRelativeBlock(Direction direction){
|
||||
return getRotationRelativeBlock(direction.toVector());
|
||||
}
|
||||
|
||||
|
||||
private Block getRotationRelativeBlock(Vector3i direction){
|
||||
private ResourcePackBlock<?> getRotationRelativeBlock(Vector3i direction){
|
||||
return getRotationRelativeBlock(
|
||||
direction.getX(),
|
||||
direction.getY(),
|
||||
@ -327,11 +329,11 @@ private Block getRotationRelativeBlock(Vector3i direction){
|
||||
}
|
||||
|
||||
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);
|
||||
makeRotationRelative(rotationRelativeBlockDirection);
|
||||
|
||||
return getNeighborBlock(
|
||||
return block.getNeighborBlock(
|
||||
Math.round(rotationRelativeBlockDirection.x),
|
||||
Math.round(rotationRelativeBlockDirection.y),
|
||||
Math.round(rotationRelativeBlockDirection.z)
|
||||
@ -369,23 +371,28 @@ private float testAo(VectorM3f vertex, Direction dir){
|
||||
|
||||
|
||||
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 (getRotationRelativeBlock(x, 0, z).isOccludingNeighborFaces()) occluding++;
|
||||
if (getRotationRelativeBlock(x, 0, z).getProperties().isOccluding()) occluding++;
|
||||
}
|
||||
|
||||
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 (getRotationRelativeBlock(x, y, z).isOccludingNeighborFaces()) occluding++;
|
||||
if (getRotationRelativeBlock(x, y, z).getProperties().isOccluding()) occluding++;
|
||||
}
|
||||
|
||||
if (occluding > 3) occluding = 3;
|
||||
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;
|
||||
|
||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||
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.BlockState;
|
||||
import de.bluecolored.bluemap.core.world.LightData;
|
||||
@ -38,21 +36,15 @@
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ChunkAnvil113 extends MCAChunk {
|
||||
private static final MinecraftVersion VERSION = new MinecraftVersion(1, 13);
|
||||
|
||||
private BiomeMapper biomeIdMapper;
|
||||
|
||||
private boolean isGenerated;
|
||||
private boolean hasLight;
|
||||
private Section[] sections;
|
||||
private int[] biomes;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkAnvil113(CompoundTag chunkTag, boolean ignoreMissingLightData, BiomeMapper biomeIdMapper) {
|
||||
public ChunkAnvil113(CompoundTag chunkTag, boolean ignoreMissingLightData) {
|
||||
super(chunkTag);
|
||||
|
||||
this.biomeIdMapper = biomeIdMapper;
|
||||
|
||||
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
||||
|
||||
String status = levelData.getString("Status");
|
||||
@ -124,14 +116,14 @@ public LightData getLightData(int x, int y, int z, LightData target) {
|
||||
}
|
||||
|
||||
@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)
|
||||
z = z & 0xF;
|
||||
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 {
|
||||
@ -178,7 +170,7 @@ public Section(CompoundTag sectionData) {
|
||||
}
|
||||
}
|
||||
|
||||
palette[i] = new BlockState(VERSION, id, properties);
|
||||
palette[i] = new BlockState(id, properties);
|
||||
}
|
||||
} else {
|
||||
this.palette = new BlockState[0];
|
||||
|
@ -24,9 +24,7 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.mca;
|
||||
|
||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||
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.BlockState;
|
||||
import de.bluecolored.bluemap.core.world.LightData;
|
||||
@ -38,21 +36,15 @@
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ChunkAnvil115 extends MCAChunk {
|
||||
private static final MinecraftVersion VERSION = new MinecraftVersion(1, 15);
|
||||
|
||||
private BiomeMapper biomeIdMapper;
|
||||
|
||||
private boolean isGenerated;
|
||||
private boolean hasLight;
|
||||
private Section[] sections;
|
||||
private int[] biomes;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkAnvil115(CompoundTag chunkTag, boolean ignoreMissingLightData, BiomeMapper biomeIdMapper) {
|
||||
public ChunkAnvil115(CompoundTag chunkTag, boolean ignoreMissingLightData) {
|
||||
super(chunkTag);
|
||||
|
||||
this.biomeIdMapper = biomeIdMapper;
|
||||
|
||||
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
||||
|
||||
String status = levelData.getString("Status");
|
||||
@ -124,16 +116,16 @@ public LightData getLightData(int x, int y, int z, LightData target) {
|
||||
}
|
||||
|
||||
@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)
|
||||
z = (z & 0xF) / 4;
|
||||
y = y / 4;
|
||||
int biomeIntIndex = y * 16 + z * 4 + x;
|
||||
|
||||
if (biomeIntIndex < 0) return Biome.DEFAULT;
|
||||
if (biomeIntIndex >= this.biomes.length) return Biome.DEFAULT;
|
||||
if (biomeIntIndex < 0) return Biome.DEFAULT.getNumeralId();
|
||||
if (biomeIntIndex >= this.biomes.length) return Biome.DEFAULT.getNumeralId();
|
||||
|
||||
return biomeIdMapper.get(biomes[biomeIntIndex]);
|
||||
return biomes[biomeIntIndex];
|
||||
}
|
||||
|
||||
private static class Section {
|
||||
@ -180,7 +172,7 @@ public Section(CompoundTag sectionData) {
|
||||
}
|
||||
}
|
||||
|
||||
palette[i] = new BlockState(VERSION, id, properties);
|
||||
palette[i] = new BlockState(id, properties);
|
||||
}
|
||||
} else {
|
||||
this.palette = new BlockState[0];
|
||||
|
@ -24,9 +24,7 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.mca;
|
||||
|
||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||
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.BlockState;
|
||||
import de.bluecolored.bluemap.core.world.LightData;
|
||||
@ -39,10 +37,6 @@
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ChunkAnvil116 extends MCAChunk {
|
||||
private static final MinecraftVersion VERSION = new MinecraftVersion(1, 16);
|
||||
|
||||
private BiomeMapper biomeIdMapper;
|
||||
|
||||
private boolean isGenerated;
|
||||
private boolean hasLight;
|
||||
|
||||
@ -52,11 +46,9 @@ public class ChunkAnvil116 extends MCAChunk {
|
||||
private int[] biomes;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkAnvil116(CompoundTag chunkTag, boolean ignoreMissingLightData, BiomeMapper biomeIdMapper) {
|
||||
public ChunkAnvil116(CompoundTag chunkTag, boolean ignoreMissingLightData) {
|
||||
super(chunkTag);
|
||||
|
||||
this.biomeIdMapper = biomeIdMapper;
|
||||
|
||||
CompoundTag levelData = chunkTag.getCompoundTag("Level");
|
||||
|
||||
String status = levelData.getString("Status");
|
||||
@ -138,8 +130,8 @@ public LightData getLightData(int x, int y, int z, LightData target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(int x, int y, int z) {
|
||||
if (biomes.length < 16) return Biome.DEFAULT;
|
||||
public int getBiome(int x, int y, int z) {
|
||||
if (biomes.length < 16) return Biome.DEFAULT.getNumeralId();
|
||||
|
||||
x = (x & 0xF) / 4; // Math.floorMod(pos.getX(), 16)
|
||||
z = (z & 0xF) / 4;
|
||||
@ -150,7 +142,7 @@ public Biome getBiome(int x, int y, int z) {
|
||||
if (biomeIntIndex >= biomes.length) biomeIntIndex -= (((biomeIntIndex - biomes.length) >> 4) + 1) * 16;
|
||||
if (biomeIntIndex < 0) biomeIntIndex -= (biomeIntIndex >> 4) * 16;
|
||||
|
||||
return biomeIdMapper.get(biomes[biomeIntIndex]);
|
||||
return biomes[biomeIntIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -213,7 +205,7 @@ public Section(CompoundTag sectionData) {
|
||||
}
|
||||
}
|
||||
|
||||
palette[i] = new BlockState(VERSION, id, properties);
|
||||
palette[i] = new BlockState(id, properties);
|
||||
}
|
||||
} else {
|
||||
this.palette = new BlockState[0];
|
||||
|
@ -48,8 +48,8 @@ public LightData getLightData(int x, int y, int z, LightData target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(int x, int y, int z) {
|
||||
return Biome.DEFAULT;
|
||||
public int getBiome(int x, int y, int z) {
|
||||
return Biome.DEFAULT.getNumeralId();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
*/
|
||||
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.Chunk;
|
||||
import de.bluecolored.bluemap.core.world.LightData;
|
||||
@ -59,7 +58,7 @@ public int getDataVersion() {
|
||||
public abstract LightData getLightData(int x, int y, int z, LightData target);
|
||||
|
||||
@Override
|
||||
public abstract Biome getBiome(int x, int y, int z);
|
||||
public abstract int getBiome(int x, int y, int z);
|
||||
|
||||
@Override
|
||||
public int getMaxY(int x, int z) {
|
||||
@ -74,10 +73,9 @@ public int getMinY(int x, int z) {
|
||||
public static MCAChunk create(MCAWorld world, CompoundTag chunkTag, boolean ignoreMissingLightData) throws IOException {
|
||||
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, world.getBiomeIdMapper());
|
||||
if (version < 2500) return new ChunkAnvil115(chunkTag, ignoreMissingLightData, world.getBiomeIdMapper());
|
||||
return new ChunkAnvil116(chunkTag, ignoreMissingLightData, world.getBiomeIdMapper());
|
||||
if (version < 2200) return new ChunkAnvil113(chunkTag, ignoreMissingLightData);
|
||||
if (version < 2500) return new ChunkAnvil115(chunkTag, ignoreMissingLightData);
|
||||
return new ChunkAnvil116(chunkTag, ignoreMissingLightData);
|
||||
}
|
||||
|
||||
public static MCAChunk empty() {
|
||||
|
@ -29,20 +29,13 @@
|
||||
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.debug.DebugDump;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.mca.extensions.*;
|
||||
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
|
||||
import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper;
|
||||
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 de.bluecolored.bluemap.core.world.BlockState;
|
||||
import de.bluecolored.bluemap.core.world.Grid;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
import net.querz.nbt.CompoundTag;
|
||||
import net.querz.nbt.ListTag;
|
||||
import net.querz.nbt.NBTUtil;
|
||||
import net.querz.nbt.Tag;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -58,62 +51,28 @@ public class MCAWorld implements World {
|
||||
|
||||
@DebugDump private final UUID uuid;
|
||||
@DebugDump private final Path worldFolder;
|
||||
private final MinecraftVersion minecraftVersion;
|
||||
@DebugDump private final String name;
|
||||
@DebugDump private final Vector3i spawnPoint;
|
||||
|
||||
@DebugDump private final boolean ignoreMissingLightData;
|
||||
|
||||
private final LoadingCache<Vector2i, MCARegion> regionCache;
|
||||
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(
|
||||
Path worldFolder,
|
||||
UUID uuid,
|
||||
MinecraftVersion minecraftVersion,
|
||||
String name,
|
||||
Vector3i spawnPoint,
|
||||
BlockIdMapper blockIdMapper,
|
||||
BlockPropertiesMapper blockPropertiesMapper,
|
||||
BiomeMapper biomeMapper,
|
||||
boolean ignoreMissingLightData
|
||||
) {
|
||||
this.uuid = uuid;
|
||||
this.worldFolder = worldFolder;
|
||||
this.minecraftVersion = minecraftVersion;
|
||||
this.name = name;
|
||||
this.spawnPoint = spawnPoint;
|
||||
|
||||
this.blockIdMapper = blockIdMapper;
|
||||
this.blockPropertiesMapper = blockPropertiesMapper;
|
||||
this.biomeMapper = biomeMapper;
|
||||
|
||||
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()
|
||||
.executor(BlueMap.THREAD_POOL)
|
||||
.maximumSize(100)
|
||||
@ -131,34 +90,6 @@ public BlockState getBlockState(Vector3i pos) {
|
||||
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
|
||||
public MCAChunk getChunkAtBlock(int x, int y, int z) {
|
||||
return getChunk(new Vector2i(x >> 4, z >> 4));
|
||||
@ -166,19 +97,19 @@ public MCAChunk getChunkAtBlock(int x, int y, int z) {
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@ -265,42 +196,10 @@ public void cleanUpChunkCache() {
|
||||
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() {
|
||||
return worldFolder;
|
||||
}
|
||||
|
||||
public String getForgeBlockIdMapping(int id) {
|
||||
return forgeBlockMappings.get(id);
|
||||
}
|
||||
|
||||
public MinecraftVersion getMinecraftVersion() {
|
||||
return minecraftVersion;
|
||||
}
|
||||
|
||||
private Path getRegionFolder() {
|
||||
return worldFolder.resolve("region");
|
||||
}
|
||||
@ -309,12 +208,6 @@ private File getMCAFile(int regionX, int regionZ) {
|
||||
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) {
|
||||
return loadRegion(regionPos.getX(), regionPos.getY());
|
||||
}
|
||||
@ -356,11 +249,11 @@ private MCAChunk loadChunk(int x, int z) {
|
||||
return MCAChunk.empty();
|
||||
}
|
||||
|
||||
public static MCAWorld load(Path worldFolder, UUID uuid, MinecraftVersion version, BlockIdMapper blockIdMapper, BlockPropertiesMapper blockPropertiesMapper, BiomeMapper biomeIdMapper) throws IOException {
|
||||
return load(worldFolder, uuid, version, blockIdMapper, blockPropertiesMapper, biomeIdMapper, null, false);
|
||||
public static MCAWorld load(Path worldFolder, UUID uuid) throws IOException {
|
||||
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 {
|
||||
StringBuilder subDimensionName = new StringBuilder();
|
||||
|
||||
@ -394,35 +287,13 @@ public static MCAWorld load(Path worldFolder, UUID uuid, MinecraftVersion versio
|
||||
levelData.getInt("SpawnZ")
|
||||
);
|
||||
|
||||
MCAWorld world = new MCAWorld(
|
||||
return new MCAWorld(
|
||||
worldFolder,
|
||||
uuid,
|
||||
version,
|
||||
name,
|
||||
spawnPoint,
|
||||
blockIdMapper,
|
||||
blockPropertiesMapper,
|
||||
biomeIdMapper,
|
||||
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) {
|
||||
throw new IOException("Invaid level.dat format!", ex);
|
||||
}
|
||||
@ -437,4 +308,17 @@ public String toString() {
|
||||
'}';
|
||||
}
|
||||
|
||||
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.matrix.Matrix3f;
|
||||
import com.flowpowered.math.vector.Vector2f;
|
||||
import com.flowpowered.math.vector.Vector3f;
|
||||
import de.bluecolored.bluemap.core.util.MathUtils;
|
||||
|
||||
@Deprecated
|
||||
public class Face {
|
||||
@ -51,7 +50,7 @@ public Face(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f uv1, Vector2f uv2, V
|
||||
|
||||
this.materialIndex = materialIndex;
|
||||
|
||||
this.n1 = getFaceNormal();
|
||||
this.n1 = calculateSurfaceNormal(new VectorM3f(0, 0, 0));
|
||||
this.n2 = new VectorM3f(n1);
|
||||
this.n3 = new VectorM3f(n1);
|
||||
this.normalizedNormals = true;
|
||||
@ -202,10 +201,6 @@ public void setMaterialIndex(int materialIndex) {
|
||||
this.materialIndex = materialIndex;
|
||||
}
|
||||
|
||||
private VectorM3f getFaceNormal() {
|
||||
return MathUtils.getSurfaceNormal(p1, p2, p3);
|
||||
}
|
||||
|
||||
private void normalizeNormals() {
|
||||
if (normalizedNormals) return;
|
||||
|
||||
@ -216,4 +211,31 @@ private void normalizeNormals() {
|
||||
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
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.mca.mapping;
|
||||
package de.bluecolored.bluemap.core.resourcepack;
|
||||
|
||||
import de.bluecolored.bluemap.core.world.Biome;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiomeMapper {
|
||||
import java.util.Map.Entry;
|
||||
|
||||
Biome get(int id);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -29,7 +29,7 @@
|
||||
import de.bluecolored.bluemap.core.util.ConfigUtils;
|
||||
import de.bluecolored.bluemap.core.util.math.Color;
|
||||
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 java.awt.image.BufferedImage;
|
||||
@ -40,21 +40,16 @@
|
||||
@DebugDump
|
||||
public class BlockColorCalculatorFactory {
|
||||
|
||||
private BufferedImage foliageMap;
|
||||
private BufferedImage grassMap;
|
||||
private final int[] foliageMap = new int[65536];
|
||||
private final int[] grassMap = new int[65536];
|
||||
|
||||
private final Map<String, ColorFunction> blockColorMap;
|
||||
|
||||
public BlockColorCalculatorFactory(BufferedImage foliageMap, BufferedImage grassMap) {
|
||||
this.foliageMap = foliageMap;
|
||||
this.grassMap = grassMap;
|
||||
|
||||
public BlockColorCalculatorFactory() {
|
||||
this.blockColorMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public void loadColorConfig(ConfigurationNode colorConfig) {
|
||||
blockColorMap.clear();
|
||||
|
||||
public void load(ConfigurationNode colorConfig) {
|
||||
for (Entry<Object, ? extends ConfigurationNode> entry : colorConfig.childrenMap().entrySet()){
|
||||
String key = entry.getKey().toString();
|
||||
String value = entry.getValue().getString("");
|
||||
@ -85,19 +80,11 @@ public void loadColorConfig(ConfigurationNode colorConfig) {
|
||||
}
|
||||
|
||||
public void setFoliageMap(BufferedImage foliageMap) {
|
||||
this.foliageMap = foliageMap;
|
||||
}
|
||||
|
||||
public BufferedImage getFoliageMap() {
|
||||
return foliageMap;
|
||||
foliageMap.getRGB(0, 0, 256, 256, this.foliageMap, 0, 256);
|
||||
}
|
||||
|
||||
public void setGrassMap(BufferedImage grassMap) {
|
||||
this.grassMap = grassMap;
|
||||
}
|
||||
|
||||
public BufferedImage getGrassMap() {
|
||||
return grassMap;
|
||||
grassMap.getRGB(0, 0, 256, 256, this.grassMap, 0, 256);
|
||||
}
|
||||
|
||||
public BlockColorCalculator createCalculator() {
|
||||
@ -106,14 +93,14 @@ public BlockColorCalculator createCalculator() {
|
||||
|
||||
@FunctionalInterface
|
||||
private interface ColorFunction {
|
||||
Color invoke(BlockColorCalculator calculator, Block block, Color target);
|
||||
Color invoke(BlockColorCalculator calculator, BlockNeighborhood block, Color target);
|
||||
}
|
||||
|
||||
public class BlockColorCalculator {
|
||||
|
||||
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();
|
||||
|
||||
ColorFunction colorFunction = blockColorMap.get(blockId);
|
||||
@ -123,7 +110,7 @@ public Color getBlockColor(Block block, Color 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");
|
||||
|
||||
int power = 15;
|
||||
@ -137,54 +124,23 @@ public Color getRedstoneColor(Block block, Color target) {
|
||||
);
|
||||
}
|
||||
|
||||
public Color getWaterAverageColor(Block block, Color target) {
|
||||
public Color getWaterAverageColor(BlockNeighborhood block, Color target) {
|
||||
target.set(0, 0, 0, 0, true);
|
||||
|
||||
int x, y, z,
|
||||
minX = block.getX() - 2,
|
||||
maxX = block.getX() + 2,
|
||||
minY = block.getY() - 1,
|
||||
maxY = block.getY() + 1,
|
||||
minZ = block.getZ() - 2,
|
||||
maxZ = block.getZ() + 2;
|
||||
minX = - 2,
|
||||
maxX = + 2,
|
||||
minY = - 1,
|
||||
maxY = + 1,
|
||||
minZ = - 2,
|
||||
maxZ = + 2;
|
||||
|
||||
for (x = minX; x <= maxX; x++) {
|
||||
for (y = minY; y <= maxY; y++) {
|
||||
for (z = minZ; z <= maxZ; z++) {
|
||||
target.add(block
|
||||
.getWorld()
|
||||
.getBiome(x, y, z)
|
||||
.getWaterColor()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target.flatten();
|
||||
}
|
||||
|
||||
public Color getFoliageAverageColor(Block block, Color target) {
|
||||
target.set(0, 0, 0, 0, true);
|
||||
|
||||
int x, y, z,
|
||||
minX = block.getX() - 2,
|
||||
maxX = block.getX() + 2,
|
||||
minY = block.getY() - 1,
|
||||
maxY = block.getY() + 1,
|
||||
minZ = block.getZ() - 2,
|
||||
maxZ = block.getZ() + 2;
|
||||
|
||||
int seaLevel = block.getWorld().getSeaLevel();
|
||||
int blocksAboveSeaLevel;
|
||||
Biome biome;
|
||||
|
||||
for (y = minY; y <= maxY; y++) {
|
||||
blocksAboveSeaLevel = Math.max(block.getY() - seaLevel, 0);
|
||||
|
||||
for (x = minX; x <= maxX; x++) {
|
||||
for (y = minY; y <= maxY; y++) {
|
||||
for (z = minZ; z <= maxZ; z++) {
|
||||
biome = block.getWorld().getBiome(x, y, z);
|
||||
target.add(getFoliageColor(biome, blocksAboveSeaLevel, tempColor));
|
||||
biome = block.getNeighborBlock(x, y, z).getBiome();
|
||||
target.add(biome.getWaterColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,33 +148,52 @@ public Color getFoliageAverageColor(Block block, Color target) {
|
||||
return target.flatten();
|
||||
}
|
||||
|
||||
public Color getFoliageColor(Biome biome, int blocksAboveSeaLevel, Color target) {
|
||||
getColorFromMap(biome, blocksAboveSeaLevel, foliageMap, target);
|
||||
public Color getFoliageAverageColor(BlockNeighborhood block, Color target) {
|
||||
target.set(0, 0, 0, 0, true);
|
||||
|
||||
int x, y, z,
|
||||
minX = - 2,
|
||||
maxX = + 2,
|
||||
minY = - 1,
|
||||
maxY = + 1,
|
||||
minZ = - 2,
|
||||
maxZ = + 2;
|
||||
|
||||
Biome biome;
|
||||
for (y = minY; y <= maxY; y++) {
|
||||
for (x = minX; x <= maxX; x++) {
|
||||
for (z = minZ; z <= maxZ; z++) {
|
||||
biome = block.getNeighborBlock(x, y, z).getBiome();
|
||||
target.add(getFoliageColor(biome, tempColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target.flatten();
|
||||
}
|
||||
|
||||
public Color getFoliageColor(Biome biome, Color target) {
|
||||
getColorFromMap(biome, foliageMap, 4764952, target);
|
||||
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);
|
||||
|
||||
int x, y, z,
|
||||
minX = block.getX() - 2,
|
||||
maxX = block.getX() + 2,
|
||||
minY = block.getY() - 1,
|
||||
maxY = block.getY() + 1,
|
||||
minZ = block.getZ() - 2,
|
||||
maxZ = block.getZ() + 2;
|
||||
minX = - 2,
|
||||
maxX = + 2,
|
||||
minY = - 1,
|
||||
maxY = + 1,
|
||||
minZ = - 2,
|
||||
maxZ = + 2;
|
||||
|
||||
int seaLevel = block.getWorld().getSeaLevel();
|
||||
int blocksAboveSeaLevel;
|
||||
Biome biome;
|
||||
|
||||
for (y = minY; y <= maxY; y++) {
|
||||
blocksAboveSeaLevel = Math.max(block.getY() - seaLevel, 0);
|
||||
|
||||
for (x = minX; x <= maxX; x++) {
|
||||
for (z = minZ; z <= maxZ; z++) {
|
||||
biome = block.getWorld().getBiome(x, y, z);
|
||||
target.add(getGrassColor(biome, blocksAboveSeaLevel, tempColor));
|
||||
biome = block.getNeighborBlock(x, y, z).getBiome();
|
||||
target.add(getGrassColor(biome, tempColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -226,24 +201,22 @@ public Color getGrassAverageColor(Block block, Color target) {
|
||||
return target.flatten();
|
||||
}
|
||||
|
||||
public Color getGrassColor(Biome biome, int blocksAboveSeaLevel, Color target) {
|
||||
getColorFromMap(biome, blocksAboveSeaLevel, grassMap, target);
|
||||
public Color getGrassColor(Biome biome, Color target) {
|
||||
getColorFromMap(biome, grassMap, 0xff52952f, target);
|
||||
return target.overlay(biome.getOverlayGrassColor());
|
||||
}
|
||||
|
||||
private void getColorFromMap(Biome biome, int blocksAboveSeaLevel, BufferedImage map, Color target) {
|
||||
float adjTemp = (float) GenericMath.clamp(biome.getTemp() - (0.00166667 * blocksAboveSeaLevel), 0, 1);
|
||||
float adjHumidity = (float) GenericMath.clamp(biome.getHumidity(), 0, 1) * adjTemp;
|
||||
private void getColorFromMap(Biome biome, int[] colorMap, int defaultColor, Color target) {
|
||||
double temperature = GenericMath.clamp(biome.getTemp(), 0, 1);
|
||||
double humidity = GenericMath.clamp(biome.getHumidity(), 0, 1) * temperature;
|
||||
|
||||
int x = (int) ((1 - adjTemp) * map.getWidth());
|
||||
int y = (int) ((1 - adjHumidity) * map.getHeight());
|
||||
int x = (int) ((1.0 - temperature) * 255.0);
|
||||
int y = (int) ((1.0 - humidity) * 255.0);
|
||||
|
||||
int cValue = map.getRGB(
|
||||
GenericMath.clamp(x, 0, map.getWidth() - 1),
|
||||
GenericMath.clamp(y, 0, map.getHeight() - 1)
|
||||
);
|
||||
int index = y << 8 | x;
|
||||
int color = index >= colorMap.length ? defaultColor : colorMap[index];
|
||||
|
||||
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
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.config;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
package de.bluecolored.bluemap.core.resourcepack;
|
||||
|
||||
import de.bluecolored.bluemap.core.world.BlockState;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
class BlockStateMapping<T> {
|
||||
private BlockState blockState;
|
||||
private T mapping;
|
@ -24,21 +24,34 @@
|
||||
*/
|
||||
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.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.CaseInsensitiveFileAccess;
|
||||
import de.bluecolored.bluemap.core.resourcepack.fileaccess.CombinedFileAccess;
|
||||
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 org.apache.commons.io.output.ByteArrayOutputStream;
|
||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
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.
|
||||
@ -46,61 +59,29 @@
|
||||
@DebugDump
|
||||
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 Map<String, BlockStateResource> blockStateResources;
|
||||
private final Map<String, BlockModelResource> blockModelResources;
|
||||
private final TextureGallery textures;
|
||||
|
||||
private final BlockPropertiesConfig blockPropertiesConfig;
|
||||
private final BiomeConfig biomeConfig;
|
||||
private final BlockColorCalculatorFactory blockColorCalculatorFactory;
|
||||
|
||||
private final Map<String, List<Resource>> configs;
|
||||
|
||||
private BufferedImage foliageMap;
|
||||
private BufferedImage grassMap;
|
||||
|
||||
public ResourcePack(MinecraftVersion minecraftVersion) {
|
||||
this.minecraftVersion = minecraftVersion;
|
||||
private final LoadingCache<BlockState, BlockProperties> blockPropertiesCache;
|
||||
|
||||
public ResourcePack() {
|
||||
blockStateResources = new HashMap<>();
|
||||
blockModelResources = new HashMap<>();
|
||||
textures = new TextureGallery();
|
||||
foliageMap = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
|
||||
foliageMap.setRGB(0, 0, 0xFF00FF00);
|
||||
grassMap = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
|
||||
grassMap.setRGB(0, 0, 0xFF00FF00);
|
||||
blockColorCalculatorFactory = new BlockColorCalculatorFactory(foliageMap, grassMap);
|
||||
configs = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
blockPropertiesConfig = new BlockPropertiesConfig();
|
||||
biomeConfig = new BiomeConfig();
|
||||
blockColorCalculatorFactory = new BlockColorCalculatorFactory();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
blockPropertiesCache = Caffeine.newBuilder()
|
||||
.executor(BlueMap.THREAD_POOL)
|
||||
.maximumSize(10000)
|
||||
.build(this::getBlockPropertiesNoCache);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,37 +140,61 @@ public void load(File... sources) throws InterruptedException {
|
||||
String filename = FileAccess.getFileName(blockstateFile);
|
||||
if (!filename.endsWith(".json")) continue;
|
||||
|
||||
String jsonFileName = filename.substring(0, filename.length() - 5);
|
||||
try {
|
||||
blockStateResources.put(namespace + ":" + filename.substring(0, filename.length() - 5), builder.build(blockstateFile));
|
||||
blockStateResources.put(namespace + ":" + jsonFileName, builder.build(blockstateFile));
|
||||
} 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
|
||||
for (String configName : CONFIG_FILES) {
|
||||
//load biomes
|
||||
try {
|
||||
Resource config = new Resource(sourcesAccess.readFile(
|
||||
"assets/" + namespace + "/" + configName));
|
||||
configs.computeIfAbsent(configName, t -> new ArrayList<>()).add(config);
|
||||
} catch (FileNotFoundException ignore) {
|
||||
GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
|
||||
.source(() -> new BufferedReader(new InputStreamReader(sourcesAccess.readFile(
|
||||
"assets/" + namespace + "/biomes.json"))))
|
||||
.build();
|
||||
biomeConfig.load(loader.load());
|
||||
} 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 {
|
||||
foliageMap = ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/foliage.png"));
|
||||
blockColorCalculatorFactory.setFoliageMap(foliageMap);
|
||||
} catch (IOException ex) {
|
||||
blockColorCalculatorFactory.setFoliageMap(
|
||||
ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/foliage.png"))
|
||||
);
|
||||
} catch (IOException | ArrayIndexOutOfBoundsException ex) {
|
||||
Logger.global.logError("Failed to load foliagemap!", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
grassMap = ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/grass.png"));
|
||||
blockColorCalculatorFactory.setGrassMap(grassMap);
|
||||
} catch (IOException ex) {
|
||||
blockColorCalculatorFactory.setGrassMap(
|
||||
ImageIO.read(sourcesAccess.readFile("assets/minecraft/textures/colormap/grass.png"))
|
||||
);
|
||||
} catch (IOException | ArrayIndexOutOfBoundsException ex) {
|
||||
Logger.global.logError("Failed to load grassmap!", ex);
|
||||
}
|
||||
|
||||
@ -198,6 +203,22 @@ public void load(File... sources) throws InterruptedException {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param state The {@link BlockState}
|
||||
@ -210,15 +231,47 @@ public BlockStateResource getBlockStateResource(BlockState state) throws NoSuchR
|
||||
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() {
|
||||
return blockColorCalculatorFactory;
|
||||
}
|
||||
|
||||
public MinecraftVersion getMinecraftVersion() {
|
||||
return minecraftVersion;
|
||||
}
|
||||
|
||||
protected static String namespacedToAbsoluteResourcePath(String namespacedPath, String resourceTypeFolder) {
|
||||
public static String namespacedToAbsoluteResourcePath(String namespacedPath, String resourceTypeFolder) {
|
||||
String path = namespacedPath;
|
||||
|
||||
resourceTypeFolder = FileAccess.normalize(resourceTypeFolder);
|
||||
@ -246,7 +299,7 @@ public static class Resource {
|
||||
|
||||
private final byte[] data;
|
||||
|
||||
public Resource(InputStream data) throws FileNotFoundException, IOException {
|
||||
public Resource(InputStream data) throws IOException {
|
||||
try (ByteArrayOutputStream bout = new ByteArrayOutputStream()) {
|
||||
bout.write(data);
|
||||
this.data = bout.toByteArray();
|
||||
|
@ -22,13 +22,16 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.resourcepack;
|
||||
package de.bluecolored.bluemap.core.resourcepack.blockmodel;
|
||||
|
||||
import com.flowpowered.math.TrigMath;
|
||||
import com.flowpowered.math.vector.Vector3f;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
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.util.Direction;
|
||||
import de.bluecolored.bluemap.core.util.math.Axis;
|
||||
@ -49,9 +52,9 @@ public class BlockModelResource {
|
||||
private boolean culling = false;
|
||||
private boolean occluding = false;
|
||||
|
||||
private boolean ambientOcclusion = true;
|
||||
private Collection<Element> elements = new ArrayList<>();
|
||||
private Map<String, Texture> textures = new HashMap<>();
|
||||
private final boolean ambientOcclusion = true; //TODO: wat?
|
||||
private final Collection<Element> elements = new ArrayList<>();
|
||||
private final Map<String, Texture> textures = new HashMap<>();
|
||||
|
||||
private BlockModelResource() {}
|
||||
|
||||
@ -477,9 +480,9 @@ private Texture getTexture(String key, int depth) throws NoSuchElementException,
|
||||
|
||||
Texture texture;
|
||||
try {
|
||||
texture = resourcePack.textures.get(path);
|
||||
texture = resourcePack.getTextures().get(path);
|
||||
} catch (NoSuchElementException ex) {
|
||||
texture = resourcePack.textures.loadTexture(sourcesAccess, path);
|
||||
texture = resourcePack.getTextures().loadTexture(sourcesAccess, path);
|
||||
}
|
||||
|
||||
return texture;
|
@ -22,7 +22,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.resourcepack;
|
||||
package de.bluecolored.bluemap.core.resourcepack.blockmodel;
|
||||
|
||||
public enum ModelType {
|
||||
|
@ -22,7 +22,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.resourcepack;
|
||||
package de.bluecolored.bluemap.core.resourcepack.blockmodel;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2f;
|
||||
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
|
||||
* 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.Vector3i;
|
||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||
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.util.MathUtils;
|
||||
import de.bluecolored.bluemap.core.world.BlockState;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -46,8 +47,6 @@
|
||||
|
||||
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 Collection<Variant> multipart = new ArrayList<>(0);
|
||||
|
||||
@ -92,53 +91,6 @@ public Collection<TransformedBlockModelResource> getModels(BlockState blockState
|
||||
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) {
|
||||
return new Builder(sourcesAccess, resourcePack);
|
||||
}
|
||||
@ -242,15 +194,8 @@ private Weighted<TransformedBlockModelResource> loadModel(ConfigurationNode node
|
||||
if (namespacedModelPath == null)
|
||||
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) {
|
||||
BlockModelResource.Builder builder = BlockModelResource.builder(sourcesAccess, resourcePack);
|
||||
try {
|
||||
@ -260,7 +205,7 @@ private Weighted<TransformedBlockModelResource> loadModel(ConfigurationNode node
|
||||
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));
|
@ -22,21 +22,24 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.mca.extensions;
|
||||
package de.bluecolored.bluemap.core.resourcepack.blockstate;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
public class Conditional<T> {
|
||||
|
||||
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(
|
||||
"minecraft:tripwire"
|
||||
));
|
||||
public Conditional(PropertyCondition condition, T value) {
|
||||
this.condition = condition;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAffectedBlockIds() {
|
||||
return AFFECTED_BLOCK_IDS;
|
||||
public PropertyCondition getCondition() {
|
||||
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
|
||||
* 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.world.BlockState;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PropertyCondition {
|
||||
|
||||
@ -152,4 +154,17 @@ static PropertyCondition property(String key, String... possibleValues) {
|
||||
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
|
||||
* 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;
|
||||
import de.bluecolored.bluemap.core.world.BlockState;
|
||||
public Weighted(T value, double weight) {
|
||||
this.value = value;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public interface BlockStateExtension {
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
BlockState extend(MCAWorld world, Vector3i pos, BlockState state);
|
||||
|
||||
Set<String> getAffectedBlockIds();
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.resourcepack;
|
||||
package de.bluecolored.bluemap.core.resourcepack.texture;
|
||||
|
||||
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
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.resourcepack;
|
||||
package de.bluecolored.bluemap.core.resourcepack.texture;
|
||||
|
||||
import com.google.gson.*;
|
||||
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.util.FileUtils;
|
||||
import de.bluecolored.bluemap.core.util.math.Color;
|
||||
@ -43,8 +44,8 @@ public class TextureGallery {
|
||||
|
||||
private static final String EMPTY_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAEUlEQVR42mNkIAAYRxWMJAUAE5gAEdz4t9QAAAAASUVORK5CYII=";
|
||||
|
||||
private Map<String, Texture> textureMap;
|
||||
private List<Texture> textureList;
|
||||
private final Map<String, Texture> textureMap;
|
||||
private final List<Texture> textureList;
|
||||
|
||||
public TextureGallery() {
|
||||
textureMap = new HashMap<>();
|
||||
@ -149,13 +150,11 @@ public synchronized void loadTextureFile(File file) throws IOException, ParseRes
|
||||
String path = texture.get("id").getAsString();
|
||||
boolean transparent = texture.get("transparent").getAsBoolean();
|
||||
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) {
|
||||
Logger.global.logWarning("Failed to load texture with id " + i + " from texture file " + file + "!");
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw ex;
|
||||
} catch (RuntimeException ex) {
|
||||
throw new ParseResourceException("Invalid texture file format!", ex);
|
||||
} finally {
|
||||
@ -221,11 +220,7 @@ public synchronized void reloadAllTextures(FileAccess fileAccess) {
|
||||
for (Texture texture : textureList.toArray(new Texture[textureList.size()])) {
|
||||
try {
|
||||
loadTexture(fileAccess, texture.getPath());
|
||||
} catch (IOException e) {
|
||||
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)");
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
@ -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.Vector3f;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import com.flowpowered.math.vector.Vector4f;
|
||||
import de.bluecolored.bluemap.core.util.math.VectorM3f;
|
||||
|
||||
@Deprecated //TODO
|
||||
public class MathUtils {
|
||||
|
@ -22,48 +22,51 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* 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 {
|
||||
|
||||
private Logger out;
|
||||
|
||||
public Slf4jLogger(Logger out) {
|
||||
this.out = out;
|
||||
TRUE (true),
|
||||
UNDEFINED (false) {
|
||||
@Override
|
||||
public Tristate getOr(Tristate other) {
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String message, Throwable throwable) {
|
||||
out.error(message, throwable);
|
||||
public boolean getOr(BooleanSupplier other) {
|
||||
return other.getAsBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
out.warn(message);
|
||||
public boolean getOr(boolean defaultValue) {
|
||||
return defaultValue;
|
||||
}
|
||||
},
|
||||
FALSE (false);
|
||||
|
||||
private final boolean value;
|
||||
|
||||
Tristate(boolean value ) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Tristate getOr(Tristate other) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getOr(BooleanSupplier other) {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean getOr(boolean defaultValue) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String message) {
|
||||
out.info(message);
|
||||
public String toString() {
|
||||
return "Tristate." + name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logDebug(String message) {
|
||||
if (out.isDebugEnabled()) out.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noFloodDebug(String message) {
|
||||
if (out.isDebugEnabled()) super.noFloodDebug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noFloodDebug(String key, String message) {
|
||||
if (out.isDebugEnabled()) super.noFloodDebug(key, message);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
public class Color {
|
||||
|
@ -24,10 +24,7 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.core.world;
|
||||
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import de.bluecolored.bluemap.core.util.Direction;
|
||||
|
||||
public class Block {
|
||||
public class Block<T extends Block<T>> {
|
||||
|
||||
private World world;
|
||||
private int x, y, z;
|
||||
@ -35,23 +32,19 @@ public class Block {
|
||||
private Chunk chunk;
|
||||
|
||||
private BlockState blockState;
|
||||
private BlockProperties properties;
|
||||
private LightData lightData;
|
||||
private Biome biome;
|
||||
|
||||
private int sunLight;
|
||||
private int blockLight;
|
||||
|
||||
private final transient LightData tempLight;
|
||||
private int biomeId;
|
||||
|
||||
public Block(World world, int x, int y, int z) {
|
||||
tempLight = new LightData(0, 0);
|
||||
|
||||
set(world, x, y, z);
|
||||
}
|
||||
|
||||
public Block set(World world, int x, int y, int z) {
|
||||
if (this.x == x && this.y == y && this.z == z && this.world == world) return this;
|
||||
public T set(World world, int x, int y, int z) {
|
||||
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.x = x;
|
||||
@ -60,11 +53,15 @@ public Block set(World world, int x, int y, int z) {
|
||||
|
||||
reset();
|
||||
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Block set(int x, int y, int z) {
|
||||
if (this.x == x && this.y == y && this.z == z) return this;
|
||||
public T set(int x, int y, int z) {
|
||||
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.y = y;
|
||||
@ -72,27 +69,49 @@ public Block set(int x, int y, int z) {
|
||||
|
||||
reset();
|
||||
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
this.chunk = null;
|
||||
|
||||
protected void reset() {
|
||||
this.blockState = null;
|
||||
this.properties = null;
|
||||
this.lightData = new LightData(-1, -1);
|
||||
this.biome = null;
|
||||
|
||||
this.blockLight = -1;
|
||||
this.sunLight = -1;
|
||||
this.biomeId = -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);
|
||||
}
|
||||
|
||||
public Block copy(Block source) {
|
||||
return set(source.world, source.x, source.y, source.z);
|
||||
public T copy(Block<?> source) {
|
||||
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() {
|
||||
@ -121,19 +140,14 @@ public BlockState getBlockState() {
|
||||
return blockState;
|
||||
}
|
||||
|
||||
public BlockProperties getProperties() {
|
||||
if (properties == null) properties = world.getBlockProperties(getBlockState());
|
||||
return properties;
|
||||
}
|
||||
|
||||
public LightData getLightData() {
|
||||
if (lightData.getSkyLight() < 0) getChunk().getLightData(x, y, z, lightData);
|
||||
return lightData;
|
||||
}
|
||||
|
||||
public Biome getBiome() {
|
||||
if (biome == null) biome = getChunk().getBiome(x, y, z);
|
||||
return biome;
|
||||
public int getBiomeId() {
|
||||
if (biomeId == -1) biomeId = getChunk().getBiome(x, y, z);
|
||||
return biomeId;
|
||||
}
|
||||
|
||||
public int getSunLightLevel() {
|
||||
@ -144,67 +158,32 @@ public int getBlockLightLevel() {
|
||||
return getLightData().getBlockLight();
|
||||
}
|
||||
|
||||
public boolean isCullingNeighborFaces() {
|
||||
return getProperties().isCulling();
|
||||
}
|
||||
|
||||
public boolean isFlammable() {
|
||||
return getProperties().isFlammable();
|
||||
}
|
||||
|
||||
public boolean isOccludingNeighborFaces(){
|
||||
return getProperties().isOccluding();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is internally used for light rendering
|
||||
* It is basically the sun light that is projected onto adjacent faces
|
||||
*/
|
||||
public int getPassedSunLight() {
|
||||
if (sunLight < 0) calculateLight();
|
||||
return sunLight;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
public String toString() {
|
||||
if (world != null) {
|
||||
return "Block{" +
|
||||
"world=" + world +
|
||||
", x=" + x +
|
||||
", y=" + y +
|
||||
", z=" + z +
|
||||
", sunLight=" + sunLight +
|
||||
", blockLight=" + blockLight +
|
||||
", chunk=" + getChunk() +
|
||||
", blockState=" + getBlockState() +
|
||||
", lightData=" + getLightData() +
|
||||
", biomeId=" + getBiomeId() +
|
||||
'}';
|
||||
} else {
|
||||
return "Block{" +
|
||||
"world=" + world +
|
||||
", x=" + x +
|
||||
", y=" + y +
|
||||
", z=" + z +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T self() {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import de.bluecolored.bluemap.core.util.Tristate;
|
||||
|
||||
public class BlockProperties {
|
||||
|
||||
public static final BlockProperties SOLID = new BlockProperties(true, true, false);
|
||||
public static final BlockProperties TRANSPARENT = new BlockProperties(false, false, false);
|
||||
public static final BlockProperties DEFAULT = new BlockProperties();
|
||||
|
||||
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.occluding = occluding;
|
||||
this.flammable = flammable;
|
||||
this.alwaysWaterlogged = alwaysWaterlogged;
|
||||
this.randomOffset = randomOffset;
|
||||
}
|
||||
|
||||
public boolean isCulling() {
|
||||
return culling;
|
||||
return culling.getOr(true);
|
||||
}
|
||||
|
||||
public boolean isOccluding() {
|
||||
return occluding.getOr(true);
|
||||
}
|
||||
|
||||
public boolean isAlwaysWaterlogged() {
|
||||
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 boolean isFlammable() {
|
||||
return flammable;
|
||||
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;
|
||||
|
||||
import de.bluecolored.bluemap.core.MinecraftVersion;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
@ -39,46 +37,10 @@
|
||||
*/
|
||||
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(
|
||||
"minecraft:seagrass",
|
||||
"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());
|
||||
public static final BlockState AIR = new BlockState("minecraft:air");
|
||||
public static final BlockState MISSING = new BlockState("bluemap:missing");
|
||||
|
||||
private boolean hashed;
|
||||
private int hash;
|
||||
@ -88,14 +50,13 @@ public class BlockState {
|
||||
private final String fullId;
|
||||
private final Map<String, String> properties;
|
||||
|
||||
// special fast-access properties
|
||||
public final boolean isAir, isWater, isWaterlogged, isRandomOffset;
|
||||
private final boolean isAir, isWater, isWaterlogged;
|
||||
|
||||
public BlockState(MinecraftVersion version, String id) {
|
||||
this(version, id, Collections.emptyMap());
|
||||
public BlockState(String id) {
|
||||
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.hash = 0;
|
||||
|
||||
@ -121,38 +82,7 @@ public BlockState(MinecraftVersion version, String id, Map<String, String> prope
|
||||
"minecraft:void_air".equals(this.fullId);
|
||||
|
||||
this.isWater = "minecraft:water".equals(this.fullId);
|
||||
|
||||
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;
|
||||
this.isWaterlogged = "true".equals(properties.get("waterlogged"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,11 +121,16 @@ public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new BlockState with the given property changed
|
||||
*/
|
||||
public BlockState with(String property, String value) {
|
||||
return new BlockState(this, property, value);
|
||||
public boolean isAir() {
|
||||
return isAir;
|
||||
}
|
||||
|
||||
public boolean isWater() {
|
||||
return isWater;
|
||||
}
|
||||
|
||||
public boolean isWaterlogged() {
|
||||
return isWaterlogged;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -205,8 +140,7 @@ public boolean equals(Object obj) {
|
||||
if (!(obj instanceof BlockState)) return false;
|
||||
BlockState b = (BlockState) obj;
|
||||
if (!Objects.equals(getFullId(), b.getFullId())) return false;
|
||||
if (!Objects.equals(getProperties(), b.getProperties())) return false;
|
||||
return true;
|
||||
return Objects.equals(getProperties(), b.getProperties());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -229,10 +163,12 @@ public String toString() {
|
||||
return getFullId() + "[" + sj.toString() + "]";
|
||||
}
|
||||
|
||||
public static BlockState fromString(MinecraftVersion version, String serializedBlockState) throws IllegalArgumentException {
|
||||
public static BlockState fromString(String serializedBlockState) throws IllegalArgumentException {
|
||||
try {
|
||||
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<>();
|
||||
String g2 = m.group(2);
|
||||
@ -246,7 +182,7 @@ public static BlockState fromString(MinecraftVersion version, String serializedB
|
||||
|
||||
String blockId = m.group(1).trim();
|
||||
|
||||
return new BlockState(version, blockId, pt);
|
||||
return new BlockState(blockId, pt);
|
||||
} catch (RuntimeException ex) {
|
||||
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);
|
||||
|
||||
Biome getBiome(int x, int y, int z);
|
||||
int getBiome(int x, int y, 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
|
||||
* 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.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;
|
||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
||||
|
||||
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) {
|
||||
this.listener = listener;
|
||||
private final ResourcePack resourcePack;
|
||||
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);
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onPlayerJoin(ClientConnectionEvent.Join evt) {
|
||||
listener.onPlayerJoin(evt.getTargetEntity().getUniqueId());
|
||||
@Override
|
||||
protected void reset() {
|
||||
super.reset();
|
||||
|
||||
this.properties = null;
|
||||
this.biome = null;
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onPlayerLeave(ClientConnectionEvent.Disconnect evt) {
|
||||
listener.onPlayerJoin(evt.getTargetEntity().getUniqueId());
|
||||
public BlockProperties getProperties() {
|
||||
if (properties == null) properties = resourcePack.getBlockProperties(getBlockState());
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onPlayerChat(MessageChannelEvent.Chat evt) {
|
||||
listener.onChatMessage(Text.of(evt.getMessage().toPlain()));
|
||||
public Biome getBiome() {
|
||||
if (biome == null) biome = resourcePack.getBiome(getBiomeId());
|
||||
return biome;
|
||||
}
|
||||
|
||||
public ResourcePack getResourcePack() {
|
||||
return resourcePack;
|
||||
}
|
||||
|
||||
}
|
@ -26,7 +26,6 @@
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -93,22 +92,6 @@ public Grid 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
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return world.getChunk(x, z);
|
||||
@ -153,11 +136,6 @@ public void cleanUpChunkCache() {
|
||||
world.cleanUpChunkCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPropertiesMapper getBlockPropertiesMapper() {
|
||||
return world.getBlockPropertiesMapper();
|
||||
}
|
||||
|
||||
private boolean isInside(int x, int z) {
|
||||
return
|
||||
x >= min.getX() &&
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
@ -57,21 +56,6 @@ public interface World {
|
||||
|
||||
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
|
||||
*/
|
||||
@ -83,7 +67,7 @@ public interface World {
|
||||
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);
|
||||
|
||||
@ -108,9 +92,4 @@ public interface World {
|
||||
*/
|
||||
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
Block a user