Merge branch 'fix_maps' into v3.4.3

# Conflicts:
#	core/src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java
#	nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java
#	nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java
#	nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java
#	nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java
#	nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java
#	nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java
This commit is contained in:
Julian Krings
2024-08-17 12:25:23 +02:00
31 changed files with 2336 additions and 369 deletions

View File

@@ -0,0 +1,236 @@
package com.volmit.iris.core.nms.v1_19_R1;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import net.minecraft.core.*;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registry.STRUCTURE_REGISTRY).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = new ResourceLocation(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registry.STRUCTURE_REGISTRY, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registry.STRUCTURE_REGISTRY, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected Codec<? extends ChunkGenerator> codec() {
return Codec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager, long i) {
delegate.createStructures(iregistrycustom, randomstate, structuremanager, ichunkaccess, structuretemplatemanager, i);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(executor, blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -14,11 +14,13 @@ import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
@@ -531,23 +533,9 @@ public class NMSBinding implements INMSBinding {
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
public void inject(long seed, Engine engine, World world) {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
@@ -602,6 +590,23 @@ public class NMSBinding implements INMSBinding {
return new Color(rgba, true);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registry.STRUCTURE_REGISTRY).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,241 @@
package com.volmit.iris.core.nms.v1_19_R2;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
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.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R2.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registries.STRUCTURE).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = new ResourceLocation(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registries.STRUCTURE, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registries.STRUCTURE, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected Codec<? extends ChunkGenerator> codec() {
return Codec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager) {
delegate.createStructures(iregistrycustom, chunkgeneratorstructurestate, structuremanager, ichunkaccess, structuretemplatemanager);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(executor, blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -14,11 +14,13 @@ import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
@@ -532,23 +534,9 @@ public class NMSBinding implements INMSBinding {
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
public void inject(long seed, Engine engine, World world) {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
}
@@ -604,6 +592,23 @@ public class NMSBinding implements INMSBinding {
return new Color(rgba, true);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registries.STRUCTURE).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,241 @@
package com.volmit.iris.core.nms.v1_19_R3;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
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.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registries.STRUCTURE).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = new ResourceLocation(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registries.STRUCTURE, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registries.STRUCTURE, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected Codec<? extends ChunkGenerator> codec() {
return Codec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager) {
delegate.createStructures(iregistrycustom, chunkgeneratorstructurestate, structuremanager, ichunkaccess, structuretemplatemanager);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(executor, blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -14,11 +14,13 @@ import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
@@ -540,17 +542,9 @@ public class NMSBinding implements INMSBinding {
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
public void inject(long seed, Engine engine, World world) {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
@@ -608,6 +602,23 @@ public class NMSBinding implements INMSBinding {
return new Color(rgba, true);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registries.STRUCTURE).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,241 @@
package com.volmit.iris.core.nms.v1_20_R1;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
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.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R1.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registries.STRUCTURE).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = new ResourceLocation(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registries.STRUCTURE, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registries.STRUCTURE, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected Codec<? extends ChunkGenerator> codec() {
return Codec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager) {
delegate.createStructures(iregistrycustom, chunkgeneratorstructurestate, structuremanager, ichunkaccess, structuretemplatemanager);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(executor, blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -1,6 +1,7 @@
package com.volmit.iris.core.nms.v1_20_R1;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.core.nms.container.BiomeColor;
@@ -29,6 +30,7 @@ import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.biome.BiomeSource;
@@ -536,12 +538,6 @@ public class NMSBinding implements INMSBinding {
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = net.minecraft.world.entity.EntityType.class.getDeclaredFields();
for (Field field : fields) {
@@ -570,17 +566,9 @@ public class NMSBinding implements INMSBinding {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
public void inject(long seed, Engine engine, World world) {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
}
@Override
@@ -607,6 +595,23 @@ public class NMSBinding implements INMSBinding {
return new Color(rgba, true);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registries.STRUCTURE).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,241 @@
package com.volmit.iris.core.nms.v1_20_R2;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
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.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registries.STRUCTURE).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = new ResourceLocation(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registries.STRUCTURE, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registries.STRUCTURE, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected Codec<? extends ChunkGenerator> codec() {
return Codec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager) {
delegate.createStructures(iregistrycustom, chunkgeneratorstructurestate, structuremanager, ichunkaccess, structuretemplatemanager);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(executor, blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -14,6 +14,7 @@ import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
@@ -534,23 +535,9 @@ public class NMSBinding implements INMSBinding {
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
public void inject(long seed, Engine engine, World world) {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
@@ -605,6 +592,23 @@ public class NMSBinding implements INMSBinding {
return new Color(rgba, true);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registries.STRUCTURE).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,244 @@
package com.volmit.iris.core.nms.v1_20_R3;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.scheduling.S;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.StructureTags;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.item.EnderEyeItem;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
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.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R3.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registries.STRUCTURE).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = new ResourceLocation(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registries.STRUCTURE, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registries.STRUCTURE, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected Codec<? extends ChunkGenerator> codec() {
return Codec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager) {
delegate.createStructures(iregistrycustom, chunkgeneratorstructurestate, structuremanager, ichunkaccess, structuretemplatemanager);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(executor, blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -14,11 +14,13 @@ import java.util.Map;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.util.scheduling.J;
import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
import org.bukkit.*;
@@ -534,23 +536,9 @@ public class NMSBinding implements INMSBinding {
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
public void inject(long seed, Engine engine, World world) {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
@@ -606,6 +594,23 @@ public class NMSBinding implements INMSBinding {
return new Color(rgba, true);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registries.STRUCTURE).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,239 @@
package com.volmit.iris.core.nms.v1_20_R4;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.MapCodec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
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.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R4.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registries.STRUCTURE).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = new ResourceLocation(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registries.STRUCTURE, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registries.STRUCTURE, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected MapCodec<? extends ChunkGenerator> codec() {
return MapCodec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager) {
delegate.createStructures(iregistrycustom, chunkgeneratorstructurestate, structuremanager, ichunkaccess, structuretemplatemanager);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(executor, blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -7,6 +7,7 @@ import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.util.nbt.tag.CompoundTag;
@@ -26,6 +27,8 @@ import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.server.commands.data.DataCommands;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
@@ -42,6 +45,7 @@ import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockStates;
import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockType;
import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R4.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R4.generator.CustomChunkGenerator;
import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R4.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
@@ -71,15 +75,12 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import sun.misc.Unsafe;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
@@ -541,23 +542,9 @@ public class NMSBinding implements INMSBinding {
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
public void inject(long seed, Engine engine, World world) {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
@@ -646,4 +633,21 @@ public class NMSBinding implements INMSBinding {
if (radius == null) throw new IllegalStateException("GameRule.SPAWN_CHUNK_RADIUS is null!");
return (int) Math.pow(2 * radius + 1, 2);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registries.STRUCTURE).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
}

View File

@@ -0,0 +1,240 @@
package com.volmit.iris.core.nms.v1_21_R1;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.MapCodec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.ResultLocator;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.engine.object.IrisJigsawStructurePlacement;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.tags.TagKey;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.NoiseColumn;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.MobSpawnSettings;
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.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_21_R1.generator.CustomChunkGenerator;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class IrisChunkGenerator extends CustomChunkGenerator {
private final ChunkGenerator delegate;
private final Engine engine;
private final BiomeSource biomeSource;
private final KMap<ResourceKey<Structure>, KSet<String>> structures = new KMap<>();
public IrisChunkGenerator(ChunkGenerator delegate, long seed, Engine engine, World world) {
super(((CraftWorld) world).getHandle(), delegate, null);
this.delegate = delegate;
this.engine = engine;
this.biomeSource = new CustomBiomeSource(seed, engine, world);
var dimension = engine.getDimension();
KSet<IrisJigsawStructure> placements = new KSet<>();
addAll(dimension.getJigsawStructures(), placements);
for (var region : dimension.getAllRegions(engine)) {
addAll(region.getJigsawStructures(), placements);
for (var biome : region.getAllBiomes(engine))
addAll(biome.getJigsawStructures(), placements);
}
var stronghold = dimension.getStronghold();
if (stronghold != null)
placements.add(engine.getData().getJigsawStructureLoader().load(stronghold));
placements.removeIf(Objects::isNull);
var registry = ((CraftWorld) world).getHandle().registryAccess().registry(Registries.STRUCTURE).orElseThrow();
for (var s : placements) {
try {
String raw = s.getStructureKey();
if (raw == null) continue;
boolean tag = raw.startsWith("#");
if (tag) raw = raw.substring(1);
var location = ResourceLocation.parse(raw);
if (!tag) {
structures.computeIfAbsent(ResourceKey.create(Registries.STRUCTURE, location), k -> new KSet<>()).add(s.getLoadKey());
continue;
}
var key = TagKey.create(Registries.STRUCTURE, location);
var set = registry.getTag(key).orElse(null);
if (set == null) {
Iris.error("Could not find structure tag: " + raw);
continue;
}
for (var holder : set) {
var resourceKey = holder.unwrapKey().orElse(null);
if (resourceKey == null) continue;
structures.computeIfAbsent(resourceKey, k -> new KSet<>()).add(s.getLoadKey());
}
} catch (Throwable e) {
Iris.error("Failed to load structure: " + s.getLoadKey());
e.printStackTrace();
}
}
}
private void addAll(KList<IrisJigsawStructurePlacement> placements, KSet<IrisJigsawStructure> structures) {
if (placements == null) return;
placements.stream()
.map(IrisJigsawStructurePlacement::getStructure)
.map(engine.getData().getJigsawStructureLoader()::load)
.filter(Objects::nonNull)
.forEach(structures::add);
}
@Override
public @Nullable Pair<BlockPos, Holder<Structure>> findNearestMapStructure(ServerLevel level, HolderSet<Structure> holders, BlockPos pos, int radius, boolean findUnexplored) {
if (engine.getDimension().isDisableExplorerMaps())
return null;
KMap<String, Holder<Structure>> structures = new KMap<>();
for (var holder : holders) {
if (holder == null) continue;
var key = holder.unwrapKey().orElse(null);
var set = this.structures.get(key);
if (set == null) continue;
for (var structure : set) {
structures.put(structure, holder);
}
}
if (structures.isEmpty())
return null;
var locator = ResultLocator.locateStructure(structures.keySet())
.then((e, p , s) -> structures.get(s.getLoadKey()));
if (findUnexplored)
locator = locator.then((e, p, s) -> e.getMantle().getMantle().getChunk(p.getX(), p.getZ()).isFlagged(MantleFlag.DISCOVERED) ? null : s);
try {
var result = locator.find(engine, new Position2(pos.getX() >> 4, pos.getZ() >> 4), radius * 10L, i -> {}, false).get();
if (result == null) return null;
var blockPos = new BlockPos(result.getBlockX(), 0, result.getBlockZ());
return Pair.of(blockPos, result.obj());
} catch (WrongEngineBroException | ExecutionException | InterruptedException e) {
return null;
}
}
@Override
protected MapCodec<? extends ChunkGenerator> codec() {
return MapCodec.unit(null);
}
@Override
public ChunkGenerator getDelegate() {
if (delegate instanceof CustomChunkGenerator chunkGenerator)
return chunkGenerator.getDelegate();
return delegate;
}
@Override
public BiomeSource getBiomeSource() {
return biomeSource;
}
@Override
public int getMinY() {
return delegate.getMinY();
}
@Override
public int getSeaLevel() {
return delegate.getSeaLevel();
}
@Override
public void createStructures(RegistryAccess iregistrycustom, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess ichunkaccess, StructureTemplateManager structuretemplatemanager) {
delegate.createStructures(iregistrycustom, chunkgeneratorstructurestate, structuremanager, ichunkaccess, structuretemplatemanager);
}
@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, GenerationStep.Carving worldgenstage_features) {
delegate.applyCarvers(regionlimitedworldaccess, seed, randomstate, biomemanager, structuremanager, ichunkaccess, worldgenstage_features);
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess ichunkaccess) {
return delegate.fillFromNoise(blender, randomstate, structuremanager, ichunkaccess);
}
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseHeight(i, j, heightmap_type, levelheightaccessor, randomstate);
}
@Override
public WeightedRandomList<MobSpawnSettings.SpawnerData> getMobsAt(Holder<Biome> holder, StructureManager structuremanager, MobCategory enumcreaturetype, BlockPos blockposition) {
return delegate.getMobsAt(holder, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) {
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager);
}
@Override
public void addDebugScreenInfo(List<String> list, RandomState randomstate, BlockPos blockposition) {
delegate.addDebugScreenInfo(list, randomstate, blockposition);
}
@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 NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
return delegate.getBaseColumn(i, j, levelheightaccessor, randomstate);
}
}

View File

@@ -11,6 +11,7 @@ import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.datafixers.util.Pair;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.util.scheduling.J;
@@ -19,6 +20,7 @@ import net.minecraft.nbt.*;
import net.minecraft.nbt.Tag;
import net.minecraft.server.commands.data.BlockDataAccessor;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.EntityBlock;
@@ -539,26 +541,17 @@ public class NMSBinding implements INMSBinding {
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
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);
Class<?> clazz = worldGenContext.generator().getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(worldGenContext.generator()), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(worldGenContext.generator(), customBiomeSource);
var newContext = new WorldGenContext(
worldGenContext.level(), new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world),
worldGenContext.structureManager(), worldGenContext.lightEngine(), worldGenContext.mainThreadMailBox());
worldGenContextField.set(chunkMap, newContext);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
@@ -647,4 +640,21 @@ public class NMSBinding implements INMSBinding {
if (radius == null) throw new IllegalStateException("GameRule.SPAWN_CHUNK_RADIUS is null!");
return (int) Math.pow(2 * radius + 1, 2);
}
@Override
public KList<String> getStructureKeys() {
KList<String> keys = new KList<>();
var registry = registry().registry(Registries.STRUCTURE).orElse(null);
if (registry == null) return keys;
registry.keySet().stream().map(ResourceLocation::toString).forEach(keys::add);
registry.getTags()
.map(Pair::getFirst)
.map(TagKey::location)
.map(ResourceLocation::toString)
.map(s -> "#" + s)
.forEach(keys::add);
return keys;
}
}