fix antigravel and upward falling blocks

This commit is contained in:
craisinlord committed 2026-08-12 13:49:03 -05:00
1 parent ea24b19068
commit 313c54e8d6
8 files changed
+53 -55

No files matched your search

@@ -26,9 +26,7 @@ public class AntigravelBlock extends Block {
@Override @Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (direction == Direction.UP) {
level.scheduleTick(pos, this, 2); level.scheduleTick(pos, this, 2);
}
return super.updateShape(state, direction, neighborState, level, pos, neighborPos); return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
} }
@@ -2,7 +2,6 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.content.block.AntimetalScaffoldingBlock; import com.craisinlord.antarchy.content.block.AntimetalScaffoldingBlock;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
@@ -12,6 +11,7 @@ import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
@@ -28,14 +28,16 @@ public class UpwardFallingBlockEntity extends Entity {
private static final EntityDataAccessor<BlockState> DATA_BLOCK_STATE = private static final EntityDataAccessor<BlockState> DATA_BLOCK_STATE =
SynchedEntityData.defineId(UpwardFallingBlockEntity.class, EntityDataSerializers.BLOCK_STATE); SynchedEntityData.defineId(UpwardFallingBlockEntity.class, EntityDataSerializers.BLOCK_STATE);
private static final double RISE_SPEED = 0.5; private static final double RISE_ACCEL = 0.04;
private static final double DRAG = 0.98;
private static final int MAX_TICKS = 200; private static final int MAX_TICKS = 200;
public int time = 0; public int time = 0;
private double distanceTraveled = 0.0;
public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) { public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) {
super(type, level); super(type, level);
this.noPhysics = true; this.blocksBuilding = true;
} }
@Override @Override
@@ -72,10 +74,11 @@ public class UpwardFallingBlockEntity extends Entity {
return; return;
} }
// Move upward directly — noPhysics=true means move() just calls setPos(). double beforeY = getY();
// Runs on both sides so the client simulates the same deterministic rise setDeltaMovement(getDeltaMovement().add(0.0, RISE_ACCEL, 0.0));
// instead of relying on interpolated network updates, matching vanilla FallingBlockEntity. move(MoverType.SELF, getDeltaMovement());
setPos(getX(), getY() + RISE_SPEED, getZ()); setDeltaMovement(getDeltaMovement().scale(DRAG));
distanceTraveled += Math.max(0.0, getY() - beforeY);
if (level().isClientSide) return; if (level().isClientSide) return;
@@ -87,7 +90,7 @@ public class UpwardFallingBlockEntity extends Entity {
damageEntitiesAlongPath(blockState); damageEntitiesAlongPath(blockState);
BlockPos headPos = BlockPos.containing(getX(), getY() + getBbHeight(), getZ()); BlockPos headPos = BlockPos.containing(getX(), getBoundingBox().maxY, getZ());
BlockState above = level().getBlockState(headPos); BlockState above = level().getBlockState(headPos);
// Leaves block the entity but can't hold scaffolding — drop as item // Leaves block the entity but can't hold scaffolding — drop as item
@@ -96,10 +99,9 @@ public class UpwardFallingBlockEntity extends Entity {
return; return;
} }
boolean hitCeiling = above.isFaceSturdy(level(), headPos, Direction.DOWN);
boolean hitScaffolding = above.getBlock() instanceof AntimetalScaffoldingBlock; boolean hitScaffolding = above.getBlock() instanceof AntimetalScaffoldingBlock;
if (hitCeiling || hitScaffolding) { if (this.verticalCollision || hitScaffolding) {
dropAndRemove(blockState); dropAndRemove(blockState);
return; return;
} }
@@ -118,8 +120,7 @@ public class UpwardFallingBlockEntity extends Entity {
} }
private float getImpactDamage(BlockState state) { private float getImpactDamage(BlockState state) {
float travelDistance = (float) this.time * (float) RISE_SPEED; float baseDamage = Math.max(0.0F, (float) this.distanceTraveled - 1.5F);
float baseDamage = Math.max(0.0F, travelDistance - 1.5F);
if (baseDamage <= 0.0F) { if (baseDamage <= 0.0F) {
return 0.0F; return 0.0F;
} }
@@ -18,7 +18,7 @@ public abstract class MountedVehicleCameraMixin {
@ModifyArgs( @ModifyArgs(
method = "setup", method = "setup",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;move(FFF)V") at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;move(DDD)V")
) )
private void antarchy$adjustMountedCameraOffset( private void antarchy$adjustMountedCameraOffset(
Args args, Args args,
@@ -34,16 +34,16 @@ public abstract class MountedVehicleCameraMixin {
Entity vehicle = this.entity.getVehicle(); Entity vehicle = this.entity.getVehicle();
if (vehicle instanceof HerculesBeetleEntity) { if (vehicle instanceof HerculesBeetleEntity) {
args.set(0, (Float) args.get(0) * 1.45F); args.set(0, (Double) args.get(0) * 1.45D);
args.set(1, (Float) args.get(1) + 0.2F); args.set(1, (Double) args.get(1) + 0.2D);
args.set(2, (Float) args.get(2) + 0.45F); args.set(2, (Double) args.get(2) + 0.45D);
return; return;
} }
// if (vehicle instanceof DorrieEntity) { // if (vehicle instanceof DorrieEntity) {
// args.set(0, (Float) args.get(0) * 0.25F); // args.set(0, (Double) args.get(0) * 0.25D);
// args.set(1, (Float) args.get(1) + 0.1F); // args.set(1, (Double) args.get(1) + 0.1D);
// args.set(2, (Float) args.get(2) + 0.55F); // args.set(2, (Double) args.get(2) + 0.55D);
// } // }
} }
} }
@@ -34,9 +34,7 @@ public class AntigravelBlock extends Block {
@Override @Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (direction == Direction.UP) {
level.scheduleTick(pos, this, 2); level.scheduleTick(pos, this, 2);
}
return super.updateShape(state, direction, neighborState, level, pos, neighborPos); return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
} }
@@ -11,6 +11,7 @@ import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@@ -28,15 +29,17 @@ public class UpwardFallingBlockEntity extends Entity {
private static final EntityDataAccessor<BlockState> DATA_BLOCK_STATE = private static final EntityDataAccessor<BlockState> DATA_BLOCK_STATE =
SynchedEntityData.defineId(UpwardFallingBlockEntity.class, EntityDataSerializers.BLOCK_STATE); SynchedEntityData.defineId(UpwardFallingBlockEntity.class, EntityDataSerializers.BLOCK_STATE);
private static final double RISE_SPEED = 0.5; private static final double RISE_ACCEL = 0.04;
private static final double DRAG = 0.98;
private static final int MAX_TICKS = 200; private static final int MAX_TICKS = 200;
public int time = 0; public int time = 0;
private boolean breaksOnLeaves = true; private boolean breaksOnLeaves = true;
private double distanceTraveled = 0.0;
public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) { public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) {
super(type, level); super(type, level);
this.noPhysics = true; this.blocksBuilding = true;
} }
@Override @Override
@@ -78,10 +81,11 @@ public class UpwardFallingBlockEntity extends Entity {
return; return;
} }
// Move upward directly — noPhysics=true means move() just calls setPos(). double beforeY = getY();
// Runs on both sides so the client simulates the same deterministic rise setDeltaMovement(getDeltaMovement().add(0.0, RISE_ACCEL, 0.0));
// instead of relying on interpolated network updates, matching vanilla FallingBlockEntity. move(MoverType.SELF, getDeltaMovement());
setPos(getX(), getY() + RISE_SPEED, getZ()); setDeltaMovement(getDeltaMovement().scale(DRAG));
distanceTraveled += Math.max(0.0, getY() - beforeY);
if (level().isClientSide) return; if (level().isClientSide) return;
@@ -93,7 +97,7 @@ public class UpwardFallingBlockEntity extends Entity {
damageEntitiesAlongPath(blockState); damageEntitiesAlongPath(blockState);
BlockPos headPos = BlockPos.containing(getX(), getY() + getBbHeight(), getZ()); BlockPos headPos = BlockPos.containing(getX(), getBoundingBox().maxY, getZ());
BlockState above = level().getBlockState(headPos); BlockState above = level().getBlockState(headPos);
// Leaves block the entity but can't hold scaffolding — drop as item, unless this // Leaves block the entity but can't hold scaffolding — drop as item, unless this
@@ -103,10 +107,9 @@ public class UpwardFallingBlockEntity extends Entity {
return; return;
} }
boolean hitCeiling = !above.isAir() && !above.getCollisionShape(level(), headPos).isEmpty();
boolean hitScaffolding = above.getBlock() instanceof AntimetalScaffoldingBlock; boolean hitScaffolding = above.getBlock() instanceof AntimetalScaffoldingBlock;
if (hitCeiling || hitScaffolding) { if (this.verticalCollision || hitScaffolding) {
placeAtLanding(blockState, headPos.below()); placeAtLanding(blockState, headPos.below());
return; return;
} }
@@ -138,8 +141,7 @@ public class UpwardFallingBlockEntity extends Entity {
} }
private float getImpactDamage(BlockState state) { private float getImpactDamage(BlockState state) {
float travelDistance = (float) this.time * (float) RISE_SPEED; float baseDamage = Math.max(0.0F, (float) this.distanceTraveled - 1.5F);
float baseDamage = Math.max(0.0F, travelDistance - 1.5F);
if (baseDamage <= 0.0F) { if (baseDamage <= 0.0F) {
return 0.0F; return 0.0F;
} }
@@ -10,6 +10,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
@@ -17,6 +18,7 @@ public final class ThoraxisUndersideManager {
public static final int GRAVITY_FLIP_Y = 0; public static final int GRAVITY_FLIP_Y = 0;
private static final ResourceLocation THORAXIS_DIMENSION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "thoraxis"); private static final ResourceLocation THORAXIS_DIMENSION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "thoraxis");
private static final AntarchyGravityTransition TRANSITION = new AntarchyGravityTransition(12); private static final AntarchyGravityTransition TRANSITION = new AntarchyGravityTransition(12);
private static final int EFFECT_DURATION_TICKS = 40;
private static final Set<UUID> UNDERSIDE_FORCED_GRAVITY = new HashSet<>(); private static final Set<UUID> UNDERSIDE_FORCED_GRAVITY = new HashSet<>();
private ThoraxisUndersideManager() { private ThoraxisUndersideManager() {
@@ -33,8 +35,19 @@ public final class ThoraxisUndersideManager {
continue; continue;
} }
boolean inUnderside = entity.getY() < GRAVITY_FLIP_Y;
if (entity instanceof LivingEntity living) {
if (inUnderside) {
living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), EFFECT_DURATION_TICKS, 0, true, false, false));
} else if (living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
living.removeEffect(AntarchyObjects.INVERTED_EFFECT.get());
}
continue;
}
UUID uuid = entity.getUUID(); UUID uuid = entity.getUUID();
if (entity.getY() < GRAVITY_FLIP_Y) { if (inUnderside) {
activeThisTick.add(uuid); activeThisTick.add(uuid);
UNDERSIDE_FORCED_GRAVITY.add(uuid); UNDERSIDE_FORCED_GRAVITY.add(uuid);
if (AntarchyGravityApi.getGravityDirection(entity) != AntarchyGravityDirection.UP if (AntarchyGravityApi.getGravityDirection(entity) != AntarchyGravityDirection.UP
@@ -44,11 +57,9 @@ public final class ThoraxisUndersideManager {
continue; continue;
} }
if (!UNDERSIDE_FORCED_GRAVITY.remove(uuid)) { if (UNDERSIDE_FORCED_GRAVITY.remove(uuid)
continue; && AntarchyGravityApi.getGravityDirection(entity) == AntarchyGravityDirection.UP
} && AntarchyGravityApi.isGravityForced(entity)) {
if (shouldReleaseGravity(entity)) {
AntarchyGravityApi.setGravityDirection(entity, AntarchyGravityDirection.DOWN, false, TRANSITION); AntarchyGravityApi.setGravityDirection(entity, AntarchyGravityDirection.DOWN, false, TRANSITION);
} }
} }
@@ -56,18 +67,6 @@ public final class ThoraxisUndersideManager {
UNDERSIDE_FORCED_GRAVITY.retainAll(activeThisTick); UNDERSIDE_FORCED_GRAVITY.retainAll(activeThisTick);
} }
private static boolean shouldReleaseGravity(Entity entity) {
if (AntarchyGravityApi.getGravityDirection(entity) != AntarchyGravityDirection.UP) {
return false;
}
if (entity instanceof LivingEntity living && living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
return false;
}
return AntarchyGravityApi.isGravityForced(entity);
}
public static boolean isThoraxis(ServerLevel level) { public static boolean isThoraxis(ServerLevel level) {
return level.dimension().location().equals(THORAXIS_DIMENSION); return level.dimension().location().equals(THORAXIS_DIMENSION);
} }
@@ -8,7 +8,7 @@
"argument1": { "argument1": {
"type": "minecraft:y_clamped_gradient", "type": "minecraft:y_clamped_gradient",
"from_y": -256, "from_y": -256,
"to_y": -16, "to_y": -1,
"from_value": -2.0, "from_value": -2.0,
"to_value": 1.05 "to_value": 1.05
}, },
@@ -74,7 +74,7 @@
"from_value": 0.0, "from_value": 0.0,
"from_y": -8, "from_y": -8,
"to_value": 1.0, "to_value": 1.0,
"to_y": 24 "to_y": 4
}, },
"argument2": -2.5 "argument2": -2.5
}, },
@@ -150,7 +150,7 @@
"type": "minecraft:y_above", "type": "minecraft:y_above",
"add_stone_depth": false, "add_stone_depth": false,
"anchor": { "anchor": {
"absolute": 4 "absolute": 1
}, },
"surface_depth_multiplier": 0 "surface_depth_multiplier": 0
} }