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()));
|
|
}
|
|
}
|
|
}
|