use mapped 1.18 NMS

This commit is contained in:
dfsek 2022-06-12 18:13:00 -07:00
parent b3efaa4f6a
commit 0c2a8c6bbc
9 changed files with 258 additions and 247 deletions

View File

@ -1,10 +1,10 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2; package com.dfsek.terra.bukkit.nms.v1_18_R2;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import com.dfsek.terra.api.properties.Properties; import com.dfsek.terra.api.properties.Properties;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.BiomeBase;
public record NMSBiomeInfo(ResourceKey<Biome> biomeKey) implements Properties {
public record NMSBiomeInfo(ResourceKey<BiomeBase> biomeKey) implements Properties {
} }

View File

@ -3,23 +3,19 @@ package com.dfsek.terra.bukkit.nms.v1_18_R2;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry; import net.minecraft.core.MappedRegistry;
import net.minecraft.core.IRegistryWritable; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryMaterials; import net.minecraft.core.WritableRegistry;
import net.minecraft.data.RegistryGeneration; import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey; import net.minecraft.tags.TagKey;
import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeFog; import net.minecraft.world.level.biome.BiomeSpecialEffects;
import net.minecraft.world.level.biome.BiomeFog.GrassColor;
import net.minecraft.world.level.biome.BiomeSettingsGeneration;
import net.minecraft.world.level.biome.BiomeSettingsMobs;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -29,7 +25,6 @@ import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
import com.dfsek.terra.registry.master.ConfigRegistry; import com.dfsek.terra.registry.master.ConfigRegistry;
@ -37,34 +32,33 @@ import com.dfsek.terra.registry.master.ConfigRegistry;
public class NMSBiomeInjector { public class NMSBiomeInjector {
private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class); private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class);
private static final Map<MinecraftKey, List<MinecraftKey>> terraBiomeMap = new HashMap<>(); private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
public static void registerBiomes(ConfigRegistry configRegistry) { public static void registerBiomes(ConfigRegistry configRegistry) {
try { try {
LOGGER.info("Hacking biome registry..."); LOGGER.info("Hacking biome registry...");
IRegistryWritable<BiomeBase> biomeRegistry = (IRegistryWritable<BiomeBase>) Registries.biomeRegistry(); WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) Registries.biomeRegistry();
Field frozen = RegistryMaterials.class.getDeclaredField("bL"); // registry frozen field
frozen.setAccessible(true);
frozen.set(biomeRegistry, false);
configRegistry.forEach(pack -> pack.getRegistry(Biome.class).forEach((key, biome) -> { Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
try { try {
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey(); NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
MinecraftKey vanillaMinecraftKey = new MinecraftKey(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey()); ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
BiomeBase platform = createBiome( Biome platform = createBiome(
biome, biome,
biomeRegistry.a(vanillaMinecraftKey) // get biomeRegistry.get(vanillaMinecraftKey) // get
); );
ResourceKey<BiomeBase> delegateKey = ResourceKey.a(IRegistry.aP, new MinecraftKey("terra", createBiomeID(pack, key))); ResourceKey<Biome> delegateKey = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("terra", createBiomeID(pack, key)));
RegistryGeneration.a(RegistryGeneration.i, delegateKey, platform); BuiltinRegistries.register(BuiltinRegistries.BIOME, delegateKey, platform);
biomeRegistry.a(delegateKey, platform, Lifecycle.stable()); biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.a()); terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
LOGGER.debug("Registered biome: " + delegateKey); LOGGER.debug("Registered biome: " + delegateKey);
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
@ -72,14 +66,14 @@ public class NMSBiomeInjector {
} }
})); }));
frozen.set(biomeRegistry, true); // freeze registry again :) Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
LOGGER.info("Doing tag garbage...."); LOGGER.info("Doing tag garbage....");
Map<TagKey<BiomeBase>, List<Holder<BiomeBase>>> collect = biomeRegistry Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
.g() // streamKeysAndEntries .getTags() // streamKeysAndEntries
.collect(HashMap::new, .collect(HashMap::new,
(map, pair) -> (map, pair) ->
map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().a().toList())), map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())),
HashMap::putAll); HashMap::putAll);
terraBiomeMap terraBiomeMap
@ -90,13 +84,13 @@ public class NMSBiomeInjector {
.forEach(tb -> getEntry(biomeRegistry, tb) .forEach(tb -> getEntry(biomeRegistry, tb)
.ifPresentOrElse( .ifPresentOrElse(
terra -> { terra -> {
LOGGER.debug(vanilla.e().orElseThrow().a() + LOGGER.debug(vanilla.unwrapKey().orElseThrow().location() +
" (vanilla for " + " (vanilla for " +
terra.e().orElseThrow().a() + terra.unwrapKey().orElseThrow().location() +
": " + ": " +
vanilla.c().toList()); vanilla.tags().toList());
vanilla.c() vanilla.tags()
.forEach( .forEach(
tag -> collect tag -> collect
.computeIfAbsent(tag, .computeIfAbsent(tag,
@ -108,77 +102,63 @@ public class NMSBiomeInjector {
tb))), tb))),
() -> LOGGER.error("No vanilla biome: {}", vb))); () -> LOGGER.error("No vanilla biome: {}", vb)));
biomeRegistry.k(); // clearTags biomeRegistry.resetTags(); // clearTags
biomeRegistry.a(ImmutableMap.copyOf(collect)); // populateTags biomeRegistry.bindTags(ImmutableMap.copyOf(collect)); // populateTags
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException exception) { } catch(SecurityException | IllegalArgumentException exception) {
throw new RuntimeException(exception); throw new RuntimeException(exception);
} }
} }
public static <T> Optional<Holder<T>> getEntry(IRegistry<T> registry, MinecraftKey identifier) { public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
return registry.b(identifier) return registry.getOptional(identifier)
.flatMap(registry::c) .flatMap(registry::getResourceKey)
.map(registry::c); .map(registry::getOrCreateHolder);
} }
private static BiomeBase createBiome(Biome biome, BiomeBase vanilla) private static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
BiomeBase.a builder = new BiomeBase.a(); // Builder Biome.BiomeBuilder builder = new Biome.BiomeBuilder(); // Builder
Field f = BiomeBase.class.getDeclaredField("l"); // category
f.setAccessible(true);
builder.a((BiomeBase.Geography) f.get(vanilla))
.a(vanilla.c()); // getPrecipitation
Field biomeSettingMobsField = BiomeBase.class.getDeclaredField("k"); // spawn settings builder.biomeCategory(Reflection.BIOME.getCategory(vanilla))
biomeSettingMobsField.setAccessible(true); .precipitation(vanilla.getPrecipitation()) // getPrecipitation
BiomeSettingsMobs biomeSettingMobs = (BiomeSettingsMobs) biomeSettingMobsField.get(vanilla); .mobSpawnSettings(vanilla.getMobSettings())
builder.a(biomeSettingMobs); .generationSettings(vanilla.getGenerationSettings())
.temperature(vanilla.getBaseTemperature())
.downfall(vanilla.getDownfall());
BiomeSettingsGeneration.a generationBuilder = new BiomeSettingsGeneration.a(); // builder
builder.a(generationBuilder.a())
.a(vanilla.c())
.b(vanilla.h()) // precipitation
.a(vanilla.i()); // temp
BiomeSpecialEffects.Builder effects = new BiomeSpecialEffects.Builder();
BiomeFog.a effects = new BiomeFog.a(); // Builder effects.grassColorModifier(vanilla.getSpecialEffects().getGrassColorModifier());
effects.a(GrassColor.a); // magic
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
// fog effects.fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor()))
effects.a(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.f()));
// water .waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
effects.b(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.k()));
// water fog .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
effects.c(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.l()));
// sky .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()));
effects.d(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.a()));
if(vanillaBiomeProperties.getFoliageColor() == null) { if(vanillaBiomeProperties.getFoliageColor() == null) {
vanilla.j().e().ifPresent(effects::e); vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
} else { } else {
// foliage effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
effects.e(vanillaBiomeProperties.getFoliageColor());
} }
if(vanillaBiomeProperties.getGrassColor() == null) { if(vanillaBiomeProperties.getGrassColor() == null) {
vanilla.j().f().ifPresent(effects::f); vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
} else { } else {
// grass effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
effects.f(vanillaBiomeProperties.getGrassColor());
} }
builder.a(effects.a()); // build() builder.specialEffects(effects.build());
return builder.a(); // build() return builder.build(); // build()
} }
public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) { public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) {

View File

@ -1,54 +1,49 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2; package com.dfsek.terra.bukkit.nms.v1_18_R2;
import com.mojang.serialization.Codec;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.biome.BiomeBase;
import net.minecraft.world.level.biome.Climate.Sampler;
import net.minecraft.world.level.biome.WorldChunkManager;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
import com.dfsek.terra.api.util.generic.Lazy;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
import com.mojang.serialization.Codec;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate.Sampler;
import org.jetbrains.annotations.NotNull;
public class NMSBiomeProvider extends WorldChunkManager {
public class NMSBiomeProvider extends BiomeSource {
private final BiomeProvider delegate; private final BiomeProvider delegate;
private final WorldChunkManager vanilla; private final BiomeSource vanilla;
private final long seed; private final long seed;
private final Registry<Biome> biomeRegistry = Registries.biomeRegistry();
private static final Lazy<IRegistry<BiomeBase>> biomeRegistry = Lazy.lazy(() -> { public NMSBiomeProvider(BiomeProvider delegate, BiomeSource vanilla, long seed) {
DedicatedServer dedicatedserver = ((CraftServer) Bukkit.getServer()).getServer(); super(delegate.stream()
return dedicatedserver.aU().b(IRegistry.aP); .map(biome -> Registries.biomeRegistry()
}); .getOrCreateHolder(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext()
.get(NMSBiomeInfo.class)
public NMSBiomeProvider(BiomeProvider delegate, WorldChunkManager vanilla, long seed) { .biomeKey())));
super(delegate.stream().map(biome -> biomeRegistry.value().g(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey())));
this.delegate = delegate; this.delegate = delegate;
this.vanilla = vanilla; this.vanilla = vanilla;
this.seed = seed; this.seed = seed;
} }
@Override @Override
protected Codec<? extends WorldChunkManager> a() { protected Codec<? extends BiomeSource> codec() {
return WorldChunkManager.a; return BiomeSource.CODEC;
} }
@Override @Override
public WorldChunkManager a(long seed) { public @NotNull BiomeSource withSeed(long seed) {
return withSeed(seed);
}
public WorldChunkManager withSeed(long seed) {
return new NMSBiomeProvider(delegate, vanilla, seed); return new NMSBiomeProvider(delegate, vanilla, seed);
} }
@Override @Override
public Holder<BiomeBase> getNoiseBiome(int x, int y, int z, Sampler sampler) { public @NotNull Holder<Biome> getNoiseBiome(int x, int y, int z, @NotNull Sampler sampler) {
//return CraftBlock.biomeToBiomeBase(biomeRegistry.value(), ((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getHandle()); return biomeRegistry.getOrCreateHolder(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome())
return biomeRegistry.value().g(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey()); .getContext()
.get(NMSBiomeInfo.class)
.biomeKey());
} }
} }

View File

@ -8,31 +8,29 @@ import com.dfsek.terra.api.world.info.WorldProperties;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.core.BlockPosition; import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IRegistryCustom; import net.minecraft.core.SectionPos;
import net.minecraft.core.SectionPosition; import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.server.level.RegionLimitedWorldAccess; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.BlockColumn;
import net.minecraft.world.level.ChunkCoordIntPair;
import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager; import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.biome.Climate.Sampler; import net.minecraft.world.level.biome.Climate.Sampler;
import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.IChunkAccess; import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.ChunkGeneratorAbstract; import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.HeightMap;
import net.minecraft.world.level.levelgen.WorldGenStage;
import net.minecraft.world.level.levelgen.blending.Blender; import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -53,8 +51,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
private final long seed; private final long seed;
private final Map<ConcentricRingsStructurePlacement, Lazy<List<ChunkCoordIntPair>>> h = new Object2ObjectArrayMap<>(); private final Map<ConcentricRingsStructurePlacement, Lazy<List<ChunkPos>>> ringPositions = new Object2ObjectArrayMap<>();
private static final Lazy<List<ChunkCoordIntPair>> EMPTY = Lazy.lazy(List::of); private static final Lazy<List<ChunkPos>> EMPTY = Lazy.lazy(List::of);
public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) { public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) {
@ -66,103 +64,95 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
this.seed = seed; this.seed = seed;
} }
@Override //applyCarvers @Override
public void a(RegionLimitedWorldAccess regionlimitedworldaccess, long var2, BiomeManager var4, StructureManager var5, public void applyCarvers(@NotNull WorldGenRegion chunkRegion, long seed, @NotNull BiomeManager biomeAccess, @NotNull StructureFeatureManager structureAccessor,
IChunkAccess ichunkaccess, WorldGenStage.Features var7) { @NotNull ChunkAccess chunk, GenerationStep.@NotNull Carving generationStep) {
// no-op // no-op
} }
@Override // getSeaLevel @Override
public int g() { public int getSeaLevel() {
return vanilla.g(); return vanilla.getSeaLevel();
} }
@Override //fillFromNoise @Override //fillFromNoise
public CompletableFuture<IChunkAccess> a(Executor executor, Blender blender, StructureManager structuremanager, public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender, @NotNull StructureFeatureManager structureAccessor,
IChunkAccess ichunkaccess) { @NotNull ChunkAccess chunk) {
return vanilla.a(executor, blender, structuremanager, ichunkaccess); return vanilla.fillFromNoise(executor, blender, structureAccessor, chunk);
}
@Override //buildSurface. Used to be buildBase
public void a(RegionLimitedWorldAccess regionlimitedworldaccess, StructureManager structuremanager, IChunkAccess ichunkaccess) {
} }
@Override @Override
protected Codec<? extends ChunkGenerator> b() { public void buildSurface(@NotNull WorldGenRegion region, @NotNull StructureFeatureManager structures, @NotNull ChunkAccess chunk) {
return ChunkGeneratorAbstract.a; // no-op
}
@Override
protected @NotNull Codec<? extends ChunkGenerator> codec() {
return ChunkGenerator.CODEC;
} }
@Override // getColumn @Override // getColumn
public BlockColumn a(int x, int z, LevelHeightAccessor height) { public @NotNull NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height) {
IBlockData[] array = new IBlockData[height.v_()]; BlockState[] array = new BlockState[height.getHeight()];
WorldProperties properties = new NMSWorldProperties(seed, height); WorldProperties properties = new NMSWorldProperties(seed, height);
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
for(int y = properties.getMaxHeight() - 1; y >= properties.getMinHeight(); y--) { for(int y = properties.getMaxHeight() - 1; y >= properties.getMinHeight(); y--) {
array[y - properties.getMinHeight()] = ((CraftBlockData) delegate.getBlock(properties, x, y, z, biomeProvider) array[y - properties.getMinHeight()] = ((CraftBlockData) delegate.getBlock(properties, x, y, z, biomeProvider)
.getHandle()).getState(); .getHandle()).getState();
} }
return new BlockColumn(getMinimumY(), array); return new NoiseColumn(getMinY(), array);
} }
@Override // withSeed @Override // withSeed
public ChunkGenerator a(long seed) { public @NotNull ChunkGenerator withSeed(long seed) {
return new NMSChunkGeneratorDelegate(vanilla, pack, biomeSource, seed); return new NMSChunkGeneratorDelegate(vanilla, pack, biomeSource, seed);
} }
//spawnOriginalMobs
public void a(RegionLimitedWorldAccess regionlimitedworldaccess) {
vanilla.a(regionlimitedworldaccess);
}
// getGenDepth
public int f() {
return vanilla.f();
}
// climateSampler
public Sampler d() {
return Climate.a();
}
//getMinY
@Override @Override
public int h() { public void spawnOriginalMobs(@NotNull WorldGenRegion regionlimitedworldaccess) {
return vanilla.h(); vanilla.spawnOriginalMobs(regionlimitedworldaccess);
} }
@Override // getBaseHeight @Override
public int a(int x, int z, HeightMap.Type heightmap, LevelHeightAccessor height) { public int getGenDepth() {
WorldProperties properties = new NMSWorldProperties(seed, height); return vanilla.getGenDepth();
}
@Override
public @NotNull Sampler climateSampler() {
return Climate.empty();
}
@Override
public int getMinY() {
return vanilla.getMinY();
}
@Override
public int getBaseHeight(int x, int z, Heightmap.@NotNull Types heightmap, @NotNull LevelHeightAccessor world) {
WorldProperties properties = new NMSWorldProperties(seed, world);
int y = properties.getMaxHeight(); int y = properties.getMaxHeight();
BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties);
while(y >= getMinimumY() && !heightmap.e().test( while(y >= getMinY() && !heightmap.isOpaque().test(
((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) { ((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) {
y--; y--;
} }
return y; return y;
} }
@Override
public void a(IRegistryCustom iregistrycustom, StructureManager structuremanager, IChunkAccess ichunkaccess,
DefinedStructureManager definedstructuremanager, long i) {
super.a(iregistrycustom, structuremanager, ichunkaccess, definedstructuremanager, i);
}
@Nullable @Nullable
@Override @Override
public List<ChunkCoordIntPair> a(ConcentricRingsStructurePlacement concentricringsstructureplacement) { public List<ChunkPos> getRingPositionsFor(@NotNull ConcentricRingsStructurePlacement concentricringsstructureplacement) {
this.i(); ensureStructuresGenerated();
return this.h.getOrDefault(concentricringsstructureplacement, EMPTY).value(); return ringPositions.getOrDefault(concentricringsstructureplacement, EMPTY).value();
} }
private volatile boolean rings = false; private volatile boolean rings = false;
@Override @Override
public synchronized void i() { public synchronized void ensureStructuresGenerated() {
if(!this.rings) { if(!this.rings) {
super.i(); super.ensureStructuresGenerated();
this.populateStrongholdData(); this.populateStrongholdData();
this.rings = true; this.rings = true;
} }
@ -170,70 +160,82 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
private void populateStrongholdData() { private void populateStrongholdData() {
LOGGER.info("Generating safe stronghold data. This may take up to a minute."); LOGGER.info("Generating safe stronghold data. This may take up to a minute.");
Set<Holder<BiomeBase>> set = this.d.b(); Set<Holder<Biome>> set = this.runtimeBiomeSource.possibleBiomes();
a().map(h -> h.a()).forEach((holder) -> { // we dont need the spigot crap because it doesnt touch concentric. possibleStructureSets().map(Holder::value).forEach((holder) -> { // we dont need the spigot crap because it doesnt touch concentric.
StructurePlacement structureplacement = holder.b(); StructurePlacement structureplacement = holder.placement();
if(structureplacement instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) { if(structureplacement instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) {
if(holder.a().stream().anyMatch((structureset_a1) -> structureset_a1.a(set::contains))) { if(holder.structures().stream().anyMatch((structureset_a1) -> structureset_a1.generatesInMatchingBiome(set::contains))) {
this.h.put(concentricringsstructureplacement, this.ringPositions.put(concentricringsstructureplacement,
Lazy.lazy(() -> this.generateRingPositions(holder, concentricringsstructureplacement))); Lazy.lazy(() -> this.generateRingPositions(holder, concentricringsstructureplacement)));
} }
} }
}); });
} }
private List<ChunkCoordIntPair> generateRingPositions(StructureSet holder, private List<ChunkPos> generateRingPositions(StructureSet holder,
ConcentricRingsStructurePlacement concentricringsstructureplacement) { ConcentricRingsStructurePlacement concentricringsstructureplacement) { // Spigot
if(concentricringsstructureplacement.d() == 0) { if(concentricringsstructureplacement.count() == 0) {
return List.of(); return List.of();
} }
List<ChunkCoordIntPair> list = new ArrayList<>();
Set<Holder<BiomeBase>> set = holder.a().stream().flatMap((structureset_a) -> (structureset_a.a().a()).a().a()).collect( List<ChunkPos> list = new ArrayList<>();
Collectors.toSet()); Set<Holder<Biome>> set = holder
int i = concentricringsstructureplacement.b(); .structures()
int j = concentricringsstructureplacement.d(); .stream()
int k = concentricringsstructureplacement.c(); .flatMap((structureset_a) -> structureset_a.structure().value().biomes().stream())
.collect(Collectors.toSet());
int i = concentricringsstructureplacement.distance();
int j = concentricringsstructureplacement.count();
int k = concentricringsstructureplacement.spread();
Random random = new Random(); Random random = new Random();
random.setSeed(this.j);
double d0 = random.nextDouble() * Math.PI * 2.0; // Paper start
if(this.conf.strongholdSeed != null && this.structureSets.getResourceKey(holder).orElse(null) ==
net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS) {
random.setSeed(this.conf.strongholdSeed);
} else {
// Paper end
random.setSeed(this.ringPlacementSeed);
} // Paper
double d0 = random.nextDouble() * 3.141592653589793D * 2.0D;
int l = 0; int l = 0;
int i1 = 0; int i1 = 0;
for(int j1 = 0; j1 < j; ++j1) { for(int j1 = 0; j1 < j; ++j1) {
double d1 = (double) (4 * i + i * i1 * 6) + (random.nextDouble() - 0.5) * (double) i * 2.5; double d1 = (double) (4 * i + i * i1 * 6) + (random.nextDouble() - 0.5D) * (double) i * 2.5D;
int k1 = (int) Math.round(Math.cos(d0) * d1); int k1 = (int) Math.round(Math.cos(d0) * d1);
int l1 = (int) Math.round(Math.sin(d0) * d1); int l1 = (int) Math.round(Math.sin(d0) * d1);
int i2 = SectionPosition.a(k1, 8); int i2 = SectionPos.sectionToBlockCoord(k1, 8);
int j2 = SectionPosition.a(l1, 8); int j2 = SectionPos.sectionToBlockCoord(l1, 8);
Objects.requireNonNull(set); Objects.requireNonNull(set);
Pair<BlockPosition, Holder<BiomeBase>> pair = this.c.a(i2, 0, j2, 112, set::contains, random, this.d()); Pair<BlockPos, Holder<Biome>> pair = this.biomeSource.findBiomeHorizontal(i2, 0, j2, 112, set::contains, random,
this.climateSampler());
if(pair != null) { if(pair != null) {
BlockPosition blockposition = pair.getFirst(); BlockPos blockposition = (BlockPos) pair.getFirst();
k1 = SectionPosition.a(blockposition.u());
l1 = SectionPosition.a(blockposition.w()); k1 = SectionPos.blockToSectionCoord(blockposition.getX());
l1 = SectionPos.blockToSectionCoord(blockposition.getZ());
} }
list.add(new ChunkCoordIntPair(k1, l1)); list.add(new ChunkPos(k1, l1));
d0 += 6.283185307179586 / (double) k; d0 += 6.283185307179586D / (double) k;
++l; ++l;
if(l == k) { if(l == k) {
++i1; ++i1;
l = 0; l = 0;
k += 2 * k / (i1 + 1); k += 2 * k / (i1 + 1);
k = Math.min(k, j - j1); k = Math.min(k, j - j1);
d0 += random.nextDouble() * Math.PI * 2.0; d0 += random.nextDouble() * 3.141592653589793D * 2.0D;
} }
} }
return list; return list;
} }
public int getMinimumY() { @Override
return h(); public void addDebugScreenInfo(@NotNull List<String> arg0, @NotNull BlockPos arg1) {
}
@Override //addDebugScreenInfo
public void a(List<String> arg0, BlockPosition arg1) {
} }
} }

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2; package com.dfsek.terra.bukkit.nms.v1_18_R2;
import net.minecraft.server.level.WorldServer; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
@ -30,21 +30,21 @@ public class NMSInjectListener implements Listener {
INJECTED.add(event.getWorld()); INJECTED.add(event.getWorld());
LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName()); LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName());
CraftWorld craftWorld = (CraftWorld) event.getWorld(); CraftWorld craftWorld = (CraftWorld) event.getWorld();
WorldServer serverWorld = craftWorld.getHandle(); ServerLevel serverWorld = craftWorld.getHandle();
ConfigPack pack = bukkitChunkGeneratorWrapper.getPack(); ConfigPack pack = bukkitChunkGeneratorWrapper.getPack();
ChunkGenerator vanilla = serverWorld.k().g(); ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), vanilla.e(), craftWorld.getSeed()); NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), vanilla.getBiomeSource(), craftWorld.getSeed());
NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()); NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
custom.conf = vanilla.conf; // world config from Spigot custom.conf = vanilla.conf; // world config from Spigot
serverWorld.k().a.u = custom; serverWorld.getChunkSource().chunkMap.generator = custom;
LOGGER.info("Successfully injected into world."); LOGGER.info("Successfully injected into world.");
serverWorld.k().a.u.i(); // generate stronghold data now serverWorld.getChunkSource().chunkMap.generator.ensureStructuresGenerated(); // generate stronghold data now
INJECT_LOCK.unlock(); INJECT_LOCK.unlock();
} }

View File

@ -26,11 +26,11 @@ public class NMSWorldProperties implements WorldProperties {
@Override @Override
public int getMaxHeight() { public int getMaxHeight() {
return height.ag(); return height.getMaxBuildHeight();
} }
@Override @Override
public int getMinHeight() { public int getMinHeight() {
return height.u_(); return height.getMinBuildHeight();
} }
} }

View File

@ -0,0 +1,35 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2;
import net.minecraft.core.MappedRegistry;
import net.minecraft.world.level.biome.Biome;
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
public class Reflection {
public static final MappedRegistryProxy MAPPED_REGISTRY;
public static final BiomeProxy BIOME;
static {
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper, Reflection.class.getClassLoader());
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
BIOME = reflectionProxyFactory.reflectionProxy(BiomeProxy.class);
}
@Proxies
public interface MappedRegistryProxy {
@FieldSetter("frozen")
void setFrozen(MappedRegistry<?> instance, boolean frozen);
}
@Proxies
public interface BiomeProxy {
@FieldGetter("category")
Biome.BiomeCategory getCategory(Biome instance);
}
}

View File

@ -1,30 +1,30 @@
package com.dfsek.terra.bukkit.nms.v1_18_R2; package com.dfsek.terra.bukkit.nms.v1_18_R2;
import net.minecraft.core.IRegistry; import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer; import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
public class Registries { public class Registries {
private static <T> IRegistry<T> getRegistry(ResourceKey<IRegistry<T>> key) { private static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> key) {
CraftServer craftserver = (CraftServer) Bukkit.getServer(); CraftServer craftserver = (CraftServer) Bukkit.getServer();
DedicatedServer dedicatedserver = craftserver.getServer(); DedicatedServer dedicatedserver = craftserver.getServer();
return dedicatedserver return dedicatedserver
.aU() // getRegistryManager .registryAccess()
.b( // getRegistry .registryOrThrow( // getRegistry
key key
); );
} }
public static IRegistry<BiomeBase> biomeRegistry() { public static Registry<Biome> biomeRegistry() {
return getRegistry(IRegistry.aP); return getRegistry(Registry.BIOME_REGISTRY);
} }
public static IRegistry<StructureSet> structureSet() { public static Registry<StructureSet> structureSet() {
return getRegistry(IRegistry.aM); return getRegistry(Registry.STRUCTURE_SET_REGISTRY);
} }
} }

View File

@ -110,11 +110,10 @@ public class NMSBiomeInjector {
} }
} }
@SuppressWarnings("unchecked, rawtypes")
public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) { public static <T> Optional<Holder<T>> getEntry(Registry<T> registry, ResourceLocation identifier) {
return (Optional) registry.getOptional(identifier) return registry.getOptional(identifier)
.flatMap(registry::getResourceKey) .flatMap(registry::getResourceKey)
.map(registry::getHolder); .map(registry::getOrCreateHolderOrThrow);
} }
private static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla) private static Biome createBiome(com.dfsek.terra.api.world.biome.Biome biome, Biome vanilla)