Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
1package net.lerariemann.infinity.util.config;
2
3import net.lerariemann.infinity.InfinityMod;
4import net.lerariemann.infinity.util.core.CommonIO;
5import net.lerariemann.infinity.util.core.ConfigType;
6import net.lerariemann.infinity.util.core.NbtUtils;
7import net.lerariemann.infinity.util.core.WeighedStructure;
8import net.minecraft.nbt.CompoundTag;
9import net.minecraft.nbt.ListTag;
10import net.minecraft.resources.ResourceLocation;
11import org.jspecify.annotations.Nullable;
12
13import java.util.*;
14import java.util.concurrent.atomic.AtomicInteger;
15import java.util.stream.IntStream;
16
17/** A collection of {@link WeighedStructure} objects, used in {@link ConfigGenerator} to auto-sort different types of game content by mod ID.
18 * @author LeraRiemann */
19public class DataCollection {
20 private final Map<String, List<CompoundTag>> map = new HashMap<>();
21 public static Map<ConfigType, List<Amendment>> amendmentList = Amendment.getAmendmentList();
22 ConfigType type;
23 List<Amendment> amendments;
24
25 DataCollection(ConfigType name) {
26 this.type = name;
27 this.amendments = amendmentList.getOrDefault(type, List.of());
28 }
29
30 void add(String modId, CompoundTag elem) {
31 if (!map.containsKey(modId)) map.put(modId, new ArrayList<>());
32 map.get(modId).add(elem);
33 }
34 void add(String modId, String key, @Nullable CompoundTag data) {
35 CompoundTag elem = getAmendedEntry(modId, key, data);
36 if (elem == null) return;
37 add(modId, elem);
38 }
39 void add(String modId, String key) {
40 add(modId, key, null);
41 }
42
43 CompoundTag getAmendedEntry(String modId, String key, @Nullable CompoundTag data) {
44 double weight = 1.0;
45 for (Amendment a: amendments) if (a.applies(modId, key)) {
46 weight = a.apply();
47 data = a.apply(data);
48 break;
49 }
50 if (weight == 0) return null;
51 CompoundTag elem = new CompoundTag();
52 elem.putString("key", key);
53 if (data != null) elem.put("data", data);
54 elem.putDouble("weight", weight);
55 return elem;
56 }
57
58 public void addIdentifier(ResourceLocation id) {
59 add(id.getNamespace(), id.toString());
60 }
61
62 /** Writes collected content to the disk, creating a separate file for every collected mod. */
63 void save() {
64 map.forEach((modId, data) -> CommonIO.write(wrapAndSortByKey(data),
65 InfinityMod.configPath.resolve("modular").resolve(modId),
66 type.getKey() + ".json"));
67 }
68
69 /**
70 * Wraps collected data into a format compatible with {@link CommonIO}, sorting it alphabetically in the process
71 * (this isn't strictly required but makes files much easier to navigate).
72 */
73 static CompoundTag wrapAndSortByKey(List<CompoundTag> w) {
74 CompoundTag res = new CompoundTag();
75 ListTag elements = new ListTag();
76 List<Integer> range = new ArrayList<>(IntStream.rangeClosed(0, w.size() - 1).boxed().toList());
77 range.sort(new Comparator<Integer>() {
78 public String extract(int i) {
79 CompoundTag compound = w.get(i);
80 return NbtUtils.getString(compound, "key");
81 }
82 @Override
83 public int compare(Integer i, Integer j) {
84 return extract(i).compareTo(extract(j));
85 }
86 });
87 for (int i = 0; i < w.size(); i++) {
88 elements.add(w.get(range.get(i)));
89 }
90 res.put("elements", elements);
91 return res;
92 }
93
94 static void loggerOutput(int count, String type) {
95 InfinityMod.LOGGER.info("Registered {} {}", count, type);
96 }
97
98 /** An implementation of {@link DataCollection} that logs the total amount of stored entries in the {@link InfinityMod#LOGGER}. */
99 static class Logged extends DataCollection {
100 private final AtomicInteger i = new AtomicInteger();
101 String loggerName;
102
103 Logged(ConfigType name) {
104 this(name, name.getKey());
105 }
106 Logged(ConfigType name, String loggerName) {
107 super(name);
108 this.loggerName = loggerName;
109 }
110
111 @Override
112 void add(String modId, CompoundTag elem) {
113 super.add(modId, elem);
114 i.getAndIncrement();
115 }
116 @Override
117 void save() {
118 super.save();
119 loggerOutput(i.get(), loggerName);
120 }
121 }
122}