package net.minecraft.server;
import com.google.common.collect.Maps;
import com.mojang.datafixers.DataFixer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class DefinedStructureManager implements IResourcePackListener {
private static final Logger LOGGER = LogManager.getLogger();
private final Map<MinecraftKey, DefinedStructure> b = Maps.newConcurrentMap(); // SPIGOT-5287
private final DataFixer c;
private final MinecraftServer d;
private final java.nio.file.Path e;
public DefinedStructureManager(MinecraftServer minecraftserver, File file, DataFixer datafixer) {
this.d = minecraftserver;
this.c = datafixer;
this.e = file.toPath().resolve("generated").normalize();
minecraftserver.getResourceManager().a((IReloadListener) this);
}
public DefinedStructure a(MinecraftKey minecraftkey) {
DefinedStructure definedstructure = this.b(minecraftkey);
if (definedstructure == null) {
definedstructure = new DefinedStructure();
this.b.put(minecraftkey, definedstructure);
}
return definedstructure;
}
@Nullable
public DefinedStructure b(MinecraftKey minecraftkey) {
return (DefinedStructure) this.b.computeIfAbsent(minecraftkey, (minecraftkey1) -> {
DefinedStructure definedstructure = this.f(minecraftkey1);
return definedstructure != null ? definedstructure : this.e(minecraftkey1);
});
}
@Override
public void a(IResourceManager iresourcemanager) {
this.b.clear();
}
@Nullable
private DefinedStructure e(MinecraftKey minecraftkey) {
MinecraftKey minecraftkey1 = new MinecraftKey(minecraftkey.getNamespace(), "structures/" + minecraftkey.getKey() + ".nbt");
try {
IResource iresource = this.d.getResourceManager().a(minecraftkey1);
Throwable throwable = null;
DefinedStructure definedstructure;
try {
definedstructure = this.a(iresource.b());
} catch (Throwable throwable1) {
throwable = throwable1;
throw throwable1;
} finally {
if (iresource != null) {
if (throwable != null) {
try {
iresource.close();
} catch (Throwable throwable2) {
throwable.addSuppressed(throwable2);
}
} else {
iresource.close();
}
}
}
return definedstructure;
} catch (FileNotFoundException filenotfoundexception) {
return null;
} catch (Throwable throwable3) {
DefinedStructureManager.LOGGER.error("Couldn't load structure {}: {}", minecraftkey, throwable3.toString());
return null;
}
}
@Nullable
private DefinedStructure f(MinecraftKey minecraftkey) {
if (!this.e.toFile().isDirectory()) {
return null;
} else {
java.nio.file.Path java_nio_file_path = this.b(minecraftkey, ".nbt");
try {
FileInputStream fileinputstream = new FileInputStream(java_nio_file_path.toFile());
Throwable throwable = null;
DefinedStructure definedstructure;
try {
definedstructure = this.a((InputStream) fileinputstream);
} catch (Throwable throwable1) {
throwable = throwable1;
throw throwable1;
} finally {
if (fileinputstream != null) {
if (throwable != null) {
try {
fileinputstream.close();
} catch (Throwable throwable2) {
throwable.addSuppressed(throwable2);
}
} else {
fileinputstream.close();
}
}
}
return definedstructure;
} catch (FileNotFoundException filenotfoundexception) {
return null;
} catch (IOException ioexception) {
DefinedStructureManager.LOGGER.error("Couldn't load structure from {}", java_nio_file_path, ioexception);
return null;
}
}
}
private DefinedStructure a(InputStream inputstream) throws IOException {
NBTTagCompound nbttagcompound = NBTCompressedStreamTools.a(inputstream);
return this.a(nbttagcompound);
}
public DefinedStructure a(NBTTagCompound nbttagcompound) {
if (!nbttagcompound.hasKeyOfType("DataVersion", 99)) {
nbttagcompound.setInt("DataVersion", 500);
}
DefinedStructure definedstructure = new DefinedStructure();
definedstructure.b(GameProfileSerializer.a(this.c, DataFixTypes.STRUCTURE, nbttagcompound, nbttagcompound.getInt("DataVersion")));
return definedstructure;
}
public boolean c(MinecraftKey minecraftkey) {
DefinedStructure definedstructure = (DefinedStructure) this.b.get(minecraftkey);
if (definedstructure == null) {
return false;
} else {
java.nio.file.Path java_nio_file_path = this.b(minecraftkey, ".nbt");
java.nio.file.Path java_nio_file_path1 = java_nio_file_path.getParent();
if (java_nio_file_path1 == null) {
return false;
} else {
try {
Files.createDirectories(Files.exists(java_nio_file_path1, new LinkOption[0]) ? java_nio_file_path1.toRealPath() : java_nio_file_path1);
} catch (IOException ioexception) {
DefinedStructureManager.LOGGER.error("Failed to create parent directory: {}", java_nio_file_path1);
return false;
}
NBTTagCompound nbttagcompound = definedstructure.a(new NBTTagCompound());
try {
FileOutputStream fileoutputstream = new FileOutputStream(java_nio_file_path.toFile());
Throwable throwable = null;
try {
NBTCompressedStreamTools.a(nbttagcompound, (OutputStream) fileoutputstream);
} catch (Throwable throwable1) {
throwable = throwable1;
throw throwable1;
} finally {
if (fileoutputstream != null) {
if (throwable != null) {
try {
fileoutputstream.close();
} catch (Throwable throwable2) {
throwable.addSuppressed(throwable2);
}
} else {
fileoutputstream.close();
}
}
}
return true;
} catch (Throwable throwable3) {
return false;
}
}
}
}
public java.nio.file.Path a(MinecraftKey minecraftkey, String s) {
try {
java.nio.file.Path java_nio_file_path = this.e.resolve(minecraftkey.getNamespace());
java.nio.file.Path java_nio_file_path1 = java_nio_file_path.resolve("structures");
return FileUtils.b(java_nio_file_path1, minecraftkey.getKey(), s);
} catch (InvalidPathException invalidpathexception) {
throw new ResourceKeyInvalidException("Invalid resource path: " + minecraftkey, invalidpathexception);
}
}
private java.nio.file.Path b(MinecraftKey minecraftkey, String s) {
if (minecraftkey.getKey().contains("//")) {
throw new ResourceKeyInvalidException("Invalid resource path: " + minecraftkey);
} else {
java.nio.file.Path java_nio_file_path = this.a(minecraftkey, s);
if (java_nio_file_path.startsWith(this.e) && FileUtils.a(java_nio_file_path) && FileUtils.b(java_nio_file_path)) {
return java_nio_file_path;
} else {
throw new ResourceKeyInvalidException("Invalid resource path: " + java_nio_file_path);
}
}
}
public void d(MinecraftKey minecraftkey) {
this.b.remove(minecraftkey);
}
}