190 lines
5.8 KiB
Java
190 lines
5.8 KiB
Java
/*
|
|
* 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 java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.Collections;
|
|
import java.util.Enumeration;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.zip.ZipEntry;
|
|
import java.util.zip.ZipFile;
|
|
|
|
import org.apache.commons.io.FileUtils;
|
|
|
|
import com.google.common.cache.Cache;
|
|
import com.google.common.cache.CacheBuilder;
|
|
|
|
import de.bluecolored.bluemap.core.logger.Logger;
|
|
import de.bluecolored.bluemap.core.world.BlockState;
|
|
|
|
public class ResourcePack {
|
|
|
|
private Map<Path, Resource> resources;
|
|
|
|
private TextureProvider textureProvider;
|
|
private BlockColorProvider blockColorProvider;
|
|
private Cache<BlockState, BlockStateResource> blockStateResourceCache;
|
|
|
|
public ResourcePack(List<File> dataSources, File textureExportFile) throws IOException, NoSuchResourceException {
|
|
this.resources = new HashMap<>();
|
|
|
|
load(dataSources);
|
|
|
|
blockStateResourceCache = CacheBuilder.newBuilder()
|
|
.maximumSize(10000)
|
|
.build();
|
|
|
|
textureProvider = new TextureProvider();
|
|
if (textureExportFile.exists()){
|
|
textureProvider.load(textureExportFile);
|
|
} else {
|
|
textureProvider.generate(this);
|
|
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;
|
|
}
|
|
|
|
overrideResourcesWith(resourcePath, Paths.get(""));
|
|
}
|
|
|
|
private void overrideResourcesWith(File resource, Path resourcePath){
|
|
if (resource.isDirectory()){
|
|
for (File childFile : resource.listFiles()){
|
|
overrideResourcesWith(childFile, resourcePath.resolve(childFile.getName()));
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (resource.isFile()){
|
|
try {
|
|
byte[] bytes = Files.readAllBytes(resource.toPath());
|
|
resources.put(resourcePath, new Resource(bytes));
|
|
} catch (IOException e) {
|
|
Logger.global.logError("Failed to load resource: " + resource, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void overrideResourcesWithZipFile(File resourceFile){
|
|
try (
|
|
ZipFile zipFile = new ZipFile(resourceFile);
|
|
){
|
|
Enumeration<? extends ZipEntry> files = zipFile.entries();
|
|
byte[] buffer = new byte[1024];
|
|
while (files.hasMoreElements()){
|
|
ZipEntry file = files.nextElement();
|
|
if (file.isDirectory()) continue;
|
|
|
|
Path resourcePath = Paths.get("", file.getName().split("/"));
|
|
InputStream fileInputStream = zipFile.getInputStream(file);
|
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(Math.max(8, (int) file.getSize()));
|
|
int bytesRead;
|
|
while ((bytesRead = fileInputStream.read(buffer)) != -1){
|
|
bos.write(buffer, 0, bytesRead);
|
|
}
|
|
|
|
resources.put(resourcePath, new Resource(bos.toByteArray()));
|
|
}
|
|
} catch (IOException e) {
|
|
Logger.global.logError("Failed to load resource: " + resourceFile, e);
|
|
}
|
|
}
|
|
|
|
public BlockStateResource getBlockStateResource(BlockState block) throws NoSuchResourceException, InvalidResourceDeclarationException {
|
|
BlockStateResource bsr = blockStateResourceCache.getIfPresent(block);
|
|
|
|
if (bsr == null){
|
|
bsr = new BlockStateResource(block, this);
|
|
blockStateResourceCache.put(block, bsr);
|
|
}
|
|
|
|
return bsr;
|
|
}
|
|
|
|
public TextureProvider getTextureProvider(){
|
|
return textureProvider;
|
|
}
|
|
|
|
public BlockColorProvider getBlockColorProvider(){
|
|
return blockColorProvider;
|
|
}
|
|
|
|
public Map<Path, Resource> getAllResources() {
|
|
return Collections.unmodifiableMap(resources);
|
|
}
|
|
|
|
public InputStream getResource(Path resourcePath) throws NoSuchResourceException {
|
|
Resource resource = resources.get(resourcePath);
|
|
if (resource == null) throw new NoSuchResourceException("There is no resource with that path: " + resourcePath);
|
|
return resource.getStream();
|
|
}
|
|
|
|
public class Resource {
|
|
|
|
private byte[] data;
|
|
|
|
public Resource(byte[] data) {
|
|
this.data = data;
|
|
}
|
|
|
|
public InputStream getStream(){
|
|
return new ByteArrayInputStream(data);
|
|
}
|
|
|
|
}
|
|
|
|
public static void createDefaultResource(File file) throws IOException {
|
|
if (!file.exists()) {
|
|
file.getParentFile().mkdirs();
|
|
FileUtils.copyURLToFile(ResourcePack.class.getResource("/DefaultResources.zip"), file, 10000, 10000);
|
|
}
|
|
}
|
|
|
|
}
|