final 2.0 release

This commit is contained in:
craisinlord committed 2026-09-19 13:59:56 -05:00
1 parent c6b47b496a
commit 93e2adbe12
33 files changed
+559 -145

No files matched your search

@@ -285,7 +285,7 @@ public final class AntarchySettings {
private static int queenBlackHoleActiveTicks = 120;
private static double queenBlackHolePullStrength = 0.16D;
private static int queenBlackHoleBlockSuctionCap = 160;
private static double kingFireballDamage = 32.0D;
private static double kingFireballDamage = 48.0D;
private static double kingFireballRadius = 4.5D;
private static int kingFireballCooldownTicks = 150;
private static double kingIceballDamage = 18.0D;
@@ -1,11 +1,11 @@
package com.craisinlord.antarchy.content.block;
import com.craisinlord.antarchy.content.entity.royal.KingEntity;
import java.util.Optional;
import java.util.function.Supplier;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@@ -40,7 +40,8 @@ public final class CloudBlock extends Block implements BucketPickup {
protected VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
if (context instanceof EntityCollisionContext ecc) {
Entity entity = ecc.getEntity();
if (entity instanceof net.minecraft.world.entity.LivingEntity le && le.isShiftKeyDown()) {
if (entity instanceof KingEntity
|| entity instanceof net.minecraft.world.entity.LivingEntity le && le.isShiftKeyDown()) {
return EMPTY;
}
}
@@ -73,6 +74,9 @@ public final class CloudBlock extends Block implements BucketPickup {
}
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
if (entity instanceof KingEntity) {
return;
}
Vec3 motion = entity.getDeltaMovement();
double slowedY = motion.y < 0.0D ? Math.max(motion.y * 0.4D, -0.08D) : motion.y;
entity.setDeltaMovement(motion.x * 0.92D, slowedY, motion.z * 0.92D);
@@ -0,0 +1,37 @@
package com.craisinlord.antarchy.content.block.entity;
/**
* Identifies spawn-rule checks made by an Undertrial spawner's vanilla
* TrialSpawner tick. The context is scoped to the current server-thread call
* so ordinary trial spawners and all other spawn paths retain vanilla rules.
*/
public final class UndertrialSpawnContext implements AutoCloseable {
private static final ThreadLocal<Integer> DEPTH = ThreadLocal.withInitial(() -> 0);
private boolean closed;
private UndertrialSpawnContext() {
DEPTH.set(DEPTH.get() + 1);
}
public static UndertrialSpawnContext enter() {
return new UndertrialSpawnContext();
}
public static boolean isActive() {
return DEPTH.get() > 0;
}
@Override
public void close() {
if (!closed) {
closed = true;
int depth = DEPTH.get() - 1;
if (depth <= 0) {
DEPTH.remove();
} else {
DEPTH.set(depth);
}
}
}
}
@@ -69,7 +69,9 @@ public final class UndertrialSpawnerBlockEntity extends BlockEntity implements T
boolean ominous = state.getValue(UndertrialSpawnerBlock.OMINOUS);
boolean rewardReady = previousState == TrialSpawnerState.EJECTING_REWARD
&& blockEntity.trialSpawner.getData().isReadyToEjectItems(level, 30.0F, blockEntity.trialSpawner.getTargetCooldownLength());
blockEntity.trialSpawner.tickServer(level, pos, ominous);
try (UndertrialSpawnContext ignored = UndertrialSpawnContext.enter()) {
blockEntity.trialSpawner.tickServer(level, pos, ominous);
}
if (rewardReady && blockEntity.getState() == TrialSpawnerState.EJECTING_REWARD) {
blockEntity.ejectReward(level, pos, ominous);
}
@@ -0,0 +1,112 @@
package com.craisinlord.antarchy.content.client;
import com.craisinlord.antarchy.content.entity.royal.QueenEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.DeathScreen;
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import java.util.Comparator;
public final class QueenMusicHandler {
private static final double START_RADIUS = 128.0D;
private static final double STOP_RADIUS = 160.0D;
private static final int RESTART_COOLDOWN_TICKS = 100;
private static QueenMusicSound music;
private static int cooldownTicks;
private static boolean wasInEncounter;
private QueenMusicHandler() {
}
public static void tick(Minecraft minecraft, SoundEvent soundEvent) {
if (minecraft.level == null || minecraft.player == null || minecraft.isPaused()
|| !minecraft.player.isAlive() || minecraft.player.isRemoved()
|| minecraft.player.isDeadOrDying() || minecraft.screen instanceof DeathScreen) {
reset(minecraft);
return;
}
if (cooldownTicks > 0) {
cooldownTicks--;
}
QueenEntity queen = minecraft.level.getEntitiesOfClass(
QueenEntity.class,
minecraft.player.getBoundingBox().inflate(STOP_RADIUS),
QueenEntity::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);
}
if (music == null && cooldownTicks <= 0) {
music = new QueenMusicSound(soundEvent);
minecraft.getSoundManager().play(music);
}
if (music != null) {
double distance = Math.sqrt(queen.distanceToSqr(minecraft.player));
float volume = distance <= START_RADIUS
? 1.0F
: (float) Mth.clamp(1.0D - (distance - START_RADIUS) / (STOP_RADIUS - START_RADIUS), 0.0D, 1.0D);
music.setVolume(volume);
}
}
private static void stop(Minecraft minecraft) {
if (music != null) {
minecraft.getSoundManager().stop(music);
music = null;
}
}
private static void reset(Minecraft minecraft) {
stop(minecraft);
cooldownTicks = 0;
wasInEncounter = false;
}
private static final class QueenMusicSound extends AbstractTickableSoundInstance {
private QueenMusicSound(SoundEvent soundEvent) {
super(soundEvent, SoundSource.MUSIC, RandomSource.create());
this.looping = false;
this.delay = 0;
this.relative = true;
this.attenuation = SoundInstance.Attenuation.NONE;
this.volume = 1.0F;
this.pitch = 1.0F;
}
private void setVolume(float volume) {
this.volume = volume;
}
@Override
public void tick() {
}
@Override
public boolean canStartSilent() {
return true;
}
}
}
@@ -386,6 +386,7 @@ public final class CreativeTabContents {
entry("duct_tape", "tools_and_utilities", "shears"),
entry("bug_spray", "tools_and_utilities"),
entry("music_disc_underside", "tools_and_utilities"),
entry("music_disc_the_queen", "tools_and_utilities"),
entry("diamond_minecart", "tools_and_utilities", "minecart"),
entry("bile_bucket", "tools_and_utilities"),
entry("ichor_bucket", "tools_and_utilities"),
@@ -252,17 +252,7 @@ public class KingEntity extends RoyalBossEntity {
@Override
protected boolean blocksRoyalBeamScheduling() {
if (this.royalChargeActive) {
return true;
}
LivingEntity target = this.getTarget();
if (target == null || this.royalChargeOpeningDelayTicks > 0
|| this.kingLandingStage != KingLandingStage.AERIAL
|| !this.attackScheduler.ready("royal_charge", RoyalAttackLane.MOVEMENT)) {
return false;
}
double distance = this.distanceTo(target);
return distance >= ROYAL_CHARGE_MIN_RANGE && distance <= ROYAL_CHARGE_MAX_RANGE;
return this.royalChargeActive;
}
@Override
@@ -423,7 +413,12 @@ public class KingEntity extends RoyalBossEntity {
@Override
protected double royalBeamMinimumRange() {
return AntarchySettings.kingBeamMinimumRange();
return Math.min(AntarchySettings.kingBeamMinimumRange(), 28.0D);
}
@Override
protected boolean royalBeamUsesTrackedAim() {
return false;
}
@Override
@@ -758,10 +753,12 @@ public class KingEntity extends RoyalBossEntity {
private boolean clearTreePatrolPath(Vec3 destination) {
Vec3 start = this.position();
for (int sample = 1; sample <= TREE_ORBIT_PATH_SAMPLES; sample++) {
AABB bounds = this.getBoundingBox();
for (int check = 0; check < TREE_ORBIT_PATH_SAMPLES; check++) {
int sample = check == 0 ? TREE_ORBIT_PATH_SAMPLES : check;
double progress = sample / (double) TREE_ORBIT_PATH_SAMPLES;
Vec3 point = start.lerp(destination, progress);
AABB box = this.getBoundingBox().move(point.x - this.getX(), point.y - this.getY(), point.z - this.getZ());
AABB box = bounds.move(point.x - this.getX(), point.y - this.getY(), point.z - this.getZ());
if (!this.level().noCollision(this, box)) {
return false;
}
@@ -24,15 +24,12 @@ 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.protocol.game.ClientboundSetTitleTextPacket;
import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.ChatFormatting;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.BossEvent;
@@ -74,16 +71,17 @@ public class QueenEntity extends RoyalBossEntity {
private static final int GRAVITY_STOMP_COOLDOWN = 180;
private static final int MOMENTUM_LOCK_COOLDOWN = 420;
private static final int MOMENTUM_LOCK_DURATION = 90;
private static final double MOMENTUM_LOCK_RADIUS = 26.0D;
private static final double MOMENTUM_LOCK_RADIUS = 40.0D;
private static final int CRUSHING_GRAVITY_COOLDOWN = 360;
private static final int CRUSHING_GRAVITY_DURATION = 120;
private static final double CRUSHING_GRAVITY_RADIUS = 18.0D;
private static final double CRUSHING_GRAVITY_RADIUS = 36.0D;
private static final double CRUSHING_GRAVITY_STRENGTH = 0.12D;
private static final int ACCELERATION_COOLDOWN = 500;
private static final int QUEEN_CHRONOSPHERE_COOLDOWN = 700;
private static final int QUEEN_CHRONOSPHERE_COOLDOWN = 500;
private static final int QUEEN_CHRONOSPHERE_DURATION = 200;
private static final double QUEEN_CHRONOSPHERE_RADIUS = 20.0D;
private static final int ACCELERATION_DURATION = 140;
private static final double QUEEN_CHRONOSPHERE_RADIUS = 40.0D;
private static final double QUEEN_CHRONOSPHERE_RATE = 0.14D;
private static final int ACCELERATION_DURATION = 360;
private static final int BLACK_HOLE_COOLDOWN = 340;
private static final double QUEEN_BITE_COOLDOWN_MULTIPLIER = 1.5D;
private static final int GRAVITY_STOMP_TELEGRAPH_TICKS = 22;
@@ -108,11 +106,17 @@ public class QueenEntity extends RoyalBossEntity {
private static final int GRAVITIC_UPHEAVAL_DURATION = GRAVITIC_UPHEAVAL_RISE_TICKS + GRAVITIC_UPHEAVAL_HANG_TICKS;
private static final double GRAVITIC_UPHEAVAL_RISE_SPEED = 0.55D;
private static final int LANDING_TELEGRAPH_TICKS = 30;
private static final int LANDING_DESCENT_TIMEOUT_TICKS = 120;
private static final int LANDING_IMPACT_TICKS = 18;
private static final int GROUND_COMBAT_TICKS = 160;
private static final int GROUND_COMBAT_TICKS = 240;
private static final int GROUND_CHARGE_WINDUP_TICKS = 10;
private static final int GROUND_CHARGE_DURATION_TICKS = 14;
private static final int GROUND_CHARGE_COOLDOWN_MIN = 45;
private static final int GROUND_CHARGE_COOLDOWN_VARIANCE = 25;
private static final double GROUND_CHARGE_SPEED = 1.45D;
private static final int TAKEOFF_TICKS = 30;
private static final int LANDING_COOLDOWN_MIN = 300;
private static final int LANDING_COOLDOWN_VARIANCE = 120;
private static final int LANDING_COOLDOWN_MIN = 220;
private static final int LANDING_COOLDOWN_VARIANCE = 80;
private static final int BLACK_HOLE_FOLLOW_UP_DELAY = 22;
private static final int CRUSHING_LANDING_DELAY = 40;
private static final int MOMENTUM_VOLLEY_DELAY = MOMENTUM_LOCK_DURATION + 5;
@@ -142,13 +146,20 @@ public class QueenEntity extends RoyalBossEntity {
private final List<FallingBlockEntity> graviticUpheavalBlocks = new ArrayList<>();
@Nullable
private Vec3 pendingBlackHoleAnchor;
private int queenLandingCooldownTicks = 300;
private int queenLandingCooldownTicks = 200;
private int queenLandingStageTicks;
private int queenGroundChargeCooldownTicks;
private int queenGroundChargeWindupTicks;
private int queenGroundChargeTicks;
private QueenLandingStage queenLandingStage = QueenLandingStage.AERIAL;
@Nullable
private Vec3 queenLandingWaypoint;
@Nullable
private Vec3 queenGroundChargeDirection;
@Nullable
private Phase pendingPhaseSignature;
private boolean pendingPhaseTwoCrushingGravity;
private boolean pendingPhaseThreeChronosphere;
private QueenFollowUp queuedQueenFollowUp = QueenFollowUp.NONE;
private int queuedQueenFollowUpTicks;
private int queuedQueenLandingRetryTicks;
@@ -160,6 +171,7 @@ public class QueenEntity extends RoyalBossEntity {
private boolean manticoreAnimationPending;
private final RoyalEffectController royalEffects = new RoyalEffectController();
private final Map<UUID, Vec3> frozenVelocities = new HashMap<>();
private final Map<UUID, Vec3> frozenPositions = new HashMap<>();
private long naturalTrailSiteId = Long.MIN_VALUE;
@Nullable
private BlockPos naturalTrailHome;
@@ -214,6 +226,8 @@ public class QueenEntity extends RoyalBossEntity {
|| this.queenLandingStage == QueenLandingStage.DESCENT
|| this.queenLandingStage == QueenLandingStage.IMPACT
|| this.queenLandingStage == QueenLandingStage.TAKEOFF
|| this.queenGroundChargeWindupTicks > 0
|| this.queenGroundChargeTicks > 0
|| this.isQueenAbilityTelegraphActive();
}
@@ -231,16 +245,6 @@ public class QueenEntity extends RoyalBossEntity {
this.getNavigation().stop();
this.setDeltaMovement(this.getDeltaMovement().scale(0.35D));
this.playRoyalSound(AntarchySoundEvents.QUEEN_ROAR.get(), nextPhase == Phase.THREE ? 0.66F : 0.82F);
if (this.level() instanceof ServerLevel level) {
Component title = Component.translatable(nextPhase == Phase.TWO
? "boss.antarchy.queen.phase_two" : "boss.antarchy.queen.phase_three")
.withStyle(style -> style.withColor(nextPhase == Phase.TWO
? ChatFormatting.DARK_PURPLE : ChatFormatting.RED).withBold(true));
for (ServerPlayer player : this.royalEncounterPlayers(level)) {
player.connection.send(new ClientboundSetTitlesAnimationPacket(5, 45, 10));
player.connection.send(new ClientboundSetTitleTextPacket(title));
}
}
}
@Override
@@ -260,22 +264,34 @@ public class QueenEntity extends RoyalBossEntity {
if (nextPhase == Phase.TWO) {
this.momentumLockCooldownTicks = 0;
this.pendingPhaseSignature = Phase.TWO;
this.pendingPhaseTwoCrushingGravity = true;
this.queenLandingCooldownTicks = Math.min(this.queenLandingCooldownTicks, 100);
} else if (nextPhase == Phase.THREE) {
this.accelerationCooldownTicks = 0;
this.queenChronosphereCooldownTicks = 0;
this.pendingPhaseSignature = Phase.THREE;
this.pendingPhaseThreeChronosphere = true;
this.queenLandingCooldownTicks = 0;
}
}
@Override
protected double biteApproachSpeed() {
return 1.55D;
return this.queenLandingStage == QueenLandingStage.GROUND_COMBAT && !this.isRoyalFlying()
? 1.9D : 1.55D;
}
@Override
protected double combatStandoffDistance() {
return Math.min(super.combatStandoffDistance(), 14.0D);
if (this.queenLandingStage == QueenLandingStage.GROUND_COMBAT && !this.isRoyalFlying()) {
return 0.0D;
}
return Math.max(super.combatStandoffDistance(), AntarchySettings.queenBeamMinimumRange() + 6.0D);
}
@Override
protected double biteDamageMultiplier() {
return super.biteDamageMultiplier() * 1.5D;
}
@Override
@@ -327,6 +343,11 @@ public class QueenEntity extends RoyalBossEntity {
&& !this.isAlliedTo(target);
}
public boolean shouldPlayQueenMusic() {
LivingEntity target = this.getTarget();
return !this.isDeadOrDying() && target != null && target.isAlive() && this.canAttack(target);
}
@Override
protected SoundEvent royalFlyLoopSound() {
return AntarchySoundEvents.QUEEN_FLY_LOOP.get();
@@ -395,10 +416,29 @@ public class QueenEntity extends RoyalBossEntity {
};
}
@Override
protected boolean royalBeamUsesTrackedAim() {
return false;
}
public static boolean isFieldImmune(Entity entity) {
return entity.getType().is(AntarchyTags.Entities.QUEEN_DOES_NOT_ATTACK);
}
private AABB queenEffectBounds(double radius) {
double centerY = this.getY() + this.getBbHeight() * 0.5D;
return new AABB(this.getX() - radius, centerY - radius, this.getZ() - radius,
this.getX() + radius, centerY + radius, this.getZ() + radius);
}
private boolean withinQueenEffectRange(Entity entity, double radius) {
double dx = entity.getX() - this.getX();
double dz = entity.getZ() - this.getZ();
double centerY = this.getY() + this.getBbHeight() * 0.5D;
double entityY = entity.getY() + entity.getBbHeight() * 0.5D;
return dx * dx + dz * dz <= radius * radius && Math.abs(entityY - centerY) <= radius;
}
@Override
public void tick() {
super.tick();
@@ -439,7 +479,7 @@ public class QueenEntity extends RoyalBossEntity {
private void tickQueenLandingSequence(LivingEntity target) {
if (this.queenLandingStage == QueenLandingStage.AERIAL && this.isRoyalFlying()
&& !this.isQueenAbilityTelegraphActive()
&& this.queenLandingCooldownTicks-- <= 0 && target.onGround()) {
&& this.queenLandingCooldownTicks-- <= 0) {
this.beginQueenLanding(target);
}
@@ -450,6 +490,7 @@ public class QueenEntity extends RoyalBossEntity {
this.tickQueenLandingIndicator();
if (--this.queenLandingStageTicks <= 0) {
this.queenLandingStage = QueenLandingStage.DESCENT;
this.queenLandingStageTicks = LANDING_DESCENT_TIMEOUT_TICKS;
this.playRoyalSound(AntarchySoundEvents.QUEEN_FLY_LOOP.get(), 0.72F);
}
}
@@ -468,6 +509,9 @@ public class QueenEntity extends RoyalBossEntity {
this.queenLandingStage = QueenLandingStage.IMPACT;
this.queenLandingStageTicks = LANDING_IMPACT_TICKS;
this.performGravityStomp((ServerLevel) this.level(), target);
} else if (--this.queenLandingStageTicks <= 0) {
this.resetQueenLandingSequence();
this.queenLandingCooldownTicks = 40;
}
}
case IMPACT -> {
@@ -476,10 +520,12 @@ public class QueenEntity extends RoyalBossEntity {
if (--this.queenLandingStageTicks <= 0) {
this.queenLandingStage = QueenLandingStage.GROUND_COMBAT;
this.queenLandingStageTicks = GROUND_COMBAT_TICKS;
this.queenGroundChargeCooldownTicks = 20;
this.queenLandingWaypoint = null;
}
}
case GROUND_COMBAT -> {
this.tickQueenGroundCharge(target);
if (--this.queenLandingStageTicks <= 0) {
this.beginQueenTakeoff();
}
@@ -563,6 +609,7 @@ public class QueenEntity extends RoyalBossEntity {
}
private void beginQueenTakeoff() {
this.clearQueenGroundCharge();
this.queenLandingStage = QueenLandingStage.TAKEOFF;
this.queenLandingStageTicks = TAKEOFF_TICKS;
this.triggerAnim("wing_action", "wing_gust");
@@ -580,6 +627,7 @@ public class QueenEntity extends RoyalBossEntity {
}
private void resetQueenLandingSequence() {
this.clearQueenGroundCharge();
if (this.queenLandingStage != QueenLandingStage.AERIAL) {
this.setRoyalFlying(true);
}
@@ -591,6 +639,65 @@ public class QueenEntity extends RoyalBossEntity {
}
}
private void tickQueenGroundCharge(LivingEntity target) {
if (this.queenGroundChargeWindupTicks > 0) {
this.getNavigation().stop();
this.setDeltaMovement(this.getDeltaMovement().scale(0.45D));
this.getLookControl().setLookAt(target, 90.0F, 90.0F);
if (--this.queenGroundChargeWindupTicks <= 0) {
Vec3 direction = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D);
if (direction.lengthSqr() > 1.0E-4D) {
this.queenGroundChargeDirection = direction.normalize();
this.queenGroundChargeTicks = GROUND_CHARGE_DURATION_TICKS;
} else {
this.finishQueenGroundCharge();
}
}
return;
}
if (this.queenGroundChargeTicks > 0 && this.queenGroundChargeDirection != null) {
Vec3 direction = this.queenGroundChargeDirection;
Vec3 movement = this.getDeltaMovement();
this.setDeltaMovement(direction.x * GROUND_CHARGE_SPEED, movement.y,
direction.z * GROUND_CHARGE_SPEED);
this.setYRot((float) (Mth.atan2(-direction.x, direction.z) * Mth.RAD_TO_DEG));
this.yBodyRot = this.getYRot();
this.hasImpulse = true;
if (--this.queenGroundChargeTicks <= 0) {
this.finishQueenGroundCharge();
}
return;
}
if (this.queenGroundChargeCooldownTicks-- > 0
|| target.position().multiply(1.0D, 0.0D, 1.0D)
.distanceToSqr(this.position().multiply(1.0D, 0.0D, 1.0D)) < 36.0D) {
return;
}
this.queenGroundChargeDirection = target.position().subtract(this.position())
.multiply(1.0D, 0.0D, 1.0D).normalize();
this.queenGroundChargeWindupTicks = GROUND_CHARGE_WINDUP_TICKS;
this.playRoyalSound(AntarchySoundEvents.QUEEN_ROAR.get(), 1.12F);
if (this.level() instanceof ServerLevel level) {
level.sendParticles(ACCEL_DUST, this.getX(), this.getY() + this.getBbHeight() * 0.35D, this.getZ(),
32, this.getBbWidth() * 0.2D, 0.6D, this.getBbWidth() * 0.2D, 0.04D);
}
}
private void finishQueenGroundCharge() {
this.queenGroundChargeTicks = 0;
this.queenGroundChargeWindupTicks = 0;
this.queenGroundChargeDirection = null;
this.queenGroundChargeCooldownTicks = GROUND_CHARGE_COOLDOWN_MIN
+ this.random.nextInt(GROUND_CHARGE_COOLDOWN_VARIANCE + 1);
}
private void clearQueenGroundCharge() {
this.queenGroundChargeCooldownTicks = 0;
this.queenGroundChargeWindupTicks = 0;
this.queenGroundChargeTicks = 0;
this.queenGroundChargeDirection = null;
}
private void tickDreamFireballs() {
if (this.isRoyalRecoveryActive()) return;
if (!(this.level() instanceof ServerLevel level)) return;
@@ -654,7 +761,7 @@ public class QueenEntity extends RoyalBossEntity {
}
case LANDING -> {
if (this.queenLandingStage == QueenLandingStage.AERIAL
&& this.isRoyalFlying() && target.onGround()) {
&& this.isRoyalFlying()) {
this.clearQueuedQueenFollowUp();
this.queenLandingCooldownTicks = 0;
} else if (--this.queuedQueenLandingRetryTicks <= 0) {
@@ -908,9 +1015,11 @@ public class QueenEntity extends RoyalBossEntity {
}
Phase phase = this.phase();
boolean accelerationBlocksMajor = this.royalEffects.active("acceleration")
&& !this.pendingPhaseThreeChronosphere;
boolean majorBusy = this.royalEffects.active("momentum_lock")
|| this.royalEffects.active("crushing_gravity")
|| this.royalEffects.active("acceleration")
|| accelerationBlocksMajor
|| this.royalEffects.active("gravitic_upheaval");
String[] candidates = switch (phase) {
case ONE -> new String[] {"gravity_stomp", "black_hole"};
@@ -918,7 +1027,9 @@ public class QueenEntity extends RoyalBossEntity {
case THREE -> new String[] {"gravity_stomp", "black_hole", "momentum_lock", "crushing_gravity", "acceleration", "queen_chronosphere", "debris_cyclone", "gravitic_upheaval"};
};
String forcedAttack = this.pendingPhaseSignature == Phase.TWO ? "momentum_lock"
: this.pendingPhaseSignature == Phase.THREE ? "acceleration" : null;
: this.pendingPhaseSignature == Phase.THREE ? "acceleration"
: phase == Phase.TWO && this.pendingPhaseTwoCrushingGravity ? "crushing_gravity"
: phase == Phase.THREE && this.pendingPhaseThreeChronosphere ? "queen_chronosphere" : null;
String selected = forcedAttack != null
&& this.queenAttackReady(forcedAttack, phase, majorBusy)
? forcedAttack : this.attackScheduler.chooseWeighted(candidates, id -> {
@@ -978,7 +1089,13 @@ public class QueenEntity extends RoyalBossEntity {
})) return;
this.lastQueenMajorAttack = selected;
if (selected.equals(forcedAttack)) {
this.pendingPhaseSignature = null;
if ("momentum_lock".equals(selected) || "acceleration".equals(selected)) {
this.pendingPhaseSignature = null;
} else if ("crushing_gravity".equals(selected)) {
this.pendingPhaseTwoCrushingGravity = false;
} else if ("queen_chronosphere".equals(selected)) {
this.pendingPhaseThreeChronosphere = false;
}
}
}
@@ -1020,7 +1137,8 @@ public class QueenEntity extends RoyalBossEntity {
case "queen_chronosphere" -> {
this.queenChronosphereCooldownTicks = cooldown;
TimeDilationFieldEntity field = TimeDilationApi.createField(level, this.position(),
QUEEN_CHRONOSPHERE_RADIUS, 0.08D, QUEEN_CHRONOSPHERE_DURATION, this.getUUID());
QUEEN_CHRONOSPHERE_RADIUS, QUEEN_CHRONOSPHERE_RATE,
QUEEN_CHRONOSPHERE_DURATION, this.getUUID());
field.configureQueenChronosphere(this);
this.startRoyalRecovery(35);
}
@@ -1078,7 +1196,8 @@ public class QueenEntity extends RoyalBossEntity {
return switch (phase) {
case ONE -> "black_hole".equals(id) ? 6 : 3;
case TWO -> switch (id) {
case "momentum_lock", "crushing_gravity" -> 6;
case "crushing_gravity" -> 12;
case "momentum_lock" -> 7;
case "debris_cyclone" -> 5;
case "gravitic_upheaval" -> 4;
case "gravity_stomp" -> 3;
@@ -1087,11 +1206,11 @@ public class QueenEntity extends RoyalBossEntity {
};
case THREE -> switch (id) {
case "acceleration" -> 7;
case "queen_chronosphere" -> 6;
case "black_hole", "crushing_gravity" -> 5;
case "queen_chronosphere", "crushing_gravity" -> 10;
case "black_hole" -> 5;
case "debris_cyclone", "gravitic_upheaval" -> 5;
case "gravity_stomp" -> 4;
case "momentum_lock" -> 2;
case "momentum_lock" -> 7;
default -> 0;
};
};
@@ -1296,7 +1415,9 @@ public class QueenEntity extends RoyalBossEntity {
}
if (this.momentumLockTelegraphTicks <= 14) {
for (LivingEntity living : level.getEntitiesOfClass(LivingEntity.class,
this.getBoundingBox().inflate(MOMENTUM_LOCK_RADIUS), this::canDamageWithRoyalAttack)) {
this.queenEffectBounds(MOMENTUM_LOCK_RADIUS),
living -> this.canDamageWithRoyalAttack(living)
&& this.withinQueenEffectRange(living, MOMENTUM_LOCK_RADIUS))) {
this.spawnMomentumTargetCage(level, living);
if (this.momentumLockTelegraphTicks == 12) {
NightmareBiteEntity.spawnTelegraphAt(level, living, true);
@@ -1318,7 +1439,9 @@ public class QueenEntity extends RoyalBossEntity {
double progress = elapsed / (double) CRUSHING_GRAVITY_TELEGRAPH_TICKS;
if (this.tickCount % 2 == 0) {
for (LivingEntity living : level.getEntitiesOfClass(LivingEntity.class,
this.getBoundingBox().inflate(CRUSHING_GRAVITY_RADIUS), this::canDamageWithRoyalAttack)) {
this.queenEffectBounds(CRUSHING_GRAVITY_RADIUS),
living -> this.canDamageWithRoyalAttack(living)
&& this.withinQueenEffectRange(living, CRUSHING_GRAVITY_RADIUS))) {
double downSign = AntarchyGravityApi.isGravityInverted(living) ? 1.0D : -1.0D;
this.spawnCrushingGravityArrow(level, living, downSign, progress);
}
@@ -1644,12 +1767,15 @@ public class QueenEntity extends RoyalBossEntity {
this.momentumLockCooldownTicks = MOMENTUM_LOCK_COOLDOWN;
this.royalEffects.start("momentum_lock", MOMENTUM_LOCK_DURATION, () -> {
this.frozenVelocities.clear();
this.frozenPositions.clear();
for (Entity entity : level.getEntitiesOfClass(Entity.class,
this.getBoundingBox().inflate(MOMENTUM_LOCK_RADIUS))) {
this.queenEffectBounds(MOMENTUM_LOCK_RADIUS),
entity -> this.withinQueenEffectRange(entity, MOMENTUM_LOCK_RADIUS))) {
if (entity == this || isFieldImmune(entity) || entity instanceof Player player && player.isCreative()) {
continue;
}
this.frozenVelocities.put(entity.getUUID(), entity.getDeltaMovement());
this.frozenPositions.put(entity.getUUID(), entity.position());
}
}, this::tickMomentumLockEffect, () -> {
for (Map.Entry<UUID, Vec3> entry : this.frozenVelocities.entrySet()) {
@@ -1660,6 +1786,7 @@ public class QueenEntity extends RoyalBossEntity {
}
}
this.frozenVelocities.clear();
this.frozenPositions.clear();
this.startRoyalRecovery(35);
});
this.playRoyalSound(AntarchySoundEvents.QUEEN_ROAR.get(), 0.5F);
@@ -1674,8 +1801,13 @@ public class QueenEntity extends RoyalBossEntity {
Entity entity = level.getEntity(entry.getKey());
if (entity == null || !entity.isAlive()) {
iterator.remove();
this.frozenPositions.remove(entry.getKey());
continue;
}
Vec3 lockedPosition = this.frozenPositions.get(entry.getKey());
if (lockedPosition != null && entity.position().distanceToSqr(lockedPosition) > 1.0E-6D) {
entity.teleportTo(lockedPosition.x, lockedPosition.y, lockedPosition.z);
}
entity.setDeltaMovement(Vec3.ZERO);
entity.fallDistance = 0.0F;
entity.hasImpulse = true;
@@ -1694,13 +1826,17 @@ public class QueenEntity extends RoyalBossEntity {
return;
}
for (Entity entity : level.getEntitiesOfClass(Entity.class,
this.getBoundingBox().inflate(CRUSHING_GRAVITY_RADIUS))) {
this.queenEffectBounds(CRUSHING_GRAVITY_RADIUS),
entity -> this.withinQueenEffectRange(entity, CRUSHING_GRAVITY_RADIUS))) {
if (entity == this || isFieldImmune(entity) || entity instanceof Player player && player.isCreative()) {
continue;
}
double downSign = AntarchyGravityApi.isGravityInverted(entity) ? 1.0D : -1.0D;
entity.setDeltaMovement(entity.getDeltaMovement().add(0.0D, downSign * CRUSHING_GRAVITY_STRENGTH, 0.0D));
entity.hasImpulse = true;
if (entity instanceof LivingEntity living && this.tickCount % 8 == 0) {
this.spawnCrushingGravityArrow(level, living, downSign, 1.0D);
}
}
if (this.tickCount % 8 == 0) {
level.sendParticles(ACCEL_DUST, this.getX(), this.getY() + 1.0D, this.getZ(), 20,
@@ -1756,6 +1892,7 @@ public class QueenEntity extends RoyalBossEntity {
}
this.royalEffects.clear();
this.frozenVelocities.clear();
this.frozenPositions.clear();
removeAccelModifier(this.getAttribute(Attributes.MOVEMENT_SPEED), ACCEL_SPEED_ID);
removeAccelModifier(this.getAttribute(Attributes.FLYING_SPEED), ACCEL_FLY_ID);
super.die(damageSource);
@@ -1804,6 +1941,8 @@ public class QueenEntity extends RoyalBossEntity {
tag.putInt("DebrisCycloneCooldownTicks", this.debrisCycloneCooldownTicks);
tag.putInt("GraviticUpheavalCooldownTicks", this.graviticUpheavalCooldownTicks);
tag.putInt("QueenLandingCooldownTicks", this.queenLandingCooldownTicks);
tag.putBoolean("PendingPhaseTwoCrushingGravity", this.pendingPhaseTwoCrushingGravity);
tag.putBoolean("PendingPhaseThreeChronosphere", this.pendingPhaseThreeChronosphere);
tag.putString("QueuedQueenFollowUp", this.queuedQueenFollowUp.name());
tag.putInt("QueuedQueenFollowUpTicks", this.queuedQueenFollowUpTicks);
tag.putInt("QueuedQueenLandingRetryTicks", this.queuedQueenLandingRetryTicks);
@@ -1830,7 +1969,9 @@ public class QueenEntity extends RoyalBossEntity {
this.debrisCycloneCooldownTicks = Math.max(0, tag.getInt("DebrisCycloneCooldownTicks"));
this.graviticUpheavalCooldownTicks = Math.max(0, tag.getInt("GraviticUpheavalCooldownTicks"));
this.queenLandingCooldownTicks = tag.contains("QueenLandingCooldownTicks")
? Math.max(0, tag.getInt("QueenLandingCooldownTicks")) : 300;
? Math.max(0, tag.getInt("QueenLandingCooldownTicks")) : 200;
this.pendingPhaseTwoCrushingGravity = tag.getBoolean("PendingPhaseTwoCrushingGravity");
this.pendingPhaseThreeChronosphere = tag.getBoolean("PendingPhaseThreeChronosphere");
if (tag.contains("QueuedQueenFollowUp")) {
try {
this.queuedQueenFollowUp = QueenFollowUp.valueOf(tag.getString("QueuedQueenFollowUp"));
@@ -32,6 +32,16 @@ public final class RoyalAssailantBlackHoleEntity extends RoyalBlackHoleEntity {
return Math.max(2.0D, this.radius() * 0.55D);
}
@Override
protected double effectGrowthStart() {
return 0.45D;
}
@Override
protected double pullRadius() {
return this.effectRadius();
}
@Override
protected boolean hasVisibleTimeDilationField() {
return false;
@@ -67,6 +67,8 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
private static final double EFFECT_GROWTH_START = 0.45D;
private static final double EFFECT_GROWTH_END = 1.6D;
private static final double EFFECT_GROWTH_FRACTION = 0.6D;
private static final double QUEEN_EFFECT_GROWTH_START = EFFECT_GROWTH_START * 1.5D;
private static final double QUEEN_PULL_RADIUS_SCALE = 2.0D;
private static final double MODEL_BASELINE_Y = 24.0D;
private static final double CORE_CUBE_CENTER_Y = 146.0D;
private static final double CORE_START_OFFSET_Y = -100.0D;
@@ -143,7 +145,11 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
double progress = this.activeTicks <= 0
? 1.0D
: Mth.clamp(this.age / (this.activeTicks * EFFECT_GROWTH_FRACTION), 0.0D, 1.0D);
return this.radius() * Mth.lerp(progress, EFFECT_GROWTH_START, EFFECT_GROWTH_END);
return this.radius() * Mth.lerp(progress, this.effectGrowthStart(), EFFECT_GROWTH_END);
}
protected double effectGrowthStart() {
return QUEEN_EFFECT_GROWTH_START;
}
public boolean isCollapsing() {
@@ -228,6 +234,10 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
return true;
}
protected double pullRadius() {
return this.effectRadius() * QUEEN_PULL_RADIUS_SCALE;
}
/** 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);
@@ -269,7 +279,7 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
private void applyPull() {
Vec3 center = this.effectCenter();
double radius = this.effectRadius();
double radius = this.pullRadius();
for (Entity entity : this.level().getEntitiesOfClass(Entity.class, new AABB(center, center).inflate(radius))) {
if (entity == this || entity instanceof TimeDilationFieldEntity || this.isImmune(entity)) {
continue;
@@ -302,9 +312,10 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
Vec3 center = this.effectCenter();
Vec3 terrainOrigin = center;
double radius = this.effectRadius();
double radius = this.pullRadius();
int pulledThisTick = 0;
for (int attempt = 0; attempt < BLOCK_SUCTION_ATTEMPTS && pulledThisTick < BLOCKS_PER_SUCTION
int suctionAttempts = BLOCK_SUCTION_ATTEMPTS * 4;
for (int attempt = 0; attempt < suctionAttempts && pulledThisTick < BLOCKS_PER_SUCTION
&& this.suckedBlocks < cap; attempt++) {
BlockPos pos = BlockPos.containing(
terrainOrigin.x + (this.random.nextDouble() * 2.0D - 1.0D) * radius,
@@ -339,6 +339,11 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
return Math.max(10, Mth.floor(AntarchySettings.royalBossBiteCooldownTicks() * phase.cooldownScale()));
}
/** Allows either royal boss to tune bite damage without changing the other. */
protected double biteDamageMultiplier() {
return AntarchySettings.royalBossBiteDamageMultiplier();
}
public String geoNameForRender() {
return this.geoName();
}
@@ -543,19 +548,21 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
}
this.initializeMultiplayerScaling(primaryTarget);
this.assignHeadTargets(primaryTarget);
this.tickCombatLocomotionMode(primaryTarget);
if (this.blocksRoyalAttacksForMovement()) {
boolean movementBlocksAttacks = this.blocksRoyalAttacksForMovement();
if (!movementBlocksAttacks) {
boolean aeriallyStabilized = this.steerTowardTarget(primaryTarget);
if (!aeriallyStabilized) {
this.getLookControl().setLookAt(primaryTarget, 30.0F, 30.0F);
}
}
this.tickRoyalBeam(primaryTarget,
!movementBlocksAttacks && !this.blocksRoyalBeamScheduling());
if (movementBlocksAttacks) {
return;
}
boolean aeriallyStabilized = this.steerTowardTarget(primaryTarget);
if (!aeriallyStabilized) {
this.getLookControl().setLookAt(primaryTarget, 30.0F, 30.0F);
}
this.assignHeadTargets(primaryTarget);
if (!this.blocksRoyalBeamScheduling()) {
this.tickRoyalBeam(primaryTarget);
}
this.tickBodyCrush();
Phase phase = this.phase();
@@ -590,10 +597,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|| super.isInvulnerableTo(source);
}
private void tickRoyalBeam(LivingEntity primaryTarget) {
if (this.recoveryWindowTicks > 0) {
return;
}
private void tickRoyalBeam(LivingEntity primaryTarget, boolean allowScheduling) {
Phase phase = this.phase();
int activeBeams = 0;
for (RoyalHead head : this.heads) {
@@ -625,7 +629,8 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
beamTarget,
this.royalBeamSettings(),
this.royalBeamTerrainMode(head),
end -> this.setRoyalBeamEndPosition(head.slot(), end));
end -> this.setRoyalBeamEndPosition(head.slot(), end),
this.royalBeamUsesTrackedAim());
Vec3 beamEnd = controller.beamEndPosition();
if (beamEnd != null) {
this.tickRoyalBeamEffects(head, this.beamAnchor(head), beamEnd);
@@ -635,6 +640,12 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
}
continue;
}
}
if (!allowScheduling || this.recoveryWindowTicks > 0) {
return;
}
for (RoyalHead head : this.heads) {
int index = head.slot().ordinal();
if (activeBeams >= this.beamVolleyLimit) {
continue;
}
@@ -694,6 +705,11 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
return phase.maxConcurrentHeadAttacks();
}
/** Uses the beam controller's smoothed target point instead of the boss body's forward axis. */
protected boolean royalBeamUsesTrackedAim() {
return false;
}
protected boolean isRoyalRecoveryActive() {
return this.recoveryWindowTicks > 0;
}
@@ -786,6 +802,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
protected final void stopRoyalBeamsForDirectedAttack() {
for (RoyalHead head : this.heads) {
if (head.beamActive() || head.shooting()) {
this.attackScheduler.cancel(this.headLane(head));
this.stopRoyalBeam(head);
}
}
@@ -1059,7 +1076,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
}
Vec3 anchor = this.headAnchor(head);
double reach = this.biteReach();
float damage = (float) (this.getAttributeValue(Attributes.ATTACK_DAMAGE) * AntarchySettings.royalBossBiteDamageMultiplier());
float damage = (float) (this.getAttributeValue(Attributes.ATTACK_DAMAGE) * this.biteDamageMultiplier());
DamageSource damageSource = this.damageSources().mobAttack(this);
AABB box = new AABB(anchor, anchor).inflate(reach);
for (LivingEntity living : this.level().getEntitiesOfClass(LivingEntity.class, box, entity -> entity.isAlive() && entity != this)) {
@@ -1122,7 +1139,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
AntarchyGravityApi.getGravityDirection(this)).normalize();
}
private boolean targetInBeamLine(RoyalHead head, LivingEntity target) {
protected boolean targetInBeamLine(RoyalHead head, LivingEntity target) {
Vec3 origin = this.beamAnchor(head);
Vec3 direction = this.beamDirection(head);
Vec3 toTarget = target.getEyePosition().subtract(origin);
@@ -88,6 +88,18 @@ public final class RoyalBeamController {
RoyalBeamSettings settings,
RoyalBeamTerrainMode terrainMode,
Consumer<@Nullable Vec3> syncedEndPosition
) {
this.tick(shootFrom, shootDirection, target, settings, terrainMode, syncedEndPosition, false);
}
public void tick(
Vec3 shootFrom,
Vec3 shootDirection,
@Nullable LivingEntity target,
RoyalBeamSettings settings,
RoyalBeamTerrainMode terrainMode,
Consumer<@Nullable Vec3> syncedEndPosition,
boolean useTrackedTargetAim
) {
if (this.beamTicks <= 0) {
syncedEndPosition.accept(null);
@@ -111,7 +123,10 @@ public final class RoyalBeamController {
return;
}
Vec3 direction = shootDirection.lengthSqr() < 1.0E-7D
Vec3 trackedDirection = this.serverTarget.subtract(shootFrom);
Vec3 direction = useTrackedTargetAim && trackedDirection.lengthSqr() >= 1.0E-7D
? trackedDirection.normalize()
: shootDirection.lengthSqr() < 1.0E-7D
? this.owner.getLookAngle().normalize()
: shootDirection.normalize();
double committedDistance = Math.min(settings.range(), Math.max(settings.pathStep(),
@@ -1,55 +0,0 @@
package com.craisinlord.antarchy.content.fluid;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BubbleColumnBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
/** Converts a full Antiwater cell next to a vanilla bubble-column source. */
public final class AntiwaterBubbleColumnUtil {
private AntiwaterBubbleColumnUtil() {
}
public static void update(LevelAccessor level, BlockPos pos, FluidState fluidState) {
if (!AntarchyFluidChecks.isAntiwater(fluidState)
|| (!fluidState.isSource() && fluidState.getAmount() < 7)) {
return;
}
BlockState below = level.getBlockState(pos.below());
if (isBubbleSource(below)) {
replaceColumn(level, pos, Direction.UP, below.is(Blocks.MAGMA_BLOCK));
return;
}
BlockState above = level.getBlockState(pos.above());
if (isBubbleSource(above)) {
replaceColumn(level, pos, Direction.DOWN, above.is(Blocks.MAGMA_BLOCK));
}
}
private static boolean isBubbleSource(BlockState state) {
return state.is(Blocks.MAGMA_BLOCK) || state.is(Blocks.SOUL_SAND);
}
private static void replaceColumn(LevelAccessor level, BlockPos start, Direction direction, boolean dragDown) {
BlockPos.MutableBlockPos cursor = start.mutable();
BlockState columnState = Blocks.BUBBLE_COLUMN.defaultBlockState()
.setValue(BubbleColumnBlock.DRAG_DOWN, dragDown);
while (true) {
BlockState state = level.getBlockState(cursor);
FluidState fluidState = state.getFluidState();
if (!AntarchyFluidChecks.isAntiwater(fluidState)
&& !state.is(Blocks.BUBBLE_COLUMN)) {
return;
}
level.setBlock(cursor, columnState, 3);
cursor.move(direction);
}
}
}
@@ -47,6 +47,7 @@ public final class ThoraxisUndersideManager {
private static final int CROSSING_TIMEOUT_TICKS = 100;
private static final int SETTLE_TIMEOUT_TICKS = 70;
private static final double MIN_CROSSING_SPEED = 0.48D;
private static final double MIN_ENTRY_CROSSING_SPEED = 0.02D;
private static final int RECENT_UNDERSIDE_WINDOW_TICKS = 40;
private static final int UNDERSIDE_ENTRY_BORDER_Y = GRAVITY_FLIP_Y - 7;
private static final int FRESH_ENTRY_DELAY_TICKS = 20;
@@ -225,6 +226,16 @@ public final class ThoraxisUndersideManager {
continue;
}
if (AntarchyGravityApi.getGravityDirection(player) == AntarchyGravityDirection.DOWN
&& player.getY() < UNDERSIDE_ENTRY_BORDER_Y
&& flipReady(tracking, player.getUUID(), now)) {
AntarchyGravityApi.setAirborneGravityDirection(player, AntarchyGravityDirection.UP, true, THROAT_TRANSITION);
player.resetFallDistance();
tracking.lastFlipTick.put(player.getUUID(), now);
refreshInvertedEffect(player);
continue;
}
if (AntarchyGravityApi.isGravityInverted(player) && player.getY() < EXIT_UNDERSIDE_Y) {
refreshInvertedEffect(player);
}
@@ -297,7 +308,7 @@ public final class ThoraxisUndersideManager {
AABB swept = player.getBoundingBox().expandTowards(velocity.scale(-1.0D)).inflate(0.08D);
AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(player);
return direction == AntarchyGravityDirection.DOWN
? swept.minY < UNDERSIDE_ENTRY_BORDER_Y && swept.maxY >= UNDERSIDE_ENTRY_BORDER_Y && velocity.y <= -MIN_CROSSING_SPEED
? swept.minY < UNDERSIDE_ENTRY_BORDER_Y && swept.maxY >= UNDERSIDE_ENTRY_BORDER_Y && velocity.y <= -MIN_ENTRY_CROSSING_SPEED
: swept.minY <= GRAVITY_FLIP_Y && swept.maxY > GRAVITY_FLIP_Y && velocity.y >= MIN_CROSSING_SPEED;
}
@@ -0,0 +1,32 @@
package com.craisinlord.antarchy.mixins;
import com.craisinlord.antarchy.content.block.entity.UndertrialSpawnContext;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.SpawnPlacements;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* Lets the Undertrial's vanilla TrialSpawner path spawn entities whose normal
* placement predicate assumes floor support. TrialSpawner already performs
* its own no-collision and obstruction checks before this method is reached.
*/
@Mixin(SpawnPlacements.class)
public abstract class UndertrialSpawnPlacementsMixin {
@Inject(method = "checkSpawnRules", at = @At("RETURN"), cancellable = true)
private static <T extends net.minecraft.world.entity.Entity> void antarchy$allowUndertrialSpawn(
net.minecraft.world.entity.EntityType<T> entityType,
net.minecraft.world.level.ServerLevelAccessor level,
MobSpawnType spawnReason,
net.minecraft.core.BlockPos pos,
net.minecraft.util.RandomSource random,
CallbackInfoReturnable<Boolean> cir) {
if (!cir.getReturnValueZ()
&& spawnReason == MobSpawnType.TRIAL_SPAWNER
&& UndertrialSpawnContext.isActive()) {
cir.setReturnValue(true);
}
}
}
@@ -30,6 +30,7 @@
"KingsTreeLocateCommandMixin",
"LivingEntityJumpingAccessor",
"CommandedMobMixin",
"UndertrialSpawnPlacementsMixin",
"LivingEntityRoyalEffectsMixin",
"JudgmentMarkEntityMixin",
"RoyalJudgmentCombatMixin",
@@ -388,6 +388,8 @@
"item.antarchy.nightmare_scale": "Nightmare Scale",
"item.antarchy.music_disc_underside": "Music Disc",
"jukebox_song.antarchy.underside": "docshrekbot - underside",
"item.antarchy.music_disc_the_queen": "Music Disc",
"jukebox_song.antarchy.the_queen": "The Queen",
"item.antarchy.nightmare_helmet": "Nightmare Helmet",
"item.antarchy.nightmare_chestplate": "Nightmare Chestplate",
"item.antarchy.nightmare_leggings": "Nightmare Leggings",
@@ -543,7 +545,7 @@
"item.antarchy.royal_guardian_boots": "Royal Guardian Boots",
"item.antarchy.royal_guardian_sword": "Royal Guardian Sword",
"item.antarchy.royal_guardian_shield": "Royal Guardian Shield",
"tooltip.antarchy.royal_guardian_sword.mode": "Attunement: %s",
"tooltip.antarchy.royal_guardian_sword.mode": "Mode: %s",
"tooltip.antarchy.royal_guardian_sword.mode.fire": "Fire",
"tooltip.antarchy.royal_guardian_sword.mode.frost": "Frost",
"tooltip.antarchy.royal_guardian_sword.mode.storm": "Storm",
@@ -551,7 +553,7 @@
"tooltip.antarchy.royal_guardian_sword.frost": "Fully charged hits freeze the target and raise a fan of royal ice spikes.",
"tooltip.antarchy.royal_guardian_sword.storm": "Fully charged hits call royal lightning that chains between nearby enemies.",
"tooltip.antarchy.royal_guardian_sword.controls": "Sneak-use to cycle modes. Fully charged hits unleash the selected element (%s-second cooldown).",
"message.antarchy.royal_guardian_sword.mode": "Royal Guardian attuned to %s",
"message.antarchy.royal_guardian_sword.mode": "Royal Guardian Mode: %s",
"item.antarchy.royal_assailant_helmet": "Royal Assailant Helmet",
"item.antarchy.royal_assailant_chestplate": "Royal Assailant Chestplate",
"item.antarchy.royal_assailant_leggings": "Royal Assailant Leggings",
@@ -561,10 +563,10 @@
"tooltip.antarchy.royal_assailant_staff": "Opens paired tears that summon four allied Manticores for 30 seconds.",
"tooltip.antarchy.royal_assailant_battleaxe.black_hole": "Use to create a Black Hole",
"tooltip.antarchy.royal_assailant_battleaxe.dilation": "Hits apply Temporal Dilation",
"tooltip.antarchy.royal_guardian_shield.command": "Sneak-use to muster nearby mobs. Royal Investiture empowers their offense, speed, and resilience.",
"tooltip.antarchy.royal_guardian_shield.command": "Sneak-use to command nearby mobs to fight for you, empowering their offense, speed, and resilience.",
"tooltip.antarchy.royal_guardian_helmet.judgment": "Marked for Judgment: +%s%% damage against marked targets",
"tooltip.antarchy.royal_guardian_chestplate.judgment": "Marked for Judgment: +%s%% damage against marked targets",
"tooltip.antarchy.royal_guardian_chestplate.boundary": "Royal Boundary (B by default): Freezes incoming hostile projectiles and grants Strength to allies.",
"tooltip.antarchy.royal_guardian_chestplate.boundary": "Royal Boundary Key: Freezes incoming hostile projectiles and grants Strength to allies.",
"tooltip.antarchy.royal_guardian_leggings.judgment": "Marked for Judgment: +%s%% damage against marked targets",
"tooltip.antarchy.royal_guardian_boots.judgment": "Marked for Judgment: +%s%% damage against marked targets",
"tooltip.antarchy.royal_assailant_chestplate.invert": "Press the inversion key to toggle inverted gravity on and off.",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "antarchy:item/music_disc_the_queen"
}
}
@@ -1065,6 +1065,14 @@
}
]
},
"the_queen": {
"sounds": [
{
"name": "antarchy:music/game/thoraxis/the_queen",
"stream": true
}
]
},
"lucid_lullaby": {
"sounds": [
{
Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

@@ -0,0 +1,8 @@
{
"sound_event": "antarchy:the_queen",
"description": {
"translate": "jukebox_song.antarchy.the_queen"
},
"length_in_seconds": 180.0,
"comparator_output": 13
}
@@ -2,6 +2,21 @@
"type": "minecraft:entity",
"random_sequence": "antarchy:entities/queen",
"pools": [
{
"rolls": 1.0,
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:killed_by_player"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "antarchy:music_disc_the_queen"
}
]
},
{
"rolls": 1.0,
"bonus_rolls": 0.0,
@@ -0,0 +1,7 @@
{
"replace": false,
"values": [
"antarchy:music_disc_underside",
"antarchy:music_disc_the_queen"
]
}
@@ -1,9 +1,12 @@
package com.craisinlord.antarchy.fabric.client;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.client.QueenMusicHandler;
import com.craisinlord.antarchy.content.client.game.AntarchyComputerGames;
import com.craisinlord.antarchy.fabric.network.AntarchyFabricClientNetworking;
import com.craisinlord.antarchy.fabric.registry.AntarchyFabricSounds;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.resources.ResourceLocation;
@@ -18,6 +21,7 @@ import java.util.concurrent.Executor;
public final class AntarchyFabricClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
ClientTickEvents.END_CLIENT_TICK.register(client -> QueenMusicHandler.tick(client, AntarchyFabricSounds.THE_QUEEN.get()));
AntarchyFabricClientNetworking.register();
AntarchyFabricClientNetworking.bootstrapMultipartClient();
AntarchyFabricClientBootstrap.register();
@@ -1,5 +1,4 @@
package com.craisinlord.antarchy.fabric.content.fluid;
import com.craisinlord.antarchy.content.fluid.AntiwaterBubbleColumnUtil;
import com.craisinlord.antarchy.fabric.registry.AntarchyFabricBlocks;
import com.craisinlord.antarchy.fabric.registry.AntarchyFabricItems;
import com.craisinlord.antarchy.fabric.registry.AntarchyFabricMisc;
@@ -170,8 +169,6 @@ public abstract class AntiwaterFluid extends FlowingFluid {
return;
}
AntiwaterBubbleColumnUtil.update(level, pos, state);
if (!state.isSource() && !this.isFlowingStateValid(level, pos, state)) {
level.setBlockAndUpdate(pos, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState());
this.scheduleCleanup(level, pos);
@@ -92,6 +92,11 @@ public final class AntarchyFabricItems {
.jukeboxPlayable(ResourceKey.create(Registries.JUKEBOX_SONG,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "underside"))));
public static final DeferredItem<Item> MUSIC_DISC_THE_QUEEN = ITEMS.registerSimpleItem("music_disc_the_queen",
new Item.Properties().stacksTo(1).rarity(Rarity.RARE)
.jukeboxPlayable(ResourceKey.create(Registries.JUKEBOX_SONG,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "the_queen"))));
public static final DeferredItem<Item> PRIMORDIAL_SCUTE = ITEMS.registerSimpleItem("primordial_scute",
new Item.Properties().rarity(Rarity.UNCOMMON));
@@ -528,6 +528,7 @@ public final class AntarchyFabricSounds {
public static final DeferredHolder<SoundEvent, SoundEvent> POTENT_NYXITE_GEYSER_CONTINUOUS_ACTIVE = registerSoundEvent("potent_nyxite_geyser_continuous_active");
public static final DeferredHolder<SoundEvent, SoundEvent> MUSIC_DISC_UNDERSIDE = registerSoundEvent("music_disc_underside");
public static final DeferredHolder<SoundEvent, SoundEvent> THE_QUEEN = registerSoundEvent("the_queen");
public static final DeferredHolder<SoundEvent, SoundEvent> WORM_HOOK_FLYING = registerSoundEvent("worm_hook_flying");
public static final DeferredHolder<SoundEvent, SoundEvent> BLOOD_CRYSTAL_KATANA_DASH = registerSoundEvent("blood_crystal_katana_dash");
public static final DeferredHolder<SoundEvent, SoundEvent> BLOOD_CRYSTAL_ARMOR_EQUIP = registerSoundEvent("blood_crystal_armor_equip");
@@ -686,7 +686,7 @@ public final class AntarchyMobsConfig {
QUEEN_BLACK_HOLE_ACTIVE_TICKS = b.comment("Active duration for Royal Assailant axe black holes. Queen black holes always follow their 20.125-second animation.").defineInRange("queenBlackHoleActiveTicks", 120, 20, 1200);
QUEEN_BLACK_HOLE_PULL_STRENGTH = b.defineInRange("queenBlackHolePullStrength", 0.16D, 0.0D, 2.0D);
QUEEN_BLACK_HOLE_BLOCK_SUCTION_CAP = b.comment("Maximum terrain blocks a single Queen black hole may pull into itself.").defineInRange("queenBlackHoleBlockSuctionCap", 160, 0, 4096);
KING_FIREBALL_DAMAGE = b.defineInRange("kingFireballDamage", 32.0D, 0.0D, 1024.0D);
KING_FIREBALL_DAMAGE = b.defineInRange("kingFireballDamage", 48.0D, 0.0D, 1024.0D);
KING_FIREBALL_RADIUS = b.defineInRange("kingFireballRadius", 4.5D, 0.5D, 32.0D);
KING_FIREBALL_COOLDOWN_TICKS = b.defineInRange("kingFireballCooldownTicks", 150, 1, 2400);
KING_ICEBALL_DAMAGE = b.defineInRange("kingIceballDamage", 18.0D, 0.0D, 1024.0D);
@@ -0,0 +1,22 @@
package com.craisinlord.antarchy.neoforge.client;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.client.QueenMusicHandler;
import com.craisinlord.antarchy.neoforge.registry.AntarchyNeoforgeSounds;
import net.minecraft.client.Minecraft;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class QueenMusicClientHandler {
private QueenMusicClientHandler() {
}
@SubscribeEvent
public static void onClientTick(ClientTickEvent.Post event) {
Minecraft minecraft = Minecraft.getInstance();
QueenMusicHandler.tick(minecraft, AntarchyNeoforgeSounds.THE_QUEEN.get());
}
}
@@ -1,6 +1,5 @@
package com.craisinlord.antarchy.neoforge.content.fluid;
import com.craisinlord.antarchy.content.fluid.AntiwaterBubbleColumnUtil;
import com.craisinlord.antarchy.neoforge.registry.AntarchyNeoforgeBlocks;
import java.util.HashSet;
import java.util.Set;
@@ -174,8 +173,6 @@ public abstract class AntiwaterFluid extends BaseFlowingFluid {
return;
}
AntiwaterBubbleColumnUtil.update(level, pos, state);
if (!state.isSource() && !this.isFlowingStateValid(level, pos, state)) {
level.setBlockAndUpdate(pos, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState());
this.scheduleCleanup(level, pos);
@@ -100,6 +100,11 @@ public final class AntarchyNeoforgeItems {
.jukeboxPlayable(ResourceKey.create(Registries.JUKEBOX_SONG,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "underside"))));
public static final DeferredItem<Item> MUSIC_DISC_THE_QUEEN = ITEMS.registerSimpleItem("music_disc_the_queen",
new Item.Properties().stacksTo(1).rarity(Rarity.RARE)
.jukeboxPlayable(ResourceKey.create(Registries.JUKEBOX_SONG,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "the_queen"))));
private static final DeferredHolder<ArmorMaterial, ArmorMaterial> ULTIMATE_ARMOR_MATERIAL = ARMOR_MATERIALS.register("ultimate",
() -> new ArmorMaterial(
createUltimateArmorDefense(),
@@ -205,6 +205,7 @@ public final class AntarchyNeoforgeSounds {
public static final DeferredHolder<SoundEvent, SoundEvent> POTENT_NYXITE_GEYSER_CONTINUOUS_START = registerSoundEvent("potent_nyxite_geyser_continuous_start");
public static final DeferredHolder<SoundEvent, SoundEvent> POTENT_NYXITE_GEYSER_CONTINUOUS_ACTIVE = registerSoundEvent("potent_nyxite_geyser_continuous_active");
public static final DeferredHolder<SoundEvent, SoundEvent> MUSIC_DISC_UNDERSIDE = registerSoundEvent("music_disc_underside");
public static final DeferredHolder<SoundEvent, SoundEvent> THE_QUEEN = registerSoundEvent("the_queen");
public static final DeferredHolder<SoundEvent, SoundEvent> WORM_HOOK_FLYING = registerSoundEvent("worm_hook_flying");
public static final DeferredHolder<SoundEvent, SoundEvent> BLOOD_CRYSTAL_KATANA_DASH = registerSoundEvent("blood_crystal_katana_dash");
public static final DeferredHolder<SoundEvent, SoundEvent> BLOOD_CRYSTAL_ARMOR_EQUIP = registerSoundEvent("blood_crystal_armor_equip");