Fix not loading textures if they are outside the block(s) folder

This commit is contained in:
Lukas Rieger (Blue) 2022-08-01 00:15:39 +02:00
parent bc8e52abbf
commit ffc472ce84
No known key found for this signature in database
GPG Key ID: 2D09EC5ED2687FF2
2 changed files with 85 additions and 60 deletions

View File

@ -59,7 +59,6 @@
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.concurrent.CompletionException;
import java.util.stream.Stream;
/**
@ -329,20 +328,14 @@ public synchronized ResourcePack getResourcePack() throws ConfigurationException
}
try {
Logger.global.logInfo("Loading resources...");
resourcePack = new ResourcePack();
List<Path> resourcePackRoots = new ArrayList<>();
// load from resourcepack folder
try (Stream<Path> resourcepackFiles = Files.list(resourcePackFolder)) {
resourcepackFiles
.sorted(Comparator.reverseOrder())
.forEach(resourcepackFile -> {
try {
resourcePack.loadResources(resourcepackFile);
} catch (IOException e) {
throw new CompletionException(e);
}
});
.forEach(resourcePackRoots::add);
}
if (configs.getCoreConfig().isScanForModResources()) {
@ -354,13 +347,7 @@ public synchronized ResourcePack getResourcePack() throws ConfigurationException
resourcepackFiles
.filter(Files::isRegularFile)
.filter(file -> file.getFileName().toString().endsWith(".jar"))
.forEach(resourcepackFile -> {
try {
resourcePack.loadResources(resourcepackFile);
} catch (IOException e) {
throw new CompletionException(e);
}
});
.forEach(resourcePackRoots::add);
}
}
@ -370,23 +357,16 @@ public synchronized ResourcePack getResourcePack() throws ConfigurationException
if (!Files.isDirectory(datapacksFolder)) continue;
try (Stream<Path> resourcepackFiles = Files.list(worldFolder.resolve("datapacks"))) {
resourcepackFiles
.forEach(resourcepackFile -> {
try {
resourcePack.loadResources(resourcepackFile);
} catch (IOException e) {
throw new CompletionException(e);
}
});
resourcepackFiles.forEach(resourcePackRoots::add);
}
}
}
resourcePack.loadResources(resourceExtensionsFile);
resourcePack.loadResources(defaultResourceFile);
resourcePack.bake();
Logger.global.logInfo("Resources loaded.");
resourcePackRoots.add(resourceExtensionsFile);
resourcePackRoots.add(defaultResourceFile);
resourcePack.loadResources(resourcePackRoots);
} catch (IOException | RuntimeException e) {
throw new ConfigurationException("Failed to parse resources!\n" +
"Is one of your resource-packs corrupted?", e);

View File

@ -4,8 +4,8 @@
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.api.debug.DebugDump;
import de.bluecolored.bluemap.core.BlueMap;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.resources.BlockColorCalculatorFactory;
import de.bluecolored.bluemap.core.resources.BlockPropertiesConfig;
@ -13,6 +13,7 @@
import de.bluecolored.bluemap.core.resources.adapter.ResourcesGson;
import de.bluecolored.bluemap.core.resources.biome.BiomeConfig;
import de.bluecolored.bluemap.core.resources.resourcepack.blockmodel.BlockModel;
import de.bluecolored.bluemap.core.resources.resourcepack.blockmodel.TextureVariable;
import de.bluecolored.bluemap.core.resources.resourcepack.blockstate.BlockState;
import de.bluecolored.bluemap.core.resources.resourcepack.texture.Texture;
import de.bluecolored.bluemap.core.util.Tristate;
@ -30,7 +31,9 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.regex.Pattern;
@ -157,18 +160,33 @@ private BlockProperties loadBlockProperties(de.bluecolored.bluemap.core.world.Bl
return props.build();
}
public synchronized void loadResources(Path root) throws IOException {
Logger.global.logDebug("Loading resources from: " + root + " ...");
loadResourcesInternal(root);
public synchronized void loadResources(Iterable<Path> roots) throws IOException {
Logger.global.logInfo("Loading resources...");
for (Path root : roots) {
Logger.global.logDebug("Loading resources from: " + root + " ...");
loadResourcePath(root, this::loadResources);
}
Logger.global.logInfo("Loading textures...");
for (Path root : roots) {
Logger.global.logDebug("Loading textures from: " + root + " ...");
loadResourcePath(root, this::loadTextures);
}
Logger.global.logInfo("Baking resources...");
bake();
Logger.global.logInfo("Resources loaded.");
}
private synchronized void loadResourcesInternal(Path root) throws IOException {
private void loadResourcePath(Path root, PathLoader resourceLoader) throws IOException {
if (!Files.isDirectory(root)) {
try (FileSystem fileSystem = FileSystems.newFileSystem(root, (ClassLoader) null)) {
for (Path fsRoot : fileSystem.getRootDirectories()) {
if (!Files.isDirectory(fsRoot)) continue;
this.loadResourcesInternal(fsRoot);
loadResourcePath(fsRoot, resourceLoader);
}
} catch (Exception ex) {
Logger.global.logDebug("Failed to read '" + root + "': " + ex);
@ -180,16 +198,20 @@ private synchronized void loadResourcesInternal(Path root) throws IOException {
Path fabricModJson = root.resolve("fabric.mod.json");
if (Files.isRegularFile(fabricModJson)) {
try (BufferedReader reader = Files.newBufferedReader(fabricModJson)) {
JsonObject rootElement = ResourcesGson.INSTANCE.fromJson(reader, JsonObject.class);
for (JsonElement element : rootElement.getAsJsonArray("jars")) {
Path file = root.resolve(element.getAsJsonObject().get("file").getAsString());
if (Files.exists(file)) loadResourcesInternal(file);
}
JsonObject rootElement = ResourcesGson.INSTANCE.fromJson(reader, JsonObject.class);
for (JsonElement element : rootElement.getAsJsonArray("jars")) {
Path file = root.resolve(element.getAsJsonObject().get("file").getAsString());
if (Files.exists(file)) loadResourcePath(file, resourceLoader);
}
} catch (Exception ex) {
Logger.global.logDebug("Failed to read fabric.mod.json: " + ex);
}
}
resourceLoader.load(root);
}
private void loadResources(Path root) throws IOException {
try {
// do those in parallel
CompletableFuture.allOf(
@ -226,24 +248,6 @@ private synchronized void loadResourcesInternal(Path root) throws IOException {
}, blockModels));
}, BlueMap.THREAD_POOL),
// load textures
CompletableFuture.runAsync(() -> {
list(root.resolve("assets"))
.map(path -> path.resolve("textures"))
.flatMap(ResourcePack::list)
.filter(path -> Pattern.matches("blocks?", path.getFileName().toString()))
.filter(Files::isDirectory)
.flatMap(ResourcePack::walk)
.filter(path -> path.getFileName().toString().endsWith(".png"))
.filter(Files::isRegularFile)
.forEach(file -> loadResource(root, file, () -> {
ResourcePath<Texture> resourcePath = new ResourcePath<>(root.relativize(file));
try (InputStream in = Files.newInputStream(file)) {
return Texture.from(resourcePath, ImageIO.read(in));
}
}, textures));
}, BlueMap.THREAD_POOL),
// load colormaps
CompletableFuture.runAsync(() -> {
walk(root.resolve("assets").resolve("minecraft").resolve("textures").resolve("colormap"))
@ -322,8 +326,42 @@ private synchronized void loadResourcesInternal(Path root) throws IOException {
}
}
public synchronized void bake() throws IOException {
Logger.global.logDebug("Baking resources...");
private void loadTextures(Path root) throws IOException {
try {
// collect all used textures
Set<ResourcePath<Texture>> usedTextures = new HashSet<>();
for (BlockModel model : blockModels.values()) {
for (TextureVariable textureVariable : model.getTextures().values()) {
if (textureVariable.isReference()) continue;
usedTextures.add(textureVariable.getTexturePath());
}
}
// load textures
list(root.resolve("assets"))
.map(path -> path.resolve("textures"))
.flatMap(ResourcePack::walk)
.filter(path -> path.getFileName().toString().endsWith(".png"))
.filter(Files::isRegularFile)
.forEach(file -> loadResource(root, file, () -> {
ResourcePath<Texture> resourcePath = new ResourcePath<>(root.relativize(file));
if (!usedTextures.contains(resourcePath)) return null; // don't load unused textures
try (InputStream in = Files.newInputStream(file)) {
return Texture.from(resourcePath, ImageIO.read(in));
}
}, textures));
} catch (RuntimeException ex) {
Throwable cause = ex.getCause();
if (cause instanceof IOException) throw (IOException) cause;
if (cause != null) throw new IOException(cause);
throw new IOException(ex);
}
}
private void bake() throws IOException {
// fill path maps
blockStates.keySet().forEach(path -> blockStatePaths.put(path.getFormatted(), path));
@ -352,6 +390,7 @@ public synchronized void bake() throws IOException {
BufferedImage grass = new ResourcePath<BufferedImage>("minecraft:colormap/grass").getResource(colormaps::get);
if (grass == null) throw new IOException("Failed to bake resource-pack: No grass-colormap found!");
this.colorCalculatorFactory.setGrassMap(grass);
}
private <T> void loadResource(Path root, Path file, Loader<T> loader, Map<ResourcePath<T>, T> resultMap) {
@ -360,6 +399,8 @@ private <T> void loadResource(Path root, Path file, Loader<T> loader, Map<Resour
if (resultMap.containsKey(resourcePath)) return; // don't load already present resources
T resource = loader.load();
if (resource == null) return; // don't load missing resources
resourcePath.setResource(resource);
resultMap.put(resourcePath, resource);
} catch (Exception ex) {
@ -389,4 +430,8 @@ private interface Loader<T> {
T load() throws IOException;
}
private interface PathLoader {
void load(Path root) throws IOException;
}
}