fixed game dev not working
various fabric issues added archives to loot tables
This commit is contained in:
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;
|
||||
|
||||
+51
-4
@@ -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;
|
||||
|
||||
+15
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
+128
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
-6
@@ -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) {
|
||||
|
||||
+14
-1
@@ -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) {
|
||||
|
||||
+35
@@ -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);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
+1
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+1
-1
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -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();
|
||||
}
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+21
-8
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -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();
|
||||
|
||||
+1
@@ -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;
|
||||
}
|
||||
|
||||
+4
-1
@@ -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);
|
||||
|
||||
+4
-2
@@ -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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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() {
|
||||
|
||||
+11
@@ -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));
|
||||
}
|
||||
+15
-10
@@ -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));
|
||||
|
||||
+29
-15
@@ -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);
|
||||
|
||||
+39
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user