211 lines
6.3 KiB
Java
211 lines
6.3 KiB
Java
package net.minecraft.server.packs;
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
import com.google.common.collect.Sets;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.file.Path;
|
|
import java.util.ArrayList;
|
|
import java.util.Enumeration;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Set;
|
|
import java.util.zip.ZipEntry;
|
|
import java.util.zip.ZipFile;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.server.packs.repository.Pack;
|
|
import net.minecraft.server.packs.resources.IoSupplier;
|
|
import org.apache.commons.io.IOUtils;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class FilePackResources extends AbstractPackResources {
|
|
static final Logger LOGGER = LogUtils.getLogger();
|
|
private final FilePackResources.SharedZipFileAccess zipFileAccess;
|
|
private final String prefix;
|
|
|
|
FilePackResources(PackLocationInfo location, FilePackResources.SharedZipFileAccess zipFileAccess, String prefix) {
|
|
super(location);
|
|
this.zipFileAccess = zipFileAccess;
|
|
this.prefix = prefix;
|
|
}
|
|
|
|
private static String getPathFromLocation(PackType packType, ResourceLocation location) {
|
|
return String.format(Locale.ROOT, "%s/%s/%s", packType.getDirectory(), location.getNamespace(), location.getPath());
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public IoSupplier<InputStream> getRootResource(String... elements) {
|
|
return this.getResource(String.join("/", elements));
|
|
}
|
|
|
|
@Override
|
|
public IoSupplier<InputStream> getResource(PackType packType, ResourceLocation location) {
|
|
return this.getResource(getPathFromLocation(packType, location));
|
|
}
|
|
|
|
private String addPrefix(String resourcePath) {
|
|
return this.prefix.isEmpty() ? resourcePath : this.prefix + "/" + resourcePath;
|
|
}
|
|
|
|
@Nullable
|
|
private IoSupplier<InputStream> getResource(String resourcePath) {
|
|
ZipFile zipFile = this.zipFileAccess.getOrCreateZipFile();
|
|
if (zipFile == null) {
|
|
return null;
|
|
} else {
|
|
ZipEntry zipEntry = zipFile.getEntry(this.addPrefix(resourcePath));
|
|
return zipEntry == null ? null : IoSupplier.create(zipFile, zipEntry);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getNamespaces(PackType type) {
|
|
ZipFile zipFile = this.zipFileAccess.getOrCreateZipFile();
|
|
if (zipFile == null) {
|
|
return Set.of();
|
|
} else {
|
|
Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
|
|
Set<String> set = Sets.<String>newHashSet();
|
|
String string = this.addPrefix(type.getDirectory() + "/");
|
|
|
|
while (enumeration.hasMoreElements()) {
|
|
ZipEntry zipEntry = (ZipEntry)enumeration.nextElement();
|
|
String string2 = zipEntry.getName();
|
|
String string3 = extractNamespace(string, string2);
|
|
if (!string3.isEmpty()) {
|
|
if (ResourceLocation.isValidNamespace(string3)) {
|
|
set.add(string3);
|
|
} else {
|
|
LOGGER.warn("Non [a-z0-9_.-] character in namespace {} in pack {}, ignoring", string3, this.zipFileAccess.file);
|
|
}
|
|
}
|
|
}
|
|
|
|
return set;
|
|
}
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public static String extractNamespace(String directory, String name) {
|
|
if (!name.startsWith(directory)) {
|
|
return "";
|
|
} else {
|
|
int i = directory.length();
|
|
int j = name.indexOf(47, i);
|
|
return j == -1 ? name.substring(i) : name.substring(i, j);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
this.zipFileAccess.close();
|
|
}
|
|
|
|
@Override
|
|
public void listResources(PackType packType, String namespace, String path, PackResources.ResourceOutput resourceOutput) {
|
|
ZipFile zipFile = this.zipFileAccess.getOrCreateZipFile();
|
|
if (zipFile != null) {
|
|
Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
|
|
String string = this.addPrefix(packType.getDirectory() + "/" + namespace + "/");
|
|
String string2 = string + path + "/";
|
|
|
|
while (enumeration.hasMoreElements()) {
|
|
ZipEntry zipEntry = (ZipEntry)enumeration.nextElement();
|
|
if (!zipEntry.isDirectory()) {
|
|
String string3 = zipEntry.getName();
|
|
if (string3.startsWith(string2)) {
|
|
String string4 = string3.substring(string.length());
|
|
ResourceLocation resourceLocation = ResourceLocation.tryBuild(namespace, string4);
|
|
if (resourceLocation != null) {
|
|
resourceOutput.accept(resourceLocation, IoSupplier.create(zipFile, zipEntry));
|
|
} else {
|
|
LOGGER.warn("Invalid path in datapack: {}:{}, ignoring", namespace, string4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class FileResourcesSupplier implements Pack.ResourcesSupplier {
|
|
private final File content;
|
|
|
|
public FileResourcesSupplier(Path content) {
|
|
this(content.toFile());
|
|
}
|
|
|
|
public FileResourcesSupplier(File content) {
|
|
this.content = content;
|
|
}
|
|
|
|
@Override
|
|
public PackResources openPrimary(PackLocationInfo location) {
|
|
FilePackResources.SharedZipFileAccess sharedZipFileAccess = new FilePackResources.SharedZipFileAccess(this.content);
|
|
return new FilePackResources(location, sharedZipFileAccess, "");
|
|
}
|
|
|
|
@Override
|
|
public PackResources openFull(PackLocationInfo location, Pack.Metadata metadata) {
|
|
FilePackResources.SharedZipFileAccess sharedZipFileAccess = new FilePackResources.SharedZipFileAccess(this.content);
|
|
PackResources packResources = new FilePackResources(location, sharedZipFileAccess, "");
|
|
List<String> list = metadata.overlays();
|
|
if (list.isEmpty()) {
|
|
return packResources;
|
|
} else {
|
|
List<PackResources> list2 = new ArrayList(list.size());
|
|
|
|
for (String string : list) {
|
|
list2.add(new FilePackResources(location, sharedZipFileAccess, string));
|
|
}
|
|
|
|
return new CompositePackResources(packResources, list2);
|
|
}
|
|
}
|
|
}
|
|
|
|
static class SharedZipFileAccess implements AutoCloseable {
|
|
final File file;
|
|
@Nullable
|
|
private ZipFile zipFile;
|
|
private boolean failedToLoad;
|
|
|
|
SharedZipFileAccess(File file) {
|
|
this.file = file;
|
|
}
|
|
|
|
@Nullable
|
|
ZipFile getOrCreateZipFile() {
|
|
if (this.failedToLoad) {
|
|
return null;
|
|
} else {
|
|
if (this.zipFile == null) {
|
|
try {
|
|
this.zipFile = new ZipFile(this.file);
|
|
} catch (IOException var2) {
|
|
FilePackResources.LOGGER.error("Failed to open pack {}", this.file, var2);
|
|
this.failedToLoad = true;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return this.zipFile;
|
|
}
|
|
}
|
|
|
|
public void close() {
|
|
if (this.zipFile != null) {
|
|
IOUtils.closeQuietly(this.zipFile);
|
|
this.zipFile = null;
|
|
}
|
|
}
|
|
|
|
protected void finalize() throws Throwable {
|
|
this.close();
|
|
super.finalize();
|
|
}
|
|
}
|
|
}
|