extract resource loading into ResourceUtil

This commit is contained in:
CreepyCre 2021-10-11 12:26:08 +02:00
parent ab162ca368
commit 623079b45f
3 changed files with 99 additions and 89 deletions

View file

@ -1,16 +1,9 @@
package org.dimdev.dimdoors.pockets;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.gson.*;
import com.mojang.serialization.JsonOps;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.nbt.*;
import net.minecraft.resource.ResourceManager;
@ -24,11 +17,11 @@ import org.dimdev.dimdoors.api.util.SimpleTree;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
import org.dimdev.dimdoors.pockets.virtual.VirtualPocket;
import org.dimdev.dimdoors.api.util.WeightedList;
import org.dimdev.dimdoors.util.ResourceUtil;
import org.dimdev.dimdoors.util.schematic.Schematic;
public class PocketLoader implements SimpleSynchronousResourceReloadListener {
private static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create();
private static final PocketLoader INSTANCE = new PocketLoader();
private SimpleTree<String, PocketGenerator> pocketGenerators = new SimpleTree<>(String.class);
private SimpleTree<String, VirtualPocket> pocketGroups = new SimpleTree<>(String.class);
@ -47,12 +40,12 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener {
templates.clear();
dataTree.clear();
dataTree = loadResourcePathFromJsonToTree(manager, "pockets/json", t -> t).join();
dataTree = ResourceUtil.loadResourcePathToMap(manager, "pockets/json", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.composeIdentity(), ResourceUtil.PATH_KEY_PROVIDER).join();
CompletableFuture<SimpleTree<String, PocketGenerator>> futurePocketGeneratorMap = loadResourcePathFromJsonToTree(manager, "pockets/generators", this::loadPocketGenerator);
CompletableFuture<SimpleTree<String, VirtualPocket>> futurePocketGroups = loadResourcePathFromJsonToTree(manager, "pockets/groups", this::loadVirtualPocket);
CompletableFuture<SimpleTree<String, VirtualPocket>> futureVirtualPockets = loadResourcePathFromJsonToTree(manager, "pockets/virtual", this::loadVirtualPocket);
CompletableFuture<SimpleTree<String, PocketTemplate>> futureTemplates = loadResourcePathFromCompressedNbtToTree(manager, "pockets/schematic", ".schem", this::loadPocketTemplate);
CompletableFuture<SimpleTree<String, PocketGenerator>> futurePocketGeneratorMap = ResourceUtil.loadResourcePathToMap(manager, "pockets/generators", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.andThenReader(this::loadPocketGenerator), ResourceUtil.PATH_KEY_PROVIDER);
CompletableFuture<SimpleTree<String, VirtualPocket>> futurePocketGroups = ResourceUtil.loadResourcePathToMap(manager, "pockets/groups", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.andThenReader(this::loadVirtualPocket), ResourceUtil.PATH_KEY_PROVIDER);
CompletableFuture<SimpleTree<String, VirtualPocket>> futureVirtualPockets = ResourceUtil.loadResourcePathToMap(manager, "pockets/virtual", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.andThenReader(this::loadVirtualPocket), ResourceUtil.PATH_KEY_PROVIDER);
CompletableFuture<SimpleTree<String, PocketTemplate>> futureTemplates = ResourceUtil.loadResourcePathToMap(manager, "pockets/schematic", ".schem", new SimpleTree<>(String.class), ResourceUtil.COMPRESSED_NBT_READER.andThenReader(this::loadPocketTemplate), ResourceUtil.PATH_KEY_PROVIDER);
pocketGenerators = futurePocketGeneratorMap.join();
@ -64,45 +57,6 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener {
virtualPockets.values().forEach(VirtualPocket::init);
}
private <T> CompletableFuture<SimpleTree<String, T>> loadResourcePathFromJsonToTree(ResourceManager manager, String startingPath, Function<NbtElement, T> reader) {
int sub = startingPath.endsWith("/") ? 0 : 1;
Collection<Identifier> ids = manager.findResources(startingPath, str -> str.endsWith(".json"));
return CompletableFuture.supplyAsync(() -> {
SimpleTree<String, T> tree = new SimpleTree<>(String.class);
tree.putAll(ids.parallelStream().unordered().collect(Collectors.toConcurrentMap(
id -> Path.stringPath(id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + sub)),
id -> {
try {
JsonElement json = GSON.fromJson(new InputStreamReader(manager.getResource(id).getInputStream()), JsonElement.class);
return reader.apply(JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json));
} catch (IOException e) {
throw new RuntimeException("Error loading resource: " + id);
}
})));
return tree;
});
}
private <T> CompletableFuture<SimpleTree<String, T>> loadResourcePathFromCompressedNbtToTree(ResourceManager manager, String startingPath, String extension, BiFunction<NbtCompound, String, T> reader) {
int sub = startingPath.endsWith("/") ? 0 : 1;
Function<Identifier, Path<String>> normalizer = id -> Path.stringPath(id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + sub));
Collection<Identifier> ids = manager.findResources(startingPath, str -> str.endsWith(extension));
return CompletableFuture.supplyAsync(() -> {
SimpleTree<String, T> tree = new SimpleTree<>(String.class);
tree.putAll(ids.parallelStream().unordered().collect(Collectors.toConcurrentMap(
normalizer,
id -> {
try {
return reader.apply(NbtIo.readCompressed(manager.getResource(id).getInputStream()), normalizer.apply(id).reduce(String::concat).get());
} catch (IOException e) {
throw new RuntimeException("Error loading resource: " + id);
}
})));
return tree;
});
}
// public void load() {
// long startTime = System.currentTimeMillis();
//
@ -132,17 +86,17 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener {
return NbtUtil.asNbtCompound(getDataNbt(id), "Could not convert NbtElement \"" + id + "\" to NbtCompound!");
}
private VirtualPocket loadVirtualPocket(NbtElement nbt) {
private VirtualPocket loadVirtualPocket(NbtElement nbt, Path<String> ignore) {
return VirtualPocket.deserialize(nbt);
}
private PocketGenerator loadPocketGenerator(NbtElement nbt) {
private PocketGenerator loadPocketGenerator(NbtElement nbt, Path<String> ignore) {
return PocketGenerator.deserialize(NbtUtil.asNbtCompound(nbt, "Could not load PocketGenerator since its json does not represent an NbtCompound!"));
}
private PocketTemplate loadPocketTemplate(NbtCompound nbt, String id) {
private PocketTemplate loadPocketTemplate(NbtCompound nbt, Path<String> id) {
try {
return new PocketTemplate(Schematic.fromNbt(nbt), new Identifier(id));
return new PocketTemplate(Schematic.fromNbt(nbt), new Identifier(id.reduce(String::concat).orElseThrow()));
} catch (Exception e) {
throw new RuntimeException("Error loading " + nbt.toString(), e);
}

View file

@ -0,0 +1,85 @@
package org.dimdev.dimdoors.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.mojang.serialization.JsonOps;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtOps;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import org.dimdev.dimdoors.api.util.Path;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ResourceUtil {
private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create();
public static final BiFunction<String, Identifier, Path<String>> PATH_KEY_PROVIDER = (startingPath, id) -> Path.stringPath(id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + (startingPath.endsWith("/") ? 0 : 1)));
public static final ComposableFunction<JsonElement, NbtElement> JSON_TO_NBT = json -> JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json);
public static final ComposableFunction<InputStream, JsonElement> JSON_READER = inputStream -> GSON.fromJson(new InputStreamReader(inputStream), JsonElement.class);
public static final ComposableFunction<InputStream, NbtElement> NBT_READER = JSON_READER.andThenComposable(JSON_TO_NBT);
public static final ComposableFunction<InputStream, NbtCompound> COMPRESSED_NBT_READER = inputStream -> {
try {
return NbtIo.readCompressed(inputStream);
} catch (IOException e) {
throw new RuntimeException();
}
};
public static <K, T, M extends Map<K, T>> CompletableFuture<M> loadResourcePathToMap(ResourceManager manager, String startingPath, String extension, M map, BiFunction<InputStream, K, T> reader, BiFunction<String, Identifier, K> keyProvider) {
Collection<Identifier> ids = manager.findResources(startingPath, str -> str.endsWith(extension));
return CompletableFuture.supplyAsync(() -> {
map.putAll(ids.parallelStream().unordered().collect(Collectors.toConcurrentMap(
id -> keyProvider.apply(startingPath, id),
id -> {
try {
return reader.apply(manager.getResource(id).getInputStream(), keyProvider.apply(startingPath, id));
} catch (IOException | RuntimeException e) {
throw new RuntimeException("Error loading resource: " + id);
}
})));
return map;
});
}
public static <T, M extends Collection<T>> CompletableFuture<M> loadResourcePathToCollection(ResourceManager manager, String startingPath, String extension, M collection, BiFunction<InputStream, Identifier, T> reader) {
Collection<Identifier> ids = manager.findResources(startingPath, str -> str.endsWith(extension));
return CompletableFuture.supplyAsync(() -> {
collection.addAll(ids.parallelStream().unordered().map(id -> {
try {
return reader.apply(manager.getResource(id).getInputStream(), id);
} catch (IOException e) {
throw new RuntimeException("Error loading resource: " + id);
}
}).collect(Collectors.toList())); // TODO: change this to smthn concurrent
return collection;
});
}
public interface ComposableFunction<T, R> extends Function<T, R> {
default <K, V> BiFunction<T, K, V> andThenReader(BiFunction<R, K, V> function) {
return (t, k) -> function.apply(apply(t), k);
}
default <K> BiFunction<T, K, R> composeIdentity() {
return (t, k) -> apply(t);
}
default <V> ComposableFunction<T, V> andThenComposable(Function<? super R, ? extends V> after) {
return (T t) -> after.apply(apply(t));
}
}
}

View file

@ -1,21 +1,12 @@
package org.dimdev.dimdoors.world.decay;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
@ -25,9 +16,7 @@ import net.minecraft.resource.ResourceManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.api.util.Path;
import org.dimdev.dimdoors.api.util.SimpleTree;
import org.dimdev.dimdoors.world.decay.DecayPattern;
import org.dimdev.dimdoors.util.ResourceUtil;
import org.jetbrains.annotations.NotNull;
import net.minecraft.util.Identifier;
@ -86,7 +75,6 @@ public final class LimboDecay {
public static class DecayLoader implements SimpleSynchronousResourceReloadListener {
private static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create();
private static final DecayLoader INSTANCE = new DecayLoader();
private List<DecayPattern> patterns = new ArrayList<>();
@ -100,29 +88,12 @@ public final class LimboDecay {
@Override
public void reload(ResourceManager manager) {
patterns.clear();
CompletableFuture<List<DecayPattern>> futurePatternMap = loadResourcePathFromJsonToTree(manager, "decay_patterns", this::loadPattern);
CompletableFuture<List<DecayPattern>> futurePatternMap = ResourceUtil.loadResourcePathToCollection(manager, "decay_patterns", ".json", new ArrayList<>(), ResourceUtil.JSON_READER.andThenReader(this::loadPattern));
patterns = futurePatternMap.join();
}
private DecayPattern loadPattern(JsonObject object) {
return DecayPattern.deserialize(object);
}
private <T> CompletableFuture<List<T>> loadResourcePathFromJsonToTree(ResourceManager manager, String startingPath, Function<JsonObject, T> reader) {
Collection<Identifier> ids = manager.findResources(startingPath, str -> str.endsWith(".json"));
return CompletableFuture.supplyAsync(() -> {
List<T> tree = new ArrayList<>();
ids.parallelStream().unordered().<T>map(
id -> {
try {
JsonElement json = GSON.fromJson(new InputStreamReader(manager.getResource(id).getInputStream()), JsonElement.class);
return reader.apply(json.getAsJsonObject());
} catch (IOException e) {
throw new RuntimeException("Error loading resource: " + id);
}
}).forEach(tree::add);
return tree;
});
private DecayPattern loadPattern(JsonElement object, Identifier ignored) {
return DecayPattern.deserialize(object.getAsJsonObject());
}
public @NotNull Collection<DecayPattern> getPatterns() {