From b0a5d97e9c601797628e97714862b460aa48b728 Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Sat, 13 Jun 2026 22:03:58 -0400 Subject: [PATCH] d --- .../core/nms/v1_21_R7/CustomBiomeSource.java | 401 -------- .../core/nms/v1_21_R7/IrisChunkGenerator.java | 407 -------- .../iris/core/nms/v1_21_R7/NMSBinding.java | 931 ------------------ .../nms/v1_21_R7/VanillaStructureBiomes.java | 77 -- build.gradle | 1 - .../java/art/arcane/iris/core/nms/INMS.java | 17 +- .../art/arcane/iris/core/nms/INMSBinding.java | 2 +- .../iris/core/nms/MinecraftVersion.java | 27 +- .../iris/core/nms/datapack/DataVersion.java | 7 - .../iris/core/safeguard/task/Tasks.java | 2 +- .../IrisRuntimeSchedulerModeRoutingTest.java | 8 +- .../core/nms/INMSBindingProbeCodesTest.java | 10 +- .../iris/core/nms/MinecraftVersionTest.java | 34 +- .../world-lifecycle-smoke-matrix.txt | 10 +- settings.gradle | 1 - 15 files changed, 64 insertions(+), 1871 deletions(-) delete mode 100644 adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java delete mode 100644 adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java delete mode 100644 adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java delete mode 100644 adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/VanillaStructureBiomes.java diff --git a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java b/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java deleted file mode 100644 index 6519c70f0..000000000 --- a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/CustomBiomeSource.java +++ /dev/null @@ -1,401 +0,0 @@ -package art.arcane.iris.core.nms.v1_21_R7; - -import com.mojang.serialization.MapCodec; -import art.arcane.iris.spi.IrisLogging; -import art.arcane.iris.engine.data.cache.AtomicCache; -import art.arcane.iris.engine.framework.Engine; -import art.arcane.iris.engine.object.IrisBiome; -import art.arcane.iris.engine.object.IrisBiomeCustom; -import art.arcane.volmlib.util.collection.KMap; -import art.arcane.volmlib.util.math.RNG; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.Climate; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.CraftWorld; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -public class CustomBiomeSource extends BiomeSource { - private static final int NOISE_BIOME_CACHE_MAX = 262144; - - private final long seed; - private final Engine engine; - private final Registry biomeCustomRegistry; - private final Registry biomeRegistry; - private final AtomicCache registryAccess = new AtomicCache<>(); - private final KMap> customBiomes; - private final Holder fallbackBiome; - private final ConcurrentHashMap> noiseBiomeCache = new ConcurrentHashMap<>(); - private final ConcurrentHashMap> structureBiomeCache = new ConcurrentHashMap<>(); - - public CustomBiomeSource(long seed, Engine engine, World world) { - this.engine = engine; - this.seed = seed; - this.biomeCustomRegistry = registry().lookup(Registries.BIOME).orElse(null); - this.biomeRegistry = ((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())).lookup(Registries.BIOME).orElse(null); - this.fallbackBiome = resolveFallbackBiome(this.biomeRegistry, this.biomeCustomRegistry); - this.customBiomes = fillCustomBiomes(this.biomeCustomRegistry, engine, this.fallbackBiome); - } - - private static List> getAllBiomes(Registry customRegistry, Registry registry, Engine engine, Holder fallback) { - LinkedHashSet> biomes = new LinkedHashSet<>(); - if (fallback != null) { - biomes.add(fallback); - } - - for (IrisBiome i : engine.getAllBiomes()) { - Holder vanillaHolder = NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()); - if (vanillaHolder != null) { - biomes.add(vanillaHolder); - } else if (!i.isCustom() && fallback != null) { - biomes.add(fallback); - } - - if (i.isCustom()) { - for (IrisBiomeCustom j : i.getCustomDerivitives()) { - Holder customHolder = resolveCustomBiomeHolder(customRegistry, engine, j.getId()); - if (customHolder != null) { - biomes.add(customHolder); - } else if (fallback != null) { - biomes.add(fallback); - } - } - } - } - - return new ArrayList<>(biomes); - } - - private static Object getFor(Class type, Object source) { - Object o = fieldFor(type, source); - - if (o != null) { - return o; - } - - return invokeFor(type, source); - } - - private static Object fieldFor(Class returns, Object in) { - return fieldForClass(returns, in.getClass(), in); - } - - private static Object invokeFor(Class returns, Object in) { - for (Method i : in.getClass().getMethods()) { - if (i.getReturnType().equals(returns)) { - i.setAccessible(true); - try { - IrisLogging.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()"); - return i.invoke(in); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - return null; - } - - @SuppressWarnings("unchecked") - private static T fieldForClass(Class returnType, Class sourceType, Object in) { - for (Field i : sourceType.getDeclaredFields()) { - if (i.getType().equals(returnType)) { - i.setAccessible(true); - try { - IrisLogging.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName()); - return (T) i.get(in); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - return null; - } - - @Override - protected Stream> collectPossibleBiomes() { - return getAllBiomes( - ((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())) - .lookup(Registries.BIOME).orElse(null), - ((CraftWorld) engine.getWorld().realWorld()).getHandle().registryAccess().lookup(Registries.BIOME).orElse(null), - engine, - fallbackBiome).stream(); - } - - private KMap> fillCustomBiomes(Registry customRegistry, Engine engine, Holder fallback) { - KMap> m = new KMap<>(); - if (customRegistry == null) { - return m; - } - - for (IrisBiome i : engine.getAllBiomes()) { - if (i.isCustom()) { - for (IrisBiomeCustom j : i.getCustomDerivitives()) { - Holder holder = resolveCustomBiomeHolder(customRegistry, engine, j.getId()); - if (holder == null) { - if (fallback != null) { - m.put(j.getId(), fallback); - } - IrisLogging.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - m.put(j.getId(), holder); - } - } - } - - return m; - } - - private RegistryAccess registry() { - return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())); - } - - @Override - protected MapCodec codec() { - throw new UnsupportedOperationException("Not supported"); - } - - @Override - public Holder getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) { - long cacheKey = packNoiseKey(x, y, z); - Holder cachedHolder = structureBiomeCache.get(cacheKey); - if (cachedHolder != null) { - return cachedHolder; - } - - Holder resolvedHolder = resolveStructureBiomeHolder(x, y, z); - Holder existingHolder = structureBiomeCache.putIfAbsent(cacheKey, resolvedHolder); - if (existingHolder != null) { - return existingHolder; - } - - if (structureBiomeCache.size() > NOISE_BIOME_CACHE_MAX) { - structureBiomeCache.clear(); - } - - return resolvedHolder; - } - - public Holder getVisibleNoiseBiome(int x, int y, int z, Climate.Sampler sampler) { - long cacheKey = packNoiseKey(x, y, z); - Holder cachedHolder = noiseBiomeCache.get(cacheKey); - if (cachedHolder != null) { - return cachedHolder; - } - - Holder resolvedHolder = resolveVisibleBiomeHolder(x, y, z); - Holder existingHolder = noiseBiomeCache.putIfAbsent(cacheKey, resolvedHolder); - if (existingHolder != null) { - return existingHolder; - } - - if (noiseBiomeCache.size() > NOISE_BIOME_CACHE_MAX) { - noiseBiomeCache.clear(); - } - - return resolvedHolder; - } - - private Holder resolveStructureBiomeHolder(int x, int y, int z) { - BiomeResolution resolution = resolveBiomeResolution(x, y, z); - if (resolution == null) { - return getFallbackBiome(); - } - - Holder holder = NMSBinding.biomeToBiomeBase(biomeRegistry, resolution.irisBiome.getVanillaDerivative()); - if (holder != null) { - return holder; - } - - if (resolution.irisBiome.isCustom()) { - return resolveCustomHolder(resolution); - } - - return getFallbackBiome(); - } - - private Holder resolveVisibleBiomeHolder(int x, int y, int z) { - BiomeResolution resolution = resolveBiomeResolution(x, y, z); - if (resolution == null) { - return getFallbackBiome(); - } - - if (resolution.irisBiome.isCustom()) { - return resolveCustomHolder(resolution); - } - - org.bukkit.block.Biome vanillaBiome = resolution.underground - ? resolution.irisBiome.getGroundBiome(resolution.rng, resolution.blockX, resolution.blockY, resolution.blockZ) - : resolution.irisBiome.getSkyBiome(resolution.rng, resolution.blockX, resolution.blockY, resolution.blockZ); - Holder holder = NMSBinding.biomeToBiomeBase(biomeRegistry, vanillaBiome); - if (holder != null) { - return holder; - } - - return getFallbackBiome(); - } - - private Holder resolveCustomHolder(BiomeResolution resolution) { - IrisBiomeCustom customBiome = resolution.irisBiome.getCustomBiome(resolution.rng, resolution.blockX, resolution.blockY, resolution.blockZ); - if (customBiome != null) { - Holder holder = customBiomes.get(customBiome.getId()); - if (holder != null) { - return holder; - } - } - - return getFallbackBiome(); - } - - private BiomeResolution resolveBiomeResolution(int x, int y, int z) { - if (engine == null || engine.isClosed()) { - return null; - } - - if (engine.getComplex() == null) { - return null; - } - - int blockX = x << 2; - int blockZ = z << 2; - int blockY = y << 2; - int worldMinHeight = engine.getWorld().minHeight(); - int internalY = blockY - worldMinHeight; - int surfaceInternalY = engine.getComplex().getHeightStream().get(blockX, blockZ).intValue(); - int caveSwitchInternalY = Math.max(-8 - worldMinHeight, 40); - boolean deepUnderground = internalY <= caveSwitchInternalY; - boolean belowSurface = internalY <= surfaceInternalY - 8; - boolean underground = deepUnderground && belowSurface; - IrisBiome irisBiome = underground - ? engine.getCaveBiome(blockX, internalY, blockZ) - : engine.getComplex().getTrueBiomeStream().get(blockX, blockZ); - if (irisBiome == null && underground) { - irisBiome = engine.getComplex().getTrueBiomeStream().get(blockX, blockZ); - } - if (irisBiome == null) { - return null; - } - - RNG noiseRng = new RNG(seed - ^ (((long) blockX) * 341873128712L) - ^ (((long) blockY) * 132897987541L) - ^ (((long) blockZ) * 42317861L)); - - return new BiomeResolution(irisBiome, underground, blockX, blockY, blockZ, noiseRng); - } - - private Holder getFallbackBiome() { - if (fallbackBiome != null) { - return fallbackBiome; - } - - Holder holder = resolveFallbackBiome(biomeRegistry, biomeCustomRegistry); - if (holder != null) { - return holder; - } - - throw new IllegalStateException("Unable to resolve any biome holder fallback for Iris biome source"); - } - - private static long packNoiseKey(int x, int y, int z) { - return (((long) x & 67108863L) << 38) - | (((long) z & 67108863L) << 12) - | ((long) y & 4095L); - } - - private static Holder resolveCustomBiomeHolder(Registry customRegistry, Engine engine, String customBiomeId) { - if (customRegistry == null || engine == null || customBiomeId == null || customBiomeId.isBlank()) { - return null; - } - - Identifier resourceLocation = Identifier.fromNamespaceAndPath( - engine.getDimension().getLoadKey().toLowerCase(java.util.Locale.ROOT), - customBiomeId.toLowerCase(java.util.Locale.ROOT) - ); - Biome biome = customRegistry.getValue(resourceLocation); - if (biome == null) { - return null; - } - - Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); - if (optionalBiomeKey.isEmpty()) { - return null; - } - - Optional> optionalReferenceHolder = customRegistry.get(optionalBiomeKey.get()); - if (optionalReferenceHolder.isEmpty()) { - return null; - } - - return optionalReferenceHolder.get(); - } - - private static Holder resolveFallbackBiome(Registry registry, Registry customRegistry) { - Holder plains = NMSBinding.biomeToBiomeBase(registry, org.bukkit.block.Biome.PLAINS); - if (plains != null) { - return plains; - } - - Holder vanilla = firstHolder(registry); - if (vanilla != null) { - return vanilla; - } - - return firstHolder(customRegistry); - } - - private static Holder firstHolder(Registry registry) { - if (registry == null) { - return null; - } - - for (Biome biome : registry) { - Optional> optionalBiomeKey = registry.getResourceKey(biome); - if (optionalBiomeKey.isEmpty()) { - continue; - } - - Optional> optionalHolder = registry.get(optionalBiomeKey.get()); - if (optionalHolder.isPresent()) { - return optionalHolder.get(); - } - } - - return null; - } - - private static final class BiomeResolution { - private final IrisBiome irisBiome; - private final boolean underground; - private final int blockX; - private final int blockY; - private final int blockZ; - private final RNG rng; - - private BiomeResolution(IrisBiome irisBiome, boolean underground, int blockX, int blockY, int blockZ, RNG rng) { - this.irisBiome = irisBiome; - this.underground = underground; - this.blockX = blockX; - this.blockY = blockY; - this.blockZ = blockZ; - this.rng = rng; - } - } -} diff --git a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java b/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java deleted file mode 100644 index b724be667..000000000 --- a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/IrisChunkGenerator.java +++ /dev/null @@ -1,407 +0,0 @@ -package art.arcane.iris.core.nms.v1_21_R7; - -import com.mojang.datafixers.util.Pair; -import com.mojang.serialization.MapCodec; -import art.arcane.iris.spi.IrisLogging; -import art.arcane.iris.engine.framework.Engine; -import art.arcane.iris.engine.object.IrisImportedStructureControl; -import art.arcane.iris.util.common.reflect.WrappedField; -import art.arcane.iris.util.common.reflect.WrappedReturningMethod; -import net.minecraft.core.*; -import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.WorldGenRegion; -import net.minecraft.util.random.WeightedList; -import net.minecraft.world.entity.MobCategory; -import net.minecraft.world.level.*; -import net.minecraft.world.level.biome.*; -import net.minecraft.world.level.block.Blocks; -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.ChunkGeneratorStructureState; -import net.minecraft.world.level.chunk.status.ChunkStatus; -import net.minecraft.world.level.levelgen.*; -import net.minecraft.world.level.levelgen.blending.Blender; -import net.minecraft.world.level.levelgen.structure.Structure; -import net.minecraft.world.level.levelgen.structure.StructureSet; -import net.minecraft.world.level.levelgen.structure.StructureStart; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; -import net.minecraft.core.registries.Registries; -import java.util.stream.Collectors; -import art.arcane.iris.engine.framework.IrisStructureLocator; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.generator.CustomChunkGenerator; -import org.spigotmc.SpigotWorldConfig; - -import javax.annotation.Nullable; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.*; -import java.util.concurrent.CompletableFuture; - -public class IrisChunkGenerator extends CustomChunkGenerator { - private static final WrappedField BIOME_SOURCE; - private static final WrappedReturningMethod SET_HEIGHT; - private final ChunkGenerator delegate; - private final Engine engine; - private final CustomBiomeSource customBiomeSource; - private volatile Set reachableStructureKeysCache; - - public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) { - this(delegate, engine, world, new CustomBiomeSource(seed, engine, world)); - } - - private IrisChunkGenerator(ChunkGenerator delegate, Engine engine, World world, CustomBiomeSource customBiomeSource) { - super(((CraftWorld) world).getHandle(), edit(delegate, customBiomeSource), world.getGenerator()); - this.delegate = delegate; - this.engine = engine; - this.customBiomeSource = customBiomeSource; - } - - @Override - public @Nullable Pair> findNearestMapStructure(ServerLevel level, HolderSet holders, BlockPos pos, int radius, boolean findUnexplored) { - try { - Registry registry = level.registryAccess().lookupOrThrow(Registries.STRUCTURE); - BlockPos best = null; - Holder bestHolder = null; - long bestDist = Long.MAX_VALUE; - for (Holder holder : holders) { - Object id = registry.getKey(holder.value()); - if (id == null) { - continue; - } - int[] at = IrisStructureLocator.locate(engine, id.toString(), pos.getX(), pos.getZ(), Math.max(1, radius)); - if (at == null) { - continue; - } - long dx = (long) at[0] - pos.getX(); - long dz = (long) at[2] - pos.getZ(); - long d = dx * dx + dz * dz; - if (d < bestDist) { - bestDist = d; - best = new BlockPos(at[0], at[1], at[2]); - bestHolder = holder; - } - } - if (best != null) { - return Pair.of(best, bestHolder); - } - } catch (Throwable e) { - IrisLogging.reportError(e); - } - if (!importedControl().active()) { - return null; - } - HolderSet reachable = filterReachableStructures(level, holders); - if (reachable == null || reachable.size() == 0) { - return null; - } - try { - return delegate.findNearestMapStructure(level, reachable, pos, radius, findUnexplored); - } catch (Throwable e) { - IrisLogging.error("Vanilla structure locate failed near " + pos.getX() + ", " + pos.getZ() + ": " + e); - IrisLogging.reportError(e); - return null; - } - } - - private HolderSet filterReachableStructures(ServerLevel level, HolderSet holders) { - Set reachable = reachableStructureKeysCache; - if (reachable == null) { - reachable = VanillaStructureBiomes.reachableStructureKeys(level, delegate.getBiomeSource()); - reachableStructureKeysCache = reachable; - } - if (reachable.isEmpty()) { - return holders; - } - Registry registry = level.registryAccess().lookupOrThrow(Registries.STRUCTURE); - List> kept = new ArrayList<>(); - for (Holder holder : holders) { - Object id = registry.getKey(holder.value()); - if (id != null && reachable.contains(id.toString())) { - kept.add(holder); - } - } - if (kept.size() == holders.size()) { - return holders; - } - return HolderSet.direct(kept); - } - - @Override - protected MapCodec codec() { - return MapCodec.unit(null); - } - - @Override - public ChunkGenerator getDelegate() { - if (delegate instanceof CustomChunkGenerator chunkGenerator) - return chunkGenerator.getDelegate(); - return delegate; - } - - @Override - public int getMinY() { - return delegate.getMinY(); - } - - @Override - public int getSeaLevel() { - return delegate.getSeaLevel(); - } - - @Override - public void createStructures(RegistryAccess registryAccess, ChunkGeneratorStructureState structureState, StructureManager structureManager, ChunkAccess access, StructureTemplateManager templateManager, ResourceKey levelKey) { - if (!importedControl().active()) { - return; - } - super.createStructures(registryAccess, structureState, structureManager, access, templateManager, levelKey); - } - - private IrisImportedStructureControl importedControl() { - return engine.getDimension().getImportedStructures(); - } - - @Override - public ChunkGeneratorStructureState createState(HolderLookup holderlookup, RandomState randomstate, long i, SpigotWorldConfig conf) { - return delegate.createState(holderlookup, randomstate, i, conf); - } - - @Override - public void createReferences(WorldGenLevel generatoraccessseed, StructureManager structuremanager, ChunkAccess ichunkaccess) { - delegate.createReferences(generatoraccessseed, structuremanager, ichunkaccess); - } - - @Override - public CompletableFuture createBiomes(RandomState randomstate, Blender blender, StructureManager structuremanager, ChunkAccess ichunkaccess) { - ichunkaccess.fillBiomesFromNoise(customBiomeSource::getVisibleNoiseBiome, randomstate.sampler()); - return CompletableFuture.completedFuture(ichunkaccess); - } - - @Override - public void buildSurface(WorldGenRegion regionlimitedworldaccess, StructureManager structuremanager, RandomState randomstate, ChunkAccess ichunkaccess) { - delegate.buildSurface(regionlimitedworldaccess, structuremanager, randomstate, ichunkaccess); - } - - @Override - public void applyCarvers(WorldGenRegion regionlimitedworldaccess, long seed, RandomState randomstate, BiomeManager biomemanager, StructureManager structuremanager, ChunkAccess ichunkaccess) { - delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess); - } - - @Override - public CompletableFuture fillFromNoise(Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) { - return delegate.fillFromNoise(blender, randomstate, structuremanager, ichunkaccess); - } - - @Override - public WeightedList getMobsAt(Holder holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) { - return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition); - } - - @Override - public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) { - applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager, true); - } - - @Override - public void addDebugScreenInfo(List list, RandomState randomstate, BlockPos blockposition) { - delegate.addDebugScreenInfo(list, randomstate, blockposition); - } - - @Override - public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) { - addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager); - if (importedControl().active()) { - placeVanillaStructures(generatoraccessseed, ichunkaccess, structuremanager); - } - delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager, false); - } - - private void placeVanillaStructures(WorldGenLevel world, ChunkAccess chunk, StructureManager structureManager) { - if (!structureManager.shouldGenerateStructures()) { - return; - } - ChunkPos chunkPos = chunk.getPos(); - SectionPos sectionPos = SectionPos.of(chunkPos, world.getMinSectionY()); - BlockPos origin = sectionPos.origin(); - Registry registry = world.registryAccess().lookupOrThrow(Registries.STRUCTURE); - Map> byStep = registry.stream().collect(Collectors.groupingBy(s -> s.step().ordinal())); - WorldgenRandom random = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed())); - long decoSeed = random.setDecorationSeed(world.getSeed(), origin.getX(), origin.getZ()); - BoundingBox area = writableArea(chunk); - int steps = GenerationStep.Decoration.values().length; - IrisImportedStructureControl control = importedControl(); - for (int step = 0; step < steps; step++) { - int index = 0; - for (Structure structure : byStep.getOrDefault(step, List.of())) { - Object id = registry.getKey(structure); - String structureId = id == null ? null : id.toString(); - if (control.shouldGenerate(structureId) && !IrisStructureLocator.suppressesVanilla(engine, structureId)) { - random.setFeatureSeed(decoSeed, index, step); - int[] offset = control.resolveOffset(structureId, isUndergroundStep(structure.step())); - boolean shifted = offset[0] != 0 || offset[1] != 0 || offset[2] != 0; - WorldGenLevel target = shifted ? shiftedLevel(world, offset[0], offset[1], offset[2]) : world; - BoundingBox placeArea = shifted - ? new BoundingBox(area.minX() - offset[0], area.minY(), area.minZ() - offset[2], area.maxX() - offset[0], area.maxY(), area.maxZ() - offset[2]) - : area; - try { - structureManager.startsForStructure(sectionPos, structure) - .forEach(start -> start.placeInChunk(target, structureManager, this, random, placeArea, chunkPos)); - } catch (Throwable e) { - IrisLogging.reportError(e); - } - } - index++; - } - } - } - - private static boolean isUndergroundStep(GenerationStep.Decoration step) { - return step == GenerationStep.Decoration.UNDERGROUND_STRUCTURES - || step == GenerationStep.Decoration.STRONGHOLDS; - } - - private WorldGenLevel shiftedLevel(WorldGenLevel world, int dx, int dy, int dz) { - return (WorldGenLevel) Proxy.newProxyInstance( - WorldGenLevel.class.getClassLoader(), - new Class[]{WorldGenLevel.class}, - (proxy, method, args) -> { - if (args != null) { - for (int i = 0; i < args.length; i++) { - if (args[i] instanceof BlockPos bp) { - args[i] = new BlockPos(bp.getX() + dx, bp.getY() + dy, bp.getZ() + dz); - } - } - } - try { - return method.invoke(world, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - }); - } - - private BoundingBox writableArea(ChunkAccess chunk) { - ChunkPos cp = chunk.getPos(); - int i = cp.getMinBlockX(); - int j = cp.getMinBlockZ(); - int minY = getMinY() + 1; - int maxY = getMinY() + engine.getHeight() - 1; - return new BoundingBox(i, minY, j, i + 15, maxY, j + 15); - } - - @Override - public void addVanillaDecorations(WorldGenLevel level, ChunkAccess chunkAccess, StructureManager structureManager) { - SectionPos sectionPos = SectionPos.of(chunkAccess.getPos(), level.getMinSectionY()); - BlockPos blockPos = sectionPos.origin(); - - Heightmap surface = chunkAccess.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); - Heightmap ocean = chunkAccess.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); - Heightmap motion = chunkAccess.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING); - Heightmap motionNoLeaves = chunkAccess.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES); - - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - int wX = x + blockPos.getX(); - int wZ = z + blockPos.getZ(); - - int terrainTop = engine.getHeight(wX, wZ, false) + engine.getMinHeight() + 1; - int terrainNoFluid = engine.getHeight(wX, wZ, true) + engine.getMinHeight() + 1; - SET_HEIGHT.invoke(ocean, x, z, terrainNoFluid); - SET_HEIGHT.invoke(surface, x, z, terrainTop); - SET_HEIGHT.invoke(motion, x, z, terrainTop); - SET_HEIGHT.invoke(motionNoLeaves, x, z, terrainTop); - } - } - - Heightmap.primeHeightmaps(chunkAccess, ChunkStatus.FINAL_HEIGHTMAPS); - } - - @Override - public void spawnOriginalMobs(WorldGenRegion regionlimitedworldaccess) { - delegate.spawnOriginalMobs(regionlimitedworldaccess); - } - - @Override - public int getSpawnHeight(LevelHeightAccessor levelheightaccessor) { - return delegate.getSpawnHeight(levelheightaccessor); - } - - @Override - public int getGenDepth() { - return delegate.getGenDepth(); - } - - @Override - public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { - return levelheightaccessor.getMinY() + engine.getHeight(i, j, !heightmap_type.isOpaque().test(Blocks.WATER.defaultBlockState())) + 1; - } - - @Override - public NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { - int block = engine.getHeight(i, j, true); - int water = engine.getHeight(i, j, false); - BlockState[] column = new BlockState[levelheightaccessor.getHeight()]; - for (int k = 0; k < column.length; k++) { - if (k <= block) column[k] = Blocks.STONE.defaultBlockState(); - else if (k <= water) column[k] = Blocks.WATER.defaultBlockState(); - else column[k] = Blocks.AIR.defaultBlockState(); - } - return new NoiseColumn(levelheightaccessor.getMinY(), column); - } - - @Override - public Optional>> getTypeNameForDataFixer() { - return delegate.getTypeNameForDataFixer(); - } - - @Override - public void validate() { - delegate.validate(); - } - - static { - Field biomeSource = null; - for (Field field : ChunkGenerator.class.getDeclaredFields()) { - if (!field.getType().equals(BiomeSource.class)) - continue; - biomeSource = field; - break; - } - if (biomeSource == null) - throw new RuntimeException("Could not find biomeSource field in ChunkGenerator!"); - - Method setHeight = null; - for (Method method : Heightmap.class.getDeclaredMethods()) { - var types = method.getParameterTypes(); - if (types.length != 3 || !Arrays.equals(types, new Class[]{int.class, int.class, int.class}) - || !method.getReturnType().equals(void.class)) - continue; - setHeight = method; - break; - } - if (setHeight == null) - throw new RuntimeException("Could not find setHeight method in Heightmap!"); - - BIOME_SOURCE = new WrappedField<>(ChunkGenerator.class, biomeSource.getName()); - SET_HEIGHT = new WrappedReturningMethod<>(Heightmap.class, setHeight.getName(), setHeight.getParameterTypes()); - } - - private static ChunkGenerator edit(ChunkGenerator generator, BiomeSource source) { - try { - BIOME_SOURCE.set(generator, source); - if (generator instanceof CustomChunkGenerator custom) - BIOME_SOURCE.set(custom.getDelegate(), source); - - return generator; - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java b/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java deleted file mode 100644 index 69320da4e..000000000 --- a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/NMSBinding.java +++ /dev/null @@ -1,931 +0,0 @@ -package art.arcane.iris.core.nms.v1_21_R7; - -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import art.arcane.iris.spi.IrisLogging; -import art.arcane.iris.core.nms.INMSBinding; -import art.arcane.iris.core.nms.container.BiomeColor; -import art.arcane.iris.core.nms.container.Pair; -import art.arcane.iris.core.nms.container.BlockProperty; -import art.arcane.iris.core.nms.datapack.DataVersion; -import art.arcane.iris.engine.data.cache.AtomicCache; -import art.arcane.iris.engine.framework.Engine; -import art.arcane.iris.engine.platform.PlatformChunkGenerator; -import art.arcane.iris.util.project.agent.Agent; -import art.arcane.volmlib.util.collection.KList; -import art.arcane.volmlib.util.collection.KMap; -import art.arcane.iris.util.common.format.C; -import art.arcane.iris.util.project.hunk.Hunk; -import art.arcane.volmlib.util.json.JSONObject; -import art.arcane.volmlib.util.mantle.runtime.Mantle; -import art.arcane.volmlib.util.matter.Matter; -import art.arcane.volmlib.util.math.Vector3d; -import art.arcane.volmlib.util.matter.MatterBiomeInject; -import art.arcane.iris.util.nbt.common.mca.NBTWorld; -import art.arcane.volmlib.util.nbt.mca.palette.*; -import art.arcane.volmlib.util.nbt.tag.CompoundTag; -import art.arcane.iris.util.common.scheduling.J; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.shorts.ShortList; -import net.bytebuddy.ByteBuddy; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.matcher.ElementMatchers; -import net.minecraft.core.*; -import net.minecraft.core.Registry; -import net.minecraft.core.component.DataComponents; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.*; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.commands.data.BlockDataAccessor; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.tags.TagKey; -import net.minecraft.world.attribute.EnvironmentAttributes; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.item.component.CustomData; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.Biomes; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.status.ChunkStatus; -import net.minecraft.world.level.chunk.status.WorldGenContext; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; -import net.minecraft.world.level.levelgen.flat.FlatLayerInfo; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.StructureCheck; -import net.minecraft.world.level.storage.LevelStorageSource; -import org.bukkit.*; -import org.bukkit.block.Biome; -import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.CraftChunk; -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.block.CraftBlockState; -import org.bukkit.craftbukkit.block.CraftBlockStates; -import org.bukkit.craftbukkit.block.data.CraftBlockData; -import org.bukkit.craftbukkit.inventory.CraftItemStack; -import org.bukkit.craftbukkit.util.CraftMagicNumbers; -import org.bukkit.craftbukkit.util.CraftNamespacedKey; -import org.bukkit.entity.Entity; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.ChunkGenerator; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.awt.Color; -import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.List; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -public class NMSBinding implements INMSBinding { - private final KMap baseBiomeCache = new KMap<>(); - private final BlockData AIR = Material.AIR.createBlockData(); - private final AtomicCache> biomeMapCache = new AtomicCache<>(); - private final AtomicBoolean injected = new AtomicBoolean(); - private final AtomicCache> registryCache = new AtomicCache<>(); - private final AtomicCache> globalCache = new AtomicCache<>(); - private final AtomicCache registryAccess = new AtomicCache<>(); - private final AtomicCache byIdRef = new AtomicCache<>(); - - private static Object getFor(Class type, Object source) { - Object o = fieldFor(type, source); - - if (o != null) { - return o; - } - - return invokeFor(type, source); - } - - private static Object invokeFor(Class returns, Object in) { - for (Method i : in.getClass().getMethods()) { - if (i.getReturnType().equals(returns)) { - i.setAccessible(true); - try { - IrisLogging.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()"); - return i.invoke(in); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - return null; - } - - private static Object fieldFor(Class returns, Object in) { - return fieldForClass(returns, in.getClass(), in); - } - - @SuppressWarnings("unchecked") - private static T fieldForClass(Class returnType, Class sourceType, Object in) { - for (Field i : sourceType.getDeclaredFields()) { - if (i.getType().equals(returnType)) { - i.setAccessible(true); - try { - IrisLogging.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName()); - return (T) i.get(in); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - return null; - } - - private static Class getClassType(Class type, int ordinal) { - return type.getDeclaredClasses()[ordinal]; - } - - @Override - public boolean hasTile(Material material) { - return !CraftBlockState.class.equals(CraftBlockStates.getBlockStateType(material)); - } - - @Override - public boolean hasTile(Location l) { - return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())) != null; - } - - @Override - @SuppressWarnings("unchecked") - public KMap serializeTile(Location location) { - BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ())); - - if (e == null) { - return null; - } - - net.minecraft.nbt.CompoundTag tag = e.saveWithoutMetadata(registry()); - return (KMap) convertFromTag(tag, 0, 64); - } - - @Contract(value = "null, _, _ -> null", pure = true) - private Object convertFromTag(Tag tag, int depth, int maxDepth) { - if (tag == null || depth > maxDepth) return null; - return switch (tag) { - case CollectionTag collection -> { - KList list = new KList<>(); - - for (Object i : collection) { - if (i instanceof Tag t) - list.add(convertFromTag(t, depth + 1, maxDepth)); - else list.add(i); - } - yield list; - } - case net.minecraft.nbt.CompoundTag compound -> { - KMap map = new KMap<>(); - - for (String key : compound.keySet()) { - var child = compound.get(key); - if (child == null) continue; - var value = convertFromTag(child, depth + 1, maxDepth); - if (value == null) continue; - map.put(key, value); - } - yield map; - } - case NumericTag numeric -> numeric.box(); - default -> tag.asString().orElse(null); - }; - } - - @Override - public void deserializeTile(KMap map, Location pos) { - if (map == null || pos == null || pos.getWorld() == null) { - return; - } - - Tag converted = convertToTag(map, 0, 64); - if (!(converted instanceof net.minecraft.nbt.CompoundTag tag)) { - return; - } - - var level = ((CraftWorld) pos.getWorld()).getHandle(); - var blockPos = new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); - if (!J.runAt(pos, () -> merge(level, blockPos, tag))) { - IrisLogging.warn("[NMS] Failed to schedule tile deserialize at " + blockPos + " in world " + pos.getWorld().getName()); - } - } - - private void merge(ServerLevel level, BlockPos blockPos, net.minecraft.nbt.CompoundTag tag) { - if (level == null || blockPos == null || tag == null) { - return; - } - - try { - var blockEntity = level.getBlockEntity(blockPos); - if (blockEntity == null) { - IrisLogging.warn("[NMS] BlockEntity not found at " + blockPos); - var state = level.getBlockState(blockPos); - if (!state.hasBlockEntity()) { - return; - } - - blockEntity = ((EntityBlock) state.getBlock()) - .newBlockEntity(blockPos, state); - } - - var accessor = new BlockDataAccessor(blockEntity, blockPos); - accessor.setData(accessor.getData().merge(tag)); - } catch (Throwable e) { - IrisLogging.warn("[NMS] Failed to merge tile data at " + blockPos + ": " + e.getMessage()); - IrisLogging.reportError(e); - } - } - - private Tag convertToTag(Object object, int depth, int maxDepth) { - if (object == null || depth > maxDepth) return EndTag.INSTANCE; - return switch (object) { - case Map map -> { - var tag = new net.minecraft.nbt.CompoundTag(); - for (var i : map.entrySet()) { - tag.put(i.getKey().toString(), convertToTag(i.getValue(), depth + 1, maxDepth)); - } - yield tag; - } - case List list -> { - var tag = new ListTag(); - for (var i : list) { - tag.add(convertToTag(i, depth + 1, maxDepth)); - } - yield tag; - } - case Byte number -> ByteTag.valueOf(number); - case Short number -> ShortTag.valueOf(number); - case Integer number -> IntTag.valueOf(number); - case Long number -> LongTag.valueOf(number); - case Float number -> FloatTag.valueOf(number); - case Double number -> DoubleTag.valueOf(number); - case String string -> StringTag.valueOf(string); - default -> EndTag.INSTANCE; - }; - } - - @Override - public CompoundTag serializeEntity(Entity location) { - return null;// TODO: - } - - @Override - public Entity deserializeEntity(CompoundTag s, Location newPosition) { - return null;// TODO: - } - - @Override - public boolean supportsCustomHeight() { - return true; - } - - private RegistryAccess registry() { - return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())); - } - - private Registry getCustomBiomeRegistry() { - return registry().lookup(Registries.BIOME).orElse(null); - } - - private Registry getBlockRegistry() { - return registry().lookup(Registries.BLOCK).orElse(null); - } - - @Override - public Object getBiomeBaseFromId(int id) { - return getCustomBiomeRegistry().get(id); - } - - @Override - public int getMinHeight(World world) { - return world.getMinHeight(); - } - - @Override - public boolean supportsCustomBiomes() { - return true; - } - - @Override - public int getTrueBiomeBaseId(Object biomeBase) { - return getCustomBiomeRegistry().getId(((Holder) biomeBase).value()); - } - - @Override - public Object getTrueBiomeBase(Location location) { - return ((CraftWorld) location.getWorld()).getHandle().getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ())); - } - - @Override - public String getTrueBiomeBaseKey(Location location) { - return getKeyForBiomeBase(getTrueBiomeBase(location)); - } - - @Override - public Object getCustomBiomeBaseFor(String mckey) { - return getCustomBiomeRegistry().getValue(net.minecraft.resources.Identifier.parse(mckey)); - } - - @Override - public Object getCustomBiomeBaseHolderFor(String mckey) { - return getCustomBiomeRegistry().get(getTrueBiomeBaseId(getCustomBiomeRegistry().get(net.minecraft.resources.Identifier.parse(mckey)))).orElse(null); - } - - public int getBiomeBaseIdForKey(String key) { - return getCustomBiomeRegistry().getId(getCustomBiomeRegistry().get(net.minecraft.resources.Identifier.parse(key)).map(Holder::value).orElse(null)); - } - - @Override - public String getKeyForBiomeBase(Object biomeBase) { - return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something - } - - @Override - public Object getBiomeBase(World world, Biome biome) { - return biomeToBiomeBase(((CraftWorld) world).getHandle() - .registryAccess().lookup(Registries.BIOME).orElse(null), biome); - } - - @Override - public Object getBiomeBase(Object registry, Biome biome) { - Object v = baseBiomeCache.get(biome); - - if (v != null) { - return v; - } - //noinspection unchecked - v = biomeToBiomeBase((Registry) registry, biome); - if (v == null) { - // Ok so there is this new biome name called "CUSTOM" in Paper's new releases. - // But, this does NOT exist within CraftBukkit which makes it return an error. - // So, we will just return the ID that the plains biome returns instead. - //noinspection unchecked - return biomeToBiomeBase((Registry) registry, Biome.PLAINS); - } - baseBiomeCache.put(biome, v); - return v; - } - - @Override - public KList getBiomes() { - KList biomes = new KList<>(); - for (Biome biome : org.bukkit.Registry.BIOME) { - biomes.add(biome); - } - return biomes; - } - - @Override - public KList getStructureKeys() { - KList keys = new KList<>(); - try { - registry().lookupOrThrow(Registries.STRUCTURE).keySet().forEach(k -> keys.add(k.toString())); - } catch (Throwable e) { - IrisLogging.reportError(e); - } - return keys; - } - - @Override - public KList getStructureSetKeys() { - KList keys = new KList<>(); - try { - registry().lookupOrThrow(Registries.STRUCTURE_SET).keySet().forEach(k -> keys.add(k.toString())); - } catch (Throwable e) { - IrisLogging.reportError(e); - } - return keys; - } - - @Override - public KList getReachableStructureKeys(World world) { - KList keys = new KList<>(); - try { - ServerLevel level = ((CraftWorld) world).getHandle(); - BiomeSource source = level.getChunkSource().getGenerator().getBiomeSource(); - keys.addAll(VanillaStructureBiomes.reachableStructureKeys(level, source)); - } catch (Throwable e) { - IrisLogging.reportError(e); - } - return keys; - } - - @Override - public KList getStructureBiomeKeys(String structureKey) { - KList keys = new KList<>(); - try { - keys.addAll(VanillaStructureBiomes.structureBiomeKeys(registry(), structureKey)); - } catch (Throwable e) { - IrisLogging.reportError(e); - } - return keys; - } - - @Override - public KList getPossibleBiomeKeys(World world) { - KList keys = new KList<>(); - try { - ServerLevel level = ((CraftWorld) world).getHandle(); - BiomeSource source = level.getChunkSource().getGenerator().getBiomeSource(); - keys.addAll(VanillaStructureBiomes.possibleBiomeKeys(source)); - } catch (Throwable e) { - IrisLogging.reportError(e); - } - return keys; - } - - @Override - public int getBiomeId(Biome biome) { - for (World i : Bukkit.getWorlds()) { - if (i.getEnvironment().equals(World.Environment.NORMAL)) { - Registry registry = ((CraftWorld) i).getHandle().registryAccess().lookup(Registries.BIOME).orElse(null); - return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome)); - } - } - - List biomes = new ArrayList<>(); - for (Biome entry : org.bukkit.Registry.BIOME) { - biomes.add(entry); - } - int index = biomes.indexOf(biome); - return Math.max(index, 0); - } - - private MCAIdMap getBiomeMapping() { - return biomeMapCache.aquire(() -> new MCAIdMap<>() { - @NotNull - @Override - public Iterator iterator() { - return getCustomBiomeRegistry().iterator(); - } - - @Override - public int getId(net.minecraft.world.level.biome.Biome paramT) { - return getCustomBiomeRegistry().getId(paramT); - } - - @Override - public net.minecraft.world.level.biome.Biome byId(int paramInt) { - return (net.minecraft.world.level.biome.Biome) getBiomeBaseFromId(paramInt); - } - }); - } - - @NotNull - private MCABiomeContainer getBiomeContainerInterface(MCAIdMap biomeMapping, MCAChunkBiomeContainer base) { - return new MCABiomeContainer() { - @Override - public int[] getData() { - return base.writeBiomes(); - } - - @Override - public void setBiome(int x, int y, int z, int id) { - base.setBiome(x, y, z, biomeMapping.byId(id)); - } - - @Override - public int getBiome(int x, int y, int z) { - return biomeMapping.getId(base.getBiome(x, y, z)); - } - }; - } - - @Override - public MCABiomeContainer newBiomeContainer(int min, int max) { - MCAChunkBiomeContainer base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max); - return getBiomeContainerInterface(getBiomeMapping(), base); - } - - @Override - public MCABiomeContainer newBiomeContainer(int min, int max, int[] data) { - MCAChunkBiomeContainer base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max, data); - return getBiomeContainerInterface(getBiomeMapping(), base); - } - - @Override - public int countCustomBiomes() { - AtomicInteger a = new AtomicInteger(0); - - getCustomBiomeRegistry().keySet().forEach((i) -> { - if (i.getNamespace().equals("minecraft")) { - return; - } - - a.incrementAndGet(); - IrisLogging.debug("Custom Biome: " + i); - }); - - return a.get(); - } - - public boolean supportsDataPacks() { - return true; - } - - public void setBiomes(int cx, int cz, World world, Hunk biomes) { - LevelChunk c = ((CraftWorld) world).getHandle().getChunk(cx, cz); - biomes.iterateSync((x, y, z, b) -> c.setBiome(x, y, z, (Holder) b)); - c.markUnsaved(); - } - - @Override - public MCAPaletteAccess createPalette() { - MCAIdMapper registry = registryCache.aquireNasty(() -> { - Field cf = IdMapper.class.getDeclaredField("tToId"); - Field df = IdMapper.class.getDeclaredField("idToT"); - Field bf = IdMapper.class.getDeclaredField("nextId"); - cf.setAccessible(true); - df.setAccessible(true); - bf.setAccessible(true); - IdMapper blockData = Block.BLOCK_STATE_REGISTRY; - int b = bf.getInt(blockData); - Object2IntMap c = (Object2IntMap) cf.get(blockData); - List d = (List) df.get(blockData); - return new MCAIdMapper(c, d, b); - }); - MCAPalette global = globalCache.aquireNasty(() -> new MCAGlobalPalette<>(registry, ((CraftBlockData) AIR).getState())); - MCAPalettedContainer container = new MCAPalettedContainer<>(global, registry, - i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState(), - i -> NBTWorld.getCompound(CraftBlockData.fromData(i)), - ((CraftBlockData) AIR).getState()); - return new MCAWrappedPalettedContainer<>(container, - i -> NBTWorld.getCompound(CraftBlockData.fromData(i)), - i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState()); - } - - @Override - public void injectBiomesFromMantle(Chunk e, Mantle mantle) { - ChunkAccess chunk = ((CraftChunk) e).getHandle(ChunkStatus.FULL); - AtomicInteger c = new AtomicInteger(); - AtomicInteger r = new AtomicInteger(); - mantle.iterateChunk(e.getX(), e.getZ(), MatterBiomeInject.class, (x, y, z, b) -> { - if (b != null) { - if (b.isCustom()) { - chunk.setBiome(x, y, z, getCustomBiomeRegistry().get(b.getBiomeId()).get()); - c.getAndIncrement(); - } else { - chunk.setBiome(x, y, z, (Holder) getBiomeBase(e.getWorld(), b.getBiome())); - r.getAndIncrement(); - } - } - }); - } - - public ItemStack applyCustomNbt(ItemStack itemStack, KMap customNbt) throws IllegalArgumentException { - if (customNbt != null && !customNbt.isEmpty()) { - net.minecraft.world.item.ItemStack s = CraftItemStack.asNMSCopy(itemStack); - - try { - net.minecraft.nbt.CompoundTag tag = TagParser.parseCompoundFully((new JSONObject(customNbt)).toString()); - tag.merge(s.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag()); - s.set(DataComponents.CUSTOM_DATA, CustomData.of(tag)); - } catch (CommandSyntaxException var5) { - throw new IllegalArgumentException(var5); - } - - return CraftItemStack.asBukkitCopy(s); - } else { - return itemStack; - } - } - - public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException { - var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap; - var worldGenContextField = getField(chunkMap.getClass(), WorldGenContext.class); - worldGenContextField.setAccessible(true); - var worldGenContext = (WorldGenContext) worldGenContextField.get(chunkMap); - var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null); - String expectedDimensionType = "iris:" + engine.getDimension().getDimensionTypeKey(); - if (dimensionType != null) { - String actualDimensionType = dimensionType.identifier().toString(); - if (!dimensionType.identifier().getNamespace().equals("iris")) { - IrisLogging.error("Loaded world %s with invalid dimension type! expected=%s actual=%s", world.getName(), expectedDimensionType, actualDimensionType); - } else { - IrisLogging.debug("Loaded world " + world.getName() + " with Iris dimension type " + actualDimensionType); - } - } else { - IrisLogging.error("Loaded world %s with unknown dimension type! expected=%s", world.getName(), expectedDimensionType); - } - - IrisChunkGenerator irisGenerator = new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world); - var newContext = new WorldGenContext( - worldGenContext.level(), irisGenerator, - worldGenContext.structureManager(), worldGenContext.lightEngine(), worldGenContext.mainThreadExecutor(), worldGenContext.unsavedListener()); - - worldGenContextField.set(chunkMap, newContext); - retargetStructureCheck(((CraftWorld) world).getHandle(), irisGenerator); - } - - private static void retargetStructureCheck(ServerLevel level, IrisChunkGenerator generator) throws NoSuchFieldException, IllegalAccessException { - Field structureCheckField = getField(level.getClass(), StructureCheck.class); - structureCheckField.setAccessible(true); - Object structureCheck = structureCheckField.get(level); - if (structureCheck == null) { - return; - } - Field generatorField = getField(structureCheck.getClass(), net.minecraft.world.level.chunk.ChunkGenerator.class); - generatorField.setAccessible(true); - generatorField.set(structureCheck, generator); - Field biomeSourceField = getField(structureCheck.getClass(), BiomeSource.class); - biomeSourceField.setAccessible(true); - biomeSourceField.set(structureCheck, generator.getBiomeSource()); - } - - public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) { - if (entity == null) { - return null; - } - - try { - String descriptionId = "entity.minecraft." + entity.name().toLowerCase(Locale.ROOT); - Field[] fields = EntityType.class.getDeclaredFields(); - for (Field field : fields) { - if (!Modifier.isStatic(field.getModifiers()) || !field.getType().equals(EntityType.class)) { - continue; - } - - EntityType entityType = (EntityType) field.get(null); - if (entityType == null) { - continue; - } - - if (descriptionId.equals(entityType.getDescriptionId())) { - return new Vector3d(entityType.getWidth(), entityType.getHeight(), entityType.getWidth()); - } - } - return null; - } catch (Throwable e) { - IrisLogging.error("Unable to get entity dimensions for " + entity + "!"); - IrisLogging.reportError(e); - return null; - } - } - - - @Override - public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) { - if (location == null || location.getWorld() == null || type == null || type.getEntityClass() == null) { - return null; - } - return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason); - } - - @Override - public Color getBiomeColor(Location location, BiomeColor type) { - ServerLevel reader = ((CraftWorld) location.getWorld()).getHandle(); - var pos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - var holder = reader.getBiome(pos); - var biome = holder.value(); - if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null)); - - var attributes = reader.environmentAttributes(); - int rgba = switch (type) { - case FOG -> attributes.getValue(EnvironmentAttributes.FOG_COLOR, pos); - case WATER -> biome.getWaterColor(); - case WATER_FOG -> attributes.getValue(EnvironmentAttributes.WATER_FOG_COLOR, pos); - case SKY -> attributes.getValue(EnvironmentAttributes.SKY_COLOR, pos); - case FOLIAGE -> biome.getFoliageColor(); - case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ()); - }; - if (rgba == 0) { - if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().foliageColorOverride().isEmpty()) - return null; - if (BiomeColor.GRASS == type && biome.getSpecialEffects().grassColorOverride().isEmpty()) - return null; - } - return new Color(rgba, true); - } - - private static Field getField(Class clazz, Class fieldType) throws NoSuchFieldException { - try { - for (Field f : clazz.getDeclaredFields()) { - if (f.getType().equals(fieldType)) - return f; - } - throw new NoSuchFieldException(fieldType.getName()); - } catch (NoSuchFieldException var4) { - Class superClass = clazz.getSuperclass(); - if (superClass == null) { - throw var4; - } else { - return getField(superClass, fieldType); - } - } - } - - public static Holder biomeToBiomeBase(Registry registry, Biome biome) { - if (registry == null || biome == null) { - return null; - } - - NamespacedKey biomeKey = resolveBiomeKey(biome); - if (biomeKey == null) { - return null; - } - - ResourceKey key = ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biomeKey)); - return registry.get(key).orElse(null); - } - - private static NamespacedKey resolveBiomeKey(Biome biome) { - Object keyOrNullValue = invokeNoThrow(biome, "getKeyOrNull", new Class[0]); - if (keyOrNullValue instanceof NamespacedKey namespacedKey) { - return namespacedKey; - } - - Object keyOrThrowValue = invokeNoThrow(biome, "getKeyOrThrow", new Class[0]); - if (keyOrThrowValue instanceof NamespacedKey namespacedKey) { - return namespacedKey; - } - - Object keyValue = invokeNoThrow(biome, "getKey", new Class[0]); - if (keyValue instanceof NamespacedKey namespacedKey) { - return namespacedKey; - } - - return null; - } - - private static Object invokeNoThrow(Object target, String methodName, Class[] parameterTypes, Object... args) { - if (target == null) { - return null; - } - - try { - Method method = target.getClass().getMethod(methodName, parameterTypes); - return method.invoke(target, args); - } catch (Throwable ignored) { - return null; - } - } - - @Override - public DataVersion getDataVersion() { - return DataVersion.V1_21_11; - } - - @Override - public int getSpawnChunkCount(World world) { - return 0; - } - - @Override - public boolean missingDimensionTypes(String... keys) { - var type = registry().lookupOrThrow(Registries.DIMENSION_TYPE); - return !Arrays.stream(keys) - .map(key -> Identifier.fromNamespaceAndPath("iris", key)) - .allMatch(type::containsKey); - } - - @Override - public boolean injectBukkit() { - if (injected.getAndSet(true)) - return true; - try { - IrisLogging.info("Injecting Bukkit"); - var buddy = new ByteBuddy(); - buddy.redefine(ServerLevel.class) - .visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor() - .and(ElementMatchers.takesArgument(0, MinecraftServer.class)) - .and(ElementMatchers.takesArgument(5, LevelStem.class)))) - .make() - .load(ServerLevel.class.getClassLoader(), Agent.installed()); - for (Class clazz : List.of(ChunkAccess.class, ProtoChunk.class)) { - buddy.redefine(clazz) - .visit(Advice.to(ChunkAccessAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(ShortList.class, int.class)))) - .make() - .load(clazz.getClassLoader(), Agent.installed()); - } - - return true; - } catch (Throwable e) { - IrisLogging.error(C.RED + "Failed to inject Bukkit"); - e.printStackTrace(); - } - return false; - } - - @Override - public KMap> getBlockProperties() { - KMap> states = new KMap<>(); - - for (var block : registry().lookupOrThrow(Registries.BLOCK)) { - var state = block.defaultBlockState(); - if (state == null) state = block.getStateDefinition().any(); - final var finalState = state; - - states.put(CraftMagicNumbers.getMaterial(block), block.getStateDefinition() - .getProperties() - .stream() - .map(p -> createProperty(p, finalState)) - .toList()); - } - return states; - } - - private > BlockProperty createProperty(Property property, BlockState state) { - return new BlockProperty(property.getName(), property.getValueClass(), state.getValue(property), property.getPossibleValues(), property::getName); - } - - @Override - public Object createRuntimeLevelStem(Object registryAccess, ChunkGenerator raw) { - if (!(registryAccess instanceof RegistryAccess access)) { - throw new IllegalStateException("Runtime LevelStem creation requires a RegistryAccess instance."); - } - if (!(raw instanceof PlatformChunkGenerator generator)) { - throw new IllegalStateException("Generator is not platform chunk generator!"); - } - - Identifier dimensionKey = Identifier.fromNamespaceAndPath("iris", generator.getTarget().getDimension().getDimensionTypeKey()); - Holder.Reference dimensionType = access.lookupOrThrow(Registries.DIMENSION_TYPE) - .getOrThrow(ResourceKey.create(Registries.DIMENSION_TYPE, dimensionKey)); - return new LevelStem(dimensionType, chunkGenerator(access)); - } - - private net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator(RegistryAccess access) { - var settings = new FlatLevelGeneratorSettings(Optional.empty(), access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID), List.of()); - settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR)); - settings.updateLayers(); - return new FlatLevelSource(settings); - } - - private static class ChunkAccessAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This ChunkAccess access, @Advice.Argument(1) int index) { - return index >= access.getPostProcessing().length; - } - } - - private static class ServerLevelAdvice { - @Advice.OnMethodEnter - static void enter( - @Advice.Argument(0) MinecraftServer server, - @Advice.Argument(2) LevelStorageSource.LevelStorageAccess levelStorageAccess, - @Advice.Argument(value = 5, readOnly = false) LevelStem levelStem - ) { - if (levelStorageAccess == null) - return; - - try { - String levelId = levelStorageAccess.getLevelId(); - if (levelId == null || levelId.isBlank()) { - return; - } - - Object generator = Class.forName("art.arcane.iris.core.lifecycle.WorldLifecycleStaging", true, Bukkit.getPluginManager().getPlugin("Iris") - .getClass() - .getClassLoader()) - .getDeclaredMethod("consumeStemGenerator", String.class) - .invoke(null, levelId); - if (!(generator instanceof ChunkGenerator gen) || !gen.getClass().getPackageName().startsWith("art.arcane.iris")) { - return; - } - - Object bindings = Class.forName("art.arcane.iris.core.nms.INMS", true, Bukkit.getPluginManager().getPlugin("Iris") - .getClass() - .getClassLoader()) - .getDeclaredMethod("get") - .invoke(null); - if (bindings == null) { - throw new IllegalStateException("Iris failed to resolve an INMSBinding instance."); - } - - java.lang.reflect.Method stemMethod = null; - for (java.lang.reflect.Method candidate : bindings.getClass().getMethods()) { - if (candidate.getName().equals("createRuntimeLevelStem") && candidate.getParameterCount() == 2) { - stemMethod = candidate; - break; - } - } - if (stemMethod == null) { - throw new IllegalStateException("Iris binding is missing createRuntimeLevelStem."); - } - Object resolvedStem = stemMethod.invoke(bindings, server.registryAccess(), gen); - if (!(resolvedStem instanceof LevelStem runtimeStem)) { - throw new IllegalStateException("Iris runtime LevelStem binding returned " + (resolvedStem == null ? "null" : resolvedStem.getClass().getName()) + "."); - } - levelStem = runtimeStem; - } catch (Throwable e) { - throw new RuntimeException("Iris failed to replace the levelStem", e instanceof InvocationTargetException ex ? ex.getCause() : e); - } - } - } -} diff --git a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/VanillaStructureBiomes.java b/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/VanillaStructureBiomes.java deleted file mode 100644 index 9ade4057b..000000000 --- a/adapters/bukkit/nms/v1_21_R7/src/main/java/art/arcane/iris/core/nms/v1_21_R7/VanillaStructureBiomes.java +++ /dev/null @@ -1,77 +0,0 @@ -package art.arcane.iris.core.nms.v1_21_R7; - -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.levelgen.structure.Structure; - -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -final class VanillaStructureBiomes { - private VanillaStructureBiomes() { - } - - static Set possibleBiomeKeys(BiomeSource source) { - Set keys = new LinkedHashSet<>(); - if (source == null) { - return keys; - } - for (Holder holder : source.possibleBiomes()) { - Optional> key = holder.unwrapKey(); - if (key.isPresent()) { - keys.add(key.get().identifier().toString()); - } - } - return keys; - } - - static Set structureBiomeKeys(RegistryAccess access, String structureKey) { - Set keys = new LinkedHashSet<>(); - if (access == null || structureKey == null || structureKey.isEmpty()) { - return keys; - } - Registry registry = access.lookupOrThrow(Registries.STRUCTURE); - Structure structure = registry.getValue(Identifier.parse(structureKey)); - if (structure == null) { - return keys; - } - for (Holder holder : structure.biomes()) { - Optional> key = holder.unwrapKey(); - if (key.isPresent()) { - keys.add(key.get().identifier().toString()); - } - } - return keys; - } - - static Set reachableStructureKeys(ServerLevel level, BiomeSource source) { - Set reachable = new LinkedHashSet<>(); - if (level == null || source == null) { - return reachable; - } - Set possible = possibleBiomeKeys(source); - if (possible.isEmpty()) { - return reachable; - } - Registry registry = level.registryAccess().lookupOrThrow(Registries.STRUCTURE); - for (Map.Entry, Structure> entry : registry.entrySet()) { - for (Holder holder : entry.getValue().biomes()) { - Optional> key = holder.unwrapKey(); - if (key.isPresent() && possible.contains(key.get().identifier().toString())) { - reachable.add(entry.getKey().identifier().toString()); - break; - } - } - } - return reachable; - } -} diff --git a/build.gradle b/build.gradle index 5e496edc7..ea6315eb1 100644 --- a/build.gradle +++ b/build.gradle @@ -101,7 +101,6 @@ registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugin // ============================================================== def nmsBindings = [ - v1_21_R7: '1.21.11-R0.1-SNAPSHOT', v26_1_R1: '26.1.2.build.66-stable', ] Class nmsTypeClass = Class.forName('NMSBinding$Type') diff --git a/core/src/main/java/art/arcane/iris/core/nms/INMS.java b/core/src/main/java/art/arcane/iris/core/nms/INMS.java index a296596cd..0dc4346f0 100644 --- a/core/src/main/java/art/arcane/iris/core/nms/INMS.java +++ b/core/src/main/java/art/arcane/iris/core/nms/INMS.java @@ -28,13 +28,10 @@ import java.util.List; import java.util.Set; public class INMS { - private static final Version CURRENT = Boolean.getBoolean("iris.no-version-limit") ? - new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, null) : - new Version(26, 1, null); + private static final Version CURRENT = new Version(26, 1, 2, "v26_1_R1"); private static final List REVISION = List.of( - new Version(26, 1, "v26_1_R1"), - new Version(21, 11, "v1_21_R7") + CURRENT ); //@done @@ -88,7 +85,7 @@ public class INMS { MinecraftVersion detectedVersion = getMinecraftVersion(); String serverVersion = detectedVersion == null ? Bukkit.getServer().getVersion() : detectedVersion.value(); - throw new IllegalStateException("Iris requires Minecraft 1.21.11 or newer. Detected server version: " + serverVersion); + throw new IllegalStateException("Iris requires Minecraft 26.1.2. Detected server version: " + serverVersion); } private static String getTag(List versions, String def) { @@ -97,12 +94,8 @@ public class INMS { return def; } - if (detectedVersion.isNewerThan(CURRENT.major, CURRENT.minor)) { - return versions.getFirst().tag; - } - for (Version p : versions) { - if (!detectedVersion.isAtLeast(p.major, p.minor)) { + if (!detectedVersion.isSameRelease(p.major, p.minor, p.patch)) { continue; } return p.tag; @@ -155,5 +148,5 @@ public class INMS { return codes; } - private record Version(int major, int minor, String tag) {} + private record Version(int major, int minor, int patch, String tag) {} } diff --git a/core/src/main/java/art/arcane/iris/core/nms/INMSBinding.java b/core/src/main/java/art/arcane/iris/core/nms/INMSBinding.java index 2e6ea7ed0..8d131c61b 100644 --- a/core/src/main/java/art/arcane/iris/core/nms/INMSBinding.java +++ b/core/src/main/java/art/arcane/iris/core/nms/INMSBinding.java @@ -187,7 +187,7 @@ public interface INMSBinding { Color getBiomeColor(Location location, BiomeColor type); default DataVersion getDataVersion() { - return DataVersion.V1_19_2; + return DataVersion.V26_1_2; } default int getSpawnChunkCount(World world) { diff --git a/core/src/main/java/art/arcane/iris/core/nms/MinecraftVersion.java b/core/src/main/java/art/arcane/iris/core/nms/MinecraftVersion.java index 57c343ca5..e50bd12bf 100644 --- a/core/src/main/java/art/arcane/iris/core/nms/MinecraftVersion.java +++ b/core/src/main/java/art/arcane/iris/core/nms/MinecraftVersion.java @@ -12,11 +12,13 @@ final class MinecraftVersion { private final String value; private final int major; private final int minor; + private final int patch; - private MinecraftVersion(String value, int major, int minor) { + private MinecraftVersion(String value, int major, int minor, int patch) { this.value = value; this.major = major; this.minor = minor; + this.patch = patch; } public static MinecraftVersion detect(Server server) { @@ -92,12 +94,13 @@ final class MinecraftVersion { if ("1".equals(parts[0])) { int major = Integer.parseInt(parts[1]); int minor = parts.length > 2 ? Integer.parseInt(parts[2]) : 0; - return new MinecraftVersion(input, major, minor); + return new MinecraftVersion(input, major, minor, 0); } int major = Integer.parseInt(parts[0]); int minor = Integer.parseInt(parts[1]); - return new MinecraftVersion(input, major, minor); + int patch = parts.length > 2 ? Integer.parseInt(parts[2]) : 0; + return new MinecraftVersion(input, major, minor, patch); } catch (NumberFormatException ignored) { return null; } @@ -115,10 +118,28 @@ final class MinecraftVersion { return minor; } + public int patch() { + return patch; + } + public boolean isAtLeast(int major, int minor) { return this.major > major || (this.major == major && this.minor >= minor); } + public boolean isAtLeast(int major, int minor, int patch) { + if (this.major != major) { + return this.major > major; + } + if (this.minor != minor) { + return this.minor > minor; + } + return this.patch >= patch; + } + + public boolean isSameRelease(int major, int minor, int patch) { + return this.major == major && this.minor == minor && this.patch == patch; + } + public boolean isNewerThan(int major, int minor) { return this.major > major || (this.major == major && this.minor > minor); } diff --git a/core/src/main/java/art/arcane/iris/core/nms/datapack/DataVersion.java b/core/src/main/java/art/arcane/iris/core/nms/datapack/DataVersion.java index e04687df6..86ab73da7 100644 --- a/core/src/main/java/art/arcane/iris/core/nms/datapack/DataVersion.java +++ b/core/src/main/java/art/arcane/iris/core/nms/datapack/DataVersion.java @@ -2,9 +2,6 @@ package art.arcane.iris.core.nms.datapack; import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.core.nms.INMS; -import art.arcane.iris.core.nms.datapack.v1192.DataFixerV1192; -import art.arcane.iris.core.nms.datapack.v1206.DataFixerV1206; -import art.arcane.iris.core.nms.datapack.v1213.DataFixerV1213; import art.arcane.iris.core.nms.datapack.v1217.DataFixerV1217; import art.arcane.volmlib.util.collection.KMap; import lombok.AccessLevel; @@ -16,10 +13,6 @@ import java.util.function.Supplier; @Getter public enum DataVersion { UNSUPPORTED("0.0.0", 0, () -> null), - V1_19_2("1.19.2", 10, DataFixerV1192::new), - V1_20_5("1.20.6", 41, DataFixerV1206::new), - V1_21_3("1.21.3", 57, DataFixerV1213::new), - V1_21_11("1.21.11", 75, DataFixerV1217::new), V26_1_2("26.1.2", 101, DataFixerV1217::new); private static final KMap cache = new KMap<>(); @Getter(AccessLevel.NONE) diff --git a/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java b/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java index 6aee4290b..537a5a78a 100644 --- a/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java +++ b/core/src/main/java/art/arcane/iris/core/safeguard/task/Tasks.java @@ -94,7 +94,7 @@ public final class Tasks { } else if (parts.length >= 2) { supportedVersions = parts[1]; } else { - supportedVersions = "1.21.11"; + supportedVersions = "26.1.2"; } if (!(INMS.get() instanceof NMSBinding1X)) { diff --git a/core/src/test/java/art/arcane/iris/core/IrisRuntimeSchedulerModeRoutingTest.java b/core/src/test/java/art/arcane/iris/core/IrisRuntimeSchedulerModeRoutingTest.java index 37ff046f6..86e7e0975 100644 --- a/core/src/test/java/art/arcane/iris/core/IrisRuntimeSchedulerModeRoutingTest.java +++ b/core/src/test/java/art/arcane/iris/core/IrisRuntimeSchedulerModeRoutingTest.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.mockingDetails; public class IrisRuntimeSchedulerModeRoutingTest { @Test public void autoResolvesToPaperLikeOnPurpurBranding() { - installServer("Purpur", "git-Purpur-2562 (MC: 1.21.11)"); + installServer("Purpur", "git-Purpur-2562 (MC: 26.1.2)"); IrisSettings.IrisSettingsPregen pregen = new IrisSettings.IrisSettingsPregen(); pregen.runtimeSchedulerMode = IrisRuntimeSchedulerMode.AUTO; @@ -32,7 +32,7 @@ public class IrisRuntimeSchedulerModeRoutingTest { @Test public void autoResolvesToFoliaWhenBrandingContainsFolia() { - installServer("Folia", "git-Folia-123 (MC: 1.21.11)"); + installServer("Folia", "git-Folia-123 (MC: 26.1.2)"); IrisSettings.IrisSettingsPregen pregen = new IrisSettings.IrisSettingsPregen(); pregen.runtimeSchedulerMode = IrisRuntimeSchedulerMode.AUTO; @@ -42,7 +42,7 @@ public class IrisRuntimeSchedulerModeRoutingTest { @Test public void autoResolvesToPaperLikeOnCanvasBranding() { - installServer("Canvas", "git-Canvas-101 (MC: 1.21.11)"); + installServer("Canvas", "git-Canvas-101 (MC: 26.1.2)"); IrisSettings.IrisSettingsPregen pregen = new IrisSettings.IrisSettingsPregen(); pregen.runtimeSchedulerMode = IrisRuntimeSchedulerMode.AUTO; @@ -52,7 +52,7 @@ public class IrisRuntimeSchedulerModeRoutingTest { @Test public void explicitModeBypassesAutoDetection() { - installServer("Purpur", "git-Purpur-2562 (MC: 1.21.11)"); + installServer("Purpur", "git-Purpur-2562 (MC: 26.1.2)"); IrisSettings.IrisSettingsPregen pregen = new IrisSettings.IrisSettingsPregen(); pregen.runtimeSchedulerMode = IrisRuntimeSchedulerMode.FOLIA; diff --git a/core/src/test/java/art/arcane/iris/core/nms/INMSBindingProbeCodesTest.java b/core/src/test/java/art/arcane/iris/core/nms/INMSBindingProbeCodesTest.java index 7a67bba86..88b274e6d 100644 --- a/core/src/test/java/art/arcane/iris/core/nms/INMSBindingProbeCodesTest.java +++ b/core/src/test/java/art/arcane/iris/core/nms/INMSBindingProbeCodesTest.java @@ -10,22 +10,22 @@ import static org.junit.Assert.assertTrue; public class INMSBindingProbeCodesTest { @Test public void skipsSyntheticBukkitBindingWhenNmsIsEnabled() { - List probeCodes = NmsBindingProbeSupport.getBindingProbeCodes("BUKKIT", false, List.of("v1_21_R7")); + List probeCodes = NmsBindingProbeSupport.getBindingProbeCodes("BUKKIT", false, List.of("v26_1_R1")); - assertEquals(List.of("v1_21_R7"), probeCodes); + assertEquals(List.of("v26_1_R1"), probeCodes); } @Test public void leavesBukkitFallbackEmptyWhenNmsIsDisabled() { - List probeCodes = NmsBindingProbeSupport.getBindingProbeCodes("BUKKIT", true, List.of("v1_21_R7")); + List probeCodes = NmsBindingProbeSupport.getBindingProbeCodes("BUKKIT", true, List.of("v26_1_R1")); assertTrue(probeCodes.isEmpty()); } @Test public void keepsConcreteBindingCodesAsPrimaryProbe() { - List probeCodes = NmsBindingProbeSupport.getBindingProbeCodes("v1_21_R7", false, List.of("v1_21_R7")); + List probeCodes = NmsBindingProbeSupport.getBindingProbeCodes("v26_1_R1", false, List.of("v26_1_R1")); - assertEquals(List.of("v1_21_R7"), probeCodes); + assertEquals(List.of("v26_1_R1"), probeCodes); } } diff --git a/core/src/test/java/art/arcane/iris/core/nms/MinecraftVersionTest.java b/core/src/test/java/art/arcane/iris/core/nms/MinecraftVersionTest.java index da9d93fd9..7830ecc21 100644 --- a/core/src/test/java/art/arcane/iris/core/nms/MinecraftVersionTest.java +++ b/core/src/test/java/art/arcane/iris/core/nms/MinecraftVersionTest.java @@ -18,26 +18,28 @@ public class MinecraftVersionTest { @Test public void detectsMinecraftVersionFromPurpurDecoratedVersion() { Server server = mock(Server.class); - doReturn("git-Purpur-2570 (MC: 1.21.11)").when(server).getVersion(); + doReturn("git-Purpur-2570 (MC: 26.1.2)").when(server).getVersion(); doReturn("26.1.2.build.2570-experimental").when(server).getBukkitVersion(); MinecraftVersion version = MinecraftVersion.detect(server); - assertEquals("1.21.11", version.value()); - assertEquals(21, version.major()); - assertEquals(11, version.minor()); + assertEquals("26.1.2", version.value()); + assertEquals(26, version.major()); + assertEquals(1, version.minor()); + assertEquals(2, version.patch()); } @Test public void prefersRuntimeMinecraftVersionMethodWhenPresent() { PaperLikeServer server = mock(PaperLikeServer.class); - doReturn("1.21.11").when(server).getMinecraftVersion(); + doReturn("26.1.2").when(server).getMinecraftVersion(); doReturn("26.1.2-2570-e64b1b2 (MC: 26.1.2)").when(server).getVersion(); doReturn("26.1.2.build.2570-experimental").when(server).getBukkitVersion(); MinecraftVersion version = MinecraftVersion.detect(server); - assertEquals("1.21.11", version.value()); - assertEquals(21, version.major()); - assertEquals(11, version.minor()); + assertEquals("26.1.2", version.value()); + assertEquals(26, version.major()); + assertEquals(1, version.minor()); + assertEquals(2, version.patch()); } @Test @@ -48,16 +50,18 @@ public class MinecraftVersionTest { @Test public void parsesStandardBukkitSnapshotVersion() { - MinecraftVersion version = MinecraftVersion.fromBukkitVersion("1.21.11-R0.1-SNAPSHOT"); - assertEquals("1.21.11", version.value()); - assertEquals(21, version.major()); - assertEquals(11, version.minor()); + MinecraftVersion version = MinecraftVersion.fromBukkitVersion("26.1.2-R0.1-SNAPSHOT"); + assertEquals("26.1.2", version.value()); + assertEquals(26, version.major()); + assertEquals(1, version.minor()); + assertEquals(2, version.patch()); } @Test public void comparesMajorBeforeMinor() { - MinecraftVersion version = MinecraftVersion.fromBukkitVersion("1.20.12-R0.1-SNAPSHOT"); - assertFalse(version.isAtLeast(21, 11)); - assertTrue(version.isNewerThan(20, 11)); + MinecraftVersion version = MinecraftVersion.fromBukkitVersion("26.1.2-R0.1-SNAPSHOT"); + assertFalse(version.isAtLeast(26, 1, 3)); + assertTrue(version.isAtLeast(26, 1, 2)); + assertTrue(version.isSameRelease(26, 1, 2)); } } diff --git a/core/src/test/resources/art/arcane/iris/core/lifecycle/world-lifecycle-smoke-matrix.txt b/core/src/test/resources/art/arcane/iris/core/lifecycle/world-lifecycle-smoke-matrix.txt index cf5348099..4a54de701 100644 --- a/core/src/test/resources/art/arcane/iris/core/lifecycle/world-lifecycle-smoke-matrix.txt +++ b/core/src/test/resources/art/arcane/iris/core/lifecycle/world-lifecycle-smoke-matrix.txt @@ -1,28 +1,28 @@ -Paper 1.21.11 +Paper 26.1.2 /iris create matrix-paper overworld /iris std o overworld close Studio world benchmark create/unload -Purpur 1.21.11 +Purpur 26.1.2 /iris create matrix-purpur overworld /iris std o overworld close Studio world benchmark create/unload -Canvas 1.21.11 +Canvas 26.1.2 /iris create matrix-canvas overworld /iris std o overworld close Studio world benchmark create/unload -Folia 1.21.11 +Folia 26.1.2 /iris create matrix-folia overworld /iris std o overworld close Studio world benchmark create/unload -Spigot 1.21.11 +Spigot 26.1.2 /iris create matrix-spigot overworld /iris std o overworld close Studio world diff --git a/settings.gradle b/settings.gradle index 10bb1dd72..7de2b59dd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -72,5 +72,4 @@ include(':core', ':core:agent') include(':probe') include(':spi') include(':adapters:bukkit:plugin') -include(':adapters:bukkit:nms:v1_21_R7') include(':adapters:bukkit:nms:v26_1_R1')