mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-21 15:57:38 +00:00
Added 26.1.2 and 26.2 mod targets
- Mod targets 26.2 and 26.1.2 (inheriting 26.2) with Fabric 0.19.5, Forge 65.1.3 and 64.1.4, NeoForge 26.2.0.89 and 26.1.2.116 - The 26.3 target reads the minecraft26_3 native access rules - Per-version pack.mcmeta ranges for 26.2 and 26.1.2 - 26.2 and 26.1.2 test overlays and replacements for the pre-26.3 biome, spawn, carver and sign APIs - NeoForge compiles against the loader's own ASM while the mod jar keeps the bundled ASM
This commit is contained in:
1 parent
0073002b57
commit
4daae925c6
9 files changed
+624
-2
No files matched your search
+101
@@ -0,0 +1,101 @@
|
||||
package art.arcane.volmlib.nativelib.minecraft26_2.forge;
|
||||
|
||||
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeRegistryDefinitions;
|
||||
import art.arcane.volmlib.nativelib.modded.NativeLoaderOptions;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.RegistrationInfo;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.world.entity.EntityTypes;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraftforge.common.world.BiomeModifier;
|
||||
import net.minecraftforge.common.world.ModifiableBiomeInfo;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class NativeForgeBiomeDefinitionTest {
|
||||
private static final String BIOME_REGISTRY = "minecraft:worldgen/biome";
|
||||
private static final String BIOME_KEY = "iris:biomes/forge_modified";
|
||||
private static final String SOURCE_JSON = "{\"has_precipitation\":true,\"temperature\":0.8,\"downfall\":0.4,"
|
||||
+ "\"effects\":{\"water_color\":\"#3f76e4\"},\"carvers\":[],\"features\":[],"
|
||||
+ "\"spawners\":{},\"spawn_costs\":{}}";
|
||||
|
||||
@BeforeClass
|
||||
public static void bootstrap() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatedBiomeDefinitionExcludesForgeBiomeModifierOutput() {
|
||||
MappedRegistry<PlacedFeature> features = new MappedRegistry<>(Registries.PLACED_FEATURE, Lifecycle.stable());
|
||||
Holder.Reference<PlacedFeature> ore = features.register(
|
||||
ResourceKey.create(Registries.PLACED_FEATURE, Identifier.parse("iris:modded_ore")),
|
||||
new PlacedFeature(Holder.direct(mock(ConfiguredFeature.class)), List.of()),
|
||||
RegistrationInfo.BUILT_IN);
|
||||
features.freeze();
|
||||
MappedRegistry<ConfiguredWorldCarver<?>> carvers = new MappedRegistry<>(Registries.CONFIGURED_CARVER, Lifecycle.stable());
|
||||
carvers.freeze();
|
||||
MappedRegistry<Biome> biomes = new MappedRegistry<>(Registries.BIOME, Lifecycle.stable());
|
||||
RegistryAccess access = new RegistryAccess.ImmutableRegistryAccess(List.of(biomes, features, carvers));
|
||||
Biome source = Biome.DIRECT_CODEC.parse(RegistryOps.create(JsonOps.INSTANCE, access),
|
||||
JsonParser.parseString(SOURCE_JSON)).getOrThrow();
|
||||
Holder.Reference<Biome> biome = biomes.register(
|
||||
ResourceKey.create(Registries.BIOME, Identifier.parse(BIOME_KEY)), source, RegistrationInfo.BUILT_IN);
|
||||
biomes.freeze();
|
||||
biome.value().modifiableBiomeInfo().applyBiomeModifiers(biome, List.of(new ModdedContent(ore)));
|
||||
NativeRegistryDefinitions definitions = new NativeRegistryDefinitions(() -> access,
|
||||
new NativeForgeLoader(new NativeLoaderOptions("irisworldgen", "treefeller",
|
||||
BooleanSupplier::getAsBoolean))::unmodifiedBiome);
|
||||
|
||||
assertEquals(0.1F, biome.value().modifiableBiomeInfo().get().climateSettings().temperature(), 0.0F);
|
||||
assertEquals(0x102030, biome.value().modifiableBiomeInfo().get().effects().waterColor() & 0xFFFFFF);
|
||||
assertTrue(biome.value().getGenerationSettings().hasFeature(ore.value()));
|
||||
assertTrue(biome.value().getMobSettings().getMobs(MobCategory.MONSTER).unwrap().stream()
|
||||
.anyMatch(spawn -> spawn.value().type() == EntityTypes.ZOMBIE));
|
||||
assertEquals(JsonParser.parseString(definitions.canonicalDefinition(BIOME_REGISTRY, BIOME_KEY, SOURCE_JSON).value()),
|
||||
JsonParser.parseString(definitions.generatedDefinition(BIOME_REGISTRY, BIOME_KEY).value()));
|
||||
}
|
||||
|
||||
private record ModdedContent(Holder<PlacedFeature> ore) implements BiomeModifier {
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder) {
|
||||
if (phase != Phase.ADD) {
|
||||
return;
|
||||
}
|
||||
builder.getClimateSettings().setTemperature(0.1F);
|
||||
builder.getSpecialEffects().waterColor(0x102030);
|
||||
builder.getMobSpawnSettings().addSpawn(MobCategory.MONSTER, 5,
|
||||
new MobSpawnSettings.SpawnerData(EntityTypes.ZOMBIE, 1, 2));
|
||||
builder.getGenerationSettings().addFeature(GenerationStep.Decoration.UNDERGROUND_ORES, ore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<? extends BiomeModifier> codec() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Iris client resources and mod data",
|
||||
"min_format": [84, 0],
|
||||
"max_format": [101, 1]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"global": [
|
||||
{
|
||||
"pattern": "\\bEntityTypes\\b",
|
||||
"replacement": "EntityType"
|
||||
},
|
||||
{
|
||||
"pattern": "\\bSpeleothemBlock\\b",
|
||||
"replacement": "PointedDripstoneBlock"
|
||||
},
|
||||
{
|
||||
"pattern": "\\bSpeleothemThickness\\b",
|
||||
"replacement": "DripstoneThickness"
|
||||
}
|
||||
],
|
||||
"files": {
|
||||
"art/arcane/iris/modded/ModdedBlockResolutionContractTest.java": [
|
||||
{
|
||||
"pattern": "Blocks\\.SULFUR_SPIKE, ",
|
||||
"replacement": ""
|
||||
},
|
||||
{
|
||||
"pattern": "\"minecraft:sulfur_spike\", ",
|
||||
"replacement": ""
|
||||
},
|
||||
{
|
||||
"pattern": "sulfurAndDripstoneTipsReceivePostLoadUpdates",
|
||||
"replacement": "dripstoneTipsReceivePostLoadUpdates"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Iris client resources and mod data",
|
||||
"min_format": [88, 0],
|
||||
"max_format": [107, 1]
|
||||
}
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeStructureSetFrequencyOverrides;
|
||||
|
||||
import art.arcane.iris.structure.nativegen.IrisImportedStructureControl;
|
||||
import art.arcane.iris.structure.placement.IrisStructureSetFrequencyOverride;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderOwner;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate;
|
||||
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureSet;
|
||||
import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement;
|
||||
import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType;
|
||||
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
|
||||
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacementType;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
public class ModdedStructureSetFrequencyOverridesTest {
|
||||
@BeforeClass
|
||||
public static void bootstrapMinecraftRegistries() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createStateReplacementScalesOnlyTheExactSetAndRetainsEntries() throws Exception {
|
||||
Holder<StructureSet> complexes = structureSet(
|
||||
"minecraft:nether_complexes", 27, 4, 30084232);
|
||||
Holder<StructureSet> fossils = structureSet(
|
||||
"minecraft:nether_fossils", 2, 1, 14357921);
|
||||
ChunkGeneratorStructureState state = state(List.of(complexes, fossils));
|
||||
KList<IrisStructureSetFrequencyOverride> overrides = new KList<>();
|
||||
overrides.add(new IrisStructureSetFrequencyOverride()
|
||||
.setStructureSet("minecraft:nether_complexes")
|
||||
.setMultiplier(1.1D));
|
||||
IrisImportedStructureControl control = new IrisImportedStructureControl()
|
||||
.setFrequencyOverrides(overrides);
|
||||
|
||||
ChunkGeneratorStructureState returned =
|
||||
NativeStructureSetFrequencyOverrides.apply(state, control);
|
||||
|
||||
assertSame(state, returned);
|
||||
List<Holder<StructureSet>> scaledSets = state.possibleStructureSets();
|
||||
RandomSpreadStructurePlacement scaledComplexes =
|
||||
(RandomSpreadStructurePlacement) scaledSets.get(0).value().placement();
|
||||
assertEquals(26, scaledComplexes.spacing());
|
||||
assertEquals(4, scaledComplexes.separation());
|
||||
assertSame(complexes.value().structures(), scaledSets.get(0).value().structures());
|
||||
assertSame(fossils, scaledSets.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unrelatedCustomPlacementTypeRemainsUntouched() {
|
||||
Holder<StructureSet> custom = new BoundStructureSetHolder(
|
||||
"example:custom",
|
||||
new StructureSet(List.of(), new UnsupportedPlacement()));
|
||||
KList<IrisStructureSetFrequencyOverride> overrides = new KList<>();
|
||||
overrides.add(new IrisStructureSetFrequencyOverride()
|
||||
.setStructureSet("minecraft:nether_complexes")
|
||||
.setMultiplier(1.1D));
|
||||
IrisImportedStructureControl control = new IrisImportedStructureControl()
|
||||
.setFrequencyOverrides(overrides);
|
||||
|
||||
List<Holder<StructureSet>> scaled =
|
||||
NativeStructureSetFrequencyOverrides.scaleSets(List.of(custom), control);
|
||||
|
||||
assertSame(custom, scaled.getFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unrelatedExclusionCycleRemainsUntouched() {
|
||||
BoundStructureSetHolder first = new BoundStructureSetHolder("example:first");
|
||||
BoundStructureSetHolder second = new BoundStructureSetHolder("example:second");
|
||||
first.bind(new StructureSet(List.of(), placement(32, 8, 1, second)));
|
||||
second.bind(new StructureSet(List.of(), placement(40, 10, 2, first)));
|
||||
KList<IrisStructureSetFrequencyOverride> overrides = new KList<>();
|
||||
overrides.add(new IrisStructureSetFrequencyOverride()
|
||||
.setStructureSet("minecraft:nether_complexes")
|
||||
.setMultiplier(1.1D));
|
||||
IrisImportedStructureControl control = new IrisImportedStructureControl()
|
||||
.setFrequencyOverrides(overrides);
|
||||
|
||||
List<Holder<StructureSet>> scaled = NativeStructureSetFrequencyOverrides.scaleSets(
|
||||
List.of(first, second), control);
|
||||
|
||||
assertSame(first, scaled.get(0));
|
||||
assertSame(second, scaled.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void affectedExclusionCycleUsesBoundScaledHolders() {
|
||||
BoundStructureSetHolder first = new BoundStructureSetHolder("example:first");
|
||||
BoundStructureSetHolder second = new BoundStructureSetHolder("example:second");
|
||||
first.bind(new StructureSet(List.of(), placement(32, 8, 1, second)));
|
||||
second.bind(new StructureSet(List.of(), placement(40, 10, 2, first)));
|
||||
KList<IrisStructureSetFrequencyOverride> overrides = new KList<>();
|
||||
overrides.add(new IrisStructureSetFrequencyOverride()
|
||||
.setStructureSet("example:first")
|
||||
.setMultiplier(1.1D));
|
||||
IrisImportedStructureControl control = new IrisImportedStructureControl()
|
||||
.setFrequencyOverrides(overrides);
|
||||
|
||||
List<Holder<StructureSet>> scaled = NativeStructureSetFrequencyOverrides.scaleSets(
|
||||
List.of(first, second), control);
|
||||
|
||||
assertEquals(31, ((RandomSpreadStructurePlacement)
|
||||
scaled.get(0).value().placement()).spacing());
|
||||
assertEquals(40, ((RandomSpreadStructurePlacement)
|
||||
scaled.get(1).value().placement()).spacing());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void affectedRandomSpreadSubclassFailsInsteadOfLosingSubtypeBehavior() {
|
||||
Holder<StructureSet> custom = new BoundStructureSetHolder(
|
||||
"example:custom",
|
||||
new StructureSet(List.of(), new CustomRandomSpreadPlacement()));
|
||||
KList<IrisStructureSetFrequencyOverride> overrides = new KList<>();
|
||||
overrides.add(new IrisStructureSetFrequencyOverride()
|
||||
.setStructureSet("example:custom")
|
||||
.setMultiplier(1.1D));
|
||||
IrisImportedStructureControl control = new IrisImportedStructureControl()
|
||||
.setFrequencyOverrides(overrides);
|
||||
|
||||
assertThrows(IllegalStateException.class, () ->
|
||||
NativeStructureSetFrequencyOverrides.scaleSets(List.of(custom), control));
|
||||
}
|
||||
|
||||
private static Holder<StructureSet> structureSet(
|
||||
String key,
|
||||
int spacing,
|
||||
int separation,
|
||||
int salt
|
||||
) {
|
||||
StructureSet value = new StructureSet(
|
||||
List.of(),
|
||||
new RandomSpreadStructurePlacement(
|
||||
spacing, separation, RandomSpreadType.LINEAR, salt));
|
||||
return new BoundStructureSetHolder(key, value);
|
||||
}
|
||||
|
||||
private static RandomSpreadStructurePlacement placement(
|
||||
int spacing,
|
||||
int separation,
|
||||
int salt,
|
||||
Holder<StructureSet> exclusionTarget
|
||||
) {
|
||||
return new RandomSpreadStructurePlacement(
|
||||
Vec3i.ZERO,
|
||||
StructurePlacement.FrequencyReductionMethod.DEFAULT,
|
||||
1F,
|
||||
salt,
|
||||
Optional.of(new StructurePlacement.ExclusionZone(exclusionTarget, 1)),
|
||||
spacing,
|
||||
separation,
|
||||
RandomSpreadType.LINEAR);
|
||||
}
|
||||
|
||||
private static ChunkGeneratorStructureState state(
|
||||
List<Holder<StructureSet>> sets
|
||||
) throws Exception {
|
||||
Constructor<ChunkGeneratorStructureState> constructor =
|
||||
ChunkGeneratorStructureState.class.getDeclaredConstructor(
|
||||
RandomState.class,
|
||||
BiomeSource.class,
|
||||
long.class,
|
||||
long.class,
|
||||
List.class);
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance(
|
||||
null,
|
||||
new EmptyBiomeSource(),
|
||||
1L,
|
||||
1L,
|
||||
sets);
|
||||
}
|
||||
|
||||
private static final class BoundStructureSetHolder extends Holder.Reference<StructureSet> {
|
||||
private BoundStructureSetHolder(String key) {
|
||||
this(key, null);
|
||||
}
|
||||
|
||||
private BoundStructureSetHolder(String key, StructureSet value) {
|
||||
super(Type.STAND_ALONE, new HolderOwner<>() {
|
||||
}, ResourceKey.create(Registries.STRUCTURE_SET, Identifier.parse(key)), value);
|
||||
}
|
||||
|
||||
private void bind(StructureSet value) {
|
||||
bindValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class EmptyBiomeSource extends BiomeSource {
|
||||
@Override
|
||||
public Holder<Biome> getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BiomeSource> codec() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<Holder<Biome>> collectPossibleBiomes() {
|
||||
return HolderSet.<Biome>empty().stream();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class UnsupportedPlacement extends StructurePlacement {
|
||||
private UnsupportedPlacement() {
|
||||
super(Vec3i.ZERO, FrequencyReductionMethod.DEFAULT, 1F, 0, Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPlacementChunk(ChunkGeneratorStructureState state, int x, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructurePlacementType<?> type() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CustomRandomSpreadPlacement extends RandomSpreadStructurePlacement {
|
||||
private CustomRandomSpreadPlacement() {
|
||||
super(27, 4, RandomSpreadType.LINEAR, 30084232);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"global": [
|
||||
{
|
||||
"pattern": "new MobSpawnSettings\\.SpawnerData\\((EntityTypes\\.[A-Z_]+), UniformInt\\.of\\((\\d+), (\\d+)\\)\\)",
|
||||
"replacement": "new MobSpawnSettings.SpawnerData($1, $2, $3)"
|
||||
}
|
||||
],
|
||||
"files": {
|
||||
"art/arcane/volmlib/nativelib/minecraft26_2/fabric/NativeFabricBiomeDefinitionTest.java": [
|
||||
{
|
||||
"pattern": "import net\\.minecraft\\.world\\.level\\.levelgen\\.carver\\.WorldCarver;",
|
||||
"replacement": "import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;"
|
||||
},
|
||||
{
|
||||
"pattern": "import net\\.minecraft\\.world\\.level\\.levelgen\\.feature\\.Feature;",
|
||||
"replacement": "import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;"
|
||||
},
|
||||
{
|
||||
"pattern": "mock\\(Feature\\.class\\)",
|
||||
"replacement": "mock(ConfiguredFeature.class)"
|
||||
},
|
||||
{
|
||||
"pattern": "MappedRegistry<WorldCarver> carvers = new MappedRegistry<>\\(Registries\\.CARVER,",
|
||||
"replacement": "MappedRegistry<ConfiguredWorldCarver<?>> carvers = new MappedRegistry<>(Registries.CONFIGURED_CARVER,"
|
||||
},
|
||||
{
|
||||
"pattern": "\\\\\"features\\\\\":\\[\\]\\}\";",
|
||||
"replacement": "\\\\\"features\\\\\":[],\\\\\"spawners\\\\\":{},\\\\\"spawn_costs\\\\\":{}}\";"
|
||||
}
|
||||
],
|
||||
"art/arcane/volmlib/nativelib/minecraft26_2/modded/NativeWorldgenScanTest.java": [
|
||||
{
|
||||
"pattern": "import net\\.minecraft\\.world\\.level\\.levelgen\\.carver\\.WorldCarver;",
|
||||
"replacement": "import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;"
|
||||
},
|
||||
{
|
||||
"pattern": "import net\\.minecraft\\.world\\.level\\.levelgen\\.feature\\.Feature;",
|
||||
"replacement": "import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;"
|
||||
},
|
||||
{
|
||||
"pattern": "mock\\(Feature\\.class\\)",
|
||||
"replacement": "mock(ConfiguredFeature.class)"
|
||||
},
|
||||
{
|
||||
"pattern": "MappedRegistry<WorldCarver> carvers = new MappedRegistry<>\\(Registries\\.CARVER,",
|
||||
"replacement": "MappedRegistry<ConfiguredWorldCarver<?>> carvers = new MappedRegistry<>(Registries.CONFIGURED_CARVER,"
|
||||
},
|
||||
{
|
||||
"pattern": "\\]\\]\\}\";",
|
||||
"replacement": "]],\\\\\"spawners\\\\\":{},\\\\\"spawn_costs\\\\\":{}}\";"
|
||||
}
|
||||
],
|
||||
"art/arcane/iris/modded/ModdedTileParityTest.java": [
|
||||
{
|
||||
"pattern": "import net\\.minecraft\\.world\\.level\\.block\\.entity\\.SignTextSlot;\\n",
|
||||
"replacement": ""
|
||||
},
|
||||
{
|
||||
"pattern": "\\.getText\\(SignTextSlot\\.FRONT\\)",
|
||||
"replacement": ".getFrontText()"
|
||||
},
|
||||
{
|
||||
"pattern": "\\.getText\\(SignTextSlot\\.BACK\\)",
|
||||
"replacement": ".getBackText()"
|
||||
},
|
||||
{
|
||||
"pattern": "\\.getMessages\\(false\\)\\.get\\((\\d+)\\)",
|
||||
"replacement": ".getMessages(false)[$1]"
|
||||
}
|
||||
],
|
||||
"art/arcane/iris/modded/ModdedWaterEntitySpawnTest.java": [
|
||||
{
|
||||
"pattern": "(?ms)^ BuiltInRegistries\\.BLOCK\\.prepareTagReload\\(new TagLoader\\.LoadResult<>.*?\\)\\)\\)\\)\\.apply\\(\\);\\n",
|
||||
"replacement": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -168,13 +168,18 @@ dependencies {
|
||||
"art.arcane:core:${irisVersion}".toString(),
|
||||
"art.arcane:spi:${irisVersion}".toString(),
|
||||
libs.paralithic,
|
||||
libs.asm,
|
||||
libs.lru,
|
||||
libs.caffeine,
|
||||
'com.fulcrumgenomics:jlibdeflate:0.2.0',
|
||||
libs.dom4j,
|
||||
libs.jaxen
|
||||
]
|
||||
add('bundle', libs.asm)
|
||||
add('devBundle', 'org.ow2.asm:asm') {
|
||||
version {
|
||||
prefer(libs.versions.asm.get())
|
||||
}
|
||||
}
|
||||
shared.each { Object notation ->
|
||||
['bundle', 'devBundle'].each { String configuration ->
|
||||
add(configuration, notation) {
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package art.arcane.volmlib.nativelib.minecraft26_2.neoforge;
|
||||
|
||||
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedServerAccess;
|
||||
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedServerLevels;
|
||||
import art.arcane.volmlib.nativelib.modded.NativeLoaderOptions;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.junit.After;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class NativeNeoForgeServerAccessTest {
|
||||
private static final ResourceKey<Level> RUNTIME_DIMENSION =
|
||||
ResourceKey.create(Registries.DIMENSION, Identifier.fromNamespaceAndPath("irisworldgen", "runtime"));
|
||||
|
||||
@BeforeClass
|
||||
public static void bootstrap() {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@After
|
||||
public void forgetLevelSnapshot() {
|
||||
ModdedServerLevels.forget();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runtimeLevelsJoinAndLeaveTheServerTickView() throws ReflectiveOperationException {
|
||||
ModdedServerAccess access = new NativeNeoForgeLoader(
|
||||
new NativeLoaderOptions("irisworldgen", "treefeller", BooleanSupplier::getAsBoolean)).serverAccess();
|
||||
MinecraftServer server = serverWithLiveLevelMap();
|
||||
ServerLevel level = mock(ServerLevel.class);
|
||||
when(level.dimension()).thenReturn(RUNTIME_DIMENSION);
|
||||
|
||||
assertNull(access.putLevelIfAbsent(server, RUNTIME_DIMENSION, level));
|
||||
assertTrue(access.hasLevel(server, RUNTIME_DIMENSION));
|
||||
assertTrue(ticks(server, level));
|
||||
assertSame(level, ModdedServerLevels.level(server, RUNTIME_DIMENSION));
|
||||
|
||||
assertSame(level, access.removeLevel(server, RUNTIME_DIMENSION));
|
||||
assertFalse(access.hasLevel(server, RUNTIME_DIMENSION));
|
||||
assertFalse(ticks(server, level));
|
||||
assertNull(ModdedServerLevels.level(server, RUNTIME_DIMENSION));
|
||||
|
||||
assertNull(access.putLevel(server, RUNTIME_DIMENSION, level));
|
||||
assertTrue(ticks(server, level));
|
||||
assertSame(level, ModdedServerLevels.level(server, RUNTIME_DIMENSION));
|
||||
}
|
||||
|
||||
private static MinecraftServer serverWithLiveLevelMap() throws ReflectiveOperationException {
|
||||
MinecraftServer server = mock(MinecraftServer.class);
|
||||
Field levels = MinecraftServer.class.getDeclaredField("levels");
|
||||
levels.setAccessible(true);
|
||||
levels.set(server, new LinkedHashMap<ResourceKey<Level>, ServerLevel>());
|
||||
doCallRealMethod().when(server).getAllLevels();
|
||||
doCallRealMethod().when(server).markWorldsDirty();
|
||||
return server;
|
||||
}
|
||||
|
||||
private static boolean ticks(MinecraftServer server, ServerLevel expected) throws ReflectiveOperationException {
|
||||
Method worldArray = MinecraftServer.class.getDeclaredMethod("getWorldArray");
|
||||
worldArray.setAccessible(true);
|
||||
for (ServerLevel level : (ServerLevel[]) worldArray.invoke(server)) {
|
||||
if (level == expected) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+51
-1
@@ -22,6 +22,56 @@
|
||||
"fabricPermissions": "0.3.1",
|
||||
"slf4j": "2.0.9"
|
||||
},
|
||||
"26.1.2": {
|
||||
"java": 25,
|
||||
"fabricRemap": false,
|
||||
"fabricLoader": "0.19.5",
|
||||
"forge": "26.1.2-64.1.4",
|
||||
"forgeRange": "[64,65)",
|
||||
"neoForge": "26.1.2.116",
|
||||
"neoForgeRange": "[26.1.2,26.2)",
|
||||
"nativeAccess": "minecraft26_1_2",
|
||||
"overlays": [
|
||||
"26.2",
|
||||
"26.1.2"
|
||||
],
|
||||
"fabricModules": {
|
||||
"fabric-api-base": "2.0.3+ece063234c",
|
||||
"fabric-registry-sync-v0": "7.1.1+2fa62b4e4c",
|
||||
"fabric-resource-loader-v1": "2.0.10+7c44c7324c",
|
||||
"fabric-lifecycle-events-v1": "4.1.1+df84eb3d4c",
|
||||
"fabric-command-api-v2": "3.0.5+e2bdee784c",
|
||||
"fabric-events-interaction-v0": "5.2.3+07b380be4c",
|
||||
"fabric-networking-api-v1": "6.3.2+a217cccf4c",
|
||||
"fabric-rendering-v1": "23.3.1+e9207d814c",
|
||||
"fabric-key-mapping-api-v1": "2.0.4+e2bdee784c",
|
||||
"fabric-permission-api-v1": "1.0.3+5730ecca4c"
|
||||
},
|
||||
"slf4j": "2.0.17"
|
||||
},
|
||||
"26.2": {
|
||||
"java": 25,
|
||||
"fabricRemap": false,
|
||||
"fabricLoader": "0.19.5",
|
||||
"forge": "26.2-65.1.3",
|
||||
"forgeRange": "[65,66)",
|
||||
"neoForge": "26.2.0.89",
|
||||
"neoForgeRange": "[26.2,26.3)",
|
||||
"nativeAccess": "minecraft26_2",
|
||||
"fabricModules": {
|
||||
"fabric-api-base": "2.0.4+ece063239e",
|
||||
"fabric-registry-sync-v0": "7.1.1+c7bd5b8e9e",
|
||||
"fabric-resource-loader-v1": "2.0.13+9edec1269e",
|
||||
"fabric-lifecycle-events-v1": "4.1.4+29b6eb019e",
|
||||
"fabric-command-api-v2": "3.1.0+00cb03469e",
|
||||
"fabric-events-interaction-v0": "5.2.8+515ac5339e",
|
||||
"fabric-networking-api-v1": "6.3.4+2989c6a09e",
|
||||
"fabric-rendering-v1": "25.3.3+515ac5339e",
|
||||
"fabric-key-mapping-api-v1": "2.0.5+e2bdee789e",
|
||||
"fabric-permission-api-v1": "1.0.5+e442d8d09e"
|
||||
},
|
||||
"slf4j": "2.0.17"
|
||||
},
|
||||
"26.3": {
|
||||
"java": 25,
|
||||
"fabricRemap": false,
|
||||
@@ -30,7 +80,7 @@
|
||||
"forgeRange": "[66,67)",
|
||||
"neoForge": "26.3.0.83",
|
||||
"neoForgeRange": "[26.3.0.65-beta,26.4)",
|
||||
"nativeAccess": "minecraft26_2",
|
||||
"nativeAccess": "minecraft26_3",
|
||||
"slf4j": "2.0.17"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user