mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-22 10:35:16 +01:00
Improve resource-loading and texture-file generation and add implementation specific configurations
This commit is contained in:
parent
2b3ef38672
commit
fd155d6ce6
@ -92,6 +92,10 @@ private Path toFolder(String pathString) throws IOException {
|
||||
if (!file.exists() && !file.mkdirs()) throw new IOException("Invalid configuration: Folders to path '" + file.getAbsolutePath() + "' could not be created");
|
||||
return file.toPath();
|
||||
}
|
||||
|
||||
public Path getDataPath() {
|
||||
return dataPath;
|
||||
}
|
||||
|
||||
public boolean isWebserverEnabled() {
|
||||
return webserverEnabled;
|
||||
|
@ -49,6 +49,7 @@ public class ConfigurationFile {
|
||||
CONFIG_PLACEHOLDERS.add(new Placeholder("version", BlueMap.VERSION));
|
||||
CONFIG_PLACEHOLDERS.add(new Placeholder("datetime-iso", () -> LocalDateTime.now().withNano(0).toString()));
|
||||
CONFIG_PLACEHOLDERS.add(new Placeholder("minecraft-client-url", ResourcePack.MINECRAFT_CLIENT_URL));
|
||||
CONFIG_PLACEHOLDERS.add(new Placeholder("minecraft-client-version", ResourcePack.MINECRAFT_CLIENT_VERSION));
|
||||
}
|
||||
|
||||
private Configuration config;
|
||||
|
@ -380,6 +380,8 @@ public static MCAWorld load(Path worldFolder, UUID uuid) throws IOException {
|
||||
levelData.getInt("SpawnZ")
|
||||
);
|
||||
|
||||
|
||||
CHUNK_CACHE.invalidateAll();
|
||||
return new MCAWorld(
|
||||
worldFolder,
|
||||
uuid,
|
||||
|
@ -47,10 +47,12 @@
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.util.FileUtil;
|
||||
import de.bluecolored.bluemap.core.world.BlockState;
|
||||
|
||||
public class ResourcePack {
|
||||
|
||||
|
||||
public static final String MINECRAFT_CLIENT_VERSION = "1.14.4";
|
||||
public static final String MINECRAFT_CLIENT_URL = "https://launcher.mojang.com/v1/objects/8c325a0c5bd674dd747d6ebaa4c791fd363ad8a9/client.jar";
|
||||
|
||||
private Map<Path, Resource> resources;
|
||||
@ -62,37 +64,31 @@ public class ResourcePack {
|
||||
public ResourcePack(List<File> dataSources, File textureExportFile) throws IOException, NoSuchResourceException {
|
||||
this.resources = new HashMap<>();
|
||||
|
||||
load(dataSources);
|
||||
//load resources in order
|
||||
for (File resource : dataSources) overrideResourcesWith(resource);
|
||||
|
||||
blockStateResourceCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(10000)
|
||||
.build();
|
||||
|
||||
textureProvider = new TextureProvider();
|
||||
|
||||
if (textureExportFile.exists()){
|
||||
textureProvider.load(textureExportFile);
|
||||
} else {
|
||||
textureProvider.generate(this);
|
||||
textureProvider.save(textureExportFile);
|
||||
}
|
||||
|
||||
textureProvider.generate(this); //if loaded add missing textures
|
||||
textureProvider.save(textureExportFile);
|
||||
|
||||
blockColorProvider = new BlockColorProvider(this);
|
||||
}
|
||||
|
||||
private void load(List<File> dataSources) throws IOException {
|
||||
resources.clear();
|
||||
|
||||
//load resourcepacks in order
|
||||
for (File resourcePath : dataSources) overrideResourcesWith(resourcePath);
|
||||
}
|
||||
|
||||
private void overrideResourcesWith(File resourcePath){
|
||||
if (resourcePath.isFile() && resourcePath.getName().endsWith(".zip") || resourcePath.getName().endsWith(".jar")){
|
||||
overrideResourcesWithZipFile(resourcePath);
|
||||
return;
|
||||
private void overrideResourcesWith(File resource){
|
||||
if (resource.isFile() && resource.getName().endsWith(".zip") || resource.getName().endsWith(".jar")){
|
||||
overrideResourcesWithZipFile(resource);
|
||||
} else {
|
||||
overrideResourcesWith(resource, Paths.get(""));
|
||||
}
|
||||
|
||||
overrideResourcesWith(resourcePath, Paths.get(""));
|
||||
}
|
||||
|
||||
private void overrideResourcesWith(File resource, Path resourcePath){
|
||||
@ -103,7 +99,7 @@ private void overrideResourcesWith(File resource, Path resourcePath){
|
||||
return;
|
||||
}
|
||||
|
||||
if (resource.isFile()){
|
||||
if (resource.isFile() && isActualResourcePath(resourcePath)){
|
||||
try {
|
||||
byte[] bytes = Files.readAllBytes(resource.toPath());
|
||||
resources.put(resourcePath, new Resource(bytes));
|
||||
@ -124,15 +120,9 @@ private void overrideResourcesWithZipFile(File resourceFile){
|
||||
if (file.isDirectory()) continue;
|
||||
|
||||
Path resourcePath = Paths.get("", file.getName().split("/"));
|
||||
if (
|
||||
!resourcePath.startsWith(Paths.get("assets", "minecraft", "blockstates")) &&
|
||||
!resourcePath.startsWith(Paths.get("assets", "minecraft", "models", "block")) &&
|
||||
!resourcePath.startsWith(Paths.get("assets", "minecraft", "textures", "block")) &&
|
||||
!resourcePath.startsWith(Paths.get("assets", "minecraft", "textures", "colormap"))
|
||||
) continue;
|
||||
if (!isActualResourcePath(resourcePath)) continue;
|
||||
|
||||
InputStream fileInputStream = zipFile.getInputStream(file);
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(Math.max(8, (int) file.getSize()));
|
||||
int bytesRead;
|
||||
while ((bytesRead = fileInputStream.read(buffer)) != -1){
|
||||
@ -146,6 +136,17 @@ private void overrideResourcesWithZipFile(File resourceFile){
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isActualResourcePath(Path path) {
|
||||
String[] blockstatesPattern = {"assets", ".*", "blockstates", "*"};
|
||||
String[] modelsPattern = {"assets", ".*", "models", "blocks?", "*"};
|
||||
String[] texturesPattern = {"assets", ".*", "textures", "block|colormap", "*"};
|
||||
|
||||
return
|
||||
FileUtil.matchPath(path, blockstatesPattern) ||
|
||||
FileUtil.matchPath(path, modelsPattern) ||
|
||||
FileUtil.matchPath(path, texturesPattern);
|
||||
}
|
||||
|
||||
public BlockStateResource getBlockStateResource(BlockState block) throws NoSuchResourceException, InvalidResourceDeclarationException {
|
||||
BlockStateResource bsr = blockStateResourceCache.getIfPresent(block);
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -44,6 +43,7 @@
|
||||
|
||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack.Resource;
|
||||
import de.bluecolored.bluemap.core.util.ConfigUtil;
|
||||
import de.bluecolored.bluemap.core.util.FileUtil;
|
||||
import de.bluecolored.bluemap.core.util.MathUtil;
|
||||
import ninja.leaping.configurate.ConfigurationNode;
|
||||
import ninja.leaping.configurate.gson.GsonConfigurationLoader;
|
||||
@ -77,29 +77,34 @@ public Texture getTexture(int index){
|
||||
}
|
||||
|
||||
public void generate(ResourcePack resources) throws IOException {
|
||||
indexMap.clear();
|
||||
textures.clear();
|
||||
|
||||
Path textureRoot = Paths.get("assets", "minecraft", "textures");
|
||||
String[] texturesPathPattern = {"assets", ".*", "textures", "block", "*"};
|
||||
|
||||
for (Entry<Path, Resource> entry : resources.getAllResources().entrySet()){
|
||||
if (entry.getKey().startsWith(textureRoot) && entry.getKey().toString().endsWith(".png")){
|
||||
BufferedImage image = ImageIO.read(entry.getValue().getStream());
|
||||
if (image == null) throw new IOException("Failed to read Image: " + entry.getKey());
|
||||
|
||||
String path = textureRoot.relativize(entry.getKey()).normalize().toString();
|
||||
Path key = entry.getKey();
|
||||
if (FileUtil.matchPath(key, texturesPathPattern) && key.toString().endsWith(".png")){
|
||||
String path = key.subpath(3, key.getNameCount()).normalize().toString();
|
||||
String id = path
|
||||
.substring(0, path.length() - ".png".length())
|
||||
.replace(File.separatorChar, '/');
|
||||
|
||||
BufferedImage image = ImageIO.read(entry.getValue().getStream());
|
||||
if (image == null) throw new IOException("Failed to read Image: " + key);
|
||||
|
||||
Texture texture = new Texture(id, image);
|
||||
textures.add(texture);
|
||||
indexMap.put(id, textures.size() - 1);
|
||||
|
||||
//update if existing else add new
|
||||
if (indexMap.containsKey(id)) {
|
||||
int index = indexMap.get(id);
|
||||
textures.set(index, texture);
|
||||
} else {
|
||||
textures.add(texture);
|
||||
indexMap.put(id, textures.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void load(File file) throws IOException {
|
||||
|
||||
indexMap.clear();
|
||||
textures.clear();
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
|
||||
@ -73,4 +74,30 @@ public static void waitForFile(File file, long time, TimeUnit unit) throws Inter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The path-elements are being matched to the pattern-elements,
|
||||
* each pattern-element can be a regex pattern to match against one path-element or "*" to represent any number of arbitrary elements (lazy: until the next pattern matches).
|
||||
*/
|
||||
public static boolean matchPath(Path path, String... pattern) {
|
||||
int p = 0;
|
||||
for (int i = 0; i < path.getNameCount(); i++) {
|
||||
while (pattern[p].equals("*")) {
|
||||
p++;
|
||||
|
||||
if (pattern.length >= p) return true;
|
||||
}
|
||||
|
||||
if (Pattern.matches(pattern[p], path.getName(i).toString())) {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p > 0 && pattern[p-1].equals("*")) continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -96,6 +96,7 @@ public String toString() {
|
||||
.add("biome", getBiome())
|
||||
.add("blocklight", getBlockLightLevel())
|
||||
.add("sunlight", getSunLightLevel())
|
||||
.add("state", getBlock())
|
||||
.toString();
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ version: "%version%"
|
||||
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
|
||||
# you confirm that you own a license to Minecraft (Java Edition)
|
||||
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
|
||||
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client.jar)
|
||||
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client-%minecraft-client-version%.jar)
|
||||
# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compilant with mojang's EULA.
|
||||
# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.)
|
||||
# %datetime-iso%
|
||||
@ -28,9 +28,8 @@ metrics: true
|
||||
data: "data"
|
||||
|
||||
web {
|
||||
# With this setting you can disable the web-server.
|
||||
# This is usefull if you want to only render the map-data for later use, or if you setup your own webserver.
|
||||
enabled: true
|
||||
# With this setting you can enable the integrated web-server.
|
||||
enabled: false
|
||||
|
||||
# The webroot of the website that displays the map.
|
||||
webroot: "web"
|
||||
|
@ -97,6 +97,7 @@ public CommandSpec createReloadCommand() {
|
||||
.permission("bluemap.reload")
|
||||
.executor((source, args) -> {
|
||||
try {
|
||||
source.sendMessage(Text.of(TextColors.GOLD, "Reloading BlueMap..."));
|
||||
plugin.reload();
|
||||
|
||||
if (plugin.isLoaded()) {
|
||||
|
@ -31,8 +31,11 @@
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -52,12 +55,11 @@
|
||||
import org.spongepowered.api.scheduler.SpongeExecutorService;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import de.bluecolored.bluemap.core.BlueMap;
|
||||
import de.bluecolored.bluemap.core.config.ConfigurationFile;
|
||||
import de.bluecolored.bluemap.core.config.Configuration;
|
||||
import de.bluecolored.bluemap.core.config.Configuration.MapConfig;
|
||||
import de.bluecolored.bluemap.core.config.ConfigurationFile;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
||||
import de.bluecolored.bluemap.core.metrics.Metrics;
|
||||
@ -130,10 +132,10 @@ public synchronized void load() throws IOException, NoSuchResourceException {
|
||||
|
||||
//load configs
|
||||
File configFile = getConfigPath().resolve("bluemap.conf").toFile();
|
||||
config = ConfigurationFile.loadOrCreate(configFile).getConfig();
|
||||
config = ConfigurationFile.loadOrCreate(configFile, SpongePlugin.class.getResource("/bluemap-sponge.conf")).getConfig();
|
||||
|
||||
//load resources
|
||||
File defaultResourceFile = getConfigPath().resolve("resourcepacks").resolve("minecraft-client.jar").toFile();
|
||||
File defaultResourceFile = config.getDataPath().resolve("minecraft-client-" + ResourcePack.MINECRAFT_CLIENT_VERSION + ".jar").toFile();
|
||||
File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile();
|
||||
|
||||
if (!defaultResourceFile.exists()) {
|
||||
@ -146,7 +148,17 @@ public synchronized void load() throws IOException, NoSuchResourceException {
|
||||
return;
|
||||
}
|
||||
|
||||
resourcePack = new ResourcePack(Lists.newArrayList(defaultResourceFile), textureExportFile);
|
||||
//find more resource packs
|
||||
File resourcePackFolder = getConfigPath().resolve("resourcepacks").toFile();
|
||||
resourcePackFolder.mkdirs();
|
||||
File[] resourcePacks = resourcePackFolder.listFiles();
|
||||
Arrays.sort(resourcePacks);
|
||||
|
||||
List<File> resources = new ArrayList<>(resourcePacks.length + 1);
|
||||
resources.add(defaultResourceFile);
|
||||
for (File file : resourcePacks) resources.add(file);
|
||||
|
||||
resourcePack = new ResourcePack(resources, textureExportFile);
|
||||
|
||||
//load maps
|
||||
for (MapConfig mapConfig : config.getMapConfigs()) {
|
||||
|
@ -13,7 +13,7 @@ version: "%version%"
|
||||
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
|
||||
# you confirm that you own a license to Minecraft (Java Edition)
|
||||
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
|
||||
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client.jar)
|
||||
# (Alternatively you can download the file yourself and store it here: <data>/minecraft-client-%minecraft-client-version%.jar)
|
||||
# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compilant with mojang's EULA.
|
||||
# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.)
|
||||
# %datetime-iso%
|
||||
@ -23,7 +23,7 @@ accept-download: false
|
||||
data: "bluemap"
|
||||
|
||||
web {
|
||||
# With this setting you can disable the web-server.
|
||||
# With this setting you can disable the integrated web-server.
|
||||
# This is usefull if you want to only render the map-data for later use, or if you setup your own webserver.
|
||||
enabled: true
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user