411 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			411 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.util.datafix.fixes;
 | |
| 
 | |
| import com.google.common.collect.ImmutableMap;
 | |
| import com.google.common.collect.Maps;
 | |
| import com.google.common.collect.ImmutableMap.Builder;
 | |
| import com.mojang.datafixers.DSL;
 | |
| import com.mojang.datafixers.DataFix;
 | |
| import com.mojang.datafixers.TypeRewriteRule;
 | |
| import com.mojang.datafixers.schemas.Schema;
 | |
| import com.mojang.serialization.Codec;
 | |
| import com.mojang.serialization.Dynamic;
 | |
| import com.mojang.serialization.DynamicLike;
 | |
| import com.mojang.serialization.DynamicOps;
 | |
| import com.mojang.serialization.OptionalDynamic;
 | |
| import com.mojang.serialization.codecs.RecordCodecBuilder;
 | |
| import java.util.Locale;
 | |
| import java.util.Map;
 | |
| import java.util.Objects;
 | |
| import java.util.Optional;
 | |
| import java.util.stream.Collectors;
 | |
| import java.util.stream.Stream;
 | |
| import org.apache.commons.lang3.math.NumberUtils;
 | |
| import org.apache.commons.lang3.mutable.MutableBoolean;
 | |
| import org.apache.commons.lang3.mutable.MutableInt;
 | |
| 
 | |
| public class WorldGenSettingsFix extends DataFix {
 | |
| 	private static final String VILLAGE = "minecraft:village";
 | |
| 	private static final String DESERT_PYRAMID = "minecraft:desert_pyramid";
 | |
| 	private static final String IGLOO = "minecraft:igloo";
 | |
| 	private static final String JUNGLE_TEMPLE = "minecraft:jungle_pyramid";
 | |
| 	private static final String SWAMP_HUT = "minecraft:swamp_hut";
 | |
| 	private static final String PILLAGER_OUTPOST = "minecraft:pillager_outpost";
 | |
| 	private static final String END_CITY = "minecraft:endcity";
 | |
| 	private static final String WOODLAND_MANSION = "minecraft:mansion";
 | |
| 	private static final String OCEAN_MONUMENT = "minecraft:monument";
 | |
| 	private static final ImmutableMap<String, WorldGenSettingsFix.StructureFeatureConfiguration> DEFAULTS = ImmutableMap.<String, WorldGenSettingsFix.StructureFeatureConfiguration>builder()
 | |
| 		.put("minecraft:village", new WorldGenSettingsFix.StructureFeatureConfiguration(32, 8, 10387312))
 | |
| 		.put("minecraft:desert_pyramid", new WorldGenSettingsFix.StructureFeatureConfiguration(32, 8, 14357617))
 | |
| 		.put("minecraft:igloo", new WorldGenSettingsFix.StructureFeatureConfiguration(32, 8, 14357618))
 | |
| 		.put("minecraft:jungle_pyramid", new WorldGenSettingsFix.StructureFeatureConfiguration(32, 8, 14357619))
 | |
| 		.put("minecraft:swamp_hut", new WorldGenSettingsFix.StructureFeatureConfiguration(32, 8, 14357620))
 | |
| 		.put("minecraft:pillager_outpost", new WorldGenSettingsFix.StructureFeatureConfiguration(32, 8, 165745296))
 | |
| 		.put("minecraft:monument", new WorldGenSettingsFix.StructureFeatureConfiguration(32, 5, 10387313))
 | |
| 		.put("minecraft:endcity", new WorldGenSettingsFix.StructureFeatureConfiguration(20, 11, 10387313))
 | |
| 		.put("minecraft:mansion", new WorldGenSettingsFix.StructureFeatureConfiguration(80, 20, 10387319))
 | |
| 		.build();
 | |
| 
 | |
| 	public WorldGenSettingsFix(Schema outputSchema) {
 | |
| 		super(outputSchema, true);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected TypeRewriteRule makeRule() {
 | |
| 		return this.fixTypeEverywhereTyped(
 | |
| 			"WorldGenSettings building",
 | |
| 			this.getInputSchema().getType(References.WORLD_GEN_SETTINGS),
 | |
| 			typed -> typed.update(DSL.remainderFinder(), WorldGenSettingsFix::fix)
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	private static <T> Dynamic<T> noise(long seed, DynamicLike<T> data, Dynamic<T> settings, Dynamic<T> biomeNoise) {
 | |
| 		return data.createMap(
 | |
| 			ImmutableMap.of(
 | |
| 				data.createString("type"),
 | |
| 				data.createString("minecraft:noise"),
 | |
| 				data.createString("biome_source"),
 | |
| 				biomeNoise,
 | |
| 				data.createString("seed"),
 | |
| 				data.createLong(seed),
 | |
| 				data.createString("settings"),
 | |
| 				settings
 | |
| 			)
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	private static <T> Dynamic<T> vanillaBiomeSource(Dynamic<T> data, long seed, boolean legacyBiomeInitLayer, boolean largeBiomes) {
 | |
| 		Builder<Dynamic<T>, Dynamic<T>> builder = ImmutableMap.<Dynamic<T>, Dynamic<T>>builder()
 | |
| 			.put(data.createString("type"), data.createString("minecraft:vanilla_layered"))
 | |
| 			.put(data.createString("seed"), data.createLong(seed))
 | |
| 			.put(data.createString("large_biomes"), data.createBoolean(largeBiomes));
 | |
| 		if (legacyBiomeInitLayer) {
 | |
| 			builder.put(data.createString("legacy_biome_init_layer"), data.createBoolean(legacyBiomeInitLayer));
 | |
| 		}
 | |
| 
 | |
| 		return data.createMap(builder.build());
 | |
| 	}
 | |
| 
 | |
| 	private static <T> Dynamic<T> fix(Dynamic<T> data) {
 | |
| 		DynamicOps<T> dynamicOps = data.getOps();
 | |
| 		long l = data.get("RandomSeed").asLong(0L);
 | |
| 		Optional<String> optional = data.get("generatorName").asString().<String>map(string -> string.toLowerCase(Locale.ROOT)).result();
 | |
| 		Optional<String> optional2 = (Optional<String>)data.get("legacy_custom_options")
 | |
| 			.asString()
 | |
| 			.result()
 | |
| 			.map(Optional::of)
 | |
| 			.orElseGet(() -> optional.equals(Optional.of("customized")) ? data.get("generatorOptions").asString().result() : Optional.empty());
 | |
| 		boolean bl = false;
 | |
| 		Dynamic<T> dynamic;
 | |
| 		if (optional.equals(Optional.of("customized"))) {
 | |
| 			dynamic = defaultOverworld(data, l);
 | |
| 		} else if (optional.isEmpty()) {
 | |
| 			dynamic = defaultOverworld(data, l);
 | |
| 		} else {
 | |
| 			String bl6 = (String)optional.get();
 | |
| 			switch (bl6) {
 | |
| 				case "flat":
 | |
| 					OptionalDynamic<T> optionalDynamic = data.get("generatorOptions");
 | |
| 					Map<Dynamic<T>, Dynamic<T>> map = fixFlatStructures(dynamicOps, optionalDynamic);
 | |
| 					dynamic = data.createMap(
 | |
| 						ImmutableMap.of(
 | |
| 							data.createString("type"),
 | |
| 							data.createString("minecraft:flat"),
 | |
| 							data.createString("settings"),
 | |
| 							data.createMap(
 | |
| 								ImmutableMap.of(
 | |
| 									data.createString("structures"),
 | |
| 									data.createMap(map),
 | |
| 									data.createString("layers"),
 | |
| 									(Dynamic<?>)optionalDynamic.get("layers")
 | |
| 										.result()
 | |
| 										.orElseGet(
 | |
| 											() -> data.createList(
 | |
| 												Stream.of(
 | |
| 													data.createMap(ImmutableMap.of(data.createString("height"), data.createInt(1), data.createString("block"), data.createString("minecraft:bedrock"))),
 | |
| 													data.createMap(ImmutableMap.of(data.createString("height"), data.createInt(2), data.createString("block"), data.createString("minecraft:dirt"))),
 | |
| 													data.createMap(
 | |
| 														ImmutableMap.of(data.createString("height"), data.createInt(1), data.createString("block"), data.createString("minecraft:grass_block"))
 | |
| 													)
 | |
| 												)
 | |
| 											)
 | |
| 										),
 | |
| 									data.createString("biome"),
 | |
| 									data.createString(optionalDynamic.get("biome").asString("minecraft:plains"))
 | |
| 								)
 | |
| 							)
 | |
| 						)
 | |
| 					);
 | |
| 					break;
 | |
| 				case "debug_all_block_states":
 | |
| 					dynamic = data.createMap(ImmutableMap.of(data.createString("type"), data.createString("minecraft:debug")));
 | |
| 					break;
 | |
| 				case "buffet":
 | |
| 					OptionalDynamic<T> optionalDynamic2 = data.get("generatorOptions");
 | |
| 					OptionalDynamic<?> optionalDynamic3 = optionalDynamic2.get("chunk_generator");
 | |
| 					Optional<String> optional3 = optionalDynamic3.get("type").asString().result();
 | |
| 					Dynamic<T> dynamic2;
 | |
| 					if (Objects.equals(optional3, Optional.of("minecraft:caves"))) {
 | |
| 						dynamic2 = data.createString("minecraft:caves");
 | |
| 						bl = true;
 | |
| 					} else if (Objects.equals(optional3, Optional.of("minecraft:floating_islands"))) {
 | |
| 						dynamic2 = data.createString("minecraft:floating_islands");
 | |
| 					} else {
 | |
| 						dynamic2 = data.createString("minecraft:overworld");
 | |
| 					}
 | |
| 
 | |
| 					Dynamic<T> dynamic3 = (Dynamic<T>)optionalDynamic2.get("biome_source")
 | |
| 						.result()
 | |
| 						.orElseGet(() -> data.createMap(ImmutableMap.of(data.createString("type"), data.createString("minecraft:fixed"))));
 | |
| 					Dynamic<T> dynamic4;
 | |
| 					if (dynamic3.get("type").asString().result().equals(Optional.of("minecraft:fixed"))) {
 | |
| 						String string = (String)dynamic3.get("options")
 | |
| 							.get("biomes")
 | |
| 							.asStream()
 | |
| 							.findFirst()
 | |
| 							.flatMap(dynamicx -> dynamicx.asString().result())
 | |
| 							.orElse("minecraft:ocean");
 | |
| 						dynamic4 = dynamic3.remove("options").set("biome", data.createString(string));
 | |
| 					} else {
 | |
| 						dynamic4 = dynamic3;
 | |
| 					}
 | |
| 
 | |
| 					dynamic = noise(l, data, dynamic2, dynamic4);
 | |
| 					break;
 | |
| 				default:
 | |
| 					boolean bl2 = ((String)optional.get()).equals("default");
 | |
| 					boolean bl3 = ((String)optional.get()).equals("default_1_1") || bl2 && data.get("generatorVersion").asInt(0) == 0;
 | |
| 					boolean bl4 = ((String)optional.get()).equals("amplified");
 | |
| 					boolean bl5 = ((String)optional.get()).equals("largebiomes");
 | |
| 					dynamic = noise(l, data, data.createString(bl4 ? "minecraft:amplified" : "minecraft:overworld"), vanillaBiomeSource(data, l, bl3, bl5));
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		boolean bl6 = data.get("MapFeatures").asBoolean(true);
 | |
| 		boolean bl7 = data.get("BonusChest").asBoolean(false);
 | |
| 		Builder<T, T> builder = ImmutableMap.builder();
 | |
| 		builder.put(dynamicOps.createString("seed"), dynamicOps.createLong(l));
 | |
| 		builder.put(dynamicOps.createString("generate_features"), dynamicOps.createBoolean(bl6));
 | |
| 		builder.put(dynamicOps.createString("bonus_chest"), dynamicOps.createBoolean(bl7));
 | |
| 		builder.put(dynamicOps.createString("dimensions"), vanillaLevels(data, l, dynamic, bl));
 | |
| 		optional2.ifPresent(string -> builder.put(dynamicOps.createString("legacy_custom_options"), dynamicOps.createString(string)));
 | |
| 		return new Dynamic<>(dynamicOps, dynamicOps.createMap(builder.build()));
 | |
| 	}
 | |
| 
 | |
| 	protected static <T> Dynamic<T> defaultOverworld(Dynamic<T> data, long seed) {
 | |
| 		return noise(seed, data, data.createString("minecraft:overworld"), vanillaBiomeSource(data, seed, false, false));
 | |
| 	}
 | |
| 
 | |
| 	protected static <T> T vanillaLevels(Dynamic<T> data, long seed, Dynamic<T> generator, boolean caves) {
 | |
| 		DynamicOps<T> dynamicOps = data.getOps();
 | |
| 		return dynamicOps.createMap(
 | |
| 			ImmutableMap.of(
 | |
| 				dynamicOps.createString("minecraft:overworld"),
 | |
| 				dynamicOps.createMap(
 | |
| 					ImmutableMap.of(
 | |
| 						dynamicOps.createString("type"),
 | |
| 						dynamicOps.createString("minecraft:overworld" + (caves ? "_caves" : "")),
 | |
| 						dynamicOps.createString("generator"),
 | |
| 						generator.getValue()
 | |
| 					)
 | |
| 				),
 | |
| 				dynamicOps.createString("minecraft:the_nether"),
 | |
| 				dynamicOps.createMap(
 | |
| 					ImmutableMap.of(
 | |
| 						dynamicOps.createString("type"),
 | |
| 						dynamicOps.createString("minecraft:the_nether"),
 | |
| 						dynamicOps.createString("generator"),
 | |
| 						noise(
 | |
| 								seed,
 | |
| 								data,
 | |
| 								data.createString("minecraft:nether"),
 | |
| 								data.createMap(
 | |
| 									ImmutableMap.of(
 | |
| 										data.createString("type"),
 | |
| 										data.createString("minecraft:multi_noise"),
 | |
| 										data.createString("seed"),
 | |
| 										data.createLong(seed),
 | |
| 										data.createString("preset"),
 | |
| 										data.createString("minecraft:nether")
 | |
| 									)
 | |
| 								)
 | |
| 							)
 | |
| 							.getValue()
 | |
| 					)
 | |
| 				),
 | |
| 				dynamicOps.createString("minecraft:the_end"),
 | |
| 				dynamicOps.createMap(
 | |
| 					ImmutableMap.of(
 | |
| 						dynamicOps.createString("type"),
 | |
| 						dynamicOps.createString("minecraft:the_end"),
 | |
| 						dynamicOps.createString("generator"),
 | |
| 						noise(
 | |
| 								seed,
 | |
| 								data,
 | |
| 								data.createString("minecraft:end"),
 | |
| 								data.createMap(ImmutableMap.of(data.createString("type"), data.createString("minecraft:the_end"), data.createString("seed"), data.createLong(seed)))
 | |
| 							)
 | |
| 							.getValue()
 | |
| 					)
 | |
| 				)
 | |
| 			)
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	private static <T> Map<Dynamic<T>, Dynamic<T>> fixFlatStructures(DynamicOps<T> ops, OptionalDynamic<T> generatorOptions) {
 | |
| 		MutableInt mutableInt = new MutableInt(32);
 | |
| 		MutableInt mutableInt2 = new MutableInt(3);
 | |
| 		MutableInt mutableInt3 = new MutableInt(128);
 | |
| 		MutableBoolean mutableBoolean = new MutableBoolean(false);
 | |
| 		Map<String, WorldGenSettingsFix.StructureFeatureConfiguration> map = Maps.<String, WorldGenSettingsFix.StructureFeatureConfiguration>newHashMap();
 | |
| 		if (generatorOptions.result().isEmpty()) {
 | |
| 			mutableBoolean.setTrue();
 | |
| 			map.put("minecraft:village", DEFAULTS.get("minecraft:village"));
 | |
| 		}
 | |
| 
 | |
| 		generatorOptions.get("structures")
 | |
| 			.flatMap(Dynamic::getMapValues)
 | |
| 			.ifSuccess(
 | |
| 				map2 -> map2.forEach(
 | |
| 					(dynamic, dynamic2) -> dynamic2.getMapValues()
 | |
| 						.result()
 | |
| 						.ifPresent(
 | |
| 							map2x -> map2x.forEach(
 | |
| 								(dynamic2x, dynamic3) -> {
 | |
| 									String string = dynamic.asString("");
 | |
| 									String string2 = dynamic2x.asString("");
 | |
| 									String string3 = dynamic3.asString("");
 | |
| 									if ("stronghold".equals(string)) {
 | |
| 										mutableBoolean.setTrue();
 | |
| 										switch (string2) {
 | |
| 											case "distance":
 | |
| 												mutableInt.setValue(getInt(string3, mutableInt.getValue(), 1));
 | |
| 												return;
 | |
| 											case "spread":
 | |
| 												mutableInt2.setValue(getInt(string3, mutableInt2.getValue(), 1));
 | |
| 												return;
 | |
| 											case "count":
 | |
| 												mutableInt3.setValue(getInt(string3, mutableInt3.getValue(), 1));
 | |
| 												return;
 | |
| 										}
 | |
| 									} else {
 | |
| 										switch (string2) {
 | |
| 											case "distance":
 | |
| 												switch (string) {
 | |
| 													case "village":
 | |
| 														setSpacing(map, "minecraft:village", string3, 9);
 | |
| 														return;
 | |
| 													case "biome_1":
 | |
| 														setSpacing(map, "minecraft:desert_pyramid", string3, 9);
 | |
| 														setSpacing(map, "minecraft:igloo", string3, 9);
 | |
| 														setSpacing(map, "minecraft:jungle_pyramid", string3, 9);
 | |
| 														setSpacing(map, "minecraft:swamp_hut", string3, 9);
 | |
| 														setSpacing(map, "minecraft:pillager_outpost", string3, 9);
 | |
| 														return;
 | |
| 													case "endcity":
 | |
| 														setSpacing(map, "minecraft:endcity", string3, 1);
 | |
| 														return;
 | |
| 													case "mansion":
 | |
| 														setSpacing(map, "minecraft:mansion", string3, 1);
 | |
| 														return;
 | |
| 													default:
 | |
| 														return;
 | |
| 												}
 | |
| 											case "separation":
 | |
| 												if ("oceanmonument".equals(string)) {
 | |
| 													WorldGenSettingsFix.StructureFeatureConfiguration structureFeatureConfiguration = (WorldGenSettingsFix.StructureFeatureConfiguration)map.getOrDefault(
 | |
| 														"minecraft:monument", DEFAULTS.get("minecraft:monument")
 | |
| 													);
 | |
| 													int i = getInt(string3, structureFeatureConfiguration.separation, 1);
 | |
| 													map.put(
 | |
| 														"minecraft:monument",
 | |
| 														new WorldGenSettingsFix.StructureFeatureConfiguration(i, structureFeatureConfiguration.separation, structureFeatureConfiguration.salt)
 | |
| 													);
 | |
| 												}
 | |
| 
 | |
| 												return;
 | |
| 											case "spacing":
 | |
| 												if ("oceanmonument".equals(string)) {
 | |
| 													setSpacing(map, "minecraft:monument", string3, 1);
 | |
| 												}
 | |
| 
 | |
| 												return;
 | |
| 										}
 | |
| 									}
 | |
| 								}
 | |
| 							)
 | |
| 						)
 | |
| 				)
 | |
| 			);
 | |
| 		Builder<Dynamic<T>, Dynamic<T>> builder = ImmutableMap.builder();
 | |
| 		builder.put(
 | |
| 			generatorOptions.createString("structures"),
 | |
| 			generatorOptions.createMap(
 | |
| 				(Map<? extends Dynamic<?>, ? extends Dynamic<?>>)map.entrySet()
 | |
| 					.stream()
 | |
| 					.collect(
 | |
| 						Collectors.toMap(
 | |
| 							entry -> generatorOptions.createString((String)entry.getKey()),
 | |
| 							entry -> ((WorldGenSettingsFix.StructureFeatureConfiguration)entry.getValue()).serialize(ops)
 | |
| 						)
 | |
| 					)
 | |
| 			)
 | |
| 		);
 | |
| 		if (mutableBoolean.isTrue()) {
 | |
| 			builder.put(
 | |
| 				generatorOptions.createString("stronghold"),
 | |
| 				generatorOptions.createMap(
 | |
| 					ImmutableMap.of(
 | |
| 						generatorOptions.createString("distance"),
 | |
| 						generatorOptions.createInt(mutableInt.getValue()),
 | |
| 						generatorOptions.createString("spread"),
 | |
| 						generatorOptions.createInt(mutableInt2.getValue()),
 | |
| 						generatorOptions.createString("count"),
 | |
| 						generatorOptions.createInt(mutableInt3.getValue())
 | |
| 					)
 | |
| 				)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		return builder.build();
 | |
| 	}
 | |
| 
 | |
| 	private static int getInt(String string, int defaultValue) {
 | |
| 		return NumberUtils.toInt(string, defaultValue);
 | |
| 	}
 | |
| 
 | |
| 	private static int getInt(String string, int defaultValue, int minValue) {
 | |
| 		return Math.max(minValue, getInt(string, defaultValue));
 | |
| 	}
 | |
| 
 | |
| 	private static void setSpacing(Map<String, WorldGenSettingsFix.StructureFeatureConfiguration> map, String structure, String spacing, int minValue) {
 | |
| 		WorldGenSettingsFix.StructureFeatureConfiguration structureFeatureConfiguration = (WorldGenSettingsFix.StructureFeatureConfiguration)map.getOrDefault(
 | |
| 			structure, DEFAULTS.get(structure)
 | |
| 		);
 | |
| 		int i = getInt(spacing, structureFeatureConfiguration.spacing, minValue);
 | |
| 		map.put(structure, new WorldGenSettingsFix.StructureFeatureConfiguration(i, structureFeatureConfiguration.separation, structureFeatureConfiguration.salt));
 | |
| 	}
 | |
| 
 | |
| 	static final class StructureFeatureConfiguration {
 | |
| 		public static final Codec<WorldGenSettingsFix.StructureFeatureConfiguration> CODEC = RecordCodecBuilder.create(
 | |
| 			instance -> instance.group(
 | |
| 					Codec.INT.fieldOf("spacing").forGetter(structureFeatureConfiguration -> structureFeatureConfiguration.spacing),
 | |
| 					Codec.INT.fieldOf("separation").forGetter(structureFeatureConfiguration -> structureFeatureConfiguration.separation),
 | |
| 					Codec.INT.fieldOf("salt").forGetter(structureFeatureConfiguration -> structureFeatureConfiguration.salt)
 | |
| 				)
 | |
| 				.apply(instance, WorldGenSettingsFix.StructureFeatureConfiguration::new)
 | |
| 		);
 | |
| 		final int spacing;
 | |
| 		final int separation;
 | |
| 		final int salt;
 | |
| 
 | |
| 		public StructureFeatureConfiguration(int spacing, int separation, int salt) {
 | |
| 			this.spacing = spacing;
 | |
| 			this.separation = separation;
 | |
| 			this.salt = salt;
 | |
| 		}
 | |
| 
 | |
| 		public <T> Dynamic<T> serialize(DynamicOps<T> ops) {
 | |
| 			return new Dynamic<>(ops, (T)CODEC.encodeStart(ops, this).result().orElse(ops.emptyMap()));
 | |
| 		}
 | |
| 	}
 | |
| }
 |