mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-29 07:20:22 +00:00
[VERY VERY VERY BAD IDEA]
This commit is contained in:
1 parent
f0e7fea13b
commit
2fa0853e42
892 files changed
+13482
-53554
No files matched your search
@@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
version = '1.0.0'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url = 'https://repo.papermc.io/repository/maven-public/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly files(providers.gradleProperty('irisJar').get())
|
||||
compileOnly 'io.papermc.paper:paper-api:26.1.2.build.74-stable'
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(25)
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['resources']
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.compilerArgs += '-parameters'
|
||||
}
|
||||
|
||||
tasks.named('jar') {
|
||||
archiveBaseName = 'IrisNativeLifecycleFixture'
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
name: IrisNativeLifecycleFixture
|
||||
version: 1.0.0
|
||||
main: art.arcane.iris.fixture.NativeLifecycleFixture
|
||||
api-version: '26.1.2'
|
||||
depend: [Iris]
|
||||
commands:
|
||||
irislifecycle:
|
||||
permission: irislifecycle.run
|
||||
permissions:
|
||||
irislifecycle.run:
|
||||
default: op
|
||||
@@ -0,0 +1 @@
|
||||
rootProject.name = 'iris-native-lifecycle-fixture'
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
package art.arcane.iris.fixture;
|
||||
|
||||
import art.arcane.volmlib.nativelib.NativeAdapters;
|
||||
import art.arcane.iris.world.runtime.RuntimeInjection;
|
||||
import art.arcane.iris.world.IrisCreator;
|
||||
import art.arcane.iris.world.IrisToolbelt;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Biome;
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeTerrainAccess;
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeStructureReader;
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeWorldRuntime;
|
||||
import art.arcane.volmlib.nativelib.terrain.WorldRuntimeExecution;
|
||||
import art.arcane.volmlib.nativelib.terrain.WorldRuntimeOptions;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public final class NativeLifecycleFixture extends JavaPlugin implements WorldRuntimeExecution {
|
||||
private static final NamespacedKey WORLD_KEY = NamespacedKey.minecraft("native_lifecycle_probe");
|
||||
private static final NamespacedKey TERRAIN_KEY = new NamespacedKey("iris", "native_terrain_probe");
|
||||
private static final long WORLD_SEED = 78264193L;
|
||||
private NativeWorldRuntime runtime;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
runtime = NativeAdapters.require(NativeWorldRuntime.class);
|
||||
NativeTerrainAccess terrain = NativeAdapters.require(NativeTerrainAccess.class);
|
||||
getLogger().info("Native lifecycle ready: " + runtime.description()
|
||||
+ "; terrain provider=" + terrain.getClass().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
return new ChunkGenerator() {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] arguments) {
|
||||
if (arguments.length != 1) {
|
||||
sender.sendMessage("Use /irislifecycle create|unload|status|structures|terrain-create|terrain-check|terrain-unload");
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
switch (arguments[0]) {
|
||||
case "create" -> create(sender);
|
||||
case "unload" -> unload(sender);
|
||||
case "structures" -> structures(sender);
|
||||
case "terrain-create" -> createTerrain(sender);
|
||||
case "terrain-check" -> checkTerrain(sender);
|
||||
case "terrain-unload" -> unloadTerrain(sender);
|
||||
case "status" -> sender.sendMessage("NATIVE_STATUS available=" + runtime.available()
|
||||
+ " loaded=" + (Bukkit.getWorld(WORLD_KEY) != null));
|
||||
default -> throw new IllegalArgumentException("Unknown lifecycle operation");
|
||||
}
|
||||
} catch (Throwable failure) {
|
||||
fail(sender, failure);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void create(CommandSender sender) throws ReflectiveOperationException {
|
||||
if (!runtime.available() || Bukkit.getWorld(WORLD_KEY) != null) {
|
||||
throw new IllegalStateException("Native runtime unavailable or probe world already loaded");
|
||||
}
|
||||
RuntimeInjection.installIfDeferred();
|
||||
WorldRuntimeOptions options = new WorldRuntimeOptions(WORLD_KEY.getKey(), WORLD_KEY,
|
||||
World.Environment.NORMAL, null, getName() + ":runtime", false, WORLD_SEED, false,
|
||||
Bukkit.getWorlds().getFirst().getWorldFolder());
|
||||
World world = runtime.create(options, this);
|
||||
if (!WORLD_KEY.equals(world.getKey()) || world.getSeed() != WORLD_SEED) {
|
||||
throw new IllegalStateException("World identity or seed differs from requested options");
|
||||
}
|
||||
world.getChunkAtAsync(0, 0, true).whenComplete((chunk, failure) -> runGlobal(() -> {
|
||||
if (failure != null) {
|
||||
fail(sender, failure);
|
||||
return;
|
||||
}
|
||||
if (chunk == null || chunk.getWorld() != world || !chunk.isLoaded()) {
|
||||
fail(sender, new IllegalStateException("Native runtime world failed chunk generation"));
|
||||
return;
|
||||
}
|
||||
sender.sendMessage("NATIVE_CREATED seed=" + world.getSeed() + " chunk=true");
|
||||
}));
|
||||
}
|
||||
|
||||
private void createTerrain(CommandSender sender) {
|
||||
if (Bukkit.getWorld(TERRAIN_KEY) != null) {
|
||||
throw new IllegalStateException("Terrain world is already loaded");
|
||||
}
|
||||
runAsync(() -> {
|
||||
try {
|
||||
new IrisCreator().name(TERRAIN_KEY.toString()).dimension("native-terrain")
|
||||
.seed(WORLD_SEED).create();
|
||||
runGlobal(() -> checkTerrain(sender));
|
||||
} catch (Throwable failure) {
|
||||
runGlobal(() -> fail(sender, failure));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkTerrain(CommandSender sender) {
|
||||
World world = Bukkit.getWorld(TERRAIN_KEY);
|
||||
if (world == null || world.getSeed() != WORLD_SEED || !IrisToolbelt.isIrisWorld(world)
|
||||
|| IrisToolbelt.access(world).getEngine() == null) {
|
||||
throw new IllegalStateException("Iris terrain engine or world identity is absent");
|
||||
}
|
||||
world.getChunkAtAsync(2, -3, true).whenComplete((chunk, failure) -> runGlobal(() -> {
|
||||
if (failure != null) {
|
||||
fail(sender, failure);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int columns = 0;
|
||||
for (int x = 32; x < 48; x += 5) {
|
||||
for (int z = -48; z < -32; z += 5) {
|
||||
int y = world.getHighestBlockYAt(x, z);
|
||||
if (y < 90 || y > 100 || world.getBlockAt(x, y, z).getType() != Material.LIME_WOOL
|
||||
|| world.getBlockAt(x, y - 3, z).getType() != Material.GREEN_CONCRETE
|
||||
|| world.getBiome(x, y, z) != Biome.PLAINS) {
|
||||
throw new IllegalStateException("Terrain column differs at " + x + "," + y + "," + z
|
||||
+ ": " + world.getBlockAt(x, y, z).getType());
|
||||
}
|
||||
columns++;
|
||||
}
|
||||
}
|
||||
sender.sendMessage("NATIVE_TERRAIN seed=" + world.getSeed() + " columns=" + columns + " biome=plains");
|
||||
} catch (Throwable assertion) {
|
||||
fail(sender, assertion);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void unloadTerrain(CommandSender sender) {
|
||||
World world = Bukkit.getWorld(TERRAIN_KEY);
|
||||
if (world == null) {
|
||||
throw new IllegalStateException("Terrain world is absent");
|
||||
}
|
||||
runtime.unload(world, true, this).whenComplete((unloaded, failure) -> runGlobal(() -> {
|
||||
if (failure != null) {
|
||||
fail(sender, failure);
|
||||
} else if (!Boolean.TRUE.equals(unloaded) || Bukkit.getWorld(TERRAIN_KEY) != null) {
|
||||
fail(sender, new IllegalStateException("Terrain world did not unload"));
|
||||
} else {
|
||||
sender.sendMessage("NATIVE_TERRAIN_UNLOADED true");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void structures(CommandSender sender) throws Exception {
|
||||
NativeStructureReader reader = NativeAdapters.require(NativeStructureReader.class);
|
||||
List<String> templates = reader.templates();
|
||||
if (!templates.contains("minecraft:village/plains/town_centers/plains_fountain_01")) {
|
||||
throw new IllegalStateException("Vanilla village template was not enumerated");
|
||||
}
|
||||
NativeStructureReader.Session session = reader.open();
|
||||
NativeStructureReader.Structure village = session.structure("minecraft:village_plains");
|
||||
if (village == null || !village.jigsaw() || village.maxDepth() <= 0
|
||||
|| village.maxDistanceFromCenter() <= 0) {
|
||||
throw new IllegalStateException("Vanilla village metadata is missing");
|
||||
}
|
||||
NativeStructureReader.Pool pool = session.pool(village.startPoolKey());
|
||||
if (pool == null || !"minecraft:empty".equals(pool.fallbackKey()) || pool.entries().isEmpty()) {
|
||||
throw new IllegalStateException("Vanilla village start pool is missing");
|
||||
}
|
||||
int connectorCount = 0;
|
||||
for (NativeStructureReader.Entry entry : pool.entries()) {
|
||||
NativeStructureReader.Element element = entry.element();
|
||||
if (entry.weight() <= 0 || element == null || element.templateLocation() == null) {
|
||||
throw new IllegalStateException("Vanilla village pool element is invalid");
|
||||
}
|
||||
NativeStructureReader.ConnectorSet connectors = element.connectors(() -> 91L);
|
||||
if (connectors.status() != NativeStructureReader.ConnectorStatus.AVAILABLE) {
|
||||
throw new IllegalStateException("Vanilla village connectors unavailable");
|
||||
}
|
||||
for (NativeStructureReader.Connector connector : connectors.connectors()) {
|
||||
NativeStructureReader.ConnectorData data = connector.read();
|
||||
if (data.front() == null || data.top() == null || data.pool() == null
|
||||
|| data.metadata().finalState() == null) {
|
||||
throw new IllegalStateException("Vanilla village connector metadata is incomplete");
|
||||
}
|
||||
connectorCount++;
|
||||
}
|
||||
}
|
||||
if (connectorCount == 0) {
|
||||
throw new IllegalStateException("Vanilla village pool has no connectors");
|
||||
}
|
||||
sender.sendMessage("NATIVE_STRUCTURES templates=" + templates.size() + " village=true connectors=" + connectorCount);
|
||||
}
|
||||
|
||||
private void unload(CommandSender sender) {
|
||||
World world = Bukkit.getWorld(WORLD_KEY);
|
||||
if (world == null) {
|
||||
throw new IllegalStateException("Probe world is absent");
|
||||
}
|
||||
runtime.unload(world, true, this).whenComplete((unloaded, failure) -> runGlobal(() -> {
|
||||
if (failure != null) {
|
||||
fail(sender, failure);
|
||||
} else if (!Boolean.TRUE.equals(unloaded) || Bukkit.getWorld(WORLD_KEY) != null) {
|
||||
fail(sender, new IllegalStateException("Native unload did not remove the world"));
|
||||
} else {
|
||||
sender.sendMessage("NATIVE_UNLOADED true");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public boolean regionized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean primaryThread() {
|
||||
return Bukkit.isPrimaryThread();
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> runGlobal(Runnable task) {
|
||||
CompletableFuture<Void> result = new CompletableFuture<>();
|
||||
Runnable wrapped = () -> {
|
||||
try {
|
||||
task.run();
|
||||
result.complete(null);
|
||||
} catch (Throwable failure) {
|
||||
result.completeExceptionally(failure);
|
||||
}
|
||||
};
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
wrapped.run();
|
||||
} else {
|
||||
Bukkit.getScheduler().runTask(this, wrapped);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> runAsync(Runnable task) {
|
||||
return CompletableFuture.runAsync(task);
|
||||
}
|
||||
|
||||
public void reportFailure(String message, Throwable failure) {
|
||||
getLogger().log(Level.SEVERE, message, failure);
|
||||
}
|
||||
|
||||
private void fail(CommandSender sender, Throwable failure) {
|
||||
reportFailure("Native lifecycle assertion failed", failure);
|
||||
sender.sendMessage("NATIVE_FAILED " + failure.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
export default {
|
||||
name: 'iris-native-lifecycle',
|
||||
description: 'Verify native structure metadata, runtime world creation, seeded chunk generation, and asynchronous unload.',
|
||||
async run(context) {
|
||||
await context.step('native world capability is available', async () => {
|
||||
await context.command('/irislifecycle status', /NATIVE_STATUS available=true loaded=false/, 10000)
|
||||
})
|
||||
await context.step('read vanilla templates, village pools, and connector metadata', async () => {
|
||||
const response = await context.command('/irislifecycle structures', /NATIVE_STRUCTURES|NATIVE_FAILED/, 30000)
|
||||
context.expect(/NATIVE_STRUCTURES templates=\d+ village=true connectors=[1-9]\d*/.test(response), response)
|
||||
})
|
||||
await context.step('create a world with the requested seed and generate a chunk', async () => {
|
||||
const response = await context.command('/irislifecycle create', /NATIVE_CREATED|NATIVE_FAILED/, 90000)
|
||||
context.expect(response.includes('NATIVE_CREATED seed=78264193 chunk=true'), response)
|
||||
})
|
||||
await context.step('unload and detach the created world', async () => {
|
||||
const response = await context.command('/irislifecycle unload', /NATIVE_UNLOADED|NATIVE_FAILED/, 90000)
|
||||
context.expect(response.includes('NATIVE_UNLOADED true'), response)
|
||||
await context.command('/irislifecycle status', /NATIVE_STATUS available=true loaded=false/, 10000)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "Flat",
|
||||
"derivative": "minecraft:plains",
|
||||
"vanillaDerivative": "minecraft:plains",
|
||||
"layers": [
|
||||
{
|
||||
"minHeight": 1,
|
||||
"maxHeight": 1,
|
||||
"palette": [
|
||||
{
|
||||
"block": "minecraft:lime_wool"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"generators": [
|
||||
{
|
||||
"generator": "flat",
|
||||
"min": 96,
|
||||
"max": 96
|
||||
}
|
||||
]
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "Native Terrain",
|
||||
"version": 1,
|
||||
"mode": {
|
||||
"type": "OVERWORLD"
|
||||
},
|
||||
"regions": [
|
||||
"flat"
|
||||
],
|
||||
"focusRegion": "flat",
|
||||
"focus": "flat",
|
||||
"landChance": 1,
|
||||
"environment": "NORMAL",
|
||||
"dimensionHeight": {
|
||||
"min": -64,
|
||||
"max": 320
|
||||
},
|
||||
"logicalHeight": 384,
|
||||
"fluidHeight": 0,
|
||||
"bedrock": false,
|
||||
"rockPalette": {
|
||||
"palette": [
|
||||
{
|
||||
"block": "minecraft:green_concrete"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"interpolator": {
|
||||
"function": "NONE",
|
||||
"horizontalScale": 1
|
||||
},
|
||||
"seed": 310,
|
||||
"composite": [
|
||||
{
|
||||
"seed": 310,
|
||||
"style": {
|
||||
"style": "FLAT"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Flat",
|
||||
"landBiomes": [
|
||||
"flat"
|
||||
],
|
||||
"seaBiomes": [
|
||||
"flat"
|
||||
],
|
||||
"shoreBiomes": [
|
||||
"flat"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export default {
|
||||
name: 'iris-native-terrain',
|
||||
description: 'Generate an Iris pack through the shared native adapter and verify terrain, biome, seed, and unload.',
|
||||
async run(context) {
|
||||
await context.step('create a real Iris terrain world', async () => {
|
||||
const response = await context.command('/irislifecycle terrain-create', /NATIVE_TERRAIN seed=|NATIVE_FAILED/, 180000)
|
||||
context.expect(response.includes('NATIVE_TERRAIN seed=78264193 columns=16 biome=plains'), response)
|
||||
})
|
||||
await context.step('read generated terrain again', async () => {
|
||||
const response = await context.command('/irislifecycle terrain-check', /NATIVE_TERRAIN seed=|NATIVE_FAILED/, 60000)
|
||||
context.expect(response.includes('NATIVE_TERRAIN seed=78264193 columns=16 biome=plains'), response)
|
||||
})
|
||||
await context.step('save and unload the terrain world', async () => {
|
||||
const response = await context.command('/irislifecycle terrain-unload', /NATIVE_TERRAIN_UNLOADED|NATIVE_FAILED/, 90000)
|
||||
context.expect(response.includes('NATIVE_TERRAIN_UNLOADED true'), response)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user