fixed game dev not working

various fabric issues
added archives to loot tables
This commit is contained in:
craisinlord committed 2026-09-19 01:01:13 -05:00
1 parent f5b589b6ba
commit c6b47b496a
102 files changed
+926 -139

No files matched your search

@@ -240,7 +240,7 @@ public final class AntarchySettings {
private static double royalGuardianSwordStormJumpRange = 9.0D;
private static double royalAssailantBattleAxeAttackDamage = 151.0D;
private static double royalAssailantBattleAxeAttackSpeed = -2.9D;
private static double royalWeaponAttackReachBonus = 1.0D;
private static double royalWeaponAttackReachBonus = 3.2D;
private static double royalWeaponAttackKnockbackBonus = 1.0D;
private static int royalWeaponDurability = 4608;
private static int royalWeaponEnchantability = 30;
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.block;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.block.entity.RoyalEggBlockEntity;
import com.craisinlord.antarchy.content.entity.royal.RoyalMountEntity;
import com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -18,6 +19,7 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.level.LevelAccessor;
@@ -30,6 +32,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.phys.shapes.CollisionContext;
@@ -39,6 +42,7 @@ import org.jetbrains.annotations.Nullable;
public abstract class RoyalEggBlock extends BaseEntityBlock {
public static final IntegerProperty HATCH = BlockStateProperties.HATCH;
public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
private static final int MAX_HATCH = 2;
private static final int FALL_DELAY = 2;
@@ -49,16 +53,23 @@ public abstract class RoyalEggBlock extends BaseEntityBlock {
Block.box(5.0D, 14.0D, 5.0D, 11.0D, 15.0D, 11.0D),
Block.box(6.0D, 15.0D, 6.0D, 10.0D, 16.0D, 10.0D));
private static final VoxelShape INVERTED_SHAPE = Shapes.or(
Block.box(3.0D, 3.0D, 3.0D, 13.0D, 16.0D, 13.0D),
Block.box(2.0D, 5.0D, 2.0D, 14.0D, 15.0D, 14.0D),
Block.box(4.0D, 2.0D, 4.0D, 12.0D, 3.0D, 12.0D),
Block.box(5.0D, 1.0D, 5.0D, 11.0D, 2.0D, 11.0D),
Block.box(6.0D, 0.0D, 6.0D, 10.0D, 1.0D, 10.0D));
protected RoyalEggBlock(Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(HATCH, 0));
this.registerDefaultState(this.stateDefinition.any().setValue(HATCH, 0).setValue(INVERTED, false));
}
protected abstract EntityType<? extends RoyalMountEntity> mountType();
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(HATCH);
builder.add(HATCH, INVERTED);
}
@Override
@@ -68,7 +79,16 @@ public abstract class RoyalEggBlock extends BaseEntityBlock {
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return SHAPE;
return state.getValue(INVERTED) ? INVERTED_SHAPE : SHAPE;
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(INVERTED, isInvertedGravityAt(context.getLevel(), context.getClickedPos()));
}
private static boolean isInvertedGravityAt(Level level, BlockPos pos) {
return ThoraxisUndersideManager.isThoraxis(level) && pos.getY() < ThoraxisUndersideManager.GRAVITY_FLIP_Y;
}
@Nullable
@@ -105,7 +125,8 @@ public abstract class RoyalEggBlock extends BaseEntityBlock {
UUID placer = source == null ? null : source.getPlacerUuid();
int hatch = state.getValue(HATCH);
level.setBlock(pos, Blocks.AIR.defaultBlockState(), 2);
level.setBlock(target, state.setValue(HATCH, Math.max(0, hatch - 1)), 2);
level.setBlock(target, state.setValue(HATCH, Math.max(0, hatch - 1))
.setValue(INVERTED, isInvertedGravityAt(level, target)), 2);
if (level.getBlockEntity(target) instanceof RoyalEggBlockEntity moved) {
moved.setPlacerUuid(placer);
}
@@ -129,6 +150,12 @@ public abstract class RoyalEggBlock extends BaseEntityBlock {
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
boolean inverted = state.getValue(INVERTED);
if (inverted) {
tickInvertedFall(state, level, pos);
return;
}
if (!FallingBlock.isFree(level.getBlockState(pos.below())) || pos.getY() < level.getMinBuildHeight()) {
return;
}
@@ -141,6 +168,26 @@ public abstract class RoyalEggBlock extends BaseEntityBlock {
}
}
/**
* Vanilla FallingBlockEntity always falls in world-down direction, so an
* unsupported egg placed with inverted underside gravity is stepped
* upward toward its support instead of being handed to that entity.
*/
private void tickInvertedFall(BlockState state, ServerLevel level, BlockPos pos) {
BlockPos above = pos.above();
if (!FallingBlock.isFree(level.getBlockState(above)) || above.getY() > level.getMaxBuildHeight()) {
return;
}
UUID placer = level.getBlockEntity(pos) instanceof RoyalEggBlockEntity egg ? egg.getPlacerUuid() : null;
level.removeBlock(pos, false);
level.setBlock(above, state, Block.UPDATE_ALL);
if (level.getBlockEntity(above) instanceof RoyalEggBlockEntity moved) {
moved.setPlacerUuid(placer);
}
level.scheduleTick(above, this, FALL_DELAY);
}
@Override
protected boolean isRandomlyTicking(BlockState state) {
return true;
@@ -0,0 +1,15 @@
package com.craisinlord.antarchy.content.client;
import com.craisinlord.antarchy.content.entity.nightmare.NightmareEntity;
import com.craisinlord.antos.api.client.archive.ArchiveEntityPreviewRegistry;
import net.minecraft.resources.ResourceLocation;
public final class AntarchyArchivePreviews {
private AntarchyArchivePreviews() {}
public static void register() {
ArchiveEntityPreviewRegistry.register(ResourceLocation.fromNamespaceAndPath("antarchy", "nightmare"), entity -> {
if (entity instanceof NightmareEntity nightmare) nightmare.setArchivePreviewFlying();
});
}
}
@@ -0,0 +1,128 @@
package com.craisinlord.antarchy.content.client;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.entity.HoverboardEntity;
import com.craisinlord.antarchy.mixins.LivingEntityJumpingAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class HoverboardSoundSystem {
private static final float MIN_PITCH = 0.75F;
private static final float MAX_PITCH = 1.6F;
private static final float MIN_VOLUME = 0.45F;
private static final float MAX_VOLUME = 0.8F;
private static final Map<Integer, IdleLoopSound> ACTIVE = new HashMap<>();
private HoverboardSoundSystem() {
}
public static void tick() {
Minecraft mc = Minecraft.getInstance();
if (mc.level == null) {
stopAll(mc);
return;
}
if (mc.isPaused()) {
return;
}
Set<Integer> activeIds = new HashSet<>();
for (Entity entity : mc.level.entitiesForRendering()) {
if (!(entity instanceof HoverboardEntity hoverboard) || !hoverboard.isVehicle()) {
continue;
}
int id = hoverboard.getId();
activeIds.add(id);
IdleLoopSound sound = ACTIVE.get(id);
if (sound == null || !mc.getSoundManager().isActive(sound)) {
sound = new IdleLoopSound(hoverboard);
ACTIVE.put(id, sound);
mc.getSoundManager().play(sound);
}
}
ACTIVE.entrySet().removeIf(entry -> {
if (activeIds.contains(entry.getKey())) {
return false;
}
mc.getSoundManager().stop(entry.getValue());
return true;
});
}
private static void stopAll(Minecraft mc) {
ACTIVE.values().forEach(mc.getSoundManager()::stop);
ACTIVE.clear();
}
private static final class IdleLoopSound extends AbstractTickableSoundInstance {
private final HoverboardEntity hoverboard;
private double lastX;
private double lastZ;
private IdleLoopSound(HoverboardEntity hoverboard) {
super(AntarchySoundEvents.HOVERBOARD_IDLE.get(), SoundSource.NEUTRAL, RandomSource.create());
this.hoverboard = hoverboard;
this.looping = true;
this.delay = 0;
this.relative = false;
this.attenuation = SoundInstance.Attenuation.LINEAR;
this.volume = MIN_VOLUME;
this.pitch = MIN_PITCH;
this.x = hoverboard.getX();
this.y = hoverboard.getY();
this.z = hoverboard.getZ();
this.lastX = this.x;
this.lastZ = this.z;
}
@Override
public void tick() {
if (this.hoverboard.isRemoved() || !this.hoverboard.isVehicle()) {
this.stop();
return;
}
double dx = this.hoverboard.getX() - this.lastX;
double dz = this.hoverboard.getZ() - this.lastZ;
double speed = Math.sqrt(dx * dx + dz * dz);
this.lastX = this.hoverboard.getX();
this.lastZ = this.hoverboard.getZ();
this.x = this.hoverboard.getX();
this.y = this.hoverboard.getY();
this.z = this.hoverboard.getZ();
double maxSpeed = Math.max(AntarchySettings.hoverboardMaxSpeed(), 0.0001D);
float speedRatio = (float) Mth.clamp(speed / maxSpeed, 0.0D, 1.0D);
boolean jumping = false;
Entity passenger = this.hoverboard.getControllingPassenger();
if (passenger instanceof net.minecraft.world.entity.player.Player player) {
jumping = ((LivingEntityJumpingAccessor) player).antarchy$isJumping();
}
boolean movingUpward = this.hoverboard.getDeltaMovement().y > 0.02D;
float liftRatio = jumping || movingUpward ? 1.0F : 0.0F;
this.volume = Mth.lerp(speedRatio, MIN_VOLUME, MAX_VOLUME);
this.pitch = Mth.lerp(speedRatio, MIN_PITCH, MAX_PITCH)
+ Mth.lerp(liftRatio, 0.0F, 0.2F);
}
@Override
public boolean canStartSilent() {
return true;
}
}
}
@@ -23,12 +23,6 @@ public final class AntarchyComputerGames {
AntarchyGameNetworking.requestBasiliskState(pos);
return new GameSession(() -> { if (!loaded.get()) loaded.set(loadScores(pos, AntarchyGamePayload.BASILISK_STATE, program::setStoredScores)); program.tick(); }, program::render, key -> loaded.get() && program.keyPressed(key), ignored -> false);
}));
registerIfMissing(game("antman", "ANTMAN.EXE", pos -> {
AntmanProgram program = new AntmanProgram(true, 0, 0, score -> AntarchyGameNetworking.saveAntmanScore(pos, score));
var loaded = new java.util.concurrent.atomic.AtomicBoolean();
AntarchyGameNetworking.requestAntmanState(pos);
return new GameSession(() -> { if (!loaded.get()) loaded.set(loadScores(pos, AntarchyGamePayload.ANTMAN_STATE, program::setStoredScores)); program.tick(); }, program::render, key -> loaded.get() && program.keyPressed(key), ignored -> false);
}));
}
private static void registerIfMissing(ComputerGame game) {
@@ -28,11 +28,12 @@ public final class RoyalIndicatorRenderer {
crownPoints(lines, pose, radius, spin, 1.0F, 0.80F, 0.22F, 0.95F);
}
if (judged) {
float markY = commanded ? -0.13F : 0.0F;
float markY = commanded ? -0.13F : 0.08F;
poseStack.translate(0.0D, markY, 0.0D);
pose = poseStack.last();
brackets(lines, pose, radius * 1.18F, -spin * 1.7F);
ring(lines, pose, radius * 0.73F, -spin * 0.7F, 1.0F, 0.91F, 0.48F, 0.85F, 24);
judgmentFlare(lines, pose, radius * 0.82F, spin);
}
poseStack.popPose();
}
@@ -79,6 +80,18 @@ public final class RoyalIndicatorRenderer {
}
}
private static void judgmentFlare(VertexConsumer out, PoseStack.Pose pose, float radius, float rotation) {
// The old mark was almost edge-on from normal gameplay camera angles. Add a vertical,
// unmistakable judgment sigil while keeping the rotating ring as its core.
for (int i = 0; i < 4; i++) {
double angle = rotation + Math.PI * 0.5D * i;
float x = (float) Math.cos(angle) * radius;
float z = (float) Math.sin(angle) * radius;
line(out, pose, x, -0.16F, z, 0.0F, 0.22F, 0.0F, 1.0F, 0.68F, 0.08F, 1.0F);
line(out, pose, 0.0F, 0.22F, 0.0F, -x, -0.16F, -z, 1.0F, 0.91F, 0.35F, 0.95F);
}
}
private static void line(VertexConsumer out, PoseStack.Pose pose,
float x1, float y1, float z1, float x2, float y2, float z2,
float r, float g, float b, float a) {
@@ -0,0 +1,35 @@
package com.craisinlord.antarchy.content.dispenser;
import com.craisinlord.antarchy.content.item.BugSprayItem;
import net.minecraft.core.Direction;
import net.minecraft.core.Position;
import net.minecraft.core.dispenser.BlockSource;
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.phys.Vec3;
public final class BugSprayDispenseBehavior extends DefaultDispenseItemBehavior {
@Override
protected ItemStack execute(BlockSource source, ItemStack stack) {
if (!(source.level() instanceof ServerLevel level)) return stack;
Direction direction = source.state().getValue(DispenserBlock.FACING);
Position position = DispenserBlock.getDispensePosition(source);
Vec3 origin = new Vec3(position.x(), position.y(), position.z());
Vec3 facing = new Vec3(direction.getStepX(), direction.getStepY(), direction.getStepZ());
BugSprayItem.spray(level, origin, facing, origin, net.minecraft.sounds.SoundSource.BLOCKS, source.pos());
stack.setDamageValue(stack.getDamageValue() + 1);
if (stack.getDamageValue() >= stack.getMaxDamage()) {
stack.shrink(1);
}
return stack;
}
@Override
protected void playSound(BlockSource source) {
source.level().levelEvent(1002, source.pos(), 0);
}
}
@@ -96,7 +96,7 @@ public class BomberEntity extends Monster implements GeoEntity {
}
public static boolean canSpawn(EntityType<BomberEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -153,7 +153,7 @@ public class ButterflyEntity extends Animal implements FlyingAnimal, GeoEntity {
}
public static boolean canSpawn(EntityType<ButterflyEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -149,7 +149,7 @@ public class CaterpillarEntity extends Animal implements GeoEntity {
}
public static boolean canSpawn(EntityType<CaterpillarEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -84,7 +84,7 @@ public class CrawlingBlightEntity extends Monster implements GeoEntity {
}
public static boolean canSpawn(EntityType<CrawlingBlightEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
BlockPos belowPos = pos.below();
@@ -235,6 +235,7 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG
|| spawnReason == MobSpawnType.SPAWNER
|| spawnReason == MobSpawnType.TRIAL_SPAWNER
|| spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -218,7 +218,7 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
}
public static boolean canSpawn(EntityType<HerculesBeetleEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
boolean floorSpawn = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP)
@@ -70,7 +70,7 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
@Override
public boolean canBeAffected(MobEffectInstance effectInstance) {
return false;
return effectInstance.getEffect().value() instanceof com.craisinlord.antarchy.content.effect.InvertedMobEffect;
}
public static AttributeSupplier.Builder createAttributes() {
@@ -98,7 +98,7 @@ public class JerryEntity extends Monster implements GeoEntity {
}
public static boolean canSpawn(EntityType<JerryEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, net.minecraft.core.BlockPos pos, net.minecraft.util.RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
return level.getDifficulty() != Difficulty.PEACEFUL
@@ -213,7 +213,7 @@ public class ReverieEntity extends PathfinderMob implements FlyingAnimal, GeoEnt
}
public static boolean canSpawn(EntityType<ReverieEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -110,7 +110,7 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
}
public static boolean canSpawn(EntityType<RollyPollyEntity> entityType, net.minecraft.world.level.ServerLevelAccessor level, net.minecraft.world.entity.MobSpawnType spawnReason, BlockPos pos, net.minecraft.util.RandomSource random) {
if (spawnReason == net.minecraft.world.entity.MobSpawnType.SPAWN_EGG || spawnReason == net.minecraft.world.entity.MobSpawnType.SPAWNER || spawnReason == net.minecraft.world.entity.MobSpawnType.COMMAND) {
if (spawnReason == net.minecraft.world.entity.MobSpawnType.SPAWN_EGG || spawnReason == net.minecraft.world.entity.MobSpawnType.SPAWNER || spawnReason == net.minecraft.world.entity.MobSpawnType.TRIAL_SPAWNER || spawnReason == net.minecraft.world.entity.MobSpawnType.COMMAND) {
return true;
}
@@ -159,6 +159,10 @@ public class ScorpionEntity extends Monster implements GeoEntity {
this.attackCooldownTicks--;
}
if (this.attackAnimTicks > 0) {
if (!this.isAlive()) {
this.resetAttackState();
return;
}
if (!this.level().isClientSide) {
this.tickAttackWindup();
}
@@ -70,7 +70,7 @@ public class SkulkingFrightEntity extends Monster implements GeoEntity {
}
public static boolean canSpawn(EntityType<SkulkingFrightEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
BlockPos belowPos = pos.below();
@@ -87,7 +87,7 @@ public class SpitBugEntity extends Monster implements GeoEntity {
}
public static boolean canSpawn(EntityType<SpitBugEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
return level.getDifficulty() != Difficulty.PEACEFUL
@@ -135,7 +135,7 @@ public class SpringbugEntity extends Monster implements GeoEntity {
}
public static boolean canSpawn(EntityType<SpringbugEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
return level.getDifficulty() != Difficulty.PEACEFUL
@@ -70,7 +70,7 @@ public class StinkBugEntity extends Animal implements GeoEntity {
}
public static boolean canSpawn(EntityType<StinkBugEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
BlockPos belowPos = pos.below();
@@ -97,7 +97,7 @@ public class WaspEntity extends Monster implements GeoEntity, FlyingAnimal {
}
public static boolean canSpawn(EntityType<WaspEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -40,6 +40,8 @@ public final class AntTeleportHelper {
private static final double COMPANION_FOLLOW_RADIUS = 16.0D;
private static final int ARRIVAL_SEARCH_RADIUS = 24;
private static final int ARRIVAL_VERTICAL_SEARCH = 24;
private static final int EXPANDED_ARRIVAL_SEARCH_RADIUS = 48;
private static final int EXPANDED_ARRIVAL_VERTICAL_SEARCH = 48;
private AntTeleportHelper() {
}
@@ -270,10 +272,21 @@ public final class AntTeleportHelper {
@Nullable
private static Vec3 findSafeArrivalPosition(ServerPlayer player, ServerLevel destination, BlockPos preferredPos) {
loadArrivalSearchArea(destination, preferredPos);
loadArrivalSearchArea(destination, preferredPos, ARRIVAL_SEARCH_RADIUS);
int[] yRange = getDimensionYRange(destination);
if (yRange != null) {
return findSafeArrivalPositionInYRange(player, destination, preferredPos, yRange[0], yRange[1]);
Vec3 safePos = findSafeArrivalPositionInYRange(
player, destination, preferredPos, yRange[0], yRange[1], ARRIVAL_SEARCH_RADIUS, ARRIVAL_VERTICAL_SEARCH);
if (safePos != null) {
return safePos;
}
// The bounded search can fail near rough or sparsely-generated terrain.
// Retry once with a wider radius before giving up.
loadArrivalSearchArea(destination, preferredPos, EXPANDED_ARRIVAL_SEARCH_RADIUS);
return findSafeArrivalPositionInYRange(
player, destination, preferredPos, yRange[0], yRange[1],
EXPANDED_ARRIVAL_SEARCH_RADIUS, EXPANDED_ARRIVAL_VERTICAL_SEARCH);
}
Set<BlockPos> candidates = new LinkedHashSet<>();
@@ -318,9 +331,9 @@ public final class AntTeleportHelper {
* bounded area up front so unloaded terrain is not mistaken for an unsafe
* destination and rejected prematurely.
*/
private static void loadArrivalSearchArea(ServerLevel destination, BlockPos preferredPos) {
private static void loadArrivalSearchArea(ServerLevel destination, BlockPos preferredPos, int searchRadius) {
ChunkPos center = new ChunkPos(preferredPos);
int chunkRadius = (ARRIVAL_SEARCH_RADIUS >> 4) + 1;
int chunkRadius = (searchRadius >> 4) + 1;
for (int chunkX = center.x - chunkRadius; chunkX <= center.x + chunkRadius; chunkX++) {
for (int chunkZ = center.z - chunkRadius; chunkZ <= center.z + chunkRadius; chunkZ++) {
destination.getChunk(chunkX, chunkZ);
@@ -347,10 +360,10 @@ public final class AntTeleportHelper {
}
@Nullable
private static Vec3 findSafeArrivalPositionInYRange(ServerPlayer player, ServerLevel destination, BlockPos preferredPos, int minY, int maxY) {
private static Vec3 findSafeArrivalPositionInYRange(ServerPlayer player, ServerLevel destination, BlockPos preferredPos, int minY, int maxY, int searchRadius, int verticalSearch) {
Set<BlockPos> surfaceCandidates = new LinkedHashSet<>();
boolean elythia = destination.dimension() == PermanentPortalType.ELYTHIA.primaryDimension();
for (int radius = 0; radius <= ARRIVAL_SEARCH_RADIUS; radius++) {
for (int radius = 0; radius <= searchRadius; radius++) {
for (int xOff = -radius; xOff <= radius; xOff++) {
for (int zOff = -radius; zOff <= radius; zOff++) {
if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) {
@@ -372,7 +385,7 @@ public final class AntTeleportHelper {
addArrivalCandidate(surfaceCandidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, column));
}
for (int yOffset = 1; yOffset <= ARRIVAL_VERTICAL_SEARCH; yOffset++) {
for (int yOffset = 1; yOffset <= verticalSearch; yOffset++) {
surfaceCandidates.add(surface.above(yOffset));
if (!elythia) {
surfaceCandidates.add(surface.below(yOffset));
@@ -404,7 +417,7 @@ public final class AntTeleportHelper {
// Heightmaps can be stale or unsuitable around structures, so retain a
// bounded exhaustive search as a final generated-terrain attempt in
// dimensions whose configured arrival ranges intentionally allow it.
for (int radius = 0; radius <= ARRIVAL_SEARCH_RADIUS; radius++) {
for (int radius = 0; radius <= searchRadius; radius++) {
for (int xOff = -radius; xOff <= radius; xOff++) {
for (int zOff = -radius; zOff <= radius; zOff++) {
if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) {
@@ -204,7 +204,7 @@ public class FlyingSquirrelEntity extends TamableAnimal implements GeoEntity {
}
public static boolean canSpawn(EntityType<FlyingSquirrelEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.TRIAL_SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
@@ -119,6 +119,7 @@ public class KingEntity extends RoyalBossEntity {
private static final int CLOSE_QUARTERS_APPROACH_TICKS = 120;
private static final int CLOSE_QUARTERS_EXIT_GRACE_TICKS = 40;
private static final int DECREE_RESPONSE_GRACE_TICKS = 30;
private static final int DECREE_ANNOUNCEMENT_TICKS = 40;
private static final int PROJECTILE_PRESSURE_MAX = 60;
private static final int PROJECTILE_PRESSURE_PER_HIT = 10;
private static final int GROUND_ASSAULT_TICKS = 200;
@@ -149,6 +150,7 @@ public class KingEntity extends RoyalBossEntity {
private int treePatrolFailures;
private int decreeCooldownTicks;
private int activeDecreeTicks;
private int decreeAnnouncementTicks;
private int decreeResponseGraceTicks;
private int stompCooldownTicks;
private int wingGustCooldownTicks;
@@ -1366,6 +1368,7 @@ public class KingEntity extends RoyalBossEntity {
this.endDecree(this.getTarget());
this.activeDecree = decree;
this.activeDecreeTicks = 300;
this.decreeAnnouncementTicks = DECREE_ANNOUNCEMENT_TICKS;
this.decreeResponseGraceTicks = DECREE_RESPONSE_GRACE_TICKS;
this.decreeCooldownTicks = 0;
this.closeQuartersEntered.clear();
@@ -1879,6 +1882,7 @@ public class KingEntity extends RoyalBossEntity {
}
this.activeDecree = null;
this.activeDecreeTicks = 0;
this.decreeAnnouncementTicks = 0;
this.decreeRetreatPressure = false;
return;
}
@@ -1892,6 +1896,7 @@ public class KingEntity extends RoyalBossEntity {
return;
}
this.activeDecreeTicks = 300;
this.decreeAnnouncementTicks = DECREE_ANNOUNCEMENT_TICKS;
this.decreeResponseGraceTicks = DECREE_RESPONSE_GRACE_TICKS;
this.activeDecree = this.pickDecree(target);
this.decreeRetreatPressure = false;
@@ -1905,6 +1910,10 @@ public class KingEntity extends RoyalBossEntity {
this.broadcastActiveDecree(level);
}
this.broadcastActiveDecree(level);
if (this.decreeAnnouncementTicks > 0) {
this.decreeAnnouncementTicks--;
return;
}
boolean hasCompletableParticipants = false;
boolean everyParticipantComplete = true;
for (ServerPlayer participant : participants) {
@@ -2024,6 +2033,7 @@ public class KingEntity extends RoyalBossEntity {
}
this.activeDecree = null;
this.activeDecreeTicks = 0;
this.decreeAnnouncementTicks = 0;
this.decreeResponseGraceTicks = 0;
this.decreeRetreatPressure = false;
this.closeQuartersEntered.clear();
@@ -131,6 +131,7 @@ public class StratosharkEntity extends Monster implements GeoEntity {
return false;
}
if (spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.SPAWN_EGG
|| spawnReason == MobSpawnType.TRIAL_SPAWNER
|| spawnReason == MobSpawnType.COMMAND || spawnReason == MobSpawnType.BUCKET) {
return true;
}
@@ -54,7 +54,10 @@ public class HoverboardItem extends Item {
HoverboardEntity hoverboard = new HoverboardEntity(this.entityType, level);
Vec3 spawnPos = hitResult.getLocation();
hoverboard.moveTo(spawnPos.x, spawnPos.y, spawnPos.z, player.getYRot(), 0.0F);
boolean invertedPlacement = com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager.isThoraxis(level)
&& spawnPos.y < com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager.GRAVITY_FLIP_Y;
double spawnY = invertedPlacement ? spawnPos.y - hoverboard.getBbHeight() : spawnPos.y;
hoverboard.moveTo(spawnPos.x, spawnY, spawnPos.z, player.getYRot(), 0.0F);
hoverboard.setColor(this.color);
if (!level.noCollision(hoverboard, hoverboard.getBoundingBox())) {
return InteractionResultHolder.fail(stack);
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.item;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.item.royal.RoyalGearHelper;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@@ -74,9 +75,10 @@ public class RoyalGuardianArmorItem extends ArmorItem {
case BOOTS -> "boots";
};
tooltipComponents.add(Component.translatable("tooltip.antarchy.royal_guardian_" + slotName + ".judgment",
Math.round(judgmentBonus() * 100.0D)));
Math.round(judgmentBonus() * 100.0D)).withStyle(ChatFormatting.LIGHT_PURPLE));
if (this.armorType == Type.CHESTPLATE) {
tooltipComponents.add(Component.translatable("tooltip.antarchy.royal_guardian_chestplate.boundary"));
tooltipComponents.add(Component.translatable("tooltip.antarchy.royal_guardian_chestplate.boundary")
.withStyle(ChatFormatting.AQUA));
}
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
}
@@ -54,7 +54,7 @@ public class RoyalGuardianShieldItem extends ShieldItem {
@Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
tooltipComponents.add(Component.translatable("tooltip.antarchy.royal_guardian_shield.command")
.withStyle(ChatFormatting.GOLD));
.withStyle(ChatFormatting.AQUA));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
}
@@ -108,7 +108,7 @@ public class RoyalGuardianSwordItem extends SwordItem implements GeoItem {
Mode mode = getMode(stack);
tooltipComponents.add(Component.translatable("tooltip.antarchy.royal_guardian_sword.mode",
Component.translatable(mode.translationKey)).withStyle(ChatFormatting.GOLD));
tooltipComponents.add(Component.translatable(mode.tooltipKey).withStyle(ChatFormatting.GRAY));
tooltipComponents.add(Component.translatable(mode.tooltipKey).withStyle(ChatFormatting.LIGHT_PURPLE));
tooltipComponents.add(Component.translatable("tooltip.antarchy.royal_guardian_sword.controls",
AntarchySettings.royalGuardianSwordElementalCooldownTicks() / 20.0D).withStyle(ChatFormatting.DARK_GRAY));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
@@ -3,7 +3,7 @@ package com.craisinlord.antarchy.content.worldgen.thoraxis;
import net.minecraft.util.RandomSource;
public final class QueenTrailGrid {
public static final int SPACING = 1_536;
public static final int SPACING = 1_500;
private static final int JITTER_MARGIN = 256;
private QueenTrailGrid() {
@@ -0,0 +1,11 @@
package com.craisinlord.antarchy.content.worldgen.thoraxis;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
public record ThoraxisTransitionThroatConfiguration(boolean large) implements FeatureConfiguration {
public static final Codec<ThoraxisTransitionThroatConfiguration> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.BOOL.fieldOf("large").forGetter(ThoraxisTransitionThroatConfiguration::large)
).apply(instance, ThoraxisTransitionThroatConfiguration::new));
}
@@ -6,17 +6,22 @@ import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public final class ThoraxisTransitionThroatFeature extends Feature<NoneFeatureConfiguration> {
public final class ThoraxisTransitionThroatFeature extends Feature<ThoraxisTransitionThroatConfiguration> {
public ThoraxisTransitionThroatFeature() {
super(NoneFeatureConfiguration.CODEC);
super(ThoraxisTransitionThroatConfiguration.CODEC);
}
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
public boolean place(FeaturePlaceContext<ThoraxisTransitionThroatConfiguration> context) {
WorldGenLevel level = context.level();
BlockPos origin = context.origin();
boolean large = context.config().large();
int searchRadius = large ? 18 : 9;
double baseRadius = large ? 10.0D : 5.0D;
double radiusVariance = large ? 5.0D : 2.5D;
double layerOffsetScale = large ? 4.0D : 2.0D;
BlockPos center = new BlockPos(origin.getX(), ThoraxisUndersideManager.GRAVITY_FLIP_Y, origin.getZ());
int upperSurface = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, center.getX(), center.getZ()) - 1;
int undersideSurface = findUndersideSurface(level, center);
@@ -26,13 +31,13 @@ public final class ThoraxisTransitionThroatFeature extends Feature<NoneFeatureCo
long seed = context.random().nextLong();
for (int y = undersideSurface; y <= upperSurface; y++) {
int layerOffsetX = noise(seed, Math.floorDiv(y, 5), 17) * 2;
int layerOffsetZ = noise(seed, Math.floorDiv(y, 5), 31) * 2;
double radiusX = 5.0D + noise01(seed, Math.floorDiv(y, 11), 43) * 2.5D;
double radiusZ = 5.0D + noise01(seed, Math.floorDiv(y, 13), 59) * 2.5D;
int layerOffsetX = (int) (noise(seed, Math.floorDiv(y, 5), 17) * layerOffsetScale);
int layerOffsetZ = (int) (noise(seed, Math.floorDiv(y, 5), 31) * layerOffsetScale);
double radiusX = baseRadius + noise01(seed, Math.floorDiv(y, 11), 43) * radiusVariance;
double radiusZ = baseRadius + noise01(seed, Math.floorDiv(y, 13), 59) * radiusVariance;
for (int x = -9; x <= 9; x++) {
for (int z = -9; z <= 9; z++) {
for (int x = -searchRadius; x <= searchRadius; x++) {
for (int z = -searchRadius; z <= searchRadius; z++) {
double dx = x - layerOffsetX;
double dz = z - layerOffsetZ;
double distance = Math.sqrt((dx * dx) / (radiusX * radiusX) + (dz * dz) / (radiusZ * radiusZ));
@@ -17,6 +17,7 @@ import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
@@ -43,9 +44,13 @@ public final class ThoraxisUndersideManager {
private static final int ENTER_UNDERSIDE_Y = GRAVITY_FLIP_Y - 4;
private static final int EXIT_UNDERSIDE_Y = GRAVITY_FLIP_Y + 4;
private static final int FLIP_COOLDOWN_TICKS = 40;
private static final int CROSSING_TIMEOUT_TICKS = 50;
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 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;
private static final int ENTRY_SLOW_FALL_DURATION_TICKS = 300;
private static final Map<ServerLevel, TrackingState> STATES = new WeakHashMap<>();
private ThoraxisUndersideManager() {
@@ -144,6 +149,7 @@ public final class ThoraxisUndersideManager {
tracking.entities.removeIf(entity -> !entity.isAlive() || entity.isRemoved());
tracking.forcedItems.removeIf(entity -> !entity.isAlive() || entity.isRemoved());
tracking.lastFlipTick.entrySet().removeIf(entry -> now - entry.getValue() > FLIP_COOLDOWN_TICKS * 4L);
tracking.lastUndersideExitTick.entrySet().removeIf(entry -> now - entry.getValue() > RECENT_UNDERSIDE_WINDOW_TICKS * 4L);
double elapsedMs = (System.nanoTime() - startNanos) / 1_000_000.0D;
if (elapsedMs >= SLOW_TICK_WARN_MS && now - tracking.lastDiagnosticTick >= DIAGNOSTIC_INTERVAL_TICKS) {
@@ -161,6 +167,7 @@ public final class ThoraxisUndersideManager {
private final Set<Entity> forcedItems = Collections.newSetFromMap(new IdentityHashMap<>());
private final Map<UUID, Long> lastFlipTick = new java.util.HashMap<>();
private final Map<UUID, PlayerCrossing> playerCrossings = new java.util.HashMap<>();
private final Map<UUID, Long> lastUndersideExitTick = new java.util.HashMap<>();
private long lastDiagnosticTick = Long.MIN_VALUE / 2L;
private DiscoveryStats discover(ServerLevel level) {
@@ -190,6 +197,7 @@ public final class ThoraxisUndersideManager {
forcedItems.clear();
lastFlipTick.clear();
playerCrossings.clear();
lastUndersideExitTick.clear();
}
}
@@ -206,19 +214,18 @@ public final class ThoraxisUndersideManager {
continue;
}
if (isCrossingGravityBoundary(player) && flipReady(tracking, player.getUUID(), now)) {
if (isCrossingGravityBoundary(player)) {
boolean toUnderside = AntarchyGravityApi.getGravityDirection(player) == AntarchyGravityDirection.DOWN;
if (!toUnderside) {
refreshInvertedEffect(player);
} else {
player.addEffect(new MobEffectInstance(MobEffects.SLOW_FALLING, ENTRY_SLOW_FALL_DURATION_TICKS, 0, false, true, true));
}
tracking.playerCrossings.put(player.getUUID(), new PlayerCrossing(toUnderside));
continue;
}
MobEffectInstance effect = player.getEffect(AntarchyObjects.INVERTED_EFFECT.get());
if (player.getY() < ENTER_UNDERSIDE_Y) {
refreshInvertedEffect(player);
} else if (effect != null && isUndersideEffect(effect) && player.getY() < EXIT_UNDERSIDE_Y) {
if (AntarchyGravityApi.isGravityInverted(player) && player.getY() < EXIT_UNDERSIDE_Y) {
refreshInvertedEffect(player);
}
}
@@ -237,10 +244,23 @@ public final class ThoraxisUndersideManager {
}
AABB bounds = player.getBoundingBox();
boolean clear = crossing.toUnderside ? bounds.maxY < GRAVITY_FLIP_Y : bounds.minY > EXIT_UNDERSIDE_Y;
boolean clear;
if (crossing.toUnderside) {
if (bounds.maxY >= UNDERSIDE_ENTRY_BORDER_Y) {
return;
}
Long lastExit = tracking.lastUndersideExitTick.get(player.getUUID());
boolean recentlyUnderside = lastExit != null && now - lastExit < RECENT_UNDERSIDE_WINDOW_TICKS;
clear = recentlyUnderside || crossing.ticks >= FRESH_ENTRY_DELAY_TICKS;
} else {
clear = bounds.minY > EXIT_UNDERSIDE_Y;
}
if (!clear) {
return;
}
if (!flipReady(tracking, player.getUUID(), now)) {
return;
}
AntarchyGravityDirection destination = crossing.toUnderside
? AntarchyGravityDirection.UP
@@ -259,6 +279,7 @@ public final class ThoraxisUndersideManager {
refreshInvertedEffect(player);
} else {
player.removeEffect(AntarchyObjects.INVERTED_EFFECT.get());
tracking.lastUndersideExitTick.put(player.getUUID(), now);
}
return;
}
@@ -276,7 +297,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 < GRAVITY_FLIP_Y && swept.maxY >= GRAVITY_FLIP_Y && velocity.y <= -MIN_CROSSING_SPEED
? swept.minY < UNDERSIDE_ENTRY_BORDER_Y && swept.maxY >= UNDERSIDE_ENTRY_BORDER_Y && velocity.y <= -MIN_CROSSING_SPEED
: swept.minY <= GRAVITY_FLIP_Y && swept.maxY > GRAVITY_FLIP_Y && velocity.y >= MIN_CROSSING_SPEED;
}
@@ -338,16 +359,10 @@ public final class ThoraxisUndersideManager {
return level.dimension().location().equals(THORAXIS_DIMENSION);
}
/** True only while an entity is physically below Thoraxis' gravity boundary. */
public static boolean isInUnderside(Entity entity) {
return isThoraxis(entity.level()) && entity.getY() < GRAVITY_FLIP_Y;
}
/**
* Projectiles perform their own movement in world coordinates, so they must
* not retain an inverted entity-local movement frame. Underside gravity is
* reversed separately when gravitational acceleration is applied.
*/
public static void normalizeProjectileGravityFrame(Projectile projectile) {
boolean stateMismatch = AntarchyGravityApi.getGravityDirection(projectile) != AntarchyGravityDirection.DOWN
|| AntarchyGravityApi.isGravityForced(projectile);
@@ -365,7 +380,6 @@ public final class ThoraxisUndersideManager {
return isThoraxis(entity.level()) && entity.getY() >= EXIT_UNDERSIDE_Y;
}
/** True while an entity is in the region where the underside gravity rule applies. */
public static boolean shouldInvertInUnderside(Entity entity) {
return AntarchyGravityApi.isGravityInverted(entity)
&& isInUnderside(entity);
@@ -0,0 +1,39 @@
package com.craisinlord.antarchy.mixins.time;
import com.craisinlord.antarchy.content.effect.ContractedMobEffect;
import com.craisinlord.antarchy.content.effect.DilatedMobEffect;
import com.craisinlord.antarchy.content.effect.RoyalEffectHooks;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.player.Player;
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;
@Mixin(Player.class)
public abstract class TemporalMiningSpeedMixin {
@Inject(method = "getDestroySpeed", at = @At("RETURN"), cancellable = true)
private void antarchy$applyTemporalMiningSpeed(
net.minecraft.world.level.block.state.BlockState state,
CallbackInfoReturnable<Float> cir) {
Player player = (Player) (Object) this;
double rate = 1.0D;
if (RoyalEffectHooks.dilatedHolder() != null) {
MobEffectInstance dilation = player.getEffect(RoyalEffectHooks.dilatedHolder());
if (dilation != null) {
rate = Math.min(rate, DilatedMobEffect.rateForAmplifier(dilation.getAmplifier()));
}
}
if (RoyalEffectHooks.contractedHolder() != null) {
MobEffectInstance contraction = player.getEffect(RoyalEffectHooks.contractedHolder());
if (contraction != null) {
rate = Math.max(rate, ContractedMobEffect.rateForAmplifier(contraction.getAmplifier()));
}
}
if (rate != 1.0D) {
cir.setReturnValue((float) (cir.getReturnValue() * rate));
}
}
}