mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-25 13:30:08 +00:00
Preserved historical biome behavior
- Generated chunks retain surface and vertical biome assignments - Floating biome assignments persist through terrain transitions - Archived pack definitions remain available for saved biome rules - Spawns and effects use each saved biome environment - Saved biome lookups load asynchronously with bounded caches - Missing biome identities recover only from exact recorded evidence - Effects and entity placement follow existing world surfaces - New pack fingerprints ignore Finder metadata - Tests cover biome storage, recovery, consumers, and scoped definitions
This commit is contained in:
1 parent
d10d70a894
commit
b17fe811f3
57 files changed
+4460
-385
No files matched your search
+11
-7
@@ -600,7 +600,8 @@ public final class IrisWorldGeneratorResolver {
|
||||
throw new IllegalStateException("Immutable Iris generation pack at " + packRoot
|
||||
+ " does not contain dimension " + dimensionKey + ".");
|
||||
}
|
||||
GenerationEpoch.DimensionContract actualContract = captureDimensionContract(data, dimension);
|
||||
GenerationEpoch.DimensionContract actualContract = GenerationEpochContractFactory.createForEpoch(
|
||||
dimension, dimensionTypeKey(data, dimension), epoch);
|
||||
if (!epoch.dimensionContract().equals(actualContract)) {
|
||||
throw new IllegalStateException("Immutable Iris generation pack dimension contract changed at "
|
||||
+ packRoot + ".");
|
||||
@@ -612,7 +613,15 @@ public final class IrisWorldGeneratorResolver {
|
||||
IrisData data,
|
||||
IrisDimension dimension
|
||||
) {
|
||||
String dimensionTypeKey = IrisPlatforms.get()
|
||||
return GenerationEpochContractFactory.create(
|
||||
dimension,
|
||||
dimension.getLoadKey(),
|
||||
dimensionTypeKey(data, dimension)
|
||||
);
|
||||
}
|
||||
|
||||
private static String dimensionTypeKey(IrisData data, IrisDimension dimension) {
|
||||
return IrisPlatforms.get()
|
||||
.registries()
|
||||
.generationRegistry()
|
||||
.dimensionTypeResourceKey(
|
||||
@@ -620,11 +629,6 @@ public final class IrisWorldGeneratorResolver {
|
||||
dimension.getLoadKey(),
|
||||
dimension.getDimensionTypeKey()
|
||||
);
|
||||
return GenerationEpochContractFactory.create(
|
||||
dimension,
|
||||
dimension.getLoadKey(),
|
||||
dimensionTypeKey
|
||||
);
|
||||
}
|
||||
|
||||
private static File requireActivePack(GenerationHistory history) {
|
||||
|
||||
+28
-5
@@ -31,6 +31,7 @@ import art.arcane.iris.engine.framework.GenerationSessionLease;
|
||||
import art.arcane.iris.engine.platform.EngineBukkitOps;
|
||||
import art.arcane.iris.util.project.context.IrisContext;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.history.SavedBiomeUnavailableException;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.util.common.director.DirectorExecutor;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
@@ -82,21 +83,36 @@ public class CommandWhat implements DirectorExecutor {
|
||||
|
||||
@Director(description = "What biome am i in?", descriptionKey = "iris.director.commandwhat.director.what_biome_am_i", origin = DirectorOrigin.PLAYER)
|
||||
public void biome() {
|
||||
VolmitSender commandSender = sender();
|
||||
Player player = player();
|
||||
onPlayerThread(player, () -> describeBiome(commandSender, player));
|
||||
}
|
||||
|
||||
private void describeBiome(VolmitSender commandSender, Player player) {
|
||||
Location location = player.getLocation();
|
||||
try {
|
||||
IrisBiome b = engine().getBiome(player().getLocation().getBlockX(), player().getLocation().getBlockY() - player().getWorld().getMinHeight(), player().getLocation().getBlockZ());
|
||||
Engine engine = IrisToolbelt.access(location.getWorld()).getEngine();
|
||||
IrisBiome b = engine.getBiome(location.getBlockX(), location.getBlockY() - location.getWorld().getMinHeight(), location.getBlockZ());
|
||||
Biome derivative = b.getDerivative();
|
||||
NamespacedKey derivativeKey = resolveBiomeKey(derivative);
|
||||
sender().sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_IBIOME, MessageArgument.untrusted("value", b.getLoadKey()), MessageArgument.untrusted("value2", derivativeKey == null ? IrisLanguage.plain(RuntimeUiMessages.STATUS_UNREGISTERED) : derivativeKey.getKey())));
|
||||
commandSender.sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_IBIOME, MessageArgument.untrusted("value", b.getLoadKey()), MessageArgument.untrusted("value2", derivativeKey == null ? IrisLanguage.plain(RuntimeUiMessages.STATUS_UNREGISTERED) : derivativeKey.getKey())));
|
||||
|
||||
} catch (SavedBiomeUnavailableException e) {
|
||||
if (e.getCause() != null) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
commandSender.sendMessage(e.isLoading()
|
||||
? "Saved biome data is loading. Run the command again shortly."
|
||||
: e.getMessage());
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Biome biome = player().getLocation().getBlock().getBiome();
|
||||
Biome biome = location.getBlock().getBiome();
|
||||
NamespacedKey key = resolveBiomeKey(biome);
|
||||
sender().sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_NON_IRIS_BIOME, MessageArgument.untrusted("value", key == null ? IrisLanguage.plain(RuntimeUiMessages.STATUS_UNREGISTERED) : key)));
|
||||
commandSender.sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_NON_IRIS_BIOME, MessageArgument.untrusted("value", key == null ? IrisLanguage.plain(RuntimeUiMessages.STATUS_UNREGISTERED) : key)));
|
||||
|
||||
if (key == null || key.getKey().equals("custom")) {
|
||||
try {
|
||||
sender().sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_DATA_PACK_BIOME_ID, MessageArgument.untrusted("value", INMS.get().getTrueBiomeBaseKey(player().getLocation())), MessageArgument.untrusted("value2", INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())))));
|
||||
commandSender.sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_DATA_PACK_BIOME_ID, MessageArgument.untrusted("value", INMS.get().getTrueBiomeBaseKey(location)), MessageArgument.untrusted("value2", INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(location)))));
|
||||
} catch (Throwable ee) {
|
||||
Iris.reportError(ee);
|
||||
}
|
||||
@@ -118,6 +134,13 @@ public class CommandWhat implements DirectorExecutor {
|
||||
IrisRegion r = EngineBukkitOps.getRegion(engine, chunk);
|
||||
commandSender.sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_IREGION, MessageArgument.untrusted("value", r.getLoadKey()), MessageArgument.untrusted("value2", r.getName())));
|
||||
|
||||
} catch (SavedBiomeUnavailableException e) {
|
||||
if (e.getCause() != null) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
commandSender.sendMessage(e.isLoading()
|
||||
? "Saved biome data is loading. Run the command again shortly."
|
||||
: e.getMessage());
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
commandSender.sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_WHAT_IRIS_WORLDS_ONLY));
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package art.arcane.iris.core.commands;
|
||||
|
||||
import art.arcane.iris.core.localization.BukkitCommandMessagesExtended;
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.platform.PlatformChunkGenerator;
|
||||
import art.arcane.iris.util.common.director.DirectorContext;
|
||||
import art.arcane.iris.util.common.plugin.VolmitSender;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.junit.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class CommandWhatBiomeTest {
|
||||
@Test
|
||||
public void scheduledBiomeDescriptionUsesThePlayersWorldAfterCommandContextClears() {
|
||||
VolmitSender sender = mock(VolmitSender.class);
|
||||
Player player = mock(Player.class);
|
||||
World world = mock(World.class);
|
||||
Engine engine = mock(Engine.class);
|
||||
PlatformChunkGenerator generator = mock(PlatformChunkGenerator.class);
|
||||
IrisBiome biome = mock(IrisBiome.class);
|
||||
AtomicReference<Runnable> scheduled = new AtomicReference<>();
|
||||
when(sender.player()).thenReturn(player);
|
||||
when(sender.isPlayer()).thenReturn(true);
|
||||
when(player.getWorld()).thenReturn(world);
|
||||
when(player.getLocation()).thenReturn(new Location(world, 19, 70, -3));
|
||||
when(world.getMinHeight()).thenReturn(-64);
|
||||
when(generator.getEngine()).thenReturn(engine);
|
||||
when(engine.getBiome(19, 134, -3)).thenReturn(biome);
|
||||
when(biome.getLoadKey()).thenReturn("retained-flat");
|
||||
try (MockedStatic<J> scheduler = mockStatic(J.class);
|
||||
MockedStatic<IrisToolbelt> toolbelt = mockStatic(IrisToolbelt.class);
|
||||
MockedStatic<IrisLanguage> language = mockStatic(IrisLanguage.class)) {
|
||||
scheduler.when(() -> J.runEntity(eq(player), any(Runnable.class))).thenAnswer(invocation -> {
|
||||
scheduled.set(invocation.getArgument(1));
|
||||
return true;
|
||||
});
|
||||
toolbelt.when(() -> IrisToolbelt.access(world)).thenReturn(generator);
|
||||
language.when(() -> IrisLanguage.plain(RuntimeUiMessages.STATUS_UNREGISTERED)).thenReturn("unregistered");
|
||||
language.when(() -> IrisLanguage.text(eq(BukkitCommandMessagesExtended.COMMAND_WHAT_IBIOME),
|
||||
any(MessageArgument.class), any(MessageArgument.class))).thenReturn("Iris biome: retained-flat");
|
||||
DirectorContext.touch(sender);
|
||||
try {
|
||||
new CommandWhat().biome();
|
||||
} finally {
|
||||
DirectorContext.remove();
|
||||
}
|
||||
assertNull(DirectorContext.get());
|
||||
assertNotNull(scheduled.get());
|
||||
verifyNoInteractions(engine);
|
||||
|
||||
scheduled.get().run();
|
||||
|
||||
verify(engine).getBiome(19, 134, -3);
|
||||
verify(sender).sendMessage("Iris biome: retained-flat");
|
||||
verify(world, never()).getBlockAt(anyInt(), anyInt(), anyInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user