228 lines
		
	
	
	
		
			8.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
	
		
			8.9 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.DataFix;
 | |
| import com.mojang.datafixers.TypeRewriteRule;
 | |
| import com.mojang.datafixers.schemas.Schema;
 | |
| import com.mojang.datafixers.types.Type;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import com.mojang.serialization.Dynamic;
 | |
| import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
 | |
| import java.util.Comparator;
 | |
| import java.util.HashMap;
 | |
| import java.util.List;
 | |
| import java.util.Locale;
 | |
| import java.util.Map;
 | |
| import java.util.Optional;
 | |
| import java.util.Map.Entry;
 | |
| import java.util.function.Function;
 | |
| import java.util.stream.LongStream;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| public class StructuresBecomeConfiguredFix extends DataFix {
 | |
| 	private static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	private static final Map<String, StructuresBecomeConfiguredFix.Conversion> CONVERSION_MAP = ImmutableMap.<String, StructuresBecomeConfiguredFix.Conversion>builder()
 | |
| 		.put(
 | |
| 			"mineshaft",
 | |
| 			StructuresBecomeConfiguredFix.Conversion.biomeMapped(
 | |
| 				Map.of(List.of("minecraft:badlands", "minecraft:eroded_badlands", "minecraft:wooded_badlands"), "minecraft:mineshaft_mesa"), "minecraft:mineshaft"
 | |
| 			)
 | |
| 		)
 | |
| 		.put(
 | |
| 			"shipwreck",
 | |
| 			StructuresBecomeConfiguredFix.Conversion.biomeMapped(
 | |
| 				Map.of(List.of("minecraft:beach", "minecraft:snowy_beach"), "minecraft:shipwreck_beached"), "minecraft:shipwreck"
 | |
| 			)
 | |
| 		)
 | |
| 		.put(
 | |
| 			"ocean_ruin",
 | |
| 			StructuresBecomeConfiguredFix.Conversion.biomeMapped(
 | |
| 				Map.of(List.of("minecraft:warm_ocean", "minecraft:lukewarm_ocean", "minecraft:deep_lukewarm_ocean"), "minecraft:ocean_ruin_warm"),
 | |
| 				"minecraft:ocean_ruin_cold"
 | |
| 			)
 | |
| 		)
 | |
| 		.put(
 | |
| 			"village",
 | |
| 			StructuresBecomeConfiguredFix.Conversion.biomeMapped(
 | |
| 				Map.of(
 | |
| 					List.of("minecraft:desert"),
 | |
| 					"minecraft:village_desert",
 | |
| 					List.of("minecraft:savanna"),
 | |
| 					"minecraft:village_savanna",
 | |
| 					List.of("minecraft:snowy_plains"),
 | |
| 					"minecraft:village_snowy",
 | |
| 					List.of("minecraft:taiga"),
 | |
| 					"minecraft:village_taiga"
 | |
| 				),
 | |
| 				"minecraft:village_plains"
 | |
| 			)
 | |
| 		)
 | |
| 		.put(
 | |
| 			"ruined_portal",
 | |
| 			StructuresBecomeConfiguredFix.Conversion.biomeMapped(
 | |
| 				Map.of(
 | |
| 					List.of("minecraft:desert"),
 | |
| 					"minecraft:ruined_portal_desert",
 | |
| 					List.of(
 | |
| 						"minecraft:badlands",
 | |
| 						"minecraft:eroded_badlands",
 | |
| 						"minecraft:wooded_badlands",
 | |
| 						"minecraft:windswept_hills",
 | |
| 						"minecraft:windswept_forest",
 | |
| 						"minecraft:windswept_gravelly_hills",
 | |
| 						"minecraft:savanna_plateau",
 | |
| 						"minecraft:windswept_savanna",
 | |
| 						"minecraft:stony_shore",
 | |
| 						"minecraft:meadow",
 | |
| 						"minecraft:frozen_peaks",
 | |
| 						"minecraft:jagged_peaks",
 | |
| 						"minecraft:stony_peaks",
 | |
| 						"minecraft:snowy_slopes"
 | |
| 					),
 | |
| 					"minecraft:ruined_portal_mountain",
 | |
| 					List.of("minecraft:bamboo_jungle", "minecraft:jungle", "minecraft:sparse_jungle"),
 | |
| 					"minecraft:ruined_portal_jungle",
 | |
| 					List.of(
 | |
| 						"minecraft:deep_frozen_ocean",
 | |
| 						"minecraft:deep_cold_ocean",
 | |
| 						"minecraft:deep_ocean",
 | |
| 						"minecraft:deep_lukewarm_ocean",
 | |
| 						"minecraft:frozen_ocean",
 | |
| 						"minecraft:ocean",
 | |
| 						"minecraft:cold_ocean",
 | |
| 						"minecraft:lukewarm_ocean",
 | |
| 						"minecraft:warm_ocean"
 | |
| 					),
 | |
| 					"minecraft:ruined_portal_ocean"
 | |
| 				),
 | |
| 				"minecraft:ruined_portal"
 | |
| 			)
 | |
| 		)
 | |
| 		.put("pillager_outpost", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:pillager_outpost"))
 | |
| 		.put("mansion", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:mansion"))
 | |
| 		.put("jungle_pyramid", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:jungle_pyramid"))
 | |
| 		.put("desert_pyramid", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:desert_pyramid"))
 | |
| 		.put("igloo", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:igloo"))
 | |
| 		.put("swamp_hut", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:swamp_hut"))
 | |
| 		.put("stronghold", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:stronghold"))
 | |
| 		.put("monument", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:monument"))
 | |
| 		.put("fortress", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:fortress"))
 | |
| 		.put("endcity", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:end_city"))
 | |
| 		.put("buried_treasure", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:buried_treasure"))
 | |
| 		.put("nether_fossil", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:nether_fossil"))
 | |
| 		.put("bastion_remnant", StructuresBecomeConfiguredFix.Conversion.trivial("minecraft:bastion_remnant"))
 | |
| 		.build();
 | |
| 
 | |
| 	public StructuresBecomeConfiguredFix(Schema outputSchema) {
 | |
| 		super(outputSchema, false);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected TypeRewriteRule makeRule() {
 | |
| 		Type<?> type = this.getInputSchema().getType(References.CHUNK);
 | |
| 		Type<?> type2 = this.getInputSchema().getType(References.CHUNK);
 | |
| 		return this.writeFixAndRead("StucturesToConfiguredStructures", type, type2, this::fix);
 | |
| 	}
 | |
| 
 | |
| 	private Dynamic<?> fix(Dynamic<?> data) {
 | |
| 		return data.update(
 | |
| 			"structures",
 | |
| 			dynamic2 -> dynamic2.update("starts", dynamic2x -> this.updateStarts(dynamic2x, data))
 | |
| 				.update("References", dynamic2x -> this.updateReferences(dynamic2x, data))
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	private Dynamic<?> updateStarts(Dynamic<?> starts, Dynamic<?> data) {
 | |
| 		Map<? extends Dynamic<?>, ? extends Dynamic<?>> map = (Map<? extends Dynamic<?>, ? extends Dynamic<?>>)starts.getMapValues().result().orElse(Map.of());
 | |
| 		HashMap<Dynamic<?>, Dynamic<?>> hashMap = Maps.newHashMap();
 | |
| 		map.forEach((dynamic2, dynamic3) -> {
 | |
| 			if (!dynamic3.get("id").asString("INVALID").equals("INVALID")) {
 | |
| 				Dynamic<?> dynamic4 = this.findUpdatedStructureType(dynamic2, data);
 | |
| 				if (dynamic4 == null) {
 | |
| 					LOGGER.warn("Encountered unknown structure in datafixer: " + dynamic2.asString("<missing key>"));
 | |
| 				} else {
 | |
| 					hashMap.computeIfAbsent(dynamic4, dynamic3x -> dynamic3.set("id", dynamic4));
 | |
| 				}
 | |
| 			}
 | |
| 		});
 | |
| 		return data.createMap(hashMap);
 | |
| 	}
 | |
| 
 | |
| 	private Dynamic<?> updateReferences(Dynamic<?> references, Dynamic<?> data) {
 | |
| 		Map<? extends Dynamic<?>, ? extends Dynamic<?>> map = (Map<? extends Dynamic<?>, ? extends Dynamic<?>>)references.getMapValues().result().orElse(Map.of());
 | |
| 		HashMap<Dynamic<?>, Dynamic<?>> hashMap = Maps.newHashMap();
 | |
| 		map.forEach(
 | |
| 			(dynamic2, dynamic3) -> {
 | |
| 				if (dynamic3.asLongStream().count() != 0L) {
 | |
| 					Dynamic<?> dynamic4 = this.findUpdatedStructureType(dynamic2, data);
 | |
| 					if (dynamic4 == null) {
 | |
| 						LOGGER.warn("Encountered unknown structure in datafixer: " + dynamic2.asString("<missing key>"));
 | |
| 					} else {
 | |
| 						hashMap.compute(
 | |
| 							dynamic4,
 | |
| 							(dynamic2x, dynamic3x) -> dynamic3x == null ? dynamic3 : dynamic3.createLongList(LongStream.concat(dynamic3x.asLongStream(), dynamic3.asLongStream()))
 | |
| 						);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		);
 | |
| 		return data.createMap(hashMap);
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	private Dynamic<?> findUpdatedStructureType(Dynamic<?> structureName, Dynamic<?> data) {
 | |
| 		String string = structureName.asString("UNKNOWN").toLowerCase(Locale.ROOT);
 | |
| 		StructuresBecomeConfiguredFix.Conversion conversion = (StructuresBecomeConfiguredFix.Conversion)CONVERSION_MAP.get(string);
 | |
| 		if (conversion == null) {
 | |
| 			return null;
 | |
| 		} else {
 | |
| 			String string2 = conversion.fallback;
 | |
| 			if (!conversion.biomeMapping().isEmpty()) {
 | |
| 				Optional<String> optional = this.guessConfiguration(data, conversion);
 | |
| 				if (optional.isPresent()) {
 | |
| 					string2 = (String)optional.get();
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return data.createString(string2);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private Optional<String> guessConfiguration(Dynamic<?> data, StructuresBecomeConfiguredFix.Conversion conversion) {
 | |
| 		Object2IntArrayMap<String> object2IntArrayMap = new Object2IntArrayMap<>();
 | |
| 		data.get("sections").asList(Function.identity()).forEach(dynamic -> dynamic.get("biomes").get("palette").asList(Function.identity()).forEach(dynamicx -> {
 | |
| 			String string = (String)conversion.biomeMapping().get(dynamicx.asString(""));
 | |
| 			if (string != null) {
 | |
| 				object2IntArrayMap.mergeInt(string, 1, Integer::sum);
 | |
| 			}
 | |
| 		}));
 | |
| 		return object2IntArrayMap.object2IntEntrySet()
 | |
| 			.stream()
 | |
| 			.max(Comparator.comparingInt(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue))
 | |
| 			.map(Entry::getKey);
 | |
| 	}
 | |
| 
 | |
| 	record Conversion(Map<String, String> biomeMapping, String fallback) {
 | |
| 
 | |
| 		public static StructuresBecomeConfiguredFix.Conversion trivial(String fallback) {
 | |
| 			return new StructuresBecomeConfiguredFix.Conversion(Map.of(), fallback);
 | |
| 		}
 | |
| 
 | |
| 		public static StructuresBecomeConfiguredFix.Conversion biomeMapped(Map<List<String>, String> biomeMapping, String fallback) {
 | |
| 			return new StructuresBecomeConfiguredFix.Conversion(unpack(biomeMapping), fallback);
 | |
| 		}
 | |
| 
 | |
| 		private static Map<String, String> unpack(Map<List<String>, String> mapping) {
 | |
| 			Builder<String, String> builder = ImmutableMap.builder();
 | |
| 
 | |
| 			for (Entry<List<String>, String> entry : mapping.entrySet()) {
 | |
| 				((List)entry.getKey()).forEach(string -> builder.put(string, (String)entry.getValue()));
 | |
| 			}
 | |
| 
 | |
| 			return builder.build();
 | |
| 		}
 | |
| 	}
 | |
| }
 |