Skip to content

Commit

Permalink
feat: pack config (hopefully functional)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zepalesque committed Jun 16, 2024
1 parent 4f46a11 commit 10d6a78
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 37 deletions.
42 changes: 6 additions & 36 deletions src/main/java/net/zepalesque/redux/Redux.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import net.zepalesque.redux.entity.ReduxEntities;
import net.zepalesque.redux.item.ReduxItems;
import net.zepalesque.redux.loot.modifer.ReduxLootModifiers;
import net.zepalesque.redux.pack.ReduxPackConfig;
import net.zepalesque.redux.pack.PackUtils;
import net.zepalesque.redux.recipe.ReduxRecipes;
import net.zepalesque.redux.tile.ReduxTiles;
import net.zepalesque.redux.world.biome.tint.ReduxBiomeTints;
Expand Down Expand Up @@ -104,45 +106,13 @@ private void commonSetup(final FMLCommonSetupEvent event) {
private void registerDataMaps(RegisterDataMapTypesEvent event) {
}

// TODO: probably fairly obvious what is TODO (pack config)
public void packSetup(AddPackFindersEvent event) {

if (event.getPackType() == PackType.CLIENT_RESOURCES) {
Path resourcePath = ModList.get().getModFileById(MODID).getFile().findResource("packs/resource/tintable_grass");
PackMetadataSection metadata = new PackMetadataSection(Component.translatable("pack.aether_redux.tintable_grass.description"),
SharedConstants.getCurrentVersion().getPackVersion(PackType.CLIENT_RESOURCES));
event.addRepositorySource((source) ->
source.accept(Pack.create(
"builtin/redux/resource/tintable_grass",
Component.translatable("pack.aether_redux.tintable_grass.title"),
false,
new PathPackResources.PathResourcesSupplier(resourcePath, true),
new Pack.Info(metadata.description(), PackCompatibility.COMPATIBLE, FeatureFlagSet.of(), List.of(), false),
Pack.Position.TOP,
false,
PackSource.BUILT_IN)
));
String pathString = "resource/overrides_pack";
String id = "overrides_pack";
PackUtils.setupPack(event, pathString, id, PackType.CLIENT_RESOURCES, true, ReduxPackConfig::generate);
} else if (event.getPackType() == PackType.SERVER_DATA) {
if (ReduxConfig.COMMON.bronze_dungeon_upgrade.get()) { requiredDatapack(event, "dungeon_upgrades/bronze", "bronze_upgrade"); }
}
}

private void requiredDatapack(AddPackFindersEvent event, String path, String id) {
if (event.getPackType() == PackType.SERVER_DATA) {
Path resourcePath = ModList.get().getModFileById(MODID).getFile().findResource("packs/data/" + path);
PackMetadataSection metadata = new PackMetadataSection(Component.translatable("pack.aether_redux." + id + ".description"),
SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA));
event.addRepositorySource((source) ->
source.accept(Pack.create(
"builtin/redux/data/" + path,
Component.translatable("pack.aether_redux." + id + ".title"),
true,
new PathPackResources.PathResourcesSupplier(resourcePath, true),
new Pack.Info(metadata.description(), PackCompatibility.COMPATIBLE, FeatureFlagSet.of(), List.of(), false),
Pack.Position.TOP,
false,
PackSource.BUILT_IN)
));
if (ReduxConfig.COMMON.bronze_dungeon_upgrade.get()) { PackUtils.setupPack(event, "dungeon_upgrades/bronze", "bronze_upgrade", PackType.SERVER_DATA, true); }
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/main/java/net/zepalesque/redux/config/ReduxConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,19 @@ public static class Client {

public final ModConfigSpec.ConfigValue<Boolean> leaf_particles;

public final ModConfigSpec.ConfigValue<Boolean> tintable_grass;

public Client(ModConfigSpec.Builder builder) {
builder.push("TODO");
builder.push("Visual");
leaf_particles = builder
.comment("Use nice falling leaf particles for Aether leaf blocks")
.define("Leaf Particles", true);
builder.pop();
builder.push("Built-in Packs");
tintable_grass = builder
.comment("Use modified models to allow tintable Aether Grass blocks and plants. Only disable if you know what you're doing!")
.define("Tinted Grass", true);
builder.pop();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package net.zepalesque.redux.pack;

import com.aetherteam.aether.client.CombinedPackResources;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.AbstractPackResources;
import net.minecraft.server.packs.CompositePackResources;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.resources.IoSupplier;
import net.neoforged.neoforge.common.conditions.ConditionalOps;
import net.zepalesque.redux.Redux;
import org.apache.commons.compress.utils.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;

public class ConfigAssembledPackResources extends AbstractPackResources {

private final Map<Supplier<Boolean>, PackResources> packs;
private final Map<String, Map<Supplier<Boolean>, PackResources>> assets;
private final Path source;
private static final Gson GSON = new Gson();
protected ConfigAssembledPackResources(String name, boolean builtin, ImmutableMap.Builder<Supplier<Boolean>, PackResources> builder, Path source) {
super(name, builtin);
this.source = source;
Map<Supplier<Boolean>, PackResources> packs = builder.build();
this.packs = packs;
this.assets = this.buildNamespaceMap(PackType.CLIENT_RESOURCES, packs);
}

private Map<String, Map<Supplier<Boolean>, PackResources>> buildNamespaceMap(PackType type, Map<Supplier<Boolean>, PackResources> packMap) {
Map<String, Map<Supplier<Boolean>, PackResources>> map = new HashMap<>();
for (Map.Entry<Supplier<Boolean>, PackResources> entry : packMap.entrySet()) {
if (entry.getValue() != null) {
PackResources pack = entry.getValue();
for (String namespace : pack.getNamespaces(type)) {
map.computeIfAbsent(namespace, k -> new HashMap<>()).put(entry.getKey(), pack);
}
}
}
map.replaceAll((k, list) -> ImmutableMap.copyOf(list));
return ImmutableMap.copyOf(map);
}

@Nullable
@Override
public IoSupplier<InputStream> getRootResource(String... paths) {
Path path = this.resolve(paths);
return !Files.exists(path) ? null : IoSupplier.create(path);
}

protected Path resolve(String... paths) {
Path path = this.source;

for (String name : paths) {
path = path.resolve(name);
}
return path;
}

@Nullable
@Override
public IoSupplier<InputStream> getResource(PackType type, ResourceLocation location) {
if (location.getPath().matches("lang/.+\\.json")) {
JsonObject combined = new JsonObject();
for (PackResources pack : getCandidatePacks(type, location)) {
IoSupplier<InputStream> ioSupplier = pack.getResource(type, location);
if (ioSupplier != null) {
try {
JsonObject jsonobject = GSON.fromJson(new InputStreamReader(ioSupplier.get(), StandardCharsets.UTF_8), JsonObject.class);
jsonobject.entrySet().forEach(entry -> combined.add(entry.getKey(), entry.getValue()));
} catch (IOException e) {
Redux.LOGGER.error("Caught exception when trying to combine language files!", e);
}
}
}

if (combined.isEmpty()) {
return null;
}
String input = GSON.toJson(combined);
return () -> new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8));
} else {
for (PackResources pack : this.getCandidatePacks(type, location)) {
IoSupplier<InputStream> ioSupplier = pack.getResource(type, location);
if (ioSupplier != null) {
return ioSupplier;
}
}
return null;
}
}

@Override
public void listResources(PackType type, String resourceNamespace, String paths, ResourceOutput resourceOutput) {
for (PackResources delegate : this.getAvaliablePacks()) {
delegate.listResources(type, resourceNamespace, paths, resourceOutput);
}
}

public List<PackResources> getAvaliablePacks() {
return packs.entrySet().stream().filter(entry -> entry.getKey().get()).map(Map.Entry::getValue).toList();
}

@Override
public @NotNull Set<String> getNamespaces(PackType type) {
return type == PackType.CLIENT_RESOURCES ? assets.keySet() : Set.of();
}

@Override
public void close() {
for (PackResources pack : packs.values()) {
pack.close();
}
}

private List<PackResources> getCandidatePacks(PackType type, ResourceLocation location) {
if (type == PackType.CLIENT_RESOURCES) {
Map<Supplier<Boolean>, PackResources> packsWithNamespace = this.assets.get(location.getNamespace());
return packsWithNamespace == null ? Collections.emptyList() : packsWithNamespace.entrySet().stream().filter(entry -> entry.getKey().get()).map(Map.Entry::getValue).toList();
} else {
return Collections.emptyList();
}
}

public String toString() {
return String.format("%s: %s", this.getClass().getName(), source);
}


public record AssembledResourcesSupplier(boolean builtin, ImmutableMap.Builder<Supplier<Boolean>, PackResources> builder, Path source) implements Pack.ResourcesSupplier {
@Override
public PackResources openPrimary(String pId) {
return new ConfigAssembledPackResources(pId, this.builtin, this.builder, this.source);
}

@Override
public PackResources openFull(String id, Pack.Info info) {
PackResources packresources = this.openPrimary(id);
List<String> list = info.overlays();
if (list.isEmpty()) {
return packresources;
} else {
List<PackResources> list1 = new ArrayList<>(list.size());

for (String s : list) {
Path path = this.source.resolve(s);
list1.add(new ConfigAssembledPackResources(id, this.builtin, this.builder, path));
}

return new CompositePackResources(packresources, list1);
}
}
}
}
45 changes: 45 additions & 0 deletions src/main/java/net/zepalesque/redux/pack/PackUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package net.zepalesque.redux.pack;

import net.minecraft.SharedConstants;
import net.minecraft.network.chat.Component;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.PathPackResources;
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackCompatibility;
import net.minecraft.server.packs.repository.PackSource;
import net.minecraft.world.flag.FeatureFlagSet;
import net.neoforged.fml.ModList;
import net.neoforged.neoforge.event.AddPackFindersEvent;
import net.zepalesque.redux.Redux;

import java.nio.file.Path;
import java.util.List;
import java.util.function.Function;

public class PackUtils {

public static void setupPack(AddPackFindersEvent event, String path, String id, PackType side, boolean required, Function<Path, Pack.ResourcesSupplier> packBuilder) {
if (event.getPackType() == side) {
String folder = (side == PackType.SERVER_DATA ? "data/" : "resource/");
Path resourcePath = ModList.get().getModFileById(Redux.MODID).getFile().findResource("packs/" + folder + path);
PackMetadataSection metadata = new PackMetadataSection(Component.translatable("pack.aether_redux." + id + ".description"),
SharedConstants.getCurrentVersion().getPackVersion(side));
event.addRepositorySource((source) ->
source.accept(Pack.create(
"builtin/redux/" + folder + path,
Component.translatable("pack.aether_redux." + id + ".title"),
required,
packBuilder.apply(resourcePath),
new Pack.Info(metadata.description(), PackCompatibility.COMPATIBLE, FeatureFlagSet.of(), List.of(), false),
Pack.Position.TOP,
false,
PackSource.BUILT_IN)
));
}
}

public static void setupPack(AddPackFindersEvent event, String path, String id, PackType side, boolean required) {
setupPack(event, path, id, side, required, resourcePath -> new PathPackResources.PathResourcesSupplier(resourcePath, true));
}
}
33 changes: 33 additions & 0 deletions src/main/java/net/zepalesque/redux/pack/ReduxPackConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.zepalesque.redux.pack;

import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import net.minecraft.SharedConstants;
import net.minecraft.network.chat.Component;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.PathPackResources;
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
import net.neoforged.fml.ModList;
import net.neoforged.neoforge.common.ModConfigSpec;
import net.zepalesque.redux.Redux;
import net.zepalesque.redux.config.ReduxConfig;

import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class ReduxPackConfig {
public static ConfigAssembledPackResources.AssembledResourcesSupplier generate(Path path) {
ImmutableMap.Builder<Supplier<Boolean>, PackResources> builder = new ImmutableMap.Builder<>();
builder.put(ReduxConfig.CLIENT.tintable_grass, createPack("resource/tintable_grass"));

return new ConfigAssembledPackResources.AssembledResourcesSupplier(true, builder, path);
}

public static PathPackResources createPack(String path) {
Path resourcePath = ModList.get().getModFileById(Redux.MODID).getFile().findResource("packs/" + path);
return new PathPackResources(ModList.get().getModFileById(Redux.MODID).getFile().getFileName() + ":" + resourcePath, resourcePath, true);
}
}

0 comments on commit 10d6a78

Please sign in to comment.