Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.

shouldn't edit one file ten times in a row anymore

Lera b252fdde 6f7c6db5

+124 -107
+114 -107
common/src/main/java/net/lerariemann/infinity/compat/cloth/AmendmentConfigFactory.java
··· 1 1 package net.lerariemann.infinity.compat.cloth; 2 2 3 3 import com.google.common.collect.Lists; 4 - import com.google.gson.JsonArray; 5 - import com.google.gson.JsonElement; 6 - import com.google.gson.JsonObject; 7 4 import me.shedaniel.clothconfig2.api.ConfigBuilder; 8 5 import me.shedaniel.clothconfig2.api.ConfigCategory; 9 6 import me.shedaniel.clothconfig2.api.Requirement; ··· 26 23 27 24 public class AmendmentConfigFactory { 28 25 public static void build(ConfigBuilder builder) { 29 - ConfigCategory amendmentCategory = builder.getOrCreateCategory(Text.translatable("config.infinity.title.amendments")); 30 - JsonObject amendmentList = readJson(configPath()+("/amendments.json")).getAsJsonObject(); 31 - var elements = amendmentList.getAsJsonArray("elements"); 32 - int numAmendments = 0; 33 - for (JsonElement amendmentElement : elements) { 34 - amendmentCategory.addEntry(AmendmentBuilder.getNew(builder, amendmentElement, numAmendments)); 35 - numAmendments++; 26 + AmendmentConfigFactory factory = new AmendmentConfigFactory(builder); 27 + builder.setSavingRunnable(factory::save); 28 + } 29 + 30 + Map<Integer, NbtCompound> amendments = new HashMap<>(); 31 + boolean edited = false; 32 + ConfigCategory amendmentCategory; 33 + ConfigBuilder builder; 34 + 35 + AmendmentConfigFactory(ConfigBuilder builder) { 36 + this.builder = builder; 37 + 38 + NbtList list = readNbt(configPath()+"/amendments.json").getList("elements", 10); 39 + int N = list.size(); 40 + for (int i = 0; i < N; i++) if (list.get(i) instanceof NbtCompound e) { 41 + amendments.put(i, e); 36 42 } 37 43 38 - var moreAmendments = builder.entryBuilder().startIntField(Text.literal("Add more amendments:"), 0).setMax(10).build(); 39 - amendmentCategory.addEntry(moreAmendments); 40 - for (int i = 0; i < 10; i++) { 41 - amendmentCategory.addEntry(AmendmentBuilder.getShadow(builder, numAmendments, moreAmendments, i)); 42 - numAmendments++; 44 + //adding amendments from the disk 45 + this.amendmentCategory = builder.getOrCreateCategory(Text.translatable("config.infinity.title.amendments")); 46 + for (int i = 0; i < N; i++) { 47 + amendmentCategory.addEntry(AmendmentBuilder.getNew(this, i)); 48 + } 49 + 50 + //"button" to show new amendments 51 + var moreAmendmentsField = builder.entryBuilder() 52 + .startIntField(Text.translatable("config.infinity.amendments.addmore"), 0) 53 + .setTooltip(amendmentTooltip("addmore")) 54 + .setMax(10) 55 + .build(); 56 + amendmentCategory.addEntry(moreAmendmentsField); 57 + 58 + //empty fields to add new amendments 59 + for (int i = N; i < N + 10; i++) { 60 + amendments.put(i, new NbtCompound()); 61 + amendmentCategory.addEntry(AmendmentBuilder.getShadow(this, i, moreAmendmentsField, i - N)); 62 + } 63 + } 64 + 65 + void save() { 66 + if (!edited) return; 67 + NbtList elements = new NbtList(); 68 + var keys = amendments.keySet().stream().sorted().toList(); 69 + for (int k: keys) { 70 + NbtCompound value = amendments.get(k); 71 + if (!value.isEmpty()) elements.add(value); 43 72 } 73 + NbtCompound res = new NbtCompound(); 74 + res.putInt("amendment_version", (int)((System.currentTimeMillis() - 1754769333185L)/1000)); 75 + res.put("elements", elements); 76 + CommonIO.write(res, configPath(), "amendments.json"); 44 77 } 45 78 46 79 interface AmendmentUpdater<T> { 47 80 boolean check(NbtCompound amendment, String key, T value); 48 - void update(NbtCompound amendment, String key, T value); 81 + NbtCompound update(NbtCompound amendment, String key, T value); 49 82 50 83 AmendmentUpdater<String> ofString = new AmendmentUpdater<>() { 51 84 @Override ··· 54 87 } 55 88 56 89 @Override 57 - public void update(NbtCompound amendment, String key, String value) { 90 + public NbtCompound update(NbtCompound amendment, String key, String value) { 58 91 amendment.putString(key, value); 92 + return amendment; 59 93 } 60 94 }; 61 95 AmendmentUpdater<Double> ofDouble = new AmendmentUpdater<>() { ··· 65 99 } 66 100 67 101 @Override 68 - public void update(NbtCompound amendment, String key, Double value) { 102 + public NbtCompound update(NbtCompound amendment, String key, Double value) { 69 103 amendment.putDouble(key, value); 104 + return amendment; 70 105 } 71 106 }; 72 107 AmendmentUpdater<List<String>> ofStringList = new AmendmentUpdater<>() { ··· 80 115 return !Objects.equals(a.toString(), b.toString()); 81 116 } 82 117 @Override 83 - public void update(NbtCompound amendment, String key, List<String> value) { 118 + public NbtCompound update(NbtCompound amendment, String key, List<String> value) { 84 119 amendment.put(key, convertNbtList(value)); 120 + return amendment; 85 121 } 86 122 }; 87 123 } ··· 91 127 return () -> Objects.equals(holder.getValue(), m); 92 128 } 93 129 94 - static class AmendmentBuilder { 95 - ConfigBuilder builder; 96 - SubCategoryBuilder subCategory; 97 - int i; 98 - JsonObject amendment; 99 - 100 - AmendmentBuilder(ConfigBuilder builder, SubCategoryBuilder subCategory, int i, JsonObject amendment) { 101 - this.builder = builder; 102 - this.subCategory = subCategory; 103 - this.i = i; 104 - this.amendment = amendment; 130 + record AmendmentBuilder(AmendmentConfigFactory parent, SubCategoryBuilder subCategory, int index) { 131 + NbtCompound getData() { 132 + return parent.amendments.get(index); 105 133 } 106 134 107 135 void build() { ··· 122 150 addStringDropdownOption("field_name", 123 151 Requirement.all(matches(area, "blocks"), matches(results, "set_field")), 124 152 Lists.newArrayList("full", "float", "top", "laggy")); 153 + addDeleteButton(); 154 + } 155 + 156 + private void addDeleteButton() { 157 + subCategory.add(parent.builder.entryBuilder().startBooleanToggle(Text.translatable("config.infinity.amendments.delete"), false) 158 + .requireRestart() 159 + .setTooltip(amendmentTooltip("delete")) 160 + .setSaveConsumer((value) -> { 161 + if (value) deleteAmendment(); 162 + }) 163 + .build()); 125 164 } 126 165 127 166 private void addStringOption(String name, Requirement req) { 128 - String current = getSafeString(amendment, name); 129 - subCategory.add(builder.entryBuilder().startStrField( 167 + String current = NbtUtils.getString(getData(), name, ""); 168 + subCategory.add(parent.builder.entryBuilder().startStrField( 130 169 Text.translatable("config.infinity.amendments."+name), 131 170 current) 171 + .requireRestart() 132 172 .setTooltip(amendmentTooltip(name)) 133 173 .setDisplayRequirement(req) 134 - .setSaveConsumer((value)-> amendmentSetter(name, value, i, AmendmentUpdater.ofString)).build()); 174 + .setSaveConsumer((value)-> amendmentSetter(name, value, AmendmentUpdater.ofString)).build()); 135 175 } 136 176 137 177 private DropdownBoxEntry<String> addStringDropdownOption(String name, Requirement req, List<String> options) { 138 - String current = getSafeString(amendment, name); 139 - DropdownBoxEntry<String> res = builder.entryBuilder().startDropdownMenu(Text.translatable("config.infinity.amendments."+name), DropdownMenuBuilder.TopCellElementBuilder.of(current, (s) -> s)) 178 + String current = NbtUtils.getString(getData(), name, ""); 179 + DropdownBoxEntry<String> res = parent.builder.entryBuilder().startDropdownMenu( 180 + Text.translatable("config.infinity.amendments."+name), 181 + DropdownMenuBuilder.TopCellElementBuilder.of(current, (s) -> s)) 182 + .requireRestart() 140 183 .setTooltip(amendmentTooltip(name)) 141 184 .setDisplayRequirement(req) 142 - .setSaveConsumer((value) -> amendmentSetter(name, String.valueOf(value), i, AmendmentUpdater.ofString)) 185 + .setSaveConsumer((value) -> amendmentSetter(name, String.valueOf(value), AmendmentUpdater.ofString)) 143 186 .setSelections(options).build(); 144 187 subCategory.add(res); 145 188 return res; 146 189 } 147 190 148 191 private void addDoubleOption(String name, Requirement req) { 149 - Double current = getSafeDouble(amendment, name); 150 - subCategory.add(builder.entryBuilder().startDoubleField( 192 + double current = NbtUtils.getDouble(getData(), name, 0d); 193 + subCategory.add(parent.builder.entryBuilder().startDoubleField( 151 194 Text.translatable("config.infinity.amendments."+name), 152 195 current) 196 + .requireRestart() 153 197 .setTooltip(amendmentTooltip(name)) 154 198 .setDisplayRequirement(req) 155 - .setSaveConsumer((value) -> amendmentSetter(name, value, i, AmendmentUpdater.ofDouble)).build()); 199 + .setSaveConsumer((value) -> amendmentSetter(name, value, AmendmentUpdater.ofDouble)).build()); 200 + } 201 + 202 + List<String> getSafeList(String name) { 203 + NbtCompound data = getData(); 204 + if (data.contains(name, NbtElement.LIST_TYPE)) return convertNbtList(data.getList(name, NbtElement.STRING_TYPE)); 205 + return List.of(""); 156 206 } 157 207 158 208 private void addListOption(String name, Requirement req) { 159 - JsonElement list = amendment.get(name); 160 - List<String> current = (list == null || !list.isJsonArray()) ? List.of("") : convertNbtList(list.getAsJsonArray()); 161 - if (!Objects.equals(current.getLast(), "")) 162 - current.add(""); 163 - subCategory.add(builder.entryBuilder().startStrList( 209 + List<String> current = getSafeList(name); 210 + if (!Objects.equals(current.getLast(), "")) current.add(""); 211 + subCategory.add(parent.builder.entryBuilder().startStrList( 164 212 Text.translatable("config.infinity.amendments."+name), 165 213 current) 214 + .requireRestart() 166 215 .setTooltip(amendmentTooltip(name)) 167 216 .setDisplayRequirement(req) 168 - .setSaveConsumer((value) -> amendmentSetter(name, value, i, AmendmentUpdater.ofStringList)).build()); 217 + .setSaveConsumer((value) -> amendmentSetter(name, value, AmendmentUpdater.ofStringList)).build()); 169 218 } 170 219 171 - <T> void amendmentSetter(String name, T newValue, int amendmentIndex, AmendmentUpdater<T> updater) { 172 - NbtCompound elements = readNbt(configPath()+"/amendments.json"); 173 - NbtList list = elements.getList("elements", 10); 174 - NbtCompound amendmentNbt = list.getCompound(amendmentIndex); 175 - 220 + <T> void amendmentSetter(String key, T newValue, AmendmentUpdater<T> updater) { 221 + NbtCompound amendmentNbt = getData(); 176 222 // Check if an amendment should be changed before writing 177 - if (updater.check(amendmentNbt, name, newValue)) { 178 - updater.update(amendmentNbt, name, newValue); 179 - updateAmendmentVersion(elements); 180 - CommonIO.write(elements, configPath(), "amendments.json"); 223 + if (updater.check(amendmentNbt, key, newValue)) { 224 + amendmentNbt = updater.update(amendmentNbt, key, newValue); 225 + parent.edited = true; 226 + parent.amendments.put(index, amendmentNbt); 181 227 } 182 228 } 183 229 184 - static SubCategoryListEntry getNew(ConfigBuilder builder, JsonElement amendmentElement, int i) { 185 - JsonObject amendment = amendmentElement.getAsJsonObject();; 186 - SubCategoryBuilder subCategory = builder.entryBuilder().startSubCategory(Text.translatable("config.infinity.amendment", String.valueOf(i))); 230 + void deleteAmendment() { 231 + parent.amendments.put(index, new NbtCompound()); 232 + parent.edited = true; 233 + } 187 234 188 - (new AmendmentBuilder(builder, subCategory, i, amendment)).build(); 235 + static SubCategoryListEntry getNew(AmendmentConfigFactory parent, int i) { 236 + SubCategoryBuilder subCategory = parent.builder.entryBuilder().startSubCategory( 237 + Text.translatable("config.infinity.amendment", String.valueOf(i))); 238 + (new AmendmentBuilder(parent, subCategory, i)).build(); 189 239 return subCategory.build(); 190 240 } 191 241 192 - static SubCategoryListEntry getShadow(ConfigBuilder builder, int i, ValueHolder<Integer> shadowAmount, int shadowI) { 193 - SubCategoryBuilder subCategory = builder.entryBuilder() 242 + static SubCategoryListEntry getShadow(AmendmentConfigFactory parent, int i, ValueHolder<Integer> shadowAmount, int shadowI) { 243 + SubCategoryBuilder subCategory = parent.builder.entryBuilder() 194 244 .startSubCategory(Text.translatable("config.infinity.amendment.new")) 195 245 .setDisplayRequirement(() -> shadowAmount.getValue() > shadowI); 196 - 197 - (new NewAmendmentBuilder(builder, subCategory, i)).build(); 246 + (new AmendmentBuilder(parent, subCategory, i)).build(); 198 247 return subCategory.build(); 199 248 } 200 - 201 - static void updateAmendmentVersion(NbtCompound elements) { 202 - elements.putInt("amendment_version", (int)((System.currentTimeMillis() - 1754769333185L)/1000)); 203 - } 204 - } 205 - 206 - static class NewAmendmentBuilder extends AmendmentBuilder { 207 - NewAmendmentBuilder(ConfigBuilder builder, SubCategoryBuilder subCategory, int i) { 208 - super(builder, subCategory, i, new JsonObject()); 209 - } 210 - 211 - @Override 212 - <T> void amendmentSetter(String name, T newValue, int amendmentIndex, AmendmentUpdater<T> updater) { 213 - NbtCompound elements = readNbt(configPath()+"/amendments.json"); 214 - NbtList list = elements.getList("elements", 10); 215 - if (amendmentIndex < list.size()) { 216 - super.amendmentSetter(name, newValue, amendmentIndex, updater); 217 - return; 218 - } 219 - NbtCompound amendmentNbt = new NbtCompound(); 220 - 221 - // Check if an amendment should be changed before writing 222 - if (updater.check(amendmentNbt, name, newValue)) { 223 - updater.update(amendmentNbt, name, newValue); 224 - list.add(amendmentNbt); 225 - updateAmendmentVersion(elements); 226 - CommonIO.write(elements, configPath(), "amendments.json"); 227 - } 228 - } 229 - } 230 - 231 - private static String getSafeString(JsonObject amendment, String key) { 232 - var amend = amendment.get(key); 233 - if (amend != null && !amend.isJsonArray()) 234 - return amend.getAsString(); 235 - else return ""; 236 - } 237 - private static Double getSafeDouble(JsonObject amendment, String key) { 238 - var amend = amendment.get(key); 239 - if (amend != null && !amend.isJsonArray()) 240 - return amend.getAsDouble(); 241 - else return 0d; 242 249 } 243 250 244 251 static NbtList convertNbtList(List<String> list) { ··· 249 256 return nbtList; 250 257 } 251 258 252 - static List<String> convertNbtList(JsonArray nbtList) { 259 + static List<String> convertNbtList(NbtList nbtList) { 253 260 ArrayList<String> list = new ArrayList<>(); 254 - for (JsonElement s : nbtList) { 255 - list.add(s.getAsString()); 261 + for (NbtElement s : nbtList) { 262 + list.add(s.asString()); 256 263 } 257 264 return list; 258 265 }
+10
common/src/main/resources/assets/infinity/lang/en_us.json
··· 171 171 "config.infinity.title.rootChances": "Root Chances", 172 172 "config.infinity.amendment": "Amendment #%s", 173 173 "config.infinity.amendment.new": "New Amendment", 174 + "config.infinity.amendments.addmore": "Add more amendments:", 175 + "config.infinity.amendments.addmore.description": "Change this number to start creating additional amendments, up to 10 at at time.", 174 176 "config.infinity.amendments.area": "Area", 175 177 "config.infinity.amendments.area.description": "What part of Infinite Dimensions generation to affect. Options include blocks, fluids, trees, mobs, structures.", 176 178 "config.infinity.amendments.mod": "Mod Name", ··· 179 181 "config.infinity.amendments.selector.description": "This governs what content within the selected mod and area is affected by the amendment, \"all\" to amend an entire mod, \"matching\" to amend a single entry, \"matching_any\" to amend a list of entries, \"matching_block_tag\" amends a block tag, \"containing\" amends any entry with certain characters in its name. ", 180 182 "config.infinity.amendments.matching": "Matching", 181 183 "config.infinity.amendments.matching.description": "Amends a single entry with the following ID.", 184 + "config.infinity.amendments.matching_any": "Matching any", 185 + "config.infinity.amendments.matching_any.description": "Amends all entries from a following list.", 186 + "config.infinity.amendments.matching_block_tag": "Matching block tag", 187 + "config.infinity.amendments.matching_block_tag.description": "Amends all entries from a following block tag.", 188 + "config.infinity.amendments.containing": "Containing", 189 + "config.infinity.amendments.containing.description": "Amends all entries which contain the following substring in their ID.", 182 190 "config.infinity.amendments.results": "Results", 183 191 "config.infinity.amendments.results.description": "Sets how to affect the matched item. Values include \"set_value\" which sets the weight of an element, \"set_field\" which can amend the internal type of a block, and \"erase\" which prevents an element from generating.", 184 192 "config.infinity.amendments.field_name": "Field Name", 185 193 "config.infinity.amendments.field_name.description": "Set the value of the field to be amended. Options include \"full\" representing standard blocks, \"float\" which represents full blocks not affected by gravity, \"top\" representing blocks that require a block below like Sand, and \"laggy\" representing block entities like Chests.", 186 194 "config.infinity.amendments.value": "Value", 187 195 "config.infinity.amendments.value.description": "How often an element occurs in generation. The default weight is 1.", 196 + "config.infinity.amendments.delete": "Delete this amendment?", 197 + "config.infinity.amendments.delete.description": "Toggle for this amendment to be removed upon saving and exiting.", 188 198 "config.infinity.salt": "Salt", 189 199 "config.infinity.salt.description": "This string will be added to the book text in the process of its conversion to the dimension ID. This can be used to ensure your dimensions are differing from dimensions with the same book text that other users generate. You can do this if you don't want to go into the mod already knowing \"oh, the dimension 90 has diamonds\" etc. Does not affect \"easter egg\"-type dimensions.", 190 200 "config.infinity.portalKey": "Portal Key",