updated spirit apple texture

fixed tigers eye shrine broken
credit russian lang
fixed queen music handler
fixed permanent portals not placing corners and not finding exisitng portals
fixed keybind conflict sprint conflicts
added back cloud sea
This commit is contained in:
craisinlord committed 2026-09-21 18:47:14 -05:00
1 parent 93e2adbe12
commit 6e12612559
30 files changed
+460 -452

No files matched your search

@@ -285,6 +285,10 @@ public final class AntarchySettings {
private static int queenBlackHoleActiveTicks = 120;
private static double queenBlackHolePullStrength = 0.16D;
private static int queenBlackHoleBlockSuctionCap = 160;
private static double axeBlackHoleRadius = 28.0D;
private static int axeBlackHoleActiveTicks = 120;
private static double axeBlackHolePullStrength = 0.16D;
private static int axeBlackHoleBlockSuctionCap = 160;
private static double kingFireballDamage = 48.0D;
private static double kingFireballRadius = 4.5D;
private static int kingFireballCooldownTicks = 150;
@@ -576,8 +580,8 @@ public final class AntarchySettings {
private static double crawlingBlightAttackDamage = 6.0D;
private static double skulkingFrightHealth = 15.0D;
private static double skulkingFrightAttackDamage = 6.0D;
private static double manticoreHealth = 40.0D;
private static double manticoreAttackDamage = 7.0D;
private static double manticoreHealth = 60.0D;
private static double manticoreAttackDamage = 11.0D;
private static int manticoreStingPoisonTicks = 100;
private static int queenManticoreCap = 15;
private static int queenManticoreSummonCooldownTicks = 800;
@@ -2167,6 +2171,14 @@ public final class AntarchySettings {
public static void setQueenBlackHolePullStrength(double v) { queenBlackHolePullStrength = v; }
public static int queenBlackHoleBlockSuctionCap() { return queenBlackHoleBlockSuctionCap; }
public static void setQueenBlackHoleBlockSuctionCap(int v) { queenBlackHoleBlockSuctionCap = v; }
public static double axeBlackHoleRadius() { return axeBlackHoleRadius; }
public static void setAxeBlackHoleRadius(double v) { axeBlackHoleRadius = v; }
public static int axeBlackHoleActiveTicks() { return axeBlackHoleActiveTicks; }
public static void setAxeBlackHoleActiveTicks(int v) { axeBlackHoleActiveTicks = v; }
public static double axeBlackHolePullStrength() { return axeBlackHolePullStrength; }
public static void setAxeBlackHolePullStrength(double v) { axeBlackHolePullStrength = v; }
public static int axeBlackHoleBlockSuctionCap() { return axeBlackHoleBlockSuctionCap; }
public static void setAxeBlackHoleBlockSuctionCap(int v) { axeBlackHoleBlockSuctionCap = v; }
public static double kingFireballDamage() { return kingFireballDamage; }
public static void setKingFireballDamage(double v) { kingFireballDamage = v; }
public static double kingFireballRadius() { return kingFireballRadius; }
@@ -18,7 +18,6 @@ public final class QueenMusicHandler {
private static final int RESTART_COOLDOWN_TICKS = 100;
private static QueenMusicSound music;
private static int cooldownTicks;
private static boolean wasInEncounter;
private QueenMusicHandler() {
}
@@ -38,21 +37,16 @@ public final class QueenMusicHandler {
QueenEntity queen = minecraft.level.getEntitiesOfClass(
QueenEntity.class,
minecraft.player.getBoundingBox().inflate(STOP_RADIUS),
QueenEntity::shouldPlayQueenMusic
entity -> entity.isQueenMusicActive() || entity.shouldPlayQueenMusic()
).stream()
.min(Comparator.comparingDouble(entity -> entity.distanceToSqr(minecraft.player)))
.orElse(null);
if (queen == null) {
stop(minecraft);
if (wasInEncounter) {
cooldownTicks = Math.max(cooldownTicks, RESTART_COOLDOWN_TICKS);
}
wasInEncounter = false;
return;
}
wasInEncounter = true;
if (music != null && !minecraft.getSoundManager().isActive(music)) {
music = null;
cooldownTicks = Math.max(cooldownTicks, RESTART_COOLDOWN_TICKS);
@@ -82,7 +76,6 @@ public final class QueenMusicHandler {
private static void reset(Minecraft minecraft) {
stop(minecraft);
cooldownTicks = 0;
wasInEncounter = false;
}
private static final class QueenMusicSound extends AbstractTickableSoundInstance {
@@ -650,6 +650,9 @@ public final class CreativeTabContents {
public static boolean populateNeoForgeVanillaTab(ResourceKey<CreativeModeTab> tabKey, HolderLookup.Provider holders,
NeoForgeVanillaTabOutput output) {
if (!ResourceLocation.DEFAULT_NAMESPACE.equals(tabKey.location().getNamespace())) {
return false;
}
String tabPath = tabKey.location().getPath();
boolean matched = false;
for (CatalogEntry entry : CATALOG) {
@@ -59,7 +59,6 @@ import software.bernie.geckolib.util.GeckoLibUtil;
public class ManticoreEntity extends Monster implements GeoEntity {
private static final String SUMMONER_KEY = "QueenSummoner";
private static final String PLAYER_SUMMONER_KEY = "PlayerSummoner";
private static final String PLAYER_SUMMON_LIFETIME_KEY = "PlayerSummonLifetime";
private static final int LOST_SUMMONER_GRACE_TICKS = 200;
private static final int TAKEOFF_COOLDOWN_TICKS = 40;
private static final int STING_COOLDOWN_TICKS = 60;
@@ -81,8 +80,6 @@ public class ManticoreEntity extends Monster implements GeoEntity {
private UUID summonerId;
@Nullable
private UUID playerSummonerId;
private int playerSummonLifetime;
private int playerSummonAge;
private int lostSummonerTicks;
private int takeoffCooldown;
private int stingCooldown;
@@ -102,8 +99,8 @@ public class ManticoreEntity extends Monster implements GeoEntity {
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, AntarchySettings.manticoreHealth())
.add(Attributes.MOVEMENT_SPEED, 0.45D)
.add(Attributes.FLYING_SPEED, 2.0D)
.add(Attributes.MOVEMENT_SPEED, 0.55D)
.add(Attributes.FLYING_SPEED, 2.6D)
.add(Attributes.ATTACK_DAMAGE, AntarchySettings.manticoreAttackDamage())
.add(Attributes.FOLLOW_RANGE, 28.0D)
.add(Attributes.KNOCKBACK_RESISTANCE, 0.2D);
@@ -161,11 +158,9 @@ public class ManticoreEntity extends Monster implements GeoEntity {
this.setPersistenceRequired();
}
public void markPlayerSummoned(UUID playerId, int lifetimeTicks) {
public void markPlayerSummoned(UUID playerId) {
this.playerSummonerId = playerId;
this.summonerId = null;
this.playerSummonLifetime = lifetimeTicks;
this.playerSummonAge = 0;
this.lostSummonerTicks = 0;
this.setPersistenceRequired();
}
@@ -202,7 +197,7 @@ public class ManticoreEntity extends Monster implements GeoEntity {
@Override
public boolean removeWhenFarAway(double distanceToClosestPlayer) {
return this.summonerId == null && super.removeWhenFarAway(distanceToClosestPlayer);
return this.summonerId == null && this.playerSummonerId == null && super.removeWhenFarAway(distanceToClosestPlayer);
}
@Override
@@ -236,8 +231,9 @@ public class ManticoreEntity extends Monster implements GeoEntity {
}
this.tickQueenSummonCleanup();
this.tickPlayerSummonCleanup();
this.tickPlayerSummon();
this.tickPlayerSummonTarget();
this.tickQueenSummonTarget();
LivingEntity target = this.getTarget();
@@ -252,17 +248,12 @@ public class ManticoreEntity extends Monster implements GeoEntity {
}
}
private void tickPlayerSummon() {
private void tickPlayerSummonTarget() {
if (this.playerSummonerId == null || !(this.level() instanceof ServerLevel serverLevel)) {
return;
}
if (++this.playerSummonAge >= this.playerSummonLifetime) {
this.discard();
return;
}
Entity entity = serverLevel.getEntity(this.playerSummonerId);
if (!(entity instanceof Player player) || !player.isAlive()) {
this.discard();
return;
}
LivingEntity target = player.getLastHurtMob();
@@ -328,6 +319,20 @@ public class ManticoreEntity extends Monster implements GeoEntity {
}
}
private void tickPlayerSummonCleanup() {
if (this.playerSummonerId == null || !(this.level() instanceof ServerLevel serverLevel)) {
return;
}
Entity summoner = serverLevel.getEntity(this.playerSummonerId);
if (summoner instanceof Player player && player.isAlive()) {
this.lostSummonerTicks = 0;
return;
}
if (++this.lostSummonerTicks > LOST_SUMMONER_GRACE_TICKS) {
this.discard();
}
}
private void takeoff() {
this.takeoffCooldown = TAKEOFF_COOLDOWN_TICKS;
this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.55D, 0.0D));
@@ -461,7 +466,6 @@ public class ManticoreEntity extends Monster implements GeoEntity {
}
if (this.playerSummonerId != null) {
tag.putUUID(PLAYER_SUMMONER_KEY, this.playerSummonerId);
tag.putInt(PLAYER_SUMMON_LIFETIME_KEY, this.playerSummonLifetime);
}
}
@@ -470,8 +474,6 @@ public class ManticoreEntity extends Monster implements GeoEntity {
super.readAdditionalSaveData(tag);
this.summonerId = tag.hasUUID(SUMMONER_KEY) ? tag.getUUID(SUMMONER_KEY) : null;
this.playerSummonerId = tag.hasUUID(PLAYER_SUMMONER_KEY) ? tag.getUUID(PLAYER_SUMMONER_KEY) : null;
this.playerSummonLifetime = tag.getInt(PLAYER_SUMMON_LIFETIME_KEY);
this.playerSummonAge = 0;
this.lostSummonerTicks = 0;
}
@@ -12,9 +12,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance;
import net.minecraft.client.sounds.SoundManager;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
@@ -79,8 +76,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
private static final Map<UUID, Set<UUID>> QUEEN_TEAR_IDS = new HashMap<>();
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
@Nullable
private TearIdleSoundInstance idleSound;
private UUID linkedTearId;
@Nullable
private DimensionalTearEntity linkedTear;
@@ -147,7 +142,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
super.tick();
if (this.level().isClientSide) {
this.tickClientParticles();
this.tickIdleSound();
return;
}
@@ -295,12 +289,12 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
continue;
}
manticore.finalizeSpawn(level, level.getCurrentDifficultyAt(BlockPos.containing(exit)), MobSpawnType.MOB_SUMMONED, null);
manticore.markPlayerSummoned(player.getUUID(), 20 * 30);
manticore.markPlayerSummoned(player.getUUID());
if (player.getLastHurtMob() != null && player.getLastHurtMob().isAlive()) {
manticore.setTarget(player.getLastHurtMob());
}
manticore.setDeltaMovement(this.getViewVector(1.0F).scale(0.2D).add(0.0D, 0.08D, 0.0D));
manticore.setNoGravity(true);
manticore.setDeltaMovement(this.getViewVector(1.0F).scale(0.7D).add(0.0D, 0.18D, 0.0D));
manticore.setNoGravity(false);
level.addFreshEntity(manticore);
}
}
@@ -439,16 +433,8 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
this.entityData.set(STATE, state.ordinal());
}
private void tickIdleSound() {
SoundManager soundManager = Minecraft.getInstance().getSoundManager();
if (this.getTearState() == TearState.OPENING) {
return;
}
if (this.idleSound != null && soundManager.isActive(this.idleSound)) {
return;
}
this.idleSound = new TearIdleSoundInstance(this);
soundManager.play(this.idleSound);
public boolean shouldPlayIdleSound() {
return this.getTearState() != TearState.OPENING;
}
private void tickClientParticles() {
@@ -572,36 +558,4 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
private static final class TearIdleSoundInstance extends AbstractTickableSoundInstance {
private final DimensionalTearEntity tear;
private TearIdleSoundInstance(DimensionalTearEntity tear) {
super(AntarchySoundEvents.DIMENSIONAL_TEAR_IDLE.get(), SoundSource.HOSTILE, tear.random);
this.tear = tear;
this.looping = true;
this.delay = 0;
this.volume = 0.6F;
this.pitch = 1.0F;
this.x = tear.getX();
this.y = tear.getY();
this.z = tear.getZ();
}
@Override
public void tick() {
if (this.tear.isRemoved() || this.tear.getTearState() == TearState.COLLAPSING) {
this.stop();
return;
}
this.x = this.tear.getX();
this.y = this.tear.getY();
this.z = this.tear.getZ();
}
@Override
public boolean canStartSilent() {
return true;
}
}
}
@@ -24,6 +24,9 @@ import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@@ -59,6 +62,8 @@ import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.Nullable;
public class QueenEntity extends RoyalBossEntity {
private static final EntityDataAccessor<Boolean> QUEEN_MUSIC_ACTIVE =
SynchedEntityData.defineId(QueenEntity.class, EntityDataSerializers.BOOLEAN);
static final double TIME_FIELD_RADIUS_SCALE = 3.0D;
private static final String SUMMON_COOLDOWN_KEY = "ManticoreSummonCooldownTicks";
private static final int FAILED_SUMMON_RETRY_TICKS = 20;
@@ -196,6 +201,12 @@ public class QueenEntity extends RoyalBossEntity {
super(entityType, level);
}
@Override
protected void defineSynchedData(SynchedEntityData.Builder builder) {
super.defineSynchedData(builder);
builder.define(QUEEN_MUSIC_ACTIVE, false);
}
public static AttributeSupplier.Builder createAttributes() {
return createBaseAttributes(AntarchySettings.queenHealth(), AntarchySettings.queenAttackDamage());
}
@@ -348,6 +359,10 @@ public class QueenEntity extends RoyalBossEntity {
return !this.isDeadOrDying() && target != null && target.isAlive() && this.canAttack(target);
}
public boolean isQueenMusicActive() {
return this.entityData.get(QUEEN_MUSIC_ACTIVE);
}
@Override
protected SoundEvent royalFlyLoopSound() {
return AntarchySoundEvents.QUEEN_FLY_LOOP.get();
@@ -442,6 +457,9 @@ public class QueenEntity extends RoyalBossEntity {
@Override
public void tick() {
super.tick();
if (!this.level().isClientSide) {
this.entityData.set(QUEEN_MUSIC_ACTIVE, this.shouldPlayQueenMusic());
}
if (this.level().isClientSide || this.isDeadOrDying()) {
return;
}
@@ -17,8 +17,8 @@ public final class RoyalAssailantBlackHoleEntity extends RoyalBlackHoleEntity {
public static RoyalAssailantBlackHoleEntity create(ServerLevel level, Vec3 center, @Nullable UUID ownerId) {
RoyalAssailantBlackHoleEntity hole = new RoyalAssailantBlackHoleEntity(
AntarchyObjects.ROYAL_ASSAILANT_BLACK_HOLE.get(), level);
hole.configure(center, AntarchySettings.queenBlackHoleRadius(),
AntarchySettings.queenBlackHoleActiveTicks(), ownerId);
hole.configure(center, AntarchySettings.axeBlackHoleRadius(),
AntarchySettings.axeBlackHoleActiveTicks(), ownerId);
return hole;
}
@@ -54,6 +54,16 @@ public final class RoyalAssailantBlackHoleEntity extends RoyalBlackHoleEntity {
@Override
protected boolean pullsTerrainBlocks() {
return false;
return true;
}
@Override
protected double pullStrength() {
return AntarchySettings.axeBlackHolePullStrength();
}
@Override
protected int blockSuctionCap() {
return AntarchySettings.axeBlackHoleBlockSuctionCap();
}
}
@@ -238,6 +238,14 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
return this.effectRadius() * QUEEN_PULL_RADIUS_SCALE;
}
protected double pullStrength() {
return AntarchySettings.queenBlackHolePullStrength();
}
protected int blockSuctionCap() {
return AntarchySettings.queenBlackHoleBlockSuctionCap();
}
/** Returns the center of the animated black-hole cube in world coordinates. */
public Vec3 effectCenter() {
double animationSeconds = Math.min(CORE_RISE_END_SECONDS, this.animationAge / 20.0D);
@@ -295,7 +303,7 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
if (distance > radius) {
continue;
}
double strength = AntarchySettings.queenBlackHolePullStrength() * (1.0D - distance / radius);
double strength = this.pullStrength() * (1.0D - distance / radius);
Vec3 pull = toCenter.scale(strength / distance);
entity.setDeltaMovement(entity.getDeltaMovement().scale(0.86D).add(pull));
entity.hasImpulse = true;
@@ -304,7 +312,7 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
}
private void pullTerrainBlocks(ServerLevel level) {
int cap = AntarchySettings.queenBlackHoleBlockSuctionCap();
int cap = this.blockSuctionCap();
if (cap <= 0 || this.suckedBlocks >= cap
|| !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
return;
@@ -19,7 +19,7 @@ public final class PermanentPortalShape {
public static final int MIN_WIDTH = 2;
public static final int MIN_HEIGHT = 3;
public static final int MAX_SIZE = 21;
public static final int ACTIVE_SEARCH_RADIUS = 24;
public static final int ACTIVE_SEARCH_RADIUS = 128;
private final TagKey<Block> frameTag;
private final Block portalBlock;
@@ -227,10 +227,6 @@ public final class PermanentPortalShape {
for (int y = -1; y <= 3; y++) {
for (int x = -1; x <= 2; x++) {
BlockPos pos = bottomLeft.relative(widthDirection, x).above(y);
boolean cornerSpot = (x == -1 || x == 2) && (y == -1 || y == 3);
if (cornerSpot) {
continue;
}
if (x == -1 || x == 2 || y == -1 || y == 3) {
level.setBlock(pos, frameState, Block.UPDATE_ALL);
} else {
@@ -250,10 +246,6 @@ public final class PermanentPortalShape {
BlockPos pos = bottomLeft.relative(widthDirection, x).above(y);
BlockState state = level.getBlockState(pos);
boolean frameSpot = x == -1 || x == 2 || y == -1 || y == 3;
boolean cornerSpot = (x == -1 || x == 2) && (y == -1 || y == 3);
if (cornerSpot) {
continue;
}
if (frameSpot) {
if (y != -1 && !state.isAir() && !state.is(frameBlock) && !state.canBeReplaced()) {
return false;
@@ -12,6 +12,7 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.vehicle.DismountHelper;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@@ -23,7 +24,7 @@ import org.jetbrains.annotations.Nullable;
public final class PermanentPortalTeleporter {
private static final int SEARCH_RADIUS = 24;
private static final int VERTICAL_SEARCH = 24;
private static final int EXISTING_PORTAL_SEARCH_RADIUS = 48;
private static final int EXISTING_PORTAL_SEARCH_RADIUS = 128;
private PermanentPortalTeleporter() {
}
@@ -46,7 +47,7 @@ public final class PermanentPortalTeleporter {
return new DimensionTransition(sourceLevel, entity, DimensionTransition.DO_NOTHING);
}
Vec3 arrival = findArrivalPosition(entity, destination, portalPos, type);
Vec3 arrival = findArrivalPosition(sourceLevel, entity, destination, portalPos, type);
if (arrival == null) {
if (entity instanceof ServerPlayer player) {
player.displayClientMessage(net.minecraft.network.chat.Component.translatable("message.antarchy.teleport_arrival_failed"), true);
@@ -65,7 +66,9 @@ public final class PermanentPortalTeleporter {
}
@Nullable
private static Vec3 findArrivalPosition(Entity entity, ServerLevel destination, BlockPos preferredPos, PermanentPortalType type) {
private static Vec3 findArrivalPosition(ServerLevel source, Entity entity, ServerLevel destination, BlockPos preferredPos, PermanentPortalType type) {
double scale = DimensionType.getTeleportationScale(source.dimensionType(), destination.dimensionType());
preferredPos = BlockPos.containing(preferredPos.getX() * scale, preferredPos.getY(), preferredPos.getZ() * scale);
PermanentPortalShape active = PermanentPortalShape.findActiveNear(destination, preferredPos, type);
if (active != null) {
Vec3 safePortalPosition = tryFindSafePosition(entity, destination, BlockPos.containing(active.center()));
@@ -16,148 +16,46 @@ import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
public class ElythiaBiomeSource extends BiomeSource {
private static final ResourceKey<Biome> MOLEWORM_CAVES = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "moleworm_caves")
);
private static final ResourceKey<Biome> ELYTHIA_LUSH_CAVES = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_lush_caves")
);
private static final ResourceKey<Biome> ELYTHIA_OCEAN = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_ocean")
);
private static final ResourceKey<Biome> ELYTHIA_CORAL_SPIKES = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_coral_spikes")
);
private static final ResourceKey<Biome> ELYTHIA_BEACH = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_beach")
);
private static final ResourceKey<Biome> OURANWOOD_FOREST = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "ouranwood_forest")
);
private static final ResourceKey<Biome> SPARSE_OURANWOOD_FOREST = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "sparse_ouranwood_forest")
);
private static final ResourceKey<Biome> PEACH_FOREST = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "peach_forest")
);
private static final ResourceKey<Biome> FUNGAL_OURANWOOD_FOREST = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "fungal_ouranwood_forest")
);
private static final ResourceKey<Biome> GLIMMERING_POOLS = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "glimmering_pools")
);
public final class ElythiaBiomeSource extends BiomeSource {
private static final ResourceKey<Biome> CLOUD_SEA = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "cloud_sea")
);
private static final int[] SURFACE_FALLBACK_BLOCK_YS = new int[]{192, 160, 128, 96, 64, 32, 0};
private static final class ColumnBiomeCache {
long key = Long.MIN_VALUE;
Holder<Biome> value;
}
private final ThreadLocal<ColumnBiomeCache> molewormSurfaceFallbackCache = ThreadLocal.withInitial(ColumnBiomeCache::new);
private final ThreadLocal<ColumnBiomeCache> peachForestSurfaceFallbackCache = ThreadLocal.withInitial(ColumnBiomeCache::new);
private final ThreadLocal<ColumnBiomeCache> landFallbackCache = ThreadLocal.withInitial(ColumnBiomeCache::new);
private static long packColumnKey(int x, int z) {
return ((long) x << 32) ^ (z & 0xFFFFFFFFL);
}
public static final MapCodec<ElythiaBiomeSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
MultiNoiseBiomeSource.DIRECT_CODEC.forGetter(ElythiaBiomeSource::parameters),
Codec.INT.optionalFieldOf("moleworm_caves_max_y", 72).forGetter(ElythiaBiomeSource::molewormCavesMaxY),
Codec.INT.optionalFieldOf("surface_biome_sample_y", 160).forGetter(ElythiaBiomeSource::surfaceBiomeSampleY),
Codec.INT.optionalFieldOf("ocean_max_y", 85).forGetter(ElythiaBiomeSource::oceanMaxY),
Codec.INT.optionalFieldOf("sea_level", 78).forGetter(ElythiaBiomeSource::seaLevel),
Codec.INT.optionalFieldOf("cloud_sea_min_y", 360).forGetter(ElythiaBiomeSource::cloudSeaMinY)
Codec.INT.optionalFieldOf("cloud_sea_min_y", 250).forGetter(ElythiaBiomeSource::cloudSeaMinY)
).apply(instance, ElythiaBiomeSource::new));
private final Climate.ParameterList<Holder<Biome>> parameters;
private final MultiNoiseBiomeSource delegate;
private final int molewormCavesMaxY;
private final int surfaceBiomeSampleY;
private final int oceanMaxY;
private final int seaLevel;
private final int cloudSeaMinY;
private final int molewormCavesMaxQuartY;
private final int surfaceBiomeSampleQuartY;
private final int oceanMaxQuartY;
private final int seaLevelQuartY;
private final int undergroundGuardMaxQuartY;
private final int cloudSeaMinQuartY;
private final Holder<Biome> oceanHolder;
private final Holder<Biome> defaultLandHolder;
private final Holder<Biome> glimmeringPoolsHolder;
private final Holder<Biome> ouranwoodForestHolder;
private final Holder<Biome> cloudSeaHolder;
private final Holder<Biome> firstConfiguredHolder;
private final Holder<Biome> fallbackHolder;
public ElythiaBiomeSource(Climate.ParameterList<Holder<Biome>> parameters, int molewormCavesMaxY, int surfaceBiomeSampleY, int oceanMaxY, int seaLevel, int cloudSeaMinY) {
public ElythiaBiomeSource(Climate.ParameterList<Holder<Biome>> parameters, int cloudSeaMinY) {
this.parameters = parameters;
this.delegate = MultiNoiseBiomeSource.createFromList(parameters);
this.molewormCavesMaxY = molewormCavesMaxY;
this.surfaceBiomeSampleY = surfaceBiomeSampleY;
this.oceanMaxY = oceanMaxY;
this.seaLevel = seaLevel;
this.cloudSeaMinY = cloudSeaMinY;
this.molewormCavesMaxQuartY = QuartPos.fromBlock(molewormCavesMaxY);
this.surfaceBiomeSampleQuartY = QuartPos.fromBlock(surfaceBiomeSampleY);
this.oceanMaxQuartY = QuartPos.fromBlock(oceanMaxY);
this.seaLevelQuartY = QuartPos.fromBlock(seaLevel);
this.undergroundGuardMaxQuartY = QuartPos.fromBlock(molewormCavesMaxY + 40);
this.cloudSeaMinQuartY = QuartPos.fromBlock(cloudSeaMinY);
this.oceanHolder = parameters.values().stream()
.map(Pair::getSecond)
.filter(h -> h.is(ELYTHIA_OCEAN))
.findFirst()
.orElse(null);
this.glimmeringPoolsHolder = parameters.values().stream()
.map(Pair::getSecond)
.filter(h -> h.is(GLIMMERING_POOLS))
.findFirst()
.orElse(null);
this.ouranwoodForestHolder = parameters.values().stream()
.map(Pair::getSecond)
.filter(h -> h.is(OURANWOOD_FOREST))
.findFirst()
.orElse(null);
this.defaultLandHolder = parameters.values().stream()
.map(Pair::getSecond)
.filter(h -> !isOceanBiome(h) && !h.is(ELYTHIA_BEACH)
&& !h.is(MOLEWORM_CAVES) && !h.is(ELYTHIA_LUSH_CAVES)
&& !h.is(GLIMMERING_POOLS))
.findFirst()
.orElse(null);
this.cloudSeaHolder = parameters.values().stream()
.map(Pair::getSecond)
.filter(h -> h.is(CLOUD_SEA))
.filter(holder -> holder.is(CLOUD_SEA))
.findFirst()
.orElse(null);
this.firstConfiguredHolder = parameters.values().stream()
this.fallbackHolder = parameters.values().stream()
.map(Pair::getSecond)
.filter(holder -> !holder.is(CLOUD_SEA))
.findFirst()
.orElse(null);
}
private Climate.ParameterList<Holder<Biome>> parameters() { return this.parameters; }
private int molewormCavesMaxY() { return this.molewormCavesMaxY; }
private int surfaceBiomeSampleY() { return this.surfaceBiomeSampleY; }
private int oceanMaxY() { return this.oceanMaxY; }
private int seaLevel() { return this.seaLevel; }
private int cloudSeaMinY() { return this.cloudSeaMinY; }
private Climate.ParameterList<Holder<Biome>> parameters() {
return this.parameters;
}
private int cloudSeaMinY() {
return this.cloudSeaMinQuartY * 4;
}
@Override
protected MapCodec<? extends BiomeSource> codec() {
@@ -168,236 +66,17 @@ public class ElythiaBiomeSource extends BiomeSource {
protected Stream<Holder<Biome>> collectPossibleBiomes() {
return this.delegate.possibleBiomes().stream();
}
private static final long OCEAN_CONTINENTALNESS_THRESHOLD = Climate.quantizeCoord(-0.87f);
private static final int CLOUD_SEA_CELL_SIZE = 96;
private static final long CLOUD_SEA_CHANCE_DENOMINATOR = 5L; // 1-in-5 columns == ~20%
@Override
public Holder<Biome> getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) {
// Only some sky columns are the cloud sea — everywhere else, altitude above the cloud
// floor just falls through to whatever biome would normally be there. Decided before
// touching the (expensive) delegate at all, both for correctness (multi-noise has no
// real notion of raw Y to gate a biome on) and as a speed win for the common case.
if (this.cloudSeaHolder != null && y >= this.cloudSeaMinQuartY && isCloudSeaColumn(x, z)) {
if (this.cloudSeaHolder != null && y >= this.cloudSeaMinQuartY) {
return this.cloudSeaHolder;
}
Holder<Biome> biome = this.delegate.getNoiseBiome(x, y, z, sampler);
if (biome == null) {
return resolveConfiguredFallback(x, y, z, sampler);
if (biome != null && !biome.is(CLOUD_SEA)) {
return biome;
}
// Defensive: cloud_sea's multi-noise parameter point is reserved far off in "offset"
// so it shouldn't win nearest-neighbor on its own, but if it ever does for a query
// below the cloud floor, treat it like any other biome that has no business at that
// altitude and fall back to a real land biome instead of leaking clouds into terrain.
if (biome.is(CLOUD_SEA)) {
return resolveLandFallback(x, z, sampler);
}
if (biome.is(MOLEWORM_CAVES) && y > this.molewormCavesMaxQuartY) {
return resolveSurfaceFallback(x, z, sampler, this.molewormSurfaceFallbackCache, MOLEWORM_CAVES, GLIMMERING_POOLS, CLOUD_SEA);
}
Climate.TargetPoint target = sampler.sample(x, this.seaLevelQuartY, z);
if (target.continentalness() < OCEAN_CONTINENTALNESS_THRESHOLD && y <= this.oceanMaxQuartY) {
if (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)) return biome;
Holder<Biome> seaLevelBiome = this.delegate.getNoiseBiome(x, this.seaLevelQuartY, z, sampler);
if (isOceanBiome(seaLevelBiome)) return seaLevelBiome;
return oceanHolder != null ? oceanHolder : nullToConfiguredFallback(seaLevelBiome, x, y, z, sampler);
}
if (y <= this.seaLevelQuartY && oceanHolder != null && !allowedBelowSeaLevel(biome)) {
return oceanHolder;
}
if (isOceanBiome(biome)) {
return resolveLandFallback(x, z, sampler);
}
if (biome.is(SPARSE_OURANWOOD_FOREST) && !isSparseOuranwoodCandidate(target, x, z)) {
biome = this.ouranwoodForestHolder != null ? this.ouranwoodForestHolder : biome;
}
if (isGlimmeringPoolsCandidate(biome, target, x, z)) {
biome = this.glimmeringPoolsHolder != null ? this.glimmeringPoolsHolder : biome;
}
if ((biome.is(PEACH_FOREST) || biome.is(GLIMMERING_POOLS)) && y <= this.undergroundGuardMaxQuartY) {
return resolveSurfaceFallback(x, z, sampler, this.peachForestSurfaceFallbackCache, PEACH_FOREST, GLIMMERING_POOLS, CLOUD_SEA);
}
return biome;
}
private static boolean allowedBelowSeaLevel(Holder<Biome> biome) {
return biome != null && (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)
|| biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES));
}
private static boolean isOceanBiome(Holder<Biome> biome) {
return biome != null && (biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES));
}
private static boolean isOuranwoodBiome(Holder<Biome> biome) {
return biome != null && (biome.is(OURANWOOD_FOREST) || biome.is(SPARSE_OURANWOOD_FOREST)
|| biome.is(FUNGAL_OURANWOOD_FOREST));
}
private static boolean isGlimmeringPoolsCandidate(Holder<Biome> biome, Climate.TargetPoint target, int x, int z) {
if (!isOuranwoodBiome(biome)) {
return false;
}
long humidity = target.humidity();
long continentalness = target.continentalness();
long weirdness = target.weirdness();
long depth = target.depth();
if (humidity < Climate.quantizeCoord(0.64F) || humidity > Climate.quantizeCoord(1.0F)) {
return false;
}
if (continentalness < Climate.quantizeCoord(0.29F) || continentalness > Climate.quantizeCoord(0.90F)) {
return false;
}
if (weirdness < Climate.quantizeCoord(-0.88F) || weirdness > Climate.quantizeCoord(0.33F)) {
return false;
}
if (depth < Climate.quantizeCoord(0.0F) || depth > Climate.quantizeCoord(0.80F)) {
return false;
}
long cellX = Math.floorDiv(x, 11);
long cellZ = Math.floorDiv(z, 11);
long gate = Math.floorMod(cellX * 73428767L + cellZ * 912931L, 5L);
return gate <= 3L;
}
private static boolean isCloudSeaColumn(int x, int z) {
long cellX = Math.floorDiv(x, CLOUD_SEA_CELL_SIZE);
long cellZ = Math.floorDiv(z, CLOUD_SEA_CELL_SIZE);
long gate = Math.floorMod(cellX * 668265263L + cellZ * 2246822519L, CLOUD_SEA_CHANCE_DENOMINATOR);
return gate == 0L;
}
private static boolean isSparseOuranwoodCandidate(Climate.TargetPoint target, int x, int z) {
if (target.temperature() > Climate.quantizeCoord(0.24F)) {
return false;
}
if (target.humidity() > Climate.quantizeCoord(0.70F)) {
return false;
}
if (target.continentalness() < Climate.quantizeCoord(0.90F)) {
return false;
}
if (target.erosion() > Climate.quantizeCoord(-0.22F)) {
return false;
}
if (target.weirdness() < Climate.quantizeCoord(0.92F)) {
return false;
}
long cellX = Math.floorDiv(x, 24);
long cellZ = Math.floorDiv(z, 24);
long gate = Math.floorMod(cellX * 1103515245L + cellZ * 2147483647L, 12L);
return gate == 0L;
}
@SafeVarargs
private Holder<Biome> resolveSurfaceFallback(int x, int z, Climate.Sampler sampler, ThreadLocal<ColumnBiomeCache> cacheHolder, ResourceKey<Biome>... excluded) {
ColumnBiomeCache cache = cacheHolder.get();
long key = packColumnKey(x, z);
if (cache.key == key) {
return cache.value;
}
Holder<Biome> result = this.delegate.getNoiseBiome(x, this.surfaceBiomeSampleQuartY, z, sampler);
if (isExcluded(result, excluded)) {
for (int sampleBlockY : SURFACE_FALLBACK_BLOCK_YS) {
Holder<Biome> candidate = this.delegate.getNoiseBiome(x, QuartPos.fromBlock(sampleBlockY), z, sampler);
if (!isExcluded(candidate, excluded)) {
result = candidate;
break;
}
}
}
result = nullToConfiguredFallback(result, x, this.surfaceBiomeSampleQuartY, z, sampler);
if (result != null && result.is(CLOUD_SEA) && this.defaultLandHolder != null) {
result = this.defaultLandHolder;
}
cache.key = key;
cache.value = result;
return result;
}
private Holder<Biome> resolveLandFallback(int x, int z, Climate.Sampler sampler) {
ColumnBiomeCache cache = this.landFallbackCache.get();
long key = packColumnKey(x, z);
if (cache.key == key) {
return cache.value;
}
Holder<Biome> result = this.delegate.getNoiseBiome(x, this.surfaceBiomeSampleQuartY, z, sampler);
if (isOceanOrCave(result)) {
Holder<Biome> resolved = null;
for (int sampleBlockY : SURFACE_FALLBACK_BLOCK_YS) {
Holder<Biome> candidate = this.delegate.getNoiseBiome(x, QuartPos.fromBlock(sampleBlockY), z, sampler);
if (!isOceanOrCave(candidate)) {
resolved = candidate;
break;
}
}
result = resolved != null ? resolved : (defaultLandHolder != null ? defaultLandHolder : result);
}
result = nullToConfiguredFallback(result, x, this.surfaceBiomeSampleQuartY, z, sampler);
cache.key = key;
cache.value = result;
return result;
}
@SafeVarargs
private static boolean isExcluded(Holder<Biome> biome, ResourceKey<Biome>... excluded) {
if (biome == null) {
return true;
}
for (ResourceKey<Biome> key : excluded) {
if (biome.is(key)) return true;
}
return false;
}
private static boolean isOceanOrCave(Holder<Biome> biome) {
return biome == null || isOceanBiome(biome) || biome.is(ELYTHIA_BEACH)
|| biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)
|| biome.is(GLIMMERING_POOLS) || biome.is(CLOUD_SEA);
}
private Holder<Biome> nullToConfiguredFallback(Holder<Biome> biome, int x, int y, int z, Climate.Sampler sampler) {
return biome != null ? biome : resolveConfiguredFallback(x, y, z, sampler);
}
private Holder<Biome> resolveConfiguredFallback(int x, int y, int z, Climate.Sampler sampler) {
if (y <= this.oceanMaxQuartY && this.oceanHolder != null) {
Climate.TargetPoint target = sampler.sample(x, this.seaLevelQuartY, z);
if (target.continentalness() < OCEAN_CONTINENTALNESS_THRESHOLD) {
return this.oceanHolder;
}
}
if (this.defaultLandHolder != null) return this.defaultLandHolder;
if (this.ouranwoodForestHolder != null) return this.ouranwoodForestHolder;
if (this.glimmeringPoolsHolder != null) return this.glimmeringPoolsHolder;
if (this.oceanHolder != null) return this.oceanHolder;
return this.firstConfiguredHolder;
}
@Override
public void addDebugInfo(java.util.List<String> debug, net.minecraft.core.BlockPos pos, Climate.Sampler sampler) {
try {
this.delegate.addDebugInfo(debug, pos, sampler);
} catch (NullPointerException ignored) {
}
debug.add("Elythia mole cave cap: y<=" + this.molewormCavesMaxY);
debug.add("Elythia sea level: " + this.seaLevel);
debug.add("Elythia cloud sea: y>=" + this.cloudSeaMinY + " in ~1/" + CLOUD_SEA_CHANCE_DENOMINATOR + " columns");
return this.fallbackHolder != null ? this.fallbackHolder : biome;
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 393 B

@@ -4,7 +4,8 @@
"type": "minecraft:noise",
"settings": "antarchy:elythia",
"biome_source": {
"type": "minecraft:multi_noise",
"type": "antarchy:elythia_biome_source",
"cloud_sea_min_y": 250,
"biomes": [
{
"biome": "antarchy:elythia_ocean",
@@ -113,6 +114,18 @@
"depth": [0.0, 0.35],
"offset": 0.0
}
},
{
"biome": "antarchy:cloud_sea",
"parameters": {
"temperature": [-1.0, 1.0],
"humidity": [-1.0, 1.0],
"continentalness": [-1.0, 1.0],
"erosion": [-1.0, 1.0],
"weirdness": [-1.0, 1.0],
"depth": [-1.0, 1.0],
"offset": 1.0
}
}
]
}
@@ -2,8 +2,6 @@
"type": "integrated_api:generic_structure",
"start_pool": "antarchy:tigers_eye_shrine/tigers_eye_shrine",
"size": 1,
"terrain_height_radius_check": 4,
"allowed_terrain_height_range": 14,
"valid_biome_radius_check": 1,
"biomes": "#antarchy:has_structure/tigers_eye_shrine_biomes",
"step": "underground_structures",