idk why all these line seperators are freaking out

This commit is contained in:
craisinlord committed 2026-08-14 13:35:46 -05:00
1 parent 05c9dd5e66
commit 700030eefd
77 files changed
+1651 -375

No files matched your search

@@ -15,6 +15,7 @@ import net.minecraft.server.level.PlayerRespawnLogic;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
@@ -262,8 +263,11 @@ public final class AntTeleportHelper {
return safeArrivalPos; return safeArrivalPos;
} }
BlockPos fallbackPos = preferredPos; if (destination.hasChunkAt(preferredPos)) {
return Vec3.atBottomCenterOf(fallbackPos); return Vec3.atBottomCenterOf(preferredPos);
}
return Vec3.atBottomCenterOf(getClampedFallbackPosition(destination, preferredPos));
} }
@Nullable @Nullable
@@ -292,8 +296,10 @@ public final class AntTeleportHelper {
} }
BlockPos searchPos = preferredPos.offset(xOffset, 0, zOffset); BlockPos searchPos = preferredPos.offset(xOffset, 0, zOffset);
addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, searchPos)); if (destination.hasChunkAt(searchPos)) {
addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, searchPos)); addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, searchPos));
addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, searchPos));
}
} }
} }
} }
@@ -356,13 +362,22 @@ public final class AntTeleportHelper {
@Nullable @Nullable
private static Vec3 tryFindSafeDismount(ServerPlayer player, ServerLevel destination, BlockPos candidate) { private static Vec3 tryFindSafeDismount(ServerPlayer player, ServerLevel destination, BlockPos candidate) {
if (!isSafeDismountAreaLoaded(destination, candidate)) {
return null;
}
Vec3 safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, candidate, true); Vec3 safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, candidate, true);
if (safePos != null && isValidArrivalPosition(destination, safePos)) { if (safePos != null && isValidArrivalPosition(destination, safePos)) {
return safePos; return safePos;
} }
for (Direction direction : Direction.Plane.HORIZONTAL) { for (Direction direction : Direction.Plane.HORIZONTAL) {
safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, candidate.relative(direction), true); BlockPos offsetCandidate = candidate.relative(direction);
if (!isSafeDismountAreaLoaded(destination, offsetCandidate)) {
continue;
}
safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, offsetCandidate, true);
if (safePos != null && isValidArrivalPosition(destination, safePos)) { if (safePos != null && isValidArrivalPosition(destination, safePos)) {
return safePos; return safePos;
} }
@@ -377,6 +392,31 @@ public final class AntTeleportHelper {
} }
BlockPos standPos = BlockPos.containing(safePos); BlockPos standPos = BlockPos.containing(safePos);
if (!destination.hasChunkAt(standPos) || !destination.hasChunkAt(standPos.below())) {
return false;
}
return !destination.getBlockState(standPos.below()).is(Blocks.BEDROCK); return !destination.getBlockState(standPos.below()).is(Blocks.BEDROCK);
} }
private static boolean isSafeDismountAreaLoaded(ServerLevel destination, BlockPos center) {
if (!destination.hasChunkAt(center) || !destination.hasChunkAt(center.above()) || !destination.hasChunkAt(center.below())) {
return false;
}
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos offset = center.relative(direction);
if (!destination.hasChunkAt(offset) || !destination.hasChunkAt(offset.above()) || !destination.hasChunkAt(offset.below())) {
return false;
}
}
return true;
}
private static BlockPos getClampedFallbackPosition(ServerLevel destination, BlockPos preferredPos) {
int minY = destination.getMinBuildHeight() + 1;
int maxY = destination.getMaxBuildHeight() - 1;
return new BlockPos(preferredPos.getX(), Mth.clamp(preferredPos.getY(), minY, maxY), preferredPos.getZ());
}
} }
@@ -127,8 +127,10 @@ public final class PermanentPortalTeleporter {
} }
BlockPos horizontalPos = preferredPos.offset(xOff, 0, zOff); BlockPos horizontalPos = preferredPos.offset(xOff, 0, zOff);
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, horizontalPos)); if (destination.hasChunkAt(horizontalPos)) {
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, horizontalPos)); addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, horizontalPos));
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, horizontalPos));
}
for (int yOff = 0; yOff <= VERTICAL_SEARCH; yOff++) { for (int yOff = 0; yOff <= VERTICAL_SEARCH; yOff++) {
addCandidate(candidates, horizontalPos.above(yOff)); addCandidate(candidates, horizontalPos.above(yOff));
if (yOff > 0) { if (yOff > 0) {
@@ -186,13 +188,22 @@ public final class PermanentPortalTeleporter {
@Nullable @Nullable
private static Vec3 tryFindSafePosition(Entity entity, ServerLevel destination, BlockPos candidate) { private static Vec3 tryFindSafePosition(Entity entity, ServerLevel destination, BlockPos candidate) {
if (!isSafeDismountAreaLoaded(destination, candidate)) {
return null;
}
Vec3 safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate, true); Vec3 safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate, true);
if (safe != null && isValidArrivalPosition(destination, safe)) { if (safe != null && isValidArrivalPosition(destination, safe)) {
return safe; return safe;
} }
for (Direction direction : Direction.Plane.HORIZONTAL) { for (Direction direction : Direction.Plane.HORIZONTAL) {
safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate.relative(direction), true); BlockPos offsetCandidate = candidate.relative(direction);
if (!isSafeDismountAreaLoaded(destination, offsetCandidate)) {
continue;
}
safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, offsetCandidate, true);
if (safe != null && isValidArrivalPosition(destination, safe)) { if (safe != null && isValidArrivalPosition(destination, safe)) {
return safe; return safe;
} }
@@ -283,11 +294,30 @@ public final class PermanentPortalTeleporter {
BlockPos standPos = BlockPos.containing(safePos); BlockPos standPos = BlockPos.containing(safePos);
if (destination.dimension() == AntarchySettings.termiteDestinationDimension() if (destination.dimension() == AntarchySettings.termiteDestinationDimension()
|| destination.dimension() == AntarchySettings.redAntDestinationDimension()) { || destination.dimension() == AntarchySettings.redAntDestinationDimension()) {
if (!destination.hasChunkAt(standPos) || !destination.hasChunkAt(standPos.below())) {
return false;
}
return !destination.getBlockState(standPos.below()).is(net.minecraft.world.level.block.Blocks.BEDROCK); return !destination.getBlockState(standPos.below()).is(net.minecraft.world.level.block.Blocks.BEDROCK);
} }
return true; return true;
} }
private static boolean isSafeDismountAreaLoaded(ServerLevel destination, BlockPos center) {
if (!destination.hasChunkAt(center) || !destination.hasChunkAt(center.above()) || !destination.hasChunkAt(center.below())) {
return false;
}
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos offset = center.relative(direction);
if (!destination.hasChunkAt(offset) || !destination.hasChunkAt(offset.above()) || !destination.hasChunkAt(offset.below())) {
return false;
}
}
return true;
}
@Nullable @Nullable
private static Entity moveEntity(Entity entity, Transition transition) { private static Entity moveEntity(Entity entity, Transition transition) {
ServerLevel destination = transition.newLevel(); ServerLevel destination = transition.newLevel();
@@ -4,6 +4,9 @@ import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.boss.BossCombatUtil; import com.craisinlord.antarchy.content.boss.BossCombatUtil;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -110,9 +113,14 @@ public class AlphaMantisEntity extends MantisEntity {
} }
boolean atSurface = level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pos).getY() <= pos.getY(); boolean atSurface = level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pos).getY() <= pos.getY();
boolean posOpen = level.isEmptyBlock(pos) && level.isEmptyBlock(pos.above()) && level.getFluidState(pos).isEmpty(); boolean hasFloorClearance = level.isEmptyBlock(pos.above());
boolean onSolidGround = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP) boolean hasCeilingClearance = level.isEmptyBlock(pos.below());
boolean floorSupport = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP)
&& !(level.getBlockState(pos.below()).getBlock() instanceof LeavesBlock); && !(level.getBlockState(pos.below()).getBlock() instanceof LeavesBlock);
boolean ceilingSupport = level.getBlockState(pos.above()).isFaceSturdy(level, pos.above(), Direction.DOWN)
&& !(level.getBlockState(pos.above()).getBlock() instanceof LeavesBlock);
boolean posOpen = level.isEmptyBlock(pos) && (hasFloorClearance || hasCeilingClearance) && level.getFluidState(pos).isEmpty();
boolean onSolidGround = floorSupport || ceilingSupport;
if (!posOpen || !onSolidGround || !atSurface) { if (!posOpen || !onSolidGround || !atSurface) {
return false; return false;
@@ -344,7 +352,8 @@ public class AlphaMantisEntity extends MantisEntity {
this.finishCommittedAttack(); this.finishCommittedAttack();
this.stopFlightBurst(); this.stopFlightBurst();
this.getNavigation().stop(); this.getNavigation().stop();
this.setDeltaMovement(0.0D, this.getDeltaMovement().y, 0.0D); Vec3 localVelocity = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(this.toWorld(0.0D, localVelocity.y, 0.0D));
this.setAggressive(false); this.setAggressive(false);
this.summonCooldownTicks = Math.min(this.summonCooldownTicks, AntarchySettings.alphaMantisSummonIntervalTicks() / 2); this.summonCooldownTicks = Math.min(this.summonCooldownTicks, AntarchySettings.alphaMantisSummonIntervalTicks() / 2);
} }
@@ -355,7 +364,8 @@ public class AlphaMantisEntity extends MantisEntity {
} }
this.phaseTransitionTicks--; this.phaseTransitionTicks--;
this.getNavigation().stop(); this.getNavigation().stop();
this.setDeltaMovement(0.0D, this.getDeltaMovement().y, 0.0D); Vec3 localVelocity = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(this.toWorld(0.0D, localVelocity.y, 0.0D));
if (this.phaseTransitionTicks <= 0 && this.getTarget() != null) { if (this.phaseTransitionTicks <= 0 && this.getTarget() != null) {
this.setAggressive(true); this.setAggressive(true);
} }
@@ -466,4 +476,16 @@ public class AlphaMantisEntity extends MantisEntity {
this.setDeltaMovement(Vec3.ZERO); this.setDeltaMovement(Vec3.ZERO);
} }
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
} }
@@ -1,5 +1,8 @@
package com.craisinlord.antarchy.content.entity; package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.EntityDataSerializers;
@@ -294,7 +297,7 @@ public abstract class AppleCowEntity extends Cow implements GeoEntity, Shearable
} }
private boolean isMovingForAnimation() { private boolean isMovingForAnimation() {
return this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-4D || this.getNavigation().isInProgress(); return this.toLocal(this.getDeltaMovement()).horizontalDistanceSqr() > 1.0E-4D || this.getNavigation().isInProgress();
} }
private void startSleeping(int sleepTicks) { private void startSleeping(int sleepTicks) {
@@ -322,13 +325,25 @@ public abstract class AppleCowEntity extends Cow implements GeoEntity, Shearable
} }
private void applySleepStillness() { private void applySleepStillness() {
Vec3 motion = this.getDeltaMovement(); Vec3 motion = this.toLocal(this.getDeltaMovement());
this.getNavigation().stop(); this.getNavigation().stop();
this.setJumping(false); this.setJumping(false);
this.setSprinting(false); this.setSprinting(false);
this.zza = 0.0F; this.zza = 0.0F;
this.xxa = 0.0F; this.xxa = 0.0F;
this.setDeltaMovement(0.0D, motion.y < 0.0D ? motion.y : 0.0D, 0.0D); this.setDeltaMovement(this.toWorld(0.0D, motion.y < 0.0D ? motion.y : 0.0D, 0.0D));
}
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
} }
private int randomNapCooldown() { private int randomNapCooldown() {
@@ -5,6 +5,9 @@ import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.block.BedBugEggBlock; import com.craisinlord.antarchy.content.block.BedBugEggBlock;
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@@ -383,13 +386,16 @@ public class BedBugEntity extends Animal implements GeoEntity {
} }
private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) { private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) {
Vec3 lunge = target.position().subtract(this.position()); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(this);
Vec3 horizontal = new Vec3(lunge.x, 0.0D, lunge.z); Vec3 localLunge = AntarchyGravityRotationUtil.vecWorldToPlayer(target.position().subtract(this.position()), direction);
Vec3 horizontal = new Vec3(localLunge.x, 0.0D, localLunge.z);
if (horizontal.lengthSqr() < 1.0E-4D) { if (horizontal.lengthSqr() < 1.0E-4D) {
return; return;
} }
horizontal = horizontal.normalize().scale(horizontalSpeed); horizontal = horizontal.normalize().scale(horizontalSpeed);
this.setDeltaMovement(this.getDeltaMovement().add(horizontal.x, verticalSpeed, horizontal.z)); Vec3 localImpulse = new Vec3(horizontal.x, verticalSpeed, horizontal.z);
Vec3 worldImpulse = AntarchyGravityRotationUtil.vecPlayerToWorld(localImpulse, direction);
this.setDeltaMovement(this.getDeltaMovement().add(worldImpulse.x, worldImpulse.y, worldImpulse.z));
this.hasImpulse = true; this.hasImpulse = true;
} }
@@ -2,6 +2,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.Objects; import java.util.Objects;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
@@ -99,7 +102,7 @@ public class BomberEntity extends Monster implements GeoEntity {
return level.getDifficulty() != Difficulty.PEACEFUL return level.getDifficulty() != Difficulty.PEACEFUL
&& level.isEmptyBlock(pos) && level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.above()) && (level.isEmptyBlock(pos.above()) || level.isEmptyBlock(pos.below()))
&& Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random); && Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
} }
@@ -282,9 +285,10 @@ public class BomberEntity extends Monster implements GeoEntity {
return; return;
} }
double x = this.getX(); Vec3 explosionCenter = this.position().add(this.toWorld(0.0D, this.getBbHeight() * 0.0625D, 0.0D));
double y = this.getY(0.0625D); double x = explosionCenter.x;
double z = this.getZ(); double y = explosionCenter.y;
double z = explosionCenter.z;
float radius = (float) (AntarchySettings.bomberExplosionRadius() * EXPLOSION_RADIUS_MULTIPLIER); float radius = (float) (AntarchySettings.bomberExplosionRadius() * EXPLOSION_RADIUS_MULTIPLIER);
serverLevel.playSound(null, x, y, z, SoundEvents.GENERIC_EXPLODE.value(), SoundSource.HOSTILE, 0.55F, 1.0F); serverLevel.playSound(null, x, y, z, SoundEvents.GENERIC_EXPLODE.value(), SoundSource.HOSTILE, 0.55F, 1.0F);
serverLevel.explode( serverLevel.explode(
@@ -306,7 +310,7 @@ public class BomberEntity extends Monster implements GeoEntity {
if (extraDamage > 0.0D) { if (extraDamage > 0.0D) {
AABB damageBox = this.getBoundingBox().inflate(radius * 2.0D); AABB damageBox = this.getBoundingBox().inflate(radius * 2.0D);
for (LivingEntity livingEntity : serverLevel.getEntitiesOfClass(LivingEntity.class, damageBox, entity -> entity.isAlive() && entity != this)) { for (LivingEntity livingEntity : serverLevel.getEntitiesOfClass(LivingEntity.class, damageBox, entity -> entity.isAlive() && entity != this)) {
double distance = Math.sqrt(this.distanceToSqr(livingEntity)); double distance = explosionCenter.distanceTo(livingEntity.position());
double falloff = radius <= 0.0F ? 0.0D : Math.max(0.0D, 1.0D - distance / radius); double falloff = radius <= 0.0F ? 0.0D : Math.max(0.0D, 1.0D - distance / radius);
if (falloff <= 0.0D) { if (falloff <= 0.0D) {
continue; continue;
@@ -332,19 +336,37 @@ public class BomberEntity extends Monster implements GeoEntity {
return; return;
} }
double dx = this.getX() - sourceEntity.getX(); Vec3 localAway = this.toLocalPlane(this.position().subtract(sourceEntity.position()));
double dz = this.getZ() - sourceEntity.getZ(); double distance = localAway.length();
double distance = Math.sqrt(dx * dx + dz * dz);
if (distance < 1.0E-4D) { if (distance < 1.0E-4D) {
return; return;
} }
double strength = 0.4D * KNOCKBACK_MULTIPLIER; double strength = 0.4D * KNOCKBACK_MULTIPLIER;
this.push(dx / distance * strength, 0.08D, dz / distance * strength); Vec3 localImpulse = localAway.scale(strength / distance);
Vec3 worldImpulse = this.toWorld(localImpulse.x, 0.08D, localImpulse.z);
this.push(worldImpulse.x, worldImpulse.y, worldImpulse.z);
} }
private boolean isMovingForAnimation() { private boolean isMovingForAnimation() {
return this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-4D || this.getNavigation().isInProgress(); return this.toLocal(this.getDeltaMovement()).horizontalDistanceSqr() > 1.0E-4D || this.getNavigation().isInProgress();
}
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
} }
private final class BomberAttackGoal extends MeleeAttackGoal { private final class BomberAttackGoal extends MeleeAttackGoal {
@@ -5,6 +5,8 @@ import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -182,7 +184,8 @@ public class ButterflyEntity extends Animal implements FlyingAnimal, GeoEntity {
FlyingPathNavigation navigation = new FlyingPathNavigation(this, level) { FlyingPathNavigation navigation = new FlyingPathNavigation(this, level) {
@Override @Override
public boolean isStableDestination(BlockPos pos) { public boolean isStableDestination(BlockPos pos) {
return !this.level.getBlockState(pos.below()).isAir(); BlockPos support = AntarchyGravityApi.isGravityInverted(ButterflyEntity.this) ? pos.above() : pos.below();
return !this.level.getBlockState(support).isAir();
} }
@Override @Override
@@ -429,7 +432,7 @@ public class ButterflyEntity extends Animal implements FlyingAnimal, GeoEntity {
@Override @Override
protected void jumpInLiquid(net.minecraft.tags.TagKey<Fluid> fluidTag) { protected void jumpInLiquid(net.minecraft.tags.TagKey<Fluid> fluidTag) {
this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.01D, 0.0D)); this.setDeltaMovement(this.getDeltaMovement().add(AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, 0.01D, 0.0D, AntarchyGravityApi.getGravityDirection(this))));
} }
@Override @Override
@@ -2,6 +2,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
@@ -85,16 +88,22 @@ public class CreepingHorrorEntity extends Monster implements GeoEntity {
return true; return true;
} }
BlockPos belowPos = pos.below(); BlockPos belowPos = pos.below();
BlockPos abovePos = pos.above();
BlockState belowState = level.getBlockState(belowPos); BlockState belowState = level.getBlockState(belowPos);
boolean validSupport = !belowState.is(Blocks.BEDROCK) BlockState aboveState = level.getBlockState(abovePos);
boolean floorSupport = !belowState.is(Blocks.BEDROCK)
&& belowState.blocksMotion() && belowState.blocksMotion()
&& belowState.isFaceSturdy(level, belowPos, Direction.UP) && belowState.isFaceSturdy(level, belowPos, Direction.UP)
&& belowState.isCollisionShapeFullBlock(level, belowPos); && belowState.isCollisionShapeFullBlock(level, belowPos);
boolean ceilingSupport = !aboveState.is(Blocks.BEDROCK)
&& aboveState.blocksMotion()
&& aboveState.isFaceSturdy(level, abovePos, Direction.DOWN)
&& aboveState.isCollisionShapeFullBlock(level, abovePos);
return level.getDifficulty() != Difficulty.PEACEFUL return level.getDifficulty() != Difficulty.PEACEFUL
&& validSupport && (floorSupport || ceilingSupport)
&& level.isEmptyBlock(pos) && level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.above()) && (level.isEmptyBlock(pos.above()) || level.isEmptyBlock(pos.below()))
&& Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random); && Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
} }
@@ -202,23 +211,35 @@ public class CreepingHorrorEntity extends Monster implements GeoEntity {
if (climbing && this.getTarget() != null) { if (climbing && this.getTarget() != null) {
LivingEntity target = this.getTarget(); LivingEntity target = this.getTarget();
Vec3 toTarget = target.position().subtract(this.position()); Vec3 toTarget = this.toLocal(target.position().subtract(this.position()));
double hDist = Math.sqrt(toTarget.x * toTarget.x + toTarget.z * toTarget.z); double hDist = Math.sqrt(toTarget.x * toTarget.x + toTarget.z * toTarget.z);
double speed = this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 2.8D; double speed = this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 2.8D;
if (hDist > 0.01D) { if (hDist > 0.01D) {
this.setDeltaMovement( this.setDeltaMovement(this.toWorld(
(toTarget.x / hDist) * speed, (toTarget.x / hDist) * speed,
0.22D, 0.22D,
(toTarget.z / hDist) * speed (toTarget.z / hDist) * speed
); ));
} else { } else {
Vec3 mov = this.getDeltaMovement(); Vec3 mov = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(mov.x, 0.22D, mov.z); this.setDeltaMovement(this.toWorld(mov.x, 0.22D, mov.z));
} }
this.getNavigation().stop(); this.getNavigation().stop();
} }
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
@Override @Override
public boolean isInWall() { public boolean isInWall() {
return false; return false;
@@ -1,6 +1,9 @@
package com.craisinlord.antarchy.content.entity; package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -416,14 +419,15 @@ public class DorrieEntity extends Animal implements GeoEntity {
if (!this.isInWater() && !this.isInLava() && !this.onGround()) { if (!this.isInWater() && !this.isInLava() && !this.onGround()) {
Vec3 mov = this.getDeltaMovement(); Vec3 mov = this.getDeltaMovement();
this.setDeltaMovement(mov.x * 0.91D, mov.y - 0.08D, mov.z * 0.91D); Vec3 localMotion = this.toLocal(mov);
this.setDeltaMovement(this.toWorld(localMotion.x * 0.91D, localMotion.y - 0.08D, localMotion.z * 0.91D));
this.move(net.minecraft.world.entity.MoverType.SELF, this.getDeltaMovement()); this.move(net.minecraft.world.entity.MoverType.SELF, this.getDeltaMovement());
return; return;
} }
if (this.isInWater() || this.isInLava()) { if (this.isInWater() || this.isInLava()) {
this.moveRelative(this.getSpeed(), new Vec3(riddenInput.x, 0.0D, riddenInput.z)); this.moveRelative(this.getSpeed(), new Vec3(riddenInput.x, 0.0D, riddenInput.z));
Vec3 motion = this.getDeltaMovement(); Vec3 localMotion = this.toLocal(this.getDeltaMovement());
double vertical = 0.0D; double vertical = 0.0D;
if (this.isUnderWater()) { if (this.isUnderWater()) {
vertical = riddenInput.y * 0.025D; vertical = riddenInput.y * 0.025D;
@@ -433,11 +437,11 @@ public class DorrieEntity extends Animal implements GeoEntity {
if (this.pressingJump) { if (this.pressingJump) {
vertical += ASCEND_SPEED; vertical += ASCEND_SPEED;
} }
this.setDeltaMovement( this.setDeltaMovement(this.toWorld(
motion.x * 0.92D, localMotion.x * 0.92D,
motion.y * 0.90D + vertical, localMotion.y * 0.90D + vertical,
motion.z * 0.92D localMotion.z * 0.92D
); ));
this.move(net.minecraft.world.entity.MoverType.SELF, this.getDeltaMovement()); this.move(net.minecraft.world.entity.MoverType.SELF, this.getDeltaMovement());
return; return;
} }
@@ -450,15 +454,15 @@ public class DorrieEntity extends Animal implements GeoEntity {
float power = this.getJumpCharge() / 100f; float power = this.getJumpCharge() / 100f;
if (power > 0.05f) { if (power > 0.05f) {
Vec3 look = this.getLookAngle(); Vec3 look = this.getLookAngle();
Vec3 flatLook = new Vec3(look.x, 0.0D, look.z).normalize(); Vec3 flatLook = this.toLocalPlane(look).normalize();
Vec3 current = this.getDeltaMovement(); Vec3 current = this.toLocal(this.getDeltaMovement());
double forwardAdd = 0.15D + power * 0.45D; double forwardAdd = 0.15D + power * 0.45D;
double vertical = 0.55D + power * 0.80D; double vertical = 0.55D + power * 0.80D;
this.setDeltaMovement( this.setDeltaMovement(this.toWorld(
current.x + flatLook.x * forwardAdd, current.x + flatLook.x * forwardAdd,
vertical, vertical,
current.z + flatLook.z * forwardAdd current.z + flatLook.z * forwardAdd
); ));
} }
} }
@@ -467,15 +471,15 @@ public class DorrieEntity extends Animal implements GeoEntity {
float power = chargeTicks / (float) MAX_CHARGE_TICKS; float power = chargeTicks / (float) MAX_CHARGE_TICKS;
if (power > 0.05F) { if (power > 0.05F) {
Vec3 look = this.getLookAngle(); Vec3 look = this.getLookAngle();
Vec3 flatLook = new Vec3(look.x, 0.0D, look.z).normalize(); Vec3 flatLook = this.toLocalPlane(look).normalize();
Vec3 current = this.getDeltaMovement(); Vec3 current = this.toLocal(this.getDeltaMovement());
double forwardAdd = 0.15D + power * 0.45D; double forwardAdd = 0.15D + power * 0.45D;
double vertical = 0.55D + power * 0.80D; double vertical = 0.55D + power * 0.80D;
this.setDeltaMovement( this.setDeltaMovement(this.toWorld(
current.x + flatLook.x * forwardAdd, current.x + flatLook.x * forwardAdd,
vertical, vertical,
current.z + flatLook.z * forwardAdd current.z + flatLook.z * forwardAdd
); ));
this.hasImpulse = true; this.hasImpulse = true;
isLeaping = true; isLeaping = true;
this.triggerAnim("main_controller", "jump_start"); this.triggerAnim("main_controller", "jump_start");
@@ -489,11 +493,13 @@ public class DorrieEntity extends Animal implements GeoEntity {
@Override @Override
protected void positionRider(Entity passenger, MoveFunction moveFunction) { protected void positionRider(Entity passenger, MoveFunction moveFunction) {
if (this.hasPassenger(passenger)) { if (this.hasPassenger(passenger)) {
Vec3 forward = this.getLookAngle().multiply(1.0D, 0.0D, 1.0D); Vec3 localForward = this.toLocalPlane(this.getLookAngle()).normalize();
Vec3 worldForward = this.toWorld(localForward);
Vec3 seatOffset = this.toWorld(0.0D, 0.5D, 0.0D).subtract(worldForward.scale(0.65D));
moveFunction.accept(passenger, moveFunction.accept(passenger,
this.getX() - forward.x * 0.65D, this.getX() + seatOffset.x,
this.getY() + 0.5D, this.getY() + seatOffset.y,
this.getZ() - forward.z * 0.65D); this.getZ() + seatOffset.z);
} }
} }
@@ -706,10 +712,11 @@ public class DorrieEntity extends Animal implements GeoEntity {
int bottom = Math.max(minY, this.level().getMinBuildHeight() + 1); int bottom = Math.max(minY, this.level().getMinBuildHeight() + 1);
for (int y = top; y >= bottom; y--) { for (int y = top; y >= bottom; y--) {
BlockPos pos = BlockPos.containing(x, y, z); BlockPos pos = BlockPos.containing(x, y, z);
if (!this.isWaterAt(pos) || this.isWaterAt(pos.above())) { BlockPos localUp = this.relativeLocal(pos, 0, 1, 0);
if (!this.isWaterAt(pos) || this.isWaterAt(localUp)) {
continue; continue;
} }
return new Vec3(x + 0.5D, y + 0.85D, z + 0.5D); return Vec3.atCenterOf(pos).add(this.toWorld(0.0D, 0.35D, 0.0D));
} }
return null; return null;
} }
@@ -737,10 +744,11 @@ public class DorrieEntity extends Animal implements GeoEntity {
int bottom = Math.max(minY, this.level().getMinBuildHeight() + 1); int bottom = Math.max(minY, this.level().getMinBuildHeight() + 1);
for (int y = top; y >= bottom; y--) { for (int y = top; y >= bottom; y--) {
BlockPos pos = BlockPos.containing(x, y, z); BlockPos pos = BlockPos.containing(x, y, z);
if (!this.isWaterAt(pos) || !this.isWaterAt(pos.below())) { BlockPos localDown = this.relativeLocal(pos, 0, -1, 0);
if (!this.isWaterAt(pos) || !this.isWaterAt(localDown)) {
continue; continue;
} }
return new Vec3(x + 0.5D, y + 0.3D, z + 0.5D); return Vec3.atCenterOf(pos).add(this.toWorld(0.0D, -0.2D, 0.0D));
} }
return null; return null;
} }
@@ -756,10 +764,36 @@ public class DorrieEntity extends Animal implements GeoEntity {
if (this.getControllingPassenger() instanceof Player player) { if (this.getControllingPassenger() instanceof Player player) {
return Math.abs(player.zza) > 0.05F || Math.abs(player.xxa) > 0.05F; return Math.abs(player.zza) > 0.05F || Math.abs(player.xxa) > 0.05F;
} }
return this.getDeltaMovement().horizontalDistanceSqr() > MOVING_ANIM_THRESHOLD_SQ return this.toLocal(this.getDeltaMovement()).horizontalDistanceSqr() > MOVING_ANIM_THRESHOLD_SQ
|| this.getNavigation().isInProgress(); || this.getNavigation().isInProgress();
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(Vec3 localVector) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(localVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
private BlockPos relativeLocal(BlockPos pos, int x, int y, int z) {
Vec3 worldOffset = this.toWorld(x, y, z);
return pos.offset(Mth.floor(worldOffset.x), Mth.floor(worldOffset.y), Mth.floor(worldOffset.z));
}
private class DolphinSwimGoal extends Goal { private class DolphinSwimGoal extends Goal {
private static final int COOLDOWN_MIN_TICKS = 120; private static final int COOLDOWN_MIN_TICKS = 120;
private static final int COOLDOWN_MAX_TICKS = 180; private static final int COOLDOWN_MAX_TICKS = 180;
@@ -6,8 +6,11 @@ import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.boss.BossCombatUtil; import com.craisinlord.antarchy.content.boss.BossCombatUtil;
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
import com.craisinlord.antarchy.content.entity.ScorpionEntity; import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
@@ -401,8 +404,9 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
} }
} }
case ACTIVE -> { case ACTIVE -> {
Vec3 motion = this.getDeltaMovement(); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(this);
this.setDeltaMovement(0.0D, motion.y, 0.0D); Vec3 motion = AntarchyGravityRotationUtil.vecWorldToPlayer(this.getDeltaMovement(), direction);
this.setDeltaMovement(AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, motion.y, 0.0D, direction));
if (--this.hardenDurationTicks <= 0) { if (--this.hardenDurationTicks <= 0) {
this.beginHardeningEnd(); this.beginHardeningEnd();
return; return;
@@ -413,8 +417,9 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
} }
} }
case END -> { case END -> {
Vec3 motion = this.getDeltaMovement(); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(this);
this.setDeltaMovement(0.0D, motion.y, 0.0D); Vec3 motion = AntarchyGravityRotationUtil.vecWorldToPlayer(this.getDeltaMovement(), direction);
this.setDeltaMovement(AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, motion.y, 0.0D, direction));
if (--this.hardenStateTicks <= 0) { if (--this.hardenStateTicks <= 0) {
this.setHardenPhase(HardenPhase.NONE); this.setHardenPhase(HardenPhase.NONE);
this.hardenCooldownTicks = Math.max(1, AntarchySettings.emperorScorpionHardenCooldownTicks()); this.hardenCooldownTicks = Math.max(1, AntarchySettings.emperorScorpionHardenCooldownTicks());
@@ -475,10 +480,13 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
} }
Vec3 anchor = this.getTarget() != null ? this.getTarget().position() : this.position(); Vec3 anchor = this.getTarget() != null ? this.getTarget().position() : this.position();
Vec3 ring = Vec3.directionFromRotation(0.0F, this.random.nextFloat() * 360.0F) AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(this);
Vec3 localRing = Vec3.directionFromRotation(0.0F, this.random.nextFloat() * 360.0F)
.scale(2.75D + this.random.nextDouble() * 1.75D); .scale(2.75D + this.random.nextDouble() * 1.75D);
BlockPos spawnPos = BlockPos.containing(anchor.x + ring.x, this.getY(), anchor.z + ring.z); Vec3 worldRing = AntarchyGravityRotationUtil.vecPlayerToWorld(localRing, direction);
scorpion.moveTo(spawnPos.getX() + 0.5D, spawnPos.getY(), spawnPos.getZ() + 0.5D, this.random.nextFloat() * 360.0F, 0.0F); BlockPos spawnPos = this.findSummonSpawnPos(anchor.add(worldRing));
Vec3 spawnCenter = Vec3.atCenterOf(spawnPos);
scorpion.moveTo(spawnCenter.x, spawnCenter.y, spawnCenter.z, this.random.nextFloat() * 360.0F, 0.0F);
scorpion.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(spawnPos), MobSpawnType.MOB_SUMMONED, null); scorpion.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(spawnPos), MobSpawnType.MOB_SUMMONED, null);
scorpion.setPersistenceRequired(); scorpion.setPersistenceRequired();
scorpion.setSummonOwner(this.getUUID()); scorpion.setSummonOwner(this.getUUID());
@@ -490,16 +498,36 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
} }
private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) { private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) {
Vec3 lunge = target.position().subtract(this.position()); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(this);
Vec3 horizontal = new Vec3(lunge.x, 0.0D, lunge.z); Vec3 localLunge = AntarchyGravityRotationUtil.vecWorldToPlayer(target.position().subtract(this.position()), direction);
Vec3 horizontal = new Vec3(localLunge.x, 0.0D, localLunge.z);
if (horizontal.lengthSqr() < 1.0E-4D) { if (horizontal.lengthSqr() < 1.0E-4D) {
return; return;
} }
horizontal = horizontal.normalize().scale(horizontalSpeed); horizontal = horizontal.normalize().scale(horizontalSpeed);
this.setDeltaMovement(this.getDeltaMovement().add(horizontal.x, verticalSpeed, horizontal.z)); Vec3 localImpulse = new Vec3(horizontal.x, verticalSpeed, horizontal.z);
Vec3 worldImpulse = AntarchyGravityRotationUtil.vecPlayerToWorld(localImpulse, direction);
this.setDeltaMovement(this.getDeltaMovement().add(worldImpulse.x, worldImpulse.y, worldImpulse.z));
this.hasImpulse = true; this.hasImpulse = true;
} }
private BlockPos findSummonSpawnPos(Vec3 center) {
BlockPos base = BlockPos.containing(center);
Direction gravityDown = AntarchyGravityRotationUtil.getGravityDownDirection(this);
Direction gravityUp = gravityDown.getOpposite();
BlockPos fallback = base;
for (int step = -2; step <= 2; step++) {
BlockPos candidate = base.relative(gravityUp, step);
BlockPos support = candidate.relative(gravityDown);
if (this.level().isEmptyBlock(candidate)
&& this.level().isEmptyBlock(candidate.relative(gravityUp))
&& this.level().getBlockState(support).isFaceSturdy(this.level(), support, gravityUp)) {
return candidate;
}
}
return fallback;
}
@Override @Override
public void handleEntityEvent(byte id) { public void handleEntityEvent(byte id) {
if (id == CLAW_ATTACK_EVENT) { if (id == CLAW_ATTACK_EVENT) {
@@ -824,12 +852,12 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
} }
Vec3 homeCenter = Vec3.atCenterOf(this.encounterHome); Vec3 homeCenter = Vec3.atCenterOf(this.encounterHome);
if (this.distanceToSqr(homeCenter) > FORCED_RETURN_RADIUS * FORCED_RETURN_RADIUS) { if (this.distanceToSqr(homeCenter) > FORCED_RETURN_RADIUS * FORCED_RETURN_RADIUS) {
this.moveTo(homeCenter.x, this.encounterHome.getY(), homeCenter.z, this.getYRot(), this.getXRot()); this.moveTo(homeCenter.x, homeCenter.y, homeCenter.z, this.getYRot(), this.getXRot());
this.setDeltaMovement(Vec3.ZERO); this.setDeltaMovement(Vec3.ZERO);
this.hasImpulse = true; this.hasImpulse = true;
return; return;
} }
this.getNavigation().moveTo(homeCenter.x, this.encounterHome.getY(), homeCenter.z, HOME_RETURN_SPEED); this.getNavigation().moveTo(homeCenter.x, homeCenter.y, homeCenter.z, HOME_RETURN_SPEED);
} }
private void resetEncounter(boolean restoreHealth) { private void resetEncounter(boolean restoreHealth) {
@@ -853,7 +881,7 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
this.discardOwnedScorpions(); this.discardOwnedScorpions();
if (this.encounterHome != null) { if (this.encounterHome != null) {
Vec3 homeCenter = Vec3.atCenterOf(this.encounterHome); Vec3 homeCenter = Vec3.atCenterOf(this.encounterHome);
this.moveTo(homeCenter.x, this.encounterHome.getY(), homeCenter.z, this.getYRot(), this.getXRot()); this.moveTo(homeCenter.x, homeCenter.y, homeCenter.z, this.getYRot(), this.getXRot());
this.setDeltaMovement(Vec3.ZERO); this.setDeltaMovement(Vec3.ZERO);
} }
} }
@@ -949,7 +977,11 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
if (EmperorScorpionEntity.this.isWithinMeleeAttackRange(target) && EmperorScorpionEntity.this.hasLineOfSight(target)) { if (EmperorScorpionEntity.this.isWithinMeleeAttackRange(target) && EmperorScorpionEntity.this.hasLineOfSight(target)) {
EmperorScorpionEntity.this.getNavigation().stop(); EmperorScorpionEntity.this.getNavigation().stop();
EmperorScorpionEntity.this.setDeltaMovement(0.0D, EmperorScorpionEntity.this.getDeltaMovement().y, 0.0D); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(EmperorScorpionEntity.this);
Vec3 localMotion = AntarchyGravityRotationUtil.vecWorldToPlayer(EmperorScorpionEntity.this.getDeltaMovement(), direction);
Vec3 localStopped = new Vec3(0.0D, localMotion.y, 0.0D);
Vec3 worldStopped = AntarchyGravityRotationUtil.vecPlayerToWorld(localStopped, direction);
EmperorScorpionEntity.this.setDeltaMovement(worldStopped);
AttackType attackType = EmperorScorpionEntity.this.selectAttack(target); AttackType attackType = EmperorScorpionEntity.this.selectAttack(target);
if (attackType != AttackType.NONE) { if (attackType != AttackType.NONE) {
EmperorScorpionEntity.this.beginAttack(target, attackType); EmperorScorpionEntity.this.beginAttack(target, attackType);
@@ -968,8 +1000,10 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
} }
private void approachDirectly(LivingEntity target) { private void approachDirectly(LivingEntity target) {
double dx = target.getX() - EmperorScorpionEntity.this.getX(); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(EmperorScorpionEntity.this);
double dz = target.getZ() - EmperorScorpionEntity.this.getZ(); Vec3 localDelta = AntarchyGravityRotationUtil.vecWorldToPlayer(target.position().subtract(EmperorScorpionEntity.this.position()), direction);
double dx = localDelta.x;
double dz = localDelta.z;
if (dx * dx + dz * dz < 1.0E-4D) { if (dx * dx + dz * dz < 1.0E-4D) {
return; return;
} }
@@ -981,14 +1015,15 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
EmperorScorpionEntity.this.yBodyRot = newYaw; EmperorScorpionEntity.this.yBodyRot = newYaw;
EmperorScorpionEntity.this.yBodyRotO = newYaw; EmperorScorpionEntity.this.yBodyRotO = newYaw;
Vec3 currentMotion = EmperorScorpionEntity.this.getDeltaMovement(); Vec3 currentMotion = AntarchyGravityRotationUtil.vecWorldToPlayer(EmperorScorpionEntity.this.getDeltaMovement(), direction);
float headingError = Math.abs(Mth.wrapDegrees(targetYaw - currentYaw)); float headingError = Math.abs(Mth.wrapDegrees(targetYaw - currentYaw));
if (headingError <= DIRECT_APPROACH_ALIGN_THRESHOLD) { if (headingError <= DIRECT_APPROACH_ALIGN_THRESHOLD) {
double speed = EmperorScorpionEntity.this.getAttributeValue(Attributes.MOVEMENT_SPEED) * CHASE_SPEED; double speed = EmperorScorpionEntity.this.getAttributeValue(Attributes.MOVEMENT_SPEED) * CHASE_SPEED;
Vec3 forward = Vec3.directionFromRotation(0.0F, newYaw).scale(speed); Vec3 forward = Vec3.directionFromRotation(0.0F, newYaw).scale(speed);
EmperorScorpionEntity.this.setDeltaMovement(forward.x, currentMotion.y, forward.z); Vec3 worldForward = AntarchyGravityRotationUtil.vecPlayerToWorld(forward.x, currentMotion.y, forward.z, direction);
EmperorScorpionEntity.this.setDeltaMovement(worldForward);
} else { } else {
EmperorScorpionEntity.this.setDeltaMovement(0.0D, currentMotion.y, 0.0D); EmperorScorpionEntity.this.setDeltaMovement(AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, currentMotion.y, 0.0D, direction));
} }
} }
@@ -6,6 +6,9 @@ import com.craisinlord.antarchy.content.AntarchyGameRules;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import com.craisinlord.antarchy.content.item.BigBerthaItem; import com.craisinlord.antarchy.content.item.BigBerthaItem;
import com.craisinlord.antarchy.content.network.HerculesBeetleImpactShakeSync; import com.craisinlord.antarchy.content.network.HerculesBeetleImpactShakeSync;
import java.util.EnumSet; import java.util.EnumSet;
@@ -218,10 +221,13 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) { if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true; return true;
} }
return level.getDifficulty() != Difficulty.PEACEFUL boolean floorSpawn = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP)
&& level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP)
&& level.isEmptyBlock(pos) && level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.above()); && level.isEmptyBlock(pos.above());
boolean ceilingSpawn = level.getBlockState(pos.above()).isFaceSturdy(level, pos.above(), Direction.DOWN)
&& level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.below());
return level.getDifficulty() != Difficulty.PEACEFUL && (floorSpawn || ceilingSpawn);
} }
@Override @Override
@@ -416,8 +422,8 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
private void tickKnockedDown() { private void tickKnockedDown() {
this.getNavigation().stop(); this.getNavigation().stop();
Vec3 motion = this.getDeltaMovement(); Vec3 motion = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(0.0D, Math.min(motion.y, 0.0D), 0.0D); this.setDeltaMovement(this.toWorld(0.0D, Math.min(motion.y, 0.0D), 0.0D));
if (this.getAnimationState() == ANIM_KNOCKED_DOWN && this.actionTicks > 0) { if (this.getAnimationState() == ANIM_KNOCKED_DOWN && this.actionTicks > 0) {
this.actionTicks--; this.actionTicks--;
if (this.actionTicks <= 0) { if (this.actionTicks <= 0) {
@@ -454,8 +460,8 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
case ANIM_OPEN_WINGS -> { case ANIM_OPEN_WINGS -> {
this.setFlying(true); this.setFlying(true);
if (this.getControllingPassenger() instanceof Player) { if (this.getControllingPassenger() instanceof Player) {
Vec3 motion = this.getDeltaMovement(); Vec3 motion = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(motion.x, Math.max(motion.y, MOUNTED_FLIGHT_LIFT), motion.z); this.setDeltaMovement(this.toWorld(motion.x, Math.max(motion.y, MOUNTED_FLIGHT_LIFT), motion.z));
this.hasImpulse = true; this.hasImpulse = true;
} }
if (this.pendingChargeStart) { if (this.pendingChargeStart) {
@@ -533,9 +539,9 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
this.setNoGravity(true); this.setNoGravity(true);
this.noPhysics = false; this.noPhysics = false;
this.fallDistance = 0.0F; this.fallDistance = 0.0F;
if (this.onGround() && this.getDeltaMovement().y <= 0.0D) { Vec3 motion = this.toLocal(this.getDeltaMovement());
Vec3 motion = this.getDeltaMovement(); if (this.onGround() && motion.y <= 0.0D) {
this.setDeltaMovement(motion.x, MOUNTED_FLIGHT_LIFT, motion.z); this.setDeltaMovement(this.toWorld(motion.x, MOUNTED_FLIGHT_LIFT, motion.z));
this.hasImpulse = true; this.hasImpulse = true;
} }
} else { } else {
@@ -753,7 +759,7 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
} }
private boolean isMountedFlightPoseActive() { private boolean isMountedFlightPoseActive() {
return this.isFlying() && (!this.onGround() || this.getDeltaMovement().y > 0.08D); return this.isFlying() && (!this.onGround() || this.toLocal(this.getDeltaMovement()).y > 0.08D);
} }
private void startMountedFlight() { private void startMountedFlight() {
@@ -763,8 +769,8 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
this.noPhysics = false; this.noPhysics = false;
this.fallDistance = 0.0F; this.fallDistance = 0.0F;
this.groundedTicks = 0; this.groundedTicks = 0;
Vec3 motion = this.getDeltaMovement(); Vec3 motion = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(motion.x, Math.max(motion.y, MOUNTED_FLIGHT_LIFT), motion.z); this.setDeltaMovement(this.toWorld(motion.x, Math.max(motion.y, MOUNTED_FLIGHT_LIFT), motion.z));
this.hasImpulse = true; this.hasImpulse = true;
this.setAnimationState(ANIM_FLY); this.setAnimationState(ANIM_FLY);
} }
@@ -883,23 +889,24 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
? target.hurt(AntarchyDamageSources.herculesBeetleObliteration(serverLevel, this), damage) ? target.hurt(AntarchyDamageSources.herculesBeetleObliteration(serverLevel, this), damage)
: target.hurt(this.damageSources().mobAttack(this), damage); : target.hurt(this.damageSources().mobAttack(this), damage);
if (hurt) { if (hurt) {
Vec3 push = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 push = this.toLocalPlane(target.position().subtract(this.position()));
if (push.lengthSqr() < 1.0E-4D) { if (push.lengthSqr() < 1.0E-4D) {
push = this.getLookAngle().multiply(1.0D, 0.0D, 1.0D); push = this.toLocalPlane(this.getLookAngle());
} }
push = push.normalize().scale(horizontalKnockback); push = push.normalize().scale(horizontalKnockback);
target.setDeltaMovement(target.getDeltaMovement().add(push.x, 1.25D, push.z)); Vec3 worldPush = this.toWorld(push.x, 1.25D, push.z);
target.setDeltaMovement(target.getDeltaMovement().add(worldPush.x, worldPush.y, worldPush.z));
target.hurtMarked = true; target.hurtMarked = true;
} }
return hurt; return hurt;
} }
private void startCharge(Vec3 direction, int durationTicks, boolean mountedCharge) { private void startCharge(Vec3 direction, int durationTicks, boolean mountedCharge) {
Vec3 horizontal = direction.multiply(1.0D, 0.0D, 1.0D); Vec3 horizontal = this.toLocalPlane(direction);
if (horizontal.lengthSqr() < 1.0E-4D) { if (horizontal.lengthSqr() < 1.0E-4D) {
horizontal = this.getLookAngle().multiply(1.0D, 0.0D, 1.0D); horizontal = this.toLocalPlane(this.getLookAngle());
} }
this.chargeDirection = horizontal.normalize(); this.chargeDirection = this.toWorld(horizontal.normalize());
this.pendingChargeDuration = Mth.clamp(durationTicks, MIN_MOUNTED_CHARGE_TICKS, MAX_CHARGE_TICKS); this.pendingChargeDuration = Mth.clamp(durationTicks, MIN_MOUNTED_CHARGE_TICKS, MAX_CHARGE_TICKS);
this.pendingMountedCharge = mountedCharge; this.pendingMountedCharge = mountedCharge;
@@ -954,12 +961,17 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
continue; continue;
} }
if (victim.hurt(AntarchyDamageSources.herculesBeetleObliteration(serverLevel, this), damage)) { if (victim.hurt(AntarchyDamageSources.herculesBeetleObliteration(serverLevel, this), damage)) {
Vec3 push = victim.position().subtract(this.position()); Vec3 push = this.toLocal(victim.position().subtract(this.position()));
if (push.lengthSqr() < 1.0E-4D) { if (push.lengthSqr() < 1.0E-4D) {
push = this.chargeDirection; push = this.toLocal(this.chargeDirection);
} }
push = push.normalize(); Vec3 horizontal = new Vec3(push.x, 0.0D, push.z);
victim.setDeltaMovement(victim.getDeltaMovement().add(push.x * 1.25D, 0.9D, push.z * 1.25D)); if (horizontal.lengthSqr() < 1.0E-4D) {
horizontal = this.toLocalPlane(this.getLookAngle());
}
horizontal = horizontal.normalize();
Vec3 worldPush = this.toWorld(horizontal.x * 1.25D, 0.9D, horizontal.z * 1.25D);
victim.setDeltaMovement(victim.getDeltaMovement().add(worldPush.x, worldPush.y, worldPush.z));
victim.hurtMarked = true; victim.hurtMarked = true;
} }
} }
@@ -1169,7 +1181,8 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
@Override @Override
protected void positionRider(Entity passenger, MoveFunction moveFunction) { protected void positionRider(Entity passenger, MoveFunction moveFunction) {
if (this.hasPassenger(passenger)) { if (this.hasPassenger(passenger)) {
Vec3 forward = this.getLookAngle().multiply(1.0D, 0.0D, 1.0D); Vec3 localForward = this.toLocalPlane(this.getLookAngle());
Vec3 forward = localForward.lengthSqr() > 1.0E-4D ? this.toWorld(localForward.normalize()) : this.toWorld(0.0D, 0.0D, 1.0D);
boolean mountedFlightPose = this.isMountedFlightPoseActive(); boolean mountedFlightPose = this.isMountedFlightPoseActive();
double yOffset = mountedFlightPose ? 5.3D : 3.0D; double yOffset = mountedFlightPose ? 5.3D : 3.0D;
double forwardOffset = mountedFlightPose ? 2.2D : 1.25D; double forwardOffset = mountedFlightPose ? 2.2D : 1.25D;
@@ -1177,11 +1190,12 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
yOffset -= 0.25D; yOffset -= 0.25D;
forwardOffset += 0.25D; forwardOffset += 0.25D;
} }
Vec3 seatOffset = forward.scale(forwardOffset).add(this.toWorld(0.0D, yOffset, 0.0D));
moveFunction.accept( moveFunction.accept(
passenger, passenger,
this.getX() + forward.x * forwardOffset, this.getX() + seatOffset.x,
this.getY() + yOffset, this.getY() + seatOffset.y,
this.getZ() + forward.z * forwardOffset this.getZ() + seatOffset.z
); );
} }
} }
@@ -1209,14 +1223,15 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
super.travel(new Vec3(riddenInput.x, travelVector.y, riddenInput.z)); super.travel(new Vec3(riddenInput.x, travelVector.y, riddenInput.z));
if (Math.abs(rider.zza) < 0.05F && Math.abs(rider.xxa) < 0.05F && this.onGround()) { if (Math.abs(rider.zza) < 0.05F && Math.abs(rider.xxa) < 0.05F && this.onGround()) {
Vec3 dampedMotion = this.getDeltaMovement(); Vec3 dampedMotion = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(dampedMotion.x * MOUNTED_GROUND_BRAKE, dampedMotion.y, dampedMotion.z * MOUNTED_GROUND_BRAKE); this.setDeltaMovement(this.toWorld(dampedMotion.x * MOUNTED_GROUND_BRAKE, dampedMotion.y, dampedMotion.z * MOUNTED_GROUND_BRAKE));
} }
} else { } else {
Vec3 motion = new Vec3(0.0D, this.getDeltaMovement().y, 0.0D); Vec3 motion = this.toLocal(this.getDeltaMovement());
this.moveRelative(this.getSpeed(), new Vec3(riddenInput.x, 0.0D, riddenInput.z)); this.moveRelative(this.getSpeed(), new Vec3(riddenInput.x, 0.0D, riddenInput.z));
motion = motion.add(this.getDeltaMovement().x, riddenInput.y, this.getDeltaMovement().z); Vec3 moved = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(motion); motion = new Vec3(moved.x, motion.y + riddenInput.y, moved.z);
this.setDeltaMovement(this.toWorld(motion));
this.move(MoverType.SELF, this.getDeltaMovement()); this.move(MoverType.SELF, this.getDeltaMovement());
} }
} }
@@ -1292,10 +1307,11 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
} }
private void lookInDirection(Vec3 direction) { private void lookInDirection(Vec3 direction) {
if (direction.lengthSqr() <= 1.0E-4D) { Vec3 localDirection = this.toLocalPlane(direction);
if (localDirection.lengthSqr() <= 1.0E-4D) {
return; return;
} }
float yaw = (float) (Mth.atan2(direction.z, direction.x) * (180.0D / Math.PI)) - 90.0F; float yaw = (float) (Mth.atan2(localDirection.z, localDirection.x) * (180.0D / Math.PI)) - 90.0F;
this.setYRot(yaw); this.setYRot(yaw);
this.yBodyRot = yaw; this.yBodyRot = yaw;
this.yHeadRot = yaw; this.yHeadRot = yaw;
@@ -1313,10 +1329,10 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
private List<LivingEntity> getFrontTargets(double range, double inflation) { private List<LivingEntity> getFrontTargets(double range, double inflation) {
AABB box = this.getBoundingBox().expandTowards(this.getLookAngle().scale(range)).inflate(inflation); AABB box = this.getBoundingBox().expandTowards(this.getLookAngle().scale(range)).inflate(inflation);
Vec3 forward = this.getLookAngle().multiply(1.0D, 0.0D, 1.0D); Vec3 forward = this.toLocalPlane(this.getLookAngle());
return this.level().getEntitiesOfClass(LivingEntity.class, box, this::canHarm).stream() return this.level().getEntitiesOfClass(LivingEntity.class, box, this::canHarm).stream()
.filter(entity -> { .filter(entity -> {
Vec3 toTarget = entity.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 toTarget = this.toLocalPlane(entity.position().subtract(this.position()));
if (forward.lengthSqr() < 1.0E-4D || toTarget.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D || toTarget.lengthSqr() < 1.0E-4D) {
return true; return true;
} }
@@ -1325,6 +1341,27 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
.toList(); .toList();
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(Vec3 localVector) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(localVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
@Nullable @Nullable
private LivingEntity findFrontTarget(double range, double inflation) { private LivingEntity findFrontTarget(double range, double inflation) {
List<LivingEntity> targets = this.getFrontTargets(range, inflation); List<LivingEntity> targets = this.getFrontTargets(range, inflation);
@@ -2,6 +2,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import com.craisinlord.antarchy.content.horde.CavarynHordeManager; import com.craisinlord.antarchy.content.horde.CavarynHordeManager;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
@@ -208,7 +211,7 @@ public class JerryEntity extends Monster implements GeoEntity {
return; return;
} }
Vec3 targetPos = target.getEyePosition().add(0.0D, -0.15D, 0.0D); Vec3 targetPos = target.getEyePosition().add(this.toWorld(0.0D, -0.15D, 0.0D));
Vec3 toTarget = targetPos.subtract(this.position()); Vec3 toTarget = targetPos.subtract(this.position());
double distance = toTarget.length(); double distance = toTarget.length();
if (distance > 0.01D) { if (distance > 0.01D) {
@@ -242,15 +245,15 @@ public class JerryEntity extends Monster implements GeoEntity {
Stage stage = this.getStage(); Stage stage = this.getStage();
Vec3 targetPos = target.getEyePosition(); Vec3 targetPos = target.getEyePosition();
Vec3 hoverPos = targetPos.add(0.0D, 5.0D, 0.0D); Vec3 hoverPos = targetPos.add(this.toWorld(0.0D, 5.0D, 0.0D));
Vec3 toHover = hoverPos.subtract(this.position()); Vec3 toHover = hoverPos.subtract(this.position());
Vec3 toTarget = targetPos.subtract(this.position()); Vec3 toTarget = targetPos.subtract(this.position());
double hoverDistance = toHover.length(); double hoverDistance = toHover.length();
double targetDistance = toTarget.length(); double targetDistance = toTarget.length();
double horizontalDistance = this.position().subtract(targetPos).horizontalDistance(); double horizontalDistance = this.toLocalPlane(this.position().subtract(targetPos)).length();
this.faceTarget(target); this.faceTarget(target);
if (this.alphaDiveCooldownTicks > 0) { if (this.alphaDiveCooldownTicks > 0) {
this.setDeltaMovement(this.getDeltaMovement().scale(0.8D).add(toTarget.normalize().scale(0.28D)).add(0.0D, -0.08D, 0.0D)); this.setDeltaMovement(this.getDeltaMovement().scale(0.8D).add(toTarget.normalize().scale(0.28D)).add(this.toWorld(0.0D, -0.08D, 0.0D)));
} else if (hoverDistance > 0.01D) { } else if (hoverDistance > 0.01D) {
Vec3 desiredMotion = toHover.normalize().scale(0.20D); Vec3 desiredMotion = toHover.normalize().scale(0.20D);
this.setDeltaMovement(this.getDeltaMovement().scale(0.72D).add(desiredMotion)); this.setDeltaMovement(this.getDeltaMovement().scale(0.72D).add(desiredMotion));
@@ -258,7 +261,7 @@ public class JerryEntity extends Monster implements GeoEntity {
if (this.alphaDiveCooldownTicks <= 0 && targetDistance < 9.0D && horizontalDistance < 7.0D) { if (this.alphaDiveCooldownTicks <= 0 && targetDistance < 9.0D && horizontalDistance < 7.0D) {
this.alphaDiveCooldownTicks = 30; this.alphaDiveCooldownTicks = 30;
this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.55D, 0.0D).add(toTarget.normalize().scale(0.42D))); this.setDeltaMovement(this.getDeltaMovement().add(this.toWorld(0.0D, -0.55D, 0.0D)).add(toTarget.normalize().scale(0.42D)));
} }
if (targetDistance < 2.3D && this.attackCooldownTicks <= 0) { if (targetDistance < 2.3D && this.attackCooldownTicks <= 0) {
@@ -271,11 +274,12 @@ public class JerryEntity extends Monster implements GeoEntity {
} }
private void faceTarget(LivingEntity target) { private void faceTarget(LivingEntity target) {
Vec3 toTarget = target.position().subtract(this.position()); Vec3 toTarget = this.toLocal(target.position().subtract(this.position()));
if (toTarget.horizontalDistanceSqr() <= 0.0001D) { Vec3 horizontal = new Vec3(toTarget.x, 0.0D, toTarget.z);
if (horizontal.lengthSqr() <= 0.0001D) {
return; return;
} }
float targetYaw = (float) (Mth.atan2(toTarget.z, toTarget.x) * (180.0F / Math.PI)) - 90.0F; float targetYaw = (float) (Mth.atan2(horizontal.z, horizontal.x) * (180.0F / Math.PI)) - 90.0F;
this.setYRot(Mth.approachDegrees(this.getYRot(), targetYaw, 30.0F)); this.setYRot(Mth.approachDegrees(this.getYRot(), targetYaw, 30.0F));
this.yBodyRot = this.getYRot(); this.yBodyRot = this.getYRot();
this.yHeadRot = this.getYRot(); this.yHeadRot = this.getYRot();
@@ -304,6 +308,23 @@ public class JerryEntity extends Monster implements GeoEntity {
: super.doHurtTarget(target); : super.doHurtTarget(target);
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
@Override @Override
@Nullable @Nullable
protected SoundEvent getAmbientSound() { protected SoundEvent getAmbientSound() {
@@ -3,6 +3,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@@ -409,7 +412,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
this.getNavigation().stop(); this.getNavigation().stop();
this.setDeltaMovement(Vec3.ZERO); this.setDeltaMovement(Vec3.ZERO);
this.move(MoverType.SELF, Vec3.ZERO); this.move(MoverType.SELF, Vec3.ZERO);
this.setPos(this.getX(), clingPos.getY() - this.getBbHeight() - 0.01D, this.getZ()); this.setPos(this.getX(), AntarchyGravityApi.isGravityInverted(this) ? clingPos.getY() + 1.01D : clingPos.getY() - this.getBbHeight() - 0.01D, this.getZ());
} }
private void tickPouncing() { private void tickPouncing() {
@@ -460,7 +463,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
boolean playerNearby = this.level().getNearestPlayer(this, CAMOUFLAGE_PLAYER_RANGE) != null; boolean playerNearby = this.level().getNearestPlayer(this, CAMOUFLAGE_PLAYER_RANGE) != null;
boolean idle = this.getTarget() == null boolean idle = this.getTarget() == null
&& this.recoveryTicks <= 0 && this.recoveryTicks <= 0
&& this.getDeltaMovement().horizontalDistanceSqr() < 0.003D && this.toLocal(this.getDeltaMovement()).horizontalDistanceSqr() < 0.003D
&& this.onGround(); && this.onGround();
boolean movingQuickly = this.getDeltaMovement().lengthSqr() > QUICK_MOVE_SQR; boolean movingQuickly = this.getDeltaMovement().lengthSqr() > QUICK_MOVE_SQR;
boolean inAmbushCover = this.findCeilingWithinRange(this.directCeilingSearchHeight()) != null; boolean inAmbushCover = this.findCeilingWithinRange(this.directCeilingSearchHeight()) != null;
@@ -480,7 +483,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
private BlockPos findCeilingWithinRange(int maxBlocks) { private BlockPos findCeilingWithinRange(int maxBlocks) {
BlockPos origin = this.blockPosition(); BlockPos origin = this.blockPosition();
for (int dy = 1; dy <= maxBlocks; dy++) { for (int dy = 1; dy <= maxBlocks; dy++) {
BlockPos candidate = origin.above(dy); BlockPos candidate = this.relativeLocal(origin, 0, dy, 0);
if (this.isUsableCeiling(candidate)) { if (this.isUsableCeiling(candidate)) {
return candidate; return candidate;
} }
@@ -504,7 +507,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
continue; continue;
} }
for (int dy = minHeight; dy <= maxHeight; dy++) { for (int dy = minHeight; dy <= maxHeight; dy++) {
BlockPos candidate = origin.offset(dx, dy, dz); BlockPos candidate = this.relativeLocal(origin, dx, dy, dz);
if (!this.isUsableCeiling(candidate)) { if (!this.isUsableCeiling(candidate)) {
continue; continue;
} }
@@ -525,7 +528,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
} }
private boolean isCeilingBlock(BlockPos pos) { private boolean isCeilingBlock(BlockPos pos) {
return this.level().getBlockState(pos).isFaceSturdy(this.level(), pos, Direction.DOWN); return this.level().getBlockState(pos).isFaceSturdy(this.level(), pos, this.gravityDownDirection());
} }
private int minimumCeilingHeight() { private int minimumCeilingHeight() {
@@ -541,7 +544,9 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
return false; return false;
} }
double x = pos.getX() + 0.5D; double x = pos.getX() + 0.5D;
double y = pos.getY() - this.getBbHeight() - 0.01D; double y = AntarchyGravityApi.isGravityInverted(this)
? pos.getY() + 1.01D
: pos.getY() - this.getBbHeight() - 0.01D;
double z = pos.getZ() + 0.5D; double z = pos.getZ() + 0.5D;
return this.canOccupy(x, y, z); return this.canOccupy(x, y, z);
} }
@@ -590,11 +595,14 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
this.leapingTicks = 0; this.leapingTicks = 0;
this.getNavigation().stop(); this.getNavigation().stop();
double dy = ceilingPos.getY() - this.getY(); Vec3 localDelta = this.toLocal(Vec3.atCenterOf(ceilingPos).subtract(this.position()));
double dy = localDelta.y;
double upwardSpeed = Math.min(2.5D, Math.sqrt(0.16D * Math.max(dy, 1.0D)) + 0.4D); double upwardSpeed = Math.min(2.5D, Math.sqrt(0.16D * Math.max(dy, 1.0D)) + 0.4D);
double dx = ceilingPos.getX() + 0.5D - this.getX(); this.setDeltaMovement(this.toWorld(
double dz = ceilingPos.getZ() + 0.5D - this.getZ(); Mth.clamp(localDelta.x * 0.18D, -0.35D, 0.35D),
this.setDeltaMovement(Mth.clamp(dx * 0.18D, -0.35D, 0.35D), upwardSpeed, Mth.clamp(dz * 0.18D, -0.35D, 0.35D)); upwardSpeed,
Mth.clamp(localDelta.z * 0.18D, -0.35D, 0.35D)
));
this.hasImpulse = true; this.hasImpulse = true;
this.playSound(AntarchySoundEvents.JUMPY_BUG_JUMP.get(), 1.0F, 0.95F + this.random.nextFloat() * 0.1F); this.playSound(AntarchySoundEvents.JUMPY_BUG_JUMP.get(), 1.0F, 0.95F + this.random.nextFloat() * 0.1F);
} }
@@ -615,12 +623,11 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
this.pounceCooldownTicks = DEFAULT_POUNCE_COOLDOWN; this.pounceCooldownTicks = DEFAULT_POUNCE_COOLDOWN;
this.pounceTicks = 0; this.pounceTicks = 0;
Vec3 from = this.position(); Vec3 to = this.toLocal(target.getEyePosition().subtract(this.position()));
Vec3 to = target.getEyePosition().subtract(from);
Vec3 horizontal = new Vec3(to.x, 0.0D, to.z); Vec3 horizontal = new Vec3(to.x, 0.0D, to.z);
Vec3 direction = horizontal.lengthSqr() > 1.0E-4D ? horizontal.normalize() : target.getLookAngle(); Vec3 direction = horizontal.lengthSqr() > 1.0E-4D ? horizontal.normalize() : this.toLocalPlane(target.getLookAngle()).normalize();
double upward = POUNCE_UPWARD_SPEED + Mth.clamp(to.y * 0.08D, -0.04D, 0.22D); double upward = POUNCE_UPWARD_SPEED + Mth.clamp(to.y * 0.08D, -0.04D, 0.22D);
this.setDeltaMovement(direction.x * POUNCE_HORIZONTAL_SPEED, upward, direction.z * POUNCE_HORIZONTAL_SPEED); this.setDeltaMovement(this.toWorld(direction.x * POUNCE_HORIZONTAL_SPEED, upward, direction.z * POUNCE_HORIZONTAL_SPEED));
this.hasImpulse = true; this.hasImpulse = true;
this.playSound(AntarchySoundEvents.JUMPY_BUG_JUMP.get(), 1.0F, 0.95F + this.random.nextFloat() * 0.1F); this.playSound(AntarchySoundEvents.JUMPY_BUG_JUMP.get(), 1.0F, 0.95F + this.random.nextFloat() * 0.1F);
} }
@@ -635,10 +642,10 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
this.pounceCooldownTicks = DEFAULT_POUNCE_COOLDOWN; this.pounceCooldownTicks = DEFAULT_POUNCE_COOLDOWN;
this.pounceTicks = 0; this.pounceTicks = 0;
Vec3 to = target.position().add(0.0D, target.getBbHeight() * 0.35D, 0.0D).subtract(this.position()); Vec3 to = this.toLocal(target.position().add(this.toWorld(0.0D, target.getBbHeight() * 0.35D, 0.0D)).subtract(this.position()));
Vec3 horizontal = new Vec3(to.x, 0.0D, to.z); Vec3 horizontal = new Vec3(to.x, 0.0D, to.z);
Vec3 direction = horizontal.lengthSqr() > 1.0E-4D ? horizontal.normalize() : target.getLookAngle(); Vec3 direction = horizontal.lengthSqr() > 1.0E-4D ? horizontal.normalize() : this.toLocalPlane(target.getLookAngle()).normalize();
this.setDeltaMovement(direction.x * CEILING_DROP_HORIZONTAL_SPEED, CEILING_DROP_UPWARD_SPEED, direction.z * CEILING_DROP_HORIZONTAL_SPEED); this.setDeltaMovement(this.toWorld(direction.x * CEILING_DROP_HORIZONTAL_SPEED, CEILING_DROP_UPWARD_SPEED, direction.z * CEILING_DROP_HORIZONTAL_SPEED));
this.hasImpulse = true; this.hasImpulse = true;
this.playSound(AntarchySoundEvents.JUMPY_BUG_JUMP.get(), 1.0F, 0.9F + this.random.nextFloat() * 0.1F); this.playSound(AntarchySoundEvents.JUMPY_BUG_JUMP.get(), 1.0F, 0.9F + this.random.nextFloat() * 0.1F);
} }
@@ -646,8 +653,8 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
private void finishPounce(boolean keepMomentum) { private void finishPounce(boolean keepMomentum) {
this.pounceTicks = 0; this.pounceTicks = 0;
if (!keepMomentum) { if (!keepMomentum) {
Vec3 movement = this.getDeltaMovement(); Vec3 movement = this.toLocal(this.getDeltaMovement());
this.setDeltaMovement(movement.x * 0.25D, Math.max(0.0D, movement.y), movement.z * 0.25D); this.setDeltaMovement(this.toWorld(movement.x * 0.25D, Math.max(0.0D, movement.y), movement.z * 0.25D));
} }
this.setAttackState(AttackState.RECOVERING); this.setAttackState(AttackState.RECOVERING);
this.recoveryTicks = DEFAULT_RECOVERY_TICKS; this.recoveryTicks = DEFAULT_RECOVERY_TICKS;
@@ -906,12 +913,12 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
JumpyBugEntity.this.getNavigation().moveTo(target, 1.05D); JumpyBugEntity.this.getNavigation().moveTo(target, 1.05D);
} else if (distSqr > CHASE_LEAP_RANGE_SQR) { } else if (distSqr > CHASE_LEAP_RANGE_SQR) {
if (JumpyBugEntity.this.onGround() && JumpyBugEntity.this.chaseJumpCooldownTicks <= 0) { if (JumpyBugEntity.this.onGround() && JumpyBugEntity.this.chaseJumpCooldownTicks <= 0) {
Vec3 dir = target.position().subtract(JumpyBugEntity.this.position()).normalize(); Vec3 dir = JumpyBugEntity.this.toLocalPlane(target.position().subtract(JumpyBugEntity.this.position())).normalize();
JumpyBugEntity.this.setDeltaMovement( JumpyBugEntity.this.setDeltaMovement(JumpyBugEntity.this.toWorld(
dir.x * CHASE_LEAP_HORIZONTAL, dir.x * CHASE_LEAP_HORIZONTAL,
CHASE_LEAP_VERTICAL, CHASE_LEAP_VERTICAL,
dir.z * CHASE_LEAP_HORIZONTAL dir.z * CHASE_LEAP_HORIZONTAL
); ));
JumpyBugEntity.this.hasImpulse = true; JumpyBugEntity.this.hasImpulse = true;
JumpyBugEntity.this.chaseJumpCooldownTicks = CHASE_JUMP_COOLDOWN; JumpyBugEntity.this.chaseJumpCooldownTicks = CHASE_JUMP_COOLDOWN;
} }
@@ -944,4 +951,30 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
&& super.canContinueToUse(); && super.canContinueToUse();
} }
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Direction gravityDownDirection() {
return this.gravityDirection().isInverted() ? Direction.UP : Direction.DOWN;
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
private BlockPos relativeLocal(BlockPos origin, int x, int y, int z) {
Vec3 worldOffset = this.toWorld(x, y, z);
return origin.offset(Mth.floor(worldOffset.x), Mth.floor(worldOffset.y), Mth.floor(worldOffset.z));
}
} }
@@ -74,16 +74,22 @@ public class LurkingTerrorEntity extends Monster implements GeoEntity {
return true; return true;
} }
BlockPos belowPos = pos.below(); BlockPos belowPos = pos.below();
BlockPos abovePos = pos.above();
BlockState belowState = level.getBlockState(belowPos); BlockState belowState = level.getBlockState(belowPos);
boolean validSupport = !belowState.is(Blocks.BEDROCK) BlockState aboveState = level.getBlockState(abovePos);
boolean floorSupport = !belowState.is(Blocks.BEDROCK)
&& belowState.blocksMotion() && belowState.blocksMotion()
&& belowState.isFaceSturdy(level, belowPos, Direction.UP) && belowState.isFaceSturdy(level, belowPos, Direction.UP)
&& belowState.isCollisionShapeFullBlock(level, belowPos); && belowState.isCollisionShapeFullBlock(level, belowPos);
boolean ceilingSupport = !aboveState.is(Blocks.BEDROCK)
&& aboveState.blocksMotion()
&& aboveState.isFaceSturdy(level, abovePos, Direction.DOWN)
&& aboveState.isCollisionShapeFullBlock(level, abovePos);
return level.getDifficulty() != Difficulty.PEACEFUL return level.getDifficulty() != Difficulty.PEACEFUL
&& validSupport && (floorSupport || ceilingSupport)
&& level.isEmptyBlock(pos) && level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.above()) && (level.isEmptyBlock(pos.above()) || level.isEmptyBlock(pos.below()))
&& Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random); && Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
} }
@@ -134,9 +134,14 @@ public class MantisEntity extends Monster implements GeoEntity {
} }
boolean atSurface = level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pos).getY() <= pos.getY(); boolean atSurface = level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pos).getY() <= pos.getY();
boolean posOpen = level.isEmptyBlock(pos) && level.isEmptyBlock(pos.above()) && level.getFluidState(pos).isEmpty(); boolean hasFloorClearance = level.isEmptyBlock(pos.above());
boolean onSolidGround = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP) boolean hasCeilingClearance = level.isEmptyBlock(pos.below());
boolean floorSupport = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP)
&& !(level.getBlockState(pos.below()).getBlock() instanceof LeavesBlock); && !(level.getBlockState(pos.below()).getBlock() instanceof LeavesBlock);
boolean ceilingSupport = level.getBlockState(pos.above()).isFaceSturdy(level, pos.above(), Direction.DOWN)
&& !(level.getBlockState(pos.above()).getBlock() instanceof LeavesBlock);
boolean posOpen = level.isEmptyBlock(pos) && (hasFloorClearance || hasCeilingClearance) && level.getFluidState(pos).isEmpty();
boolean onSolidGround = floorSupport || ceilingSupport;
if (!posOpen || !onSolidGround) { if (!posOpen || !onSolidGround) {
return false; return false;
@@ -652,5 +657,3 @@ public class MantisEntity extends Monster implements GeoEntity {
} }
@@ -3,6 +3,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.entity.kraken.KrakenEntity; import com.craisinlord.antarchy.content.entity.kraken.KrakenEntity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -446,7 +449,7 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
this.move(MoverType.SELF, velocity); this.move(MoverType.SELF, velocity);
Vec3 movedVelocity = this.getDeltaMovement(); Vec3 movedVelocity = this.getDeltaMovement();
if (!this.isNoGravity()) { if (!this.isNoGravity()) {
movedVelocity = movedVelocity.add(0.0D, -0.08D, 0.0D); movedVelocity = movedVelocity.add(this.toWorld(0.0D, -0.08D, 0.0D));
} }
this.setDeltaMovement(movedVelocity.scale(this.isInWater() ? 0.9D : 0.98D)); this.setDeltaMovement(movedVelocity.scale(this.isInWater() ? 0.9D : 0.98D));
@@ -513,9 +516,9 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
} }
private void tickGroundAggroMovement(LivingEntity target) { private void tickGroundAggroMovement(LivingEntity target) {
Vec3 horizontal = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 horizontal = this.toLocalPlane(target.position().subtract(this.position()));
if (horizontal.lengthSqr() > 1.0E-4D && this.onGround()) { if (horizontal.lengthSqr() > 1.0E-4D && this.onGround()) {
Vec3 lunge = horizontal.normalize().scale(0.16D).add(0.0D, 0.24D, 0.0D); Vec3 lunge = this.toWorld(horizontal.normalize().scale(0.16D).add(new Vec3(0.0D, 0.24D, 0.0D)));
this.setDeltaMovement(this.getDeltaMovement().add(lunge)); this.setDeltaMovement(this.getDeltaMovement().add(lunge));
this.hasImpulse = true; this.hasImpulse = true;
} }
@@ -540,7 +543,7 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
} }
private void updateSwimRotation() { private void updateSwimRotation() {
Vec3 velocity = this.getDeltaMovement(); Vec3 velocity = this.toLocal(this.getDeltaMovement());
if (velocity.horizontalDistanceSqr() > 1.0E-4D) { if (velocity.horizontalDistanceSqr() > 1.0E-4D) {
float targetYaw = (float) (Mth.atan2(velocity.z, velocity.x) * (180.0D / Math.PI)) - 90.0F; float targetYaw = (float) (Mth.atan2(velocity.z, velocity.x) * (180.0D / Math.PI)) - 90.0F;
this.setYRot(Mth.approachDegrees(this.getYRot(), targetYaw, 10.0F)); this.setYRot(Mth.approachDegrees(this.getYRot(), targetYaw, 10.0F));
@@ -658,15 +661,11 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
} }
private Vec3 createLatchAnchor(LivingEntity target) { private Vec3 createLatchAnchor(LivingEntity target) {
return target.position().add( return target.position().add(this.toWorld(0.0D, target.getBbHeight() + 0.15D, 0.0D));
0.0D,
target.getBbHeight() + 0.15D,
0.0D
);
} }
private void updateAttachedRotation(LivingEntity target) { private void updateAttachedRotation(LivingEntity target) {
Vec3 direction = target.position().subtract(this.position()); Vec3 direction = this.toLocal(target.position().subtract(this.position()));
if (direction.horizontalDistanceSqr() > 1.0E-4D) { if (direction.horizontalDistanceSqr() > 1.0E-4D) {
float targetYaw = (float)(Mth.atan2(direction.z, direction.x) * (180.0D / Math.PI)) - 90.0F; float targetYaw = (float)(Mth.atan2(direction.z, direction.x) * (180.0D / Math.PI)) - 90.0F;
this.setYRot(targetYaw); this.setYRot(targetYaw);
@@ -721,11 +720,32 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
if (this.launchedFromSquidzooka if (this.launchedFromSquidzooka
|| this.getTarget() != null || this.getTarget() != null
|| velocity.lengthSqr() > 1.0E-3D || velocity.lengthSqr() > 1.0E-3D
|| (this.isInWater() && velocity.horizontalDistanceSqr() > 1.0E-4D)) { || (this.isInWater() && this.toLocal(velocity).horizontalDistanceSqr() > 1.0E-4D)) {
this.setAnimationState(ANIM_SWIM); this.setAnimationState(ANIM_SWIM);
return; return;
} }
this.setAnimationState(ANIM_IDLE); this.setAnimationState(ANIM_IDLE);
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toWorld(Vec3 localVector) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(localVector, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
} }
@@ -4,6 +4,9 @@ import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@@ -475,12 +478,13 @@ public class MolevoreEntity extends Monster implements GeoEntity {
} }
if (entity.hurt(this.damageSources().mobAttack(this), (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE))) { if (entity.hurt(this.damageSources().mobAttack(this), (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE))) {
Vec3 push = entity.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 push = this.toLocalPlane(entity.position().subtract(this.position()));
if (push.lengthSqr() < 1.0E-4D) { if (push.lengthSqr() < 1.0E-4D) {
push = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); push = this.toLocalPlane(this.getViewVector(1.0F));
} }
push = push.normalize().scale(0.8D); push = push.normalize().scale(0.8D);
entity.push(push.x, 0.25D, push.z); Vec3 worldPush = this.toWorld(push.x, 0.25D, push.z);
entity.push(worldPush.x, worldPush.y, worldPush.z);
entity.hurtMarked = true; entity.hurtMarked = true;
} }
} }
@@ -493,12 +497,12 @@ public class MolevoreEntity extends Monster implements GeoEntity {
} }
private void startSpinCharge(LivingEntity target) { private void startSpinCharge(LivingEntity target) {
Vec3 horizontal = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 horizontal = this.toLocalPlane(target.position().subtract(this.position()));
if (horizontal.lengthSqr() < 1.0E-4D) { if (horizontal.lengthSqr() < 1.0E-4D) {
return; return;
} }
this.spinDirection = horizontal.normalize(); this.spinDirection = this.toWorld(horizontal.normalize());
this.spinHitEntities.clear(); this.spinHitEntities.clear();
this.setActionState(ACTION_SPIN_CHARGE); this.setActionState(ACTION_SPIN_CHARGE);
this.actionTicks = SPIN_TOTAL_TICKS; this.actionTicks = SPIN_TOTAL_TICKS;
@@ -514,15 +518,15 @@ public class MolevoreEntity extends Monster implements GeoEntity {
if (target != null && inWindup) { if (target != null && inWindup) {
this.getLookControl().setLookAt(target, 35.0F, 20.0F); this.getLookControl().setLookAt(target, 35.0F, 20.0F);
Vec3 horizontal = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 horizontal = this.toLocalPlane(target.position().subtract(this.position()));
if (horizontal.lengthSqr() > 1.0E-4D) { if (horizontal.lengthSqr() > 1.0E-4D) {
this.spinDirection = horizontal.normalize(); this.spinDirection = this.toWorld(horizontal.normalize());
} }
this.setDeltaMovement(this.getDeltaMovement().scale(0.2D)); this.setDeltaMovement(this.getDeltaMovement().scale(0.2D));
} else { } else {
Vec3 lookTarget = this.position().add(this.spinDirection); Vec3 lookTarget = this.position().add(this.spinDirection);
this.getLookControl().setLookAt(lookTarget.x, this.getEyeY(), lookTarget.z, 360.0F, 0.0F); this.getLookControl().setLookAt(lookTarget.x, lookTarget.y, lookTarget.z, 360.0F, 0.0F);
Vec3 motion = this.spinDirection.scale(SPIN_SPEED).add(0.0D, this.onGround() ? 0.08D : 0.0D, 0.0D); Vec3 motion = this.spinDirection.scale(SPIN_SPEED).add(this.toWorld(0.0D, this.onGround() ? 0.08D : 0.0D, 0.0D));
this.setDeltaMovement(motion); this.setDeltaMovement(motion);
this.hasImpulse = true; this.hasImpulse = true;
this.performSpinChargeHit(); this.performSpinChargeHit();
@@ -553,8 +557,15 @@ public class MolevoreEntity extends Monster implements GeoEntity {
} }
if (entity.hurt(this.damageSources().mobAttack(this), (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE) * 1.65F)) { if (entity.hurt(this.damageSources().mobAttack(this), (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE) * 1.65F)) {
Vec3 push = this.spinDirection.lengthSqr() > 0.0D ? this.spinDirection : entity.position().subtract(this.position()).normalize(); Vec3 push = this.spinDirection.lengthSqr() > 0.0D
entity.push(push.x * 1.15D, 0.35D, push.z * 1.15D); ? this.toLocalPlane(this.spinDirection)
: this.toLocalPlane(entity.position().subtract(this.position()));
if (push.lengthSqr() < 1.0E-4D) {
push = this.toLocalPlane(this.getViewVector(1.0F));
}
push = push.normalize();
Vec3 worldPush = this.toWorld(push.x * 1.15D, 0.35D, push.z * 1.15D);
entity.push(worldPush.x, worldPush.y, worldPush.z);
entity.hurtMarked = true; entity.hurtMarked = true;
this.playSound(AntarchySoundEvents.MOLEVORE_ATTACK.get(), 1.0F, 0.65F + this.random.nextFloat() * 0.1F); this.playSound(AntarchySoundEvents.MOLEVORE_ATTACK.get(), 1.0F, 0.65F + this.random.nextFloat() * 0.1F);
} }
@@ -593,21 +604,21 @@ public class MolevoreEntity extends Monster implements GeoEntity {
Vec3 forward = this.getViewVector(1.0F).normalize(); Vec3 forward = this.getViewVector(1.0F).normalize();
Vec3 digCenter = this.position() Vec3 digCenter = this.position()
.add(forward.scale(1.0D)) .add(forward.scale(1.0D))
.add(0.0D, -0.5D, 0.0D); .add(this.toWorld(0.0D, -0.5D, 0.0D));
double halfWidth = 0.9D; double halfWidth = 0.9D;
double digDepth = 1.5D; double digDepth = 1.5D;
BlockPos min = BlockPos.containing(digCenter.x - halfWidth, digCenter.y - digDepth, digCenter.z - halfWidth); BlockPos min = BlockPos.containing(digCenter.x - halfWidth, digCenter.y - digDepth, digCenter.z - halfWidth);
BlockPos max = BlockPos.containing(digCenter.x + halfWidth, digCenter.y + 0.4D, digCenter.z + halfWidth); BlockPos max = BlockPos.containing(digCenter.x + halfWidth, digCenter.y + 0.4D, digCenter.z + halfWidth);
Vec3 hForward = forward.multiply(1.0D, 0.0D, 1.0D); Vec3 hForward = this.toLocalPlane(forward);
for (BlockPos pos : BlockPos.betweenClosed(min, max)) { for (BlockPos pos : BlockPos.betweenClosed(min, max)) {
BlockState state = this.level().getBlockState(pos); BlockState state = this.level().getBlockState(pos);
if (!state.is(AntarchyTags.Blocks.MOLEVORE_BREAKABLE_BLOCKS) || state.isAir()) { if (!state.is(AntarchyTags.Blocks.MOLEVORE_BREAKABLE_BLOCKS) || state.isAir()) {
continue; continue;
} }
if (hForward.lengthSqr() > 1.0E-4D) { if (hForward.lengthSqr() > 1.0E-4D) {
Vec3 toBlock = Vec3.atCenterOf(pos).subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 toBlock = this.toLocalPlane(Vec3.atCenterOf(pos).subtract(this.position()));
if (toBlock.lengthSqr() > 1.0E-4D && hForward.normalize().dot(toBlock.normalize()) < -0.2D) { if (toBlock.lengthSqr() > 1.0E-4D && hForward.normalize().dot(toBlock.normalize()) < -0.2D) {
continue; continue;
} }
@@ -642,12 +653,12 @@ public class MolevoreEntity extends Monster implements GeoEntity {
} }
Vec3 forward = direction.normalize(); Vec3 forward = direction.normalize();
Vec3 center = this.position().add(forward.scale(range * 0.5D)).add(0.0D, this.getBbHeight() * 0.4D, 0.0D); Vec3 center = this.position().add(forward.scale(range * 0.5D)).add(this.toWorld(0.0D, this.getBbHeight() * 0.4D, 0.0D));
BlockPos min = BlockPos.containing(center.x - halfWidth, center.y - verticalRange * 0.5D, center.z - halfWidth); BlockPos min = BlockPos.containing(center.x - halfWidth, center.y - verticalRange * 0.5D, center.z - halfWidth);
BlockPos max = BlockPos.containing(center.x + halfWidth, center.y + verticalRange * 0.5D, center.z + halfWidth); BlockPos max = BlockPos.containing(center.x + halfWidth, center.y + verticalRange * 0.5D, center.z + halfWidth);
boolean broke = false; boolean broke = false;
Vec3 hForward = forward.multiply(1.0D, 0.0D, 1.0D); Vec3 hForward = this.toLocalPlane(forward);
for (BlockPos pos : BlockPos.betweenClosed(min, max)) { for (BlockPos pos : BlockPos.betweenClosed(min, max)) {
BlockState state = this.level().getBlockState(pos); BlockState state = this.level().getBlockState(pos);
if (!state.is(AntarchyTags.Blocks.MOLEVORE_BREAKABLE_BLOCKS) || state.isAir()) { if (!state.is(AntarchyTags.Blocks.MOLEVORE_BREAKABLE_BLOCKS) || state.isAir()) {
@@ -655,7 +666,7 @@ public class MolevoreEntity extends Monster implements GeoEntity {
} }
Vec3 blockCenter = Vec3.atCenterOf(pos); Vec3 blockCenter = Vec3.atCenterOf(pos);
Vec3 toBlock = blockCenter.subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 toBlock = this.toLocalPlane(blockCenter.subtract(this.position()));
if (hForward.lengthSqr() > 1.0E-4D && toBlock.lengthSqr() > 1.0E-4D if (hForward.lengthSqr() > 1.0E-4D && toBlock.lengthSqr() > 1.0E-4D
&& hForward.normalize().dot(toBlock.normalize()) < -0.15D) { && hForward.normalize().dot(toBlock.normalize()) < -0.15D) {
continue; continue;
@@ -668,14 +679,31 @@ public class MolevoreEntity extends Monster implements GeoEntity {
} }
private boolean isInFront(Vec3 position, double minimumDot) { private boolean isInFront(Vec3 position, double minimumDot) {
Vec3 forward = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); Vec3 forward = this.toLocalPlane(this.getViewVector(1.0F));
Vec3 toTarget = position.subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 toTarget = this.toLocalPlane(position.subtract(this.position()));
if (forward.lengthSqr() < 1.0E-4D || toTarget.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D || toTarget.lengthSqr() < 1.0E-4D) {
return true; return true;
} }
return forward.normalize().dot(toTarget.normalize()) >= minimumDot; return forward.normalize().dot(toTarget.normalize()) >= minimumDot;
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toWorld(Vec3 localVector) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(localVector, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
return new Vec3(local.x, 0.0D, local.z);
}
private int getActionState() { private int getActionState() {
return this.entityData.get(ACTION_STATE); return this.entityData.get(ACTION_STATE);
} }
@@ -3,6 +3,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.EnumSet; import java.util.EnumSet;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
@@ -222,7 +225,7 @@ public class OuranwoodDeerEntity extends Animal implements GeoEntity {
} }
private PlayState mainAnimController(AnimationState<OuranwoodDeerEntity> state) { private PlayState mainAnimController(AnimationState<OuranwoodDeerEntity> state) {
double speedSqr = this.getDeltaMovement().horizontalDistanceSqr(); double speedSqr = this.toLocal(this.getDeltaMovement()).horizontalDistanceSqr();
if (this.hurtTime > 0 || speedSqr > RUN_SPEED_THRESHOLD_SQR) { if (this.hurtTime > 0 || speedSqr > RUN_SPEED_THRESHOLD_SQR) {
return state.setAndContinue(RUN_ANIM); return state.setAndContinue(RUN_ANIM);
} }
@@ -242,6 +245,14 @@ public class OuranwoodDeerEntity extends Animal implements GeoEntity {
return MIN_QUIRK_COOLDOWN + this.random.nextInt(MAX_QUIRK_COOLDOWN - MIN_QUIRK_COOLDOWN + 1); return MIN_QUIRK_COOLDOWN + this.random.nextInt(MAX_QUIRK_COOLDOWN - MIN_QUIRK_COOLDOWN + 1);
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
@Override @Override
public AnimatableInstanceCache getAnimatableInstanceCache() { public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache; return this.geoCache;
@@ -4,6 +4,9 @@ import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.EnumSet; import java.util.EnumSet;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -111,14 +114,16 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
} }
BlockPos belowPos = pos.below(); BlockPos belowPos = pos.below();
BlockPos abovePos = pos.above();
if (level.getDifficulty() == Difficulty.PEACEFUL) { if (level.getDifficulty() == Difficulty.PEACEFUL) {
return false; return false;
} }
return level.getBlockState(pos).isAir() return level.getBlockState(pos).isAir()
&& level.getBlockState(pos.above()).isAir() && (level.getBlockState(pos.above()).isAir() || level.getBlockState(pos.below()).isAir())
&& level.getFluidState(pos).isEmpty() && level.getFluidState(pos).isEmpty()
&& level.getFluidState(pos.above()).isEmpty() && (level.getFluidState(pos.above()).isEmpty() || level.getFluidState(pos.below()).isEmpty())
&& level.getBlockState(belowPos).isFaceSturdy(level, belowPos, Direction.UP); && (level.getBlockState(belowPos).isFaceSturdy(level, belowPos, Direction.UP)
|| level.getBlockState(abovePos).isFaceSturdy(level, abovePos, Direction.DOWN));
} }
public static AttributeSupplier.Builder createAttributes() { public static AttributeSupplier.Builder createAttributes() {
@@ -347,7 +352,7 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
} }
private void tickRollSound() { private void tickRollSound() {
if (!this.isRolled() || this.rollTransitionTicks > 0 || this.getDeltaMovement().horizontalDistanceSqr() <= 0.003D) { if (!this.isRolled() || this.rollTransitionTicks > 0 || this.toLocal(this.getDeltaMovement()).horizontalDistanceSqr() <= 0.003D) {
this.rollSoundCooldown = 0; this.rollSoundCooldown = 0;
return; return;
} }
@@ -700,9 +705,12 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
return; return;
} }
double dx = RollyPollyEntity.this.getX() - target.getX(); Vec3 localAway = RollyPollyEntity.this.toLocalPlane(RollyPollyEntity.this.position().subtract(target.position()));
double dz = RollyPollyEntity.this.getZ() - target.getZ(); if (localAway.lengthSqr() < 1.0E-4D) {
target.knockback(AntarchySettings.rollyPollyBowlingKnockback(), dx, dz); localAway = new Vec3(1.0D, 0.0D, 0.0D);
}
Vec3 worldAway = RollyPollyEntity.this.toWorld(localAway.normalize());
target.knockback(AntarchySettings.rollyPollyBowlingKnockback(), worldAway.x, worldAway.z);
RollyPollyEntity.this.playSound(AntarchySoundEvents.ROLLY_POLLY_ROLL.get(), 1.0F, 0.8F + RollyPollyEntity.this.random.nextFloat() * 0.2F); RollyPollyEntity.this.playSound(AntarchySoundEvents.ROLLY_POLLY_ROLL.get(), 1.0F, 0.8F + RollyPollyEntity.this.random.nextFloat() * 0.2F);
} }
} }
@@ -848,8 +856,8 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
RollyPollyEntity.this.startUnroll(); RollyPollyEntity.this.startUnroll();
} }
} else { } else {
RollyPollyEntity.this.getNavigation().moveTo( Vec3 bedTarget = Vec3.atCenterOf(this.bedPos).add(RollyPollyEntity.this.toWorld(0.0D, 0.5D, 0.0D));
this.bedPos.getX() + 0.5D, this.bedPos.getY() + 1.0D, this.bedPos.getZ() + 0.5D, 1.1D); RollyPollyEntity.this.getNavigation().moveTo(bedTarget.x, bedTarget.y, bedTarget.z, 1.1D);
} }
return; return;
} }
@@ -861,4 +869,25 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
} }
} }
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(Vec3 localVector) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(localVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
} }
@@ -2,6 +2,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
@@ -195,13 +198,16 @@ public class ScorpionEntity extends Monster implements GeoEntity {
} }
private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) { private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) {
Vec3 lunge = target.position().subtract(this.position()); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(this);
Vec3 horizontal = new Vec3(lunge.x, 0.0D, lunge.z); Vec3 localLunge = AntarchyGravityRotationUtil.vecWorldToPlayer(target.position().subtract(this.position()), direction);
Vec3 horizontal = new Vec3(localLunge.x, 0.0D, localLunge.z);
if (horizontal.lengthSqr() < 1.0E-4D) { if (horizontal.lengthSqr() < 1.0E-4D) {
return; return;
} }
horizontal = horizontal.normalize().scale(horizontalSpeed); horizontal = horizontal.normalize().scale(horizontalSpeed);
this.setDeltaMovement(this.getDeltaMovement().add(horizontal.x, verticalSpeed, horizontal.z)); Vec3 localImpulse = new Vec3(horizontal.x, verticalSpeed, horizontal.z);
Vec3 worldImpulse = AntarchyGravityRotationUtil.vecPlayerToWorld(localImpulse, direction);
this.setDeltaMovement(this.getDeltaMovement().add(worldImpulse.x, worldImpulse.y, worldImpulse.z));
this.hasImpulse = true; this.hasImpulse = true;
} }
@@ -3,6 +3,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
@@ -89,7 +92,7 @@ public class SpitBugEntity extends Monster implements GeoEntity {
} }
return level.getDifficulty() != Difficulty.PEACEFUL return level.getDifficulty() != Difficulty.PEACEFUL
&& level.isEmptyBlock(pos) && level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.above()) && (level.isEmptyBlock(pos.above()) || level.isEmptyBlock(pos.below()))
&& Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random); && Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
} }
@@ -221,7 +224,7 @@ public class SpitBugEntity extends Monster implements GeoEntity {
SpitBugProjectileEntity projectile = new SpitBugProjectileEntity(projectileType, this, serverLevel); SpitBugProjectileEntity projectile = new SpitBugProjectileEntity(projectileType, this, serverLevel);
Vec3 origin = this.position() Vec3 origin = this.position()
.add(0.0D, this.getBbHeight() * 0.55D, 0.0D) .add(this.toWorld(0.0D, this.getBbHeight() * 0.55D, 0.0D))
.add(this.getViewVector(0.0F).scale(1.35D)); .add(this.getViewVector(0.0F).scale(1.35D));
Vec3 aimPoint = target.getEyePosition().add(target.getDeltaMovement().scale(0.45D)); Vec3 aimPoint = target.getEyePosition().add(target.getDeltaMovement().scale(0.45D));
Vec3 direction = aimPoint.subtract(origin).normalize(); Vec3 direction = aimPoint.subtract(origin).normalize();
@@ -232,6 +235,14 @@ public class SpitBugEntity extends Monster implements GeoEntity {
this.playSound(AntarchySoundEvents.SPIT_BUG_SPIT.get(), 1.0F, 0.85F + this.random.nextFloat() * 0.15F); this.playSound(AntarchySoundEvents.SPIT_BUG_SPIT.get(), 1.0F, 0.85F + this.random.nextFloat() * 0.15F);
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private final class SpitAttackGoal extends Goal { private final class SpitAttackGoal extends Goal {
SpitAttackGoal() { SpitAttackGoal() {
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK)); this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
@@ -70,14 +70,16 @@ public class StinkBugEntity extends Animal implements GeoEntity {
return true; return true;
} }
BlockPos belowPos = pos.below(); BlockPos belowPos = pos.below();
BlockPos abovePos = pos.above();
if (level.getDifficulty() == Difficulty.PEACEFUL) { if (level.getDifficulty() == Difficulty.PEACEFUL) {
return false; return false;
} }
return level.getBlockState(pos).isAir() return level.getBlockState(pos).isAir()
&& level.getBlockState(pos.above()).isAir() && (level.getBlockState(pos.above()).isAir() || level.getBlockState(pos.below()).isAir())
&& level.getFluidState(pos).isEmpty() && level.getFluidState(pos).isEmpty()
&& level.getFluidState(pos.above()).isEmpty() && (level.getFluidState(pos.above()).isEmpty() || level.getFluidState(pos.below()).isEmpty())
&& level.getBlockState(belowPos).isFaceSturdy(level, belowPos, Direction.UP); && (level.getBlockState(belowPos).isFaceSturdy(level, belowPos, Direction.UP)
|| level.getBlockState(abovePos).isFaceSturdy(level, abovePos, Direction.DOWN));
} }
@Override @Override
@@ -3,6 +3,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.block.entity.WaspNestBlockEntity; import com.craisinlord.antarchy.content.block.entity.WaspNestBlockEntity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Objects; import java.util.Objects;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -100,7 +103,7 @@ public class WaspEntity extends Monster implements GeoEntity, FlyingAnimal {
return level.getDifficulty() != Difficulty.PEACEFUL return level.getDifficulty() != Difficulty.PEACEFUL
&& level.isEmptyBlock(pos) && level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.above()); && (level.isEmptyBlock(pos.above()) || level.isEmptyBlock(pos.below()));
} }
@Override @Override
@@ -304,7 +307,7 @@ public class WaspEntity extends Monster implements GeoEntity, FlyingAnimal {
@Override @Override
public Vec3 getLeashOffset() { public Vec3 getLeashOffset() {
return new Vec3(0.0D, 0.2D, 0.0D); return this.toWorld(0.0D, 0.2D, 0.0D);
} }
public boolean isPandaVariant() { public boolean isPandaVariant() {
@@ -328,6 +331,14 @@ public class WaspEntity extends Monster implements GeoEntity, FlyingAnimal {
return !this.onGround(); return !this.onGround();
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private void realignHitbox() { private void realignHitbox() {
double halfWidth = this.getBbWidth() * 0.5D; double halfWidth = this.getBbWidth() * 0.5D;
double height = this.getBbHeight(); double height = this.getBbHeight();
@@ -15,6 +15,7 @@ import net.minecraft.server.level.PlayerRespawnLogic;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
@@ -253,8 +254,12 @@ public final class AntTeleportHelper {
return safeArrivalPos; return safeArrivalPos;
} }
BlockPos fallbackPos = player.adjustSpawnLocation(destination, preferredPos); if (destination.hasChunkAt(preferredPos)) {
return Vec3.atBottomCenterOf(fallbackPos); BlockPos fallbackPos = player.adjustSpawnLocation(destination, preferredPos);
return Vec3.atBottomCenterOf(fallbackPos);
}
return Vec3.atBottomCenterOf(getClampedFallbackPosition(destination, preferredPos));
} }
@Nullable @Nullable
@@ -283,8 +288,10 @@ public final class AntTeleportHelper {
} }
BlockPos searchPos = preferredPos.offset(xOffset, 0, zOffset); BlockPos searchPos = preferredPos.offset(xOffset, 0, zOffset);
addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, searchPos)); if (destination.hasChunkAt(searchPos)) {
addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, searchPos)); addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, searchPos));
addArrivalCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, searchPos));
}
} }
} }
} }
@@ -347,13 +354,22 @@ public final class AntTeleportHelper {
@Nullable @Nullable
private static Vec3 tryFindSafeDismount(ServerPlayer player, ServerLevel destination, BlockPos candidate) { private static Vec3 tryFindSafeDismount(ServerPlayer player, ServerLevel destination, BlockPos candidate) {
if (!isSafeDismountAreaLoaded(destination, candidate)) {
return null;
}
Vec3 safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, candidate, true); Vec3 safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, candidate, true);
if (safePos != null && isValidArrivalPosition(destination, safePos)) { if (safePos != null && isValidArrivalPosition(destination, safePos)) {
return safePos; return safePos;
} }
for (Direction direction : Direction.Plane.HORIZONTAL) { for (Direction direction : Direction.Plane.HORIZONTAL) {
safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, candidate.relative(direction), true); BlockPos offsetCandidate = candidate.relative(direction);
if (!isSafeDismountAreaLoaded(destination, offsetCandidate)) {
continue;
}
safePos = DismountHelper.findSafeDismountLocation(player.getType(), destination, offsetCandidate, true);
if (safePos != null && isValidArrivalPosition(destination, safePos)) { if (safePos != null && isValidArrivalPosition(destination, safePos)) {
return safePos; return safePos;
} }
@@ -368,6 +384,31 @@ public final class AntTeleportHelper {
} }
BlockPos standPos = BlockPos.containing(safePos); BlockPos standPos = BlockPos.containing(safePos);
if (!destination.hasChunkAt(standPos) || !destination.hasChunkAt(standPos.below())) {
return false;
}
return !destination.getBlockState(standPos.below()).is(Blocks.BEDROCK); return !destination.getBlockState(standPos.below()).is(Blocks.BEDROCK);
} }
private static boolean isSafeDismountAreaLoaded(ServerLevel destination, BlockPos center) {
if (!destination.hasChunkAt(center) || !destination.hasChunkAt(center.above()) || !destination.hasChunkAt(center.below())) {
return false;
}
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos offset = center.relative(direction);
if (!destination.hasChunkAt(offset) || !destination.hasChunkAt(offset.above()) || !destination.hasChunkAt(offset.below())) {
return false;
}
}
return true;
}
private static BlockPos getClampedFallbackPosition(ServerLevel destination, BlockPos preferredPos) {
int minY = destination.getMinBuildHeight() + 1;
int maxY = destination.getMaxBuildHeight() - 1;
return new BlockPos(preferredPos.getX(), Mth.clamp(preferredPos.getY(), minY, maxY), preferredPos.getZ());
}
} }
@@ -4,6 +4,8 @@ import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.boss.BossCombatUtil; import com.craisinlord.antarchy.content.boss.BossCombatUtil;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Objects; import java.util.Objects;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -568,7 +570,9 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
private boolean shouldSwipe(LivingEntity target, FightPhase phase) { private boolean shouldSwipe(LivingEntity target, FightPhase phase) {
double horizontalDistanceSqr = new Vec3(target.getX() - this.getX(), 0.0D, target.getZ() - this.getZ()).lengthSqr(); double horizontalDistanceSqr = new Vec3(target.getX() - this.getX(), 0.0D, target.getZ() - this.getZ()).lengthSqr();
boolean beneathBoss = horizontalDistanceSqr <= 16.0D && target.getY() <= this.getY() + 2.0D; Vec3 localDelta = AntarchyGravityRotationUtil.vecWorldToPlayer(target.position().subtract(this.position()), AntarchyGravityApi.getGravityDirection(this));
horizontalDistanceSqr = new Vec3(localDelta.x, 0.0D, localDelta.z).lengthSqr();
boolean beneathBoss = horizontalDistanceSqr <= 16.0D && localDelta.y <= 2.0D;
return beneathBoss || this.distanceToSqr(target) <= phase.swipeRangeSqr; return beneathBoss || this.distanceToSqr(target) <= phase.swipeRangeSqr;
} }
@@ -579,7 +583,7 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
} }
private void tickSwipe(LivingEntity target) { private void tickSwipe(LivingEntity target) {
Vec3 divePoint = target.position().add(0.0D, 1.0D, 0.0D); Vec3 divePoint = target.position().add(AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, 1.0D, 0.0D, AntarchyGravityApi.getGravityDirection(this)));
this.getMoveControl().setWantedPosition(divePoint.x, divePoint.y, divePoint.z, 1.45D); this.getMoveControl().setWantedPosition(divePoint.x, divePoint.y, divePoint.z, 1.45D);
if (this.animationTicks == 8) { if (this.animationTicks == 8) {
@@ -608,7 +612,7 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
dz = this.random.nextDouble() - 0.5D; dz = this.random.nextDouble() - 0.5D;
} }
target.knockback(SWIPE_KNOCKBACK, -dx, -dz); target.knockback(SWIPE_KNOCKBACK, -dx, -dz);
target.setDeltaMovement(target.getDeltaMovement().add(0.0D, 0.3D, 0.0D)); target.setDeltaMovement(target.getDeltaMovement().add(AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, 0.3D, 0.0D, AntarchyGravityApi.getGravityDirection(this))));
} }
} }
@@ -2,6 +2,9 @@ package com.craisinlord.antarchy.content.entity.cloud_shark;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@@ -121,7 +124,7 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
MobSpawnType spawnReason, BlockPos pos, RandomSource random) { MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
return level.getDifficulty() != Difficulty.PEACEFUL return level.getDifficulty() != Difficulty.PEACEFUL
&& level.isEmptyBlock(pos) && level.isEmptyBlock(pos)
&& level.isEmptyBlock(pos.above()) && (level.isEmptyBlock(pos.above()) || level.isEmptyBlock(pos.below()))
&& level.getFluidState(pos).isEmpty(); && level.getFluidState(pos).isEmpty();
} }
@@ -303,15 +306,15 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
public boolean doHurtTarget(Entity target) { public boolean doHurtTarget(Entity target) {
boolean hurt = super.doHurtTarget(target); boolean hurt = super.doHurtTarget(target);
if (hurt && target instanceof LivingEntity livingTarget) { if (hurt && target instanceof LivingEntity livingTarget) {
Vec3 push = livingTarget.position().subtract(this.position()); Vec3 horizontal = this.toLocalPlane(livingTarget.position().subtract(this.position()));
Vec3 horizontal = new Vec3(push.x, 0.0D, push.z); if (horizontal.lengthSqr() < 1.0E-4D) horizontal = this.toLocalPlane(this.getForward());
if (horizontal.lengthSqr() < 1.0E-4D) horizontal = this.getForward().multiply(1.0D, 0.0D, 1.0D);
if (horizontal.lengthSqr() < 1.0E-4D) horizontal = new Vec3(1.0D, 0.0D, 0.0D); if (horizontal.lengthSqr() < 1.0E-4D) horizontal = new Vec3(1.0D, 0.0D, 0.0D);
horizontal = horizontal.normalize(); horizontal = horizontal.normalize();
Vec3 sideways = new Vec3(-horizontal.z, 0.0D, horizontal.x); Vec3 sideways = new Vec3(-horizontal.z, 0.0D, horizontal.x);
if (this.random.nextBoolean()) sideways = sideways.scale(-1.0D); if (this.random.nextBoolean()) sideways = sideways.scale(-1.0D);
Vec3 knockback = horizontal.scale(0.7D).add(sideways.scale(0.45D)); Vec3 knockback = horizontal.scale(0.7D).add(sideways.scale(0.45D));
livingTarget.push(knockback.x, 0.28D, knockback.z); Vec3 worldKnockback = this.toWorld(knockback.x, 0.28D, knockback.z);
livingTarget.push(worldKnockback.x, worldKnockback.y, worldKnockback.z);
this.playSound(AntarchySoundEvents.CLOUD_SHARK_BITE.get(), 1.0F, 0.85F + this.random.nextFloat() * 0.2F); this.playSound(AntarchySoundEvents.CLOUD_SHARK_BITE.get(), 1.0F, 0.85F + this.random.nextFloat() * 0.2F);
} }
return hurt; return hurt;
@@ -366,7 +369,7 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
} }
boolean isFlyingAnim = this.getAnimationState() == ANIM_SWIM; boolean isFlyingAnim = this.getAnimationState() == ANIM_SWIM;
boolean isMoving = this.getDeltaMovement().horizontalDistanceSqr() > 0.0125D; boolean isMoving = this.toLocal(this.getDeltaMovement()).horizontalDistanceSqr() > 0.0125D;
if (!isFlyingAnim || !isMoving) { if (!isFlyingAnim || !isMoving) {
this.flySoundCooldown = 0; this.flySoundCooldown = 0;
return; return;
@@ -462,9 +465,10 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
if (this.diveCooldown > 0 || !this.hasLineOfSight(target)) return false; if (this.diveCooldown > 0 || !this.hasLineOfSight(target)) return false;
if (this.strafeTicks > Math.max(6, this.currentStrafeDuration / 2)) return false; if (this.strafeTicks > Math.max(6, this.currentStrafeDuration / 2)) return false;
double distanceToTarget = this.distanceToSqr(target); double distanceToTarget = this.distanceToSqr(target);
double localHeight = this.toLocal(target.position().subtract(this.position())).y;
return distanceToTarget >= 9.0D return distanceToTarget >= 9.0D
&& distanceToTarget <= 144.0D && distanceToTarget <= 144.0D
&& this.getY() > target.getY() + 0.5D; && localHeight < -0.5D;
} }
private boolean canConnectDive(LivingEntity target) { private boolean canConnectDive(LivingEntity target) {
@@ -479,27 +483,30 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
private Vec3 getStrafePoint(LivingEntity target) { private Vec3 getStrafePoint(LivingEntity target) {
double angle = this.tickCount * 0.18D * this.orbitDirection + this.currentStrafeAngleOffset; double angle = this.tickCount * 0.18D * this.orbitDirection + this.currentStrafeAngleOffset;
double x = target.getX() + Math.cos(angle) * this.currentStrafeRadius; Vec3 localOffset = new Vec3(
double z = target.getZ() + Math.sin(angle) * this.currentStrafeRadius; Math.cos(angle) * this.currentStrafeRadius,
double y = target.getY() + this.currentStrafeHeightOffset this.currentStrafeHeightOffset + Math.sin((this.tickCount + this.getId()) * 0.14D) * 0.5D,
+ Math.sin((this.tickCount + this.getId()) * 0.14D) * 0.5D; Math.sin(angle) * this.currentStrafeRadius
return new Vec3(x, y, z); );
return target.position().add(this.toWorld(localOffset));
} }
private Vec3 createRecoveryTarget(Vec3 strikeTarget) { private Vec3 createRecoveryTarget(Vec3 strikeTarget) {
double radius = this.currentStrafeRadius + 1.5D + this.random.nextDouble() * 1.2D; double radius = this.currentStrafeRadius + 1.5D + this.random.nextDouble() * 1.2D;
double angle = this.currentStrafeAngleOffset + (Math.PI / 2.0D) * this.orbitDirection; double angle = this.currentStrafeAngleOffset + (Math.PI / 2.0D) * this.orbitDirection;
double x = strikeTarget.x + Math.cos(angle) * radius; Vec3 localOffset = new Vec3(
double z = strikeTarget.z + Math.sin(angle) * radius; Math.cos(angle) * radius,
double y = strikeTarget.y + 2.0D + this.random.nextDouble() * 1.2D; 2.0D + this.random.nextDouble() * 1.2D,
return new Vec3(x, y, z); Math.sin(angle) * radius
);
return strikeTarget.add(this.toWorld(localOffset));
} }
private Vec3 createDiveStrikeTarget(LivingEntity target) { private Vec3 createDiveStrikeTarget(LivingEntity target) {
Vec3 predictedOffset = target.getDeltaMovement().scale(5.0D); Vec3 predictedOffset = target.getDeltaMovement().scale(5.0D);
return target.position() return target.position()
.add(predictedOffset) .add(predictedOffset)
.add(0.0D, target.getBbHeight() * 0.45D, 0.0D); .add(this.toWorld(0.0D, target.getBbHeight() * 0.45D, 0.0D));
} }
private Vec3 findPatrolTarget() { private Vec3 findPatrolTarget() {
@@ -575,7 +582,7 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
} }
private void updateFlightRotation() { private void updateFlightRotation() {
Vec3 velocity = this.getDeltaMovement(); Vec3 velocity = this.toLocal(this.getDeltaMovement());
if (velocity.horizontalDistanceSqr() > 1.0E-4D) { if (velocity.horizontalDistanceSqr() > 1.0E-4D) {
float targetYaw = (float) (Mth.atan2(velocity.z, velocity.x) * (180.0D / Math.PI)) - 90.0F; float targetYaw = (float) (Mth.atan2(velocity.z, velocity.x) * (180.0D / Math.PI)) - 90.0F;
this.setYRot(Mth.approachDegrees(this.getYRot(), targetYaw, 8.0F)); this.setYRot(Mth.approachDegrees(this.getYRot(), targetYaw, 8.0F));
@@ -589,6 +596,27 @@ public class CloudSharkEntity extends Monster implements GeoEntity {
} }
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(Vec3 localVector) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(localVector, this.gravityDirection());
}
private Vec3 toWorld(double x, double y, double z) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(x, y, z, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
private int nextStrafeDuration() { private int nextStrafeDuration() {
return STRAFE_MIN_TICKS + this.random.nextInt(STRAFE_MAX_TICKS - STRAFE_MIN_TICKS + 1); return STRAFE_MIN_TICKS + this.random.nextInt(STRAFE_MAX_TICKS - STRAFE_MIN_TICKS + 1);
} }
@@ -6,6 +6,9 @@ import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.boss.BossCombatUtil; import com.craisinlord.antarchy.content.boss.BossCombatUtil;
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
@@ -256,10 +259,10 @@ public class NightmareEntity extends Monster implements GeoEntity {
} }
public static boolean canSpawn(EntityType<NightmareEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { public static boolean canSpawn(EntityType<NightmareEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
boolean sturdy = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP);
boolean posEmpty = level.isEmptyBlock(pos); boolean posEmpty = level.isEmptyBlock(pos);
boolean aboveEmpty = level.isEmptyBlock(pos.above()); boolean floorSpawn = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP) && level.isEmptyBlock(pos.above());
return level.getDifficulty() != Difficulty.PEACEFUL && sturdy && posEmpty && aboveEmpty; boolean ceilingSpawn = level.getBlockState(pos.above()).isFaceSturdy(level, pos.above(), Direction.DOWN) && level.isEmptyBlock(pos.below());
return level.getDifficulty() != Difficulty.PEACEFUL && posEmpty && (floorSpawn || ceilingSpawn);
} }
@Override @Override
@@ -730,21 +733,23 @@ public class NightmareEntity extends Monster implements GeoEntity {
this.getNavigation().stop(); this.getNavigation().stop();
this.faceTowardTarget(target, 180.0F); this.faceTowardTarget(target, 180.0F);
Vec3 lungeTarget = this.shouldUseFlyingLocomotion() Vec3 lungeTarget = this.shouldUseFlyingLocomotion()
? new Vec3(target.getX(), this.getFlyingAttackTargetY(target), target.getZ()) ? this.getFlyingAttackTargetPos(target)
: target.getEyePosition(); : target.getEyePosition();
Vec3 lunge = lungeTarget.subtract(this.getEyePosition()); Vec3 lunge = lungeTarget.subtract(this.getEyePosition());
if (lunge.lengthSqr() > 1.0E-4D) { if (lunge.lengthSqr() > 1.0E-4D) {
Vec3 normalized = lunge.normalize(); AntarchyGravityDirection direction = this.gravityDirection();
Vec3 normalized = AntarchyGravityRotationUtil.vecWorldToPlayer(lunge, direction).normalize();
double verticalBoost = this.shouldUseFlyingLocomotion() ? 0.34D : 0.18D; double verticalBoost = this.shouldUseFlyingLocomotion() ? 0.34D : 0.18D;
Vec3 current = this.getDeltaMovement(); Vec3 current = AntarchyGravityRotationUtil.vecWorldToPlayer(this.getDeltaMovement(), direction);
double upward = this.shouldUseFlyingLocomotion() double upward = this.shouldUseFlyingLocomotion()
? Math.max(normalized.y * verticalBoost, -0.08D) ? Math.max(normalized.y * verticalBoost, -0.08D)
: normalized.y * verticalBoost; : normalized.y * verticalBoost;
this.setDeltaMovement( this.setDeltaMovement(AntarchyGravityRotationUtil.vecPlayerToWorld(
normalized.x * 0.85D, normalized.x * 0.85D,
current.y * 0.18D + upward, current.y * 0.18D + upward,
normalized.z * 0.85D normalized.z * 0.85D,
); direction
));
this.hasImpulse = true; this.hasImpulse = true;
} }
} }
@@ -990,26 +995,27 @@ public class NightmareEntity extends Monster implements GeoEntity {
} }
private void performAttackHit(@Nullable LivingEntity target) { private void performAttackHit(@Nullable LivingEntity target) {
Vec3 forward = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); Vec3 forward = this.getPlaneForward(this.getViewVector(1.0F));
if (forward.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
float yawRadians = this.getYRot() * Mth.DEG_TO_RAD; forward = this.toWorld(new Vec3(-Mth.sin(this.getYRot() * Mth.DEG_TO_RAD), 0.0D, Mth.cos(this.getYRot() * Mth.DEG_TO_RAD)));
forward = new Vec3(-Mth.sin(yawRadians), 0.0D, Mth.cos(yawRadians));
} }
if (forward.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
forward = new Vec3(0.0D, 0.0D, 1.0D); forward = this.toWorld(new Vec3(0.0D, 0.0D, 1.0D));
} }
forward = forward.normalize(); forward = forward.normalize();
Vec3 strikeOrigin = this.position() Vec3 strikeOrigin = this.position()
.add(0.0D, this.getBbHeight() * 0.55D, 0.0D) .add(this.toWorld(new Vec3(0.0D, this.getBbHeight() * 0.55D, 0.0D)))
.add(forward.scale(0.4D)); .add(forward.scale(0.4D));
Vec3 strikeCenter = strikeOrigin Vec3 strikeCenter = strikeOrigin
.add(forward.scale(ATTACK_HIT_FORWARD_OFFSET)); .add(forward.scale(ATTACK_HIT_FORWARD_OFFSET));
Vec3 strikeMin = strikeOrigin.add(this.toWorld(new Vec3(0.0D, ATTACK_HIT_MIN_Y_OFFSET, 0.0D)));
Vec3 strikeMax = strikeOrigin.add(this.toWorld(new Vec3(0.0D, ATTACK_HIT_MAX_Y_OFFSET, 0.0D)));
AABB hitBox = new AABB( AABB hitBox = new AABB(
Math.min(strikeOrigin.x, strikeCenter.x) - ATTACK_HIT_HALF_WIDTH, Math.min(strikeOrigin.x, strikeCenter.x) - ATTACK_HIT_HALF_WIDTH,
this.getBoundingBox().minY + ATTACK_HIT_MIN_Y_OFFSET, Math.min(strikeMin.y, strikeMax.y),
Math.min(strikeOrigin.z, strikeCenter.z) - ATTACK_HIT_HALF_WIDTH, Math.min(strikeOrigin.z, strikeCenter.z) - ATTACK_HIT_HALF_WIDTH,
Math.max(strikeOrigin.x, strikeCenter.x) + ATTACK_HIT_HALF_WIDTH, Math.max(strikeOrigin.x, strikeCenter.x) + ATTACK_HIT_HALF_WIDTH,
this.getBoundingBox().minY + ATTACK_HIT_MAX_Y_OFFSET, Math.max(strikeMin.y, strikeMax.y),
Math.max(strikeOrigin.z, strikeCenter.z) + ATTACK_HIT_HALF_WIDTH Math.max(strikeOrigin.z, strikeCenter.z) + ATTACK_HIT_HALF_WIDTH
); );
List<LivingEntity> victims = new ArrayList<>(this.level().getEntitiesOfClass(LivingEntity.class, hitBox, this::canTargetEntity)); List<LivingEntity> victims = new ArrayList<>(this.level().getEntitiesOfClass(LivingEntity.class, hitBox, this::canTargetEntity));
@@ -1041,17 +1047,20 @@ public class NightmareEntity extends Monster implements GeoEntity {
if (victim.getBoundingBox().inflate(0.1D).intersects(hitBox)) { if (victim.getBoundingBox().inflate(0.1D).intersects(hitBox)) {
return true; return true;
} }
Vec3 toVictim = victimCenter.subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 localForward = this.toLocalPlane(forward);
double forwardDistance = toVictim.dot(forward); Vec3 toVictim = this.toLocalPlane(victimCenter.subtract(this.position()));
double forwardDistance = toVictim.dot(localForward.normalize());
if (forwardDistance < 0.15D || forwardDistance > ATTACK_HIT_FORWARD_OFFSET + 1.25D) { if (forwardDistance < 0.15D || forwardDistance > ATTACK_HIT_FORWARD_OFFSET + 1.25D) {
return false; return false;
} }
Vec3 lateral = toVictim.subtract(forward.scale(forwardDistance)); Vec3 lateral = toVictim.subtract(localForward.normalize().scale(forwardDistance));
if (lateral.lengthSqr() > (ATTACK_HIT_HALF_WIDTH + 0.55D) * (ATTACK_HIT_HALF_WIDTH + 0.55D)) { if (lateral.lengthSqr() > (ATTACK_HIT_HALF_WIDTH + 0.55D) * (ATTACK_HIT_HALF_WIDTH + 0.55D)) {
return false; return false;
} }
double minY = this.getBoundingBox().minY + ATTACK_HIT_MIN_Y_OFFSET; Vec3 minOffset = this.toWorld(new Vec3(0.0D, ATTACK_HIT_MIN_Y_OFFSET, 0.0D));
double maxY = this.getBoundingBox().minY + ATTACK_HIT_MAX_Y_OFFSET + 0.4D; Vec3 maxOffset = this.toWorld(new Vec3(0.0D, ATTACK_HIT_MAX_Y_OFFSET + 0.4D, 0.0D));
double minY = Math.min(this.position().y + minOffset.y, this.position().y + maxOffset.y);
double maxY = Math.max(this.position().y + minOffset.y, this.position().y + maxOffset.y);
return victim.getBoundingBox().maxY >= minY && victim.getBoundingBox().minY <= maxY; return victim.getBoundingBox().maxY >= minY && victim.getBoundingBox().minY <= maxY;
} }
@@ -1088,14 +1097,67 @@ public class NightmareEntity extends Monster implements GeoEntity {
} }
private void knockAway(LivingEntity target, double horizontalStrength, double verticalStrength) { private void knockAway(LivingEntity target, double horizontalStrength, double verticalStrength) {
Vec3 direction = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); AntarchyGravityDirection direction = this.gravityDirection();
if (direction.lengthSqr() < 1.0E-4D) direction = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); Vec3 localDirection = this.toLocalPlane(target.position().subtract(this.position()));
if (direction.lengthSqr() < 1.0E-4D) direction = new Vec3(1.0D, 0.0D, 0.0D); if (localDirection.lengthSqr() < 1.0E-4D) localDirection = this.toLocalPlane(this.getViewVector(1.0F));
Vec3 push = direction.normalize().scale(horizontalStrength); if (localDirection.lengthSqr() < 1.0E-4D) localDirection = new Vec3(1.0D, 0.0D, 0.0D);
target.push(push.x, verticalStrength, push.z); Vec3 localPush = localDirection.normalize().scale(horizontalStrength);
Vec3 worldPush = AntarchyGravityRotationUtil.vecPlayerToWorld(localPush.x, verticalStrength, localPush.z, direction);
target.push(worldPush.x, worldPush.y, worldPush.z);
target.hurtMarked = true; target.hurtMarked = true;
} }
private AntarchyGravityDirection gravityDirection() {
return AntarchyGravityApi.getGravityDirection(this);
}
private Vec3 toLocal(Vec3 worldVector) {
return AntarchyGravityRotationUtil.vecWorldToPlayer(worldVector, this.gravityDirection());
}
private Vec3 toWorld(Vec3 localVector) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(localVector, this.gravityDirection());
}
private Vec3 toLocalPlane(Vec3 worldVector) {
Vec3 local = this.toLocal(worldVector);
return new Vec3(local.x, 0.0D, local.z);
}
private Vec3 localDeltaTo(Vec3 worldPosition) {
return this.toLocal(worldPosition.subtract(this.position()));
}
private double verticalDistanceTo(LivingEntity target) {
return Math.abs(this.toLocal(target.getEyePosition().subtract(this.getEyePosition())).y);
}
private double overheadGapTo(LivingEntity target) {
return -this.localDeltaTo(target.position()).y;
}
private Vec3 getPlaneForward(Vec3 worldVector) {
Vec3 local = this.toLocalPlane(worldVector);
if (local.lengthSqr() < 1.0E-4D) {
return Vec3.ZERO;
}
return this.toWorld(local.normalize());
}
private Vec3 getLocalRight(Vec3 worldForward) {
Vec3 localForward = this.toLocalPlane(worldForward);
if (localForward.lengthSqr() < 1.0E-4D) {
return Vec3.ZERO;
}
Vec3 normalized = localForward.normalize();
return this.toWorld(new Vec3(-normalized.z, 0.0D, normalized.x));
}
private Vec3 getFlyingAttackTargetPos(LivingEntity target) {
double targetHeight = Mth.clamp(target.getBbHeight() * 0.4D, FLYING_ATTACK_MIN_TARGET_HEIGHT, FLYING_ATTACK_BODY_TARGET_HEIGHT);
return target.position().add(this.toWorld(new Vec3(0.0D, targetHeight, 0.0D)));
}
private DamageSource nightmareDamageSource() { private DamageSource nightmareDamageSource() {
return this.level() instanceof ServerLevel serverLevel return this.level() instanceof ServerLevel serverLevel
? AntarchyDamageSources.nightmareMauling(serverLevel, this) ? AntarchyDamageSources.nightmareMauling(serverLevel, this)
@@ -1103,13 +1165,9 @@ public class NightmareEntity extends Monster implements GeoEntity {
} }
private boolean tryBreakBlocksToTarget(LivingEntity target) { private boolean tryBreakBlocksToTarget(LivingEntity target) {
int startY = Mth.floor(this.getY()); Direction gravityDown = AntarchyGravityRotationUtil.getGravityDownDirection(this);
int endY = Math.max(Mth.floor(target.getY()), startY - 16); BlockPos.MutableBlockPos cursor = this.blockPosition().mutable();
int x = Mth.floor(this.getX()); for (int i = 0; i <= 16; i++) {
int z = Mth.floor(this.getZ());
BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
for (int y = startY; y >= endY; y--) {
cursor.set(x, y, z);
if (this.level().getBlockState(cursor).is(AntarchyTags.Blocks.NIGHTMARE_BREAKABLE)) { if (this.level().getBlockState(cursor).is(AntarchyTags.Blocks.NIGHTMARE_BREAKABLE)) {
if (this.blockBreakCooldown <= 0) { if (this.blockBreakCooldown <= 0) {
this.level().destroyBlock(cursor.immutable(), true, this); this.level().destroyBlock(cursor.immutable(), true, this);
@@ -1118,6 +1176,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
this.getMoveControl().setWantedPosition(this.getX(), this.getY(), this.getZ(), 0.0D); this.getMoveControl().setWantedPosition(this.getX(), this.getY(), this.getZ(), 0.0D);
return true; return true;
} }
cursor.move(gravityDown);
} }
return false; return false;
} }
@@ -1134,9 +1193,9 @@ public class NightmareEntity extends Monster implements GeoEntity {
private boolean canStartAttackOn(LivingEntity target) { private boolean canStartAttackOn(LivingEntity target) {
if (!this.hasLineOfSight(target) || this.distanceToSqr(target) > ATTACK_START_RANGE_SQR) return false; if (!this.hasLineOfSight(target) || this.distanceToSqr(target) > ATTACK_START_RANGE_SQR) return false;
double hdSqr = this.horizontalDistanceToSqr(target); double hdSqr = this.horizontalDistanceToSqr(target);
double verticalDistance = Math.abs(target.getEyeY() - this.getEyeY()); double verticalDistance = this.verticalDistanceTo(target);
if (this.shouldUseFlyingLocomotion()) { if (this.shouldUseFlyingLocomotion()) {
double overheadGap = this.getY() - target.getY(); double overheadGap = this.overheadGapTo(target);
return hdSqr <= ATTACK_COMMIT_HORIZONTAL_RANGE_SQR return hdSqr <= ATTACK_COMMIT_HORIZONTAL_RANGE_SQR
&& verticalDistance <= 2.5D && verticalDistance <= 2.5D
&& overheadGap <= FLYING_ATTACK_MAX_OVERHEAD_COMMIT_HEIGHT; && overheadGap <= FLYING_ATTACK_MAX_OVERHEAD_COMMIT_HEIGHT;
@@ -1153,9 +1212,9 @@ public class NightmareEntity extends Monster implements GeoEntity {
return true; return true;
} }
double distanceSqr = this.distanceToSqr(target); double distanceSqr = this.distanceToSqr(target);
double verticalDistance = Math.abs(target.getEyeY() - this.getEyeY()); double verticalDistance = this.verticalDistanceTo(target);
double horizontalDistanceSqr = this.horizontalDistanceToSqr(target); double horizontalDistanceSqr = this.horizontalDistanceToSqr(target);
double overheadGap = this.getY() - target.getY(); double overheadGap = this.overheadGapTo(target);
if (lowProfileTarget if (lowProfileTarget
&& horizontalDistanceSqr <= LOW_PROFILE_FLIGHT_DISENGAGE_RANGE_SQR && horizontalDistanceSqr <= LOW_PROFILE_FLIGHT_DISENGAGE_RANGE_SQR
&& verticalDistance <= LOW_PROFILE_FLIGHT_DISENGAGE_VERTICAL && verticalDistance <= LOW_PROFILE_FLIGHT_DISENGAGE_VERTICAL
@@ -1179,24 +1238,23 @@ public class NightmareEntity extends Monster implements GeoEntity {
} }
private Vec3 getFlightApproachPosition(LivingEntity target) { private Vec3 getFlightApproachPosition(LivingEntity target) {
Vec3 toTarget = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 forward = this.getPlaneForward(target.position().subtract(this.position()));
if (toTarget.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
toTarget = target.getLookAngle().multiply(1.0D, 0.0D, 1.0D); forward = this.getPlaneForward(target.getLookAngle());
} }
if (toTarget.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
toTarget = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); forward = this.getPlaneForward(this.getViewVector(1.0F));
} }
if (toTarget.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
toTarget = new Vec3(0.0D, 0.0D, 1.0D); forward = this.toWorld(new Vec3(0.0D, 0.0D, 1.0D));
} }
Vec3 forward = toTarget.normalize(); Vec3 right = this.getLocalRight(forward);
Vec3 right = new Vec3(-forward.z, 0.0D, forward.x);
double strafe = this.tickCount % 32 < 16 ? FLYING_APPROACH_STRAFE_OFFSET : -FLYING_APPROACH_STRAFE_OFFSET; double strafe = this.tickCount % 32 < 16 ? FLYING_APPROACH_STRAFE_OFFSET : -FLYING_APPROACH_STRAFE_OFFSET;
double height = this.isPhaseTwo() ? FLYING_APPROACH_HEIGHT_PHASE_TWO : FLYING_APPROACH_HEIGHT; double height = this.isPhaseTwo() ? FLYING_APPROACH_HEIGHT_PHASE_TWO : FLYING_APPROACH_HEIGHT;
double horizontalDistanceSqr = this.horizontalDistanceToSqr(target); double horizontalDistanceSqr = this.horizontalDistanceToSqr(target);
double overheadGap = this.getY() - target.getY(); double overheadGap = this.overheadGapTo(target);
boolean lowProfileTarget = this.isLowProfileFlightTarget(target); boolean lowProfileTarget = this.isLowProfileFlightTarget(target);
double attackTargetY = this.getFlyingAttackTargetY(target); Vec3 attackTarget = this.getFlyingAttackTargetPos(target);
Vec3 anchor = target.position().subtract(forward.scale(1.8D)).add(right.scale(strafe)); Vec3 anchor = target.position().subtract(forward.scale(1.8D)).add(right.scale(strafe));
if (horizontalDistanceSqr <= FLYING_OVERHEAD_STALL_RANGE_SQR && overheadGap >= FLYING_OVERHEAD_STALL_HEIGHT) { if (horizontalDistanceSqr <= FLYING_OVERHEAD_STALL_RANGE_SQR && overheadGap >= FLYING_OVERHEAD_STALL_HEIGHT) {
double sideOffset = lowProfileTarget ? LOW_PROFILE_OVERHEAD_DESCENT_SIDE_OFFSET : FLYING_OVERHEAD_DESCENT_SIDE_OFFSET; double sideOffset = lowProfileTarget ? LOW_PROFILE_OVERHEAD_DESCENT_SIDE_OFFSET : FLYING_OVERHEAD_DESCENT_SIDE_OFFSET;
@@ -1204,26 +1262,26 @@ public class NightmareEntity extends Monster implements GeoEntity {
anchor = target.position() anchor = target.position()
.add(right.scale(strafe > 0.0D ? sideOffset : -sideOffset)) .add(right.scale(strafe > 0.0D ? sideOffset : -sideOffset))
.subtract(forward.scale(backOffset)); .subtract(forward.scale(backOffset));
return new Vec3(anchor.x, attackTargetY, anchor.z); return new Vec3(anchor.x, attackTarget.y, anchor.z);
} }
if (horizontalDistanceSqr <= FLYING_APPROACH_TOO_CLOSE_RANGE_SQR) { if (horizontalDistanceSqr <= FLYING_APPROACH_TOO_CLOSE_RANGE_SQR) {
double backOffset = lowProfileTarget ? LOW_PROFILE_TOO_CLOSE_BACK_OFFSET : 2.8D; double backOffset = lowProfileTarget ? LOW_PROFILE_TOO_CLOSE_BACK_OFFSET : 2.8D;
double strafeScale = lowProfileTarget ? LOW_PROFILE_TOO_CLOSE_STRAFE_SCALE : 0.6D; double strafeScale = lowProfileTarget ? LOW_PROFILE_TOO_CLOSE_STRAFE_SCALE : 0.6D;
anchor = target.position().subtract(forward.scale(backOffset)).add(right.scale(strafe * strafeScale)); anchor = target.position().subtract(forward.scale(backOffset)).add(right.scale(strafe * strafeScale));
} }
return new Vec3(anchor.x, attackTargetY + height, anchor.z); Vec3 elevated = attackTarget.add(this.toWorld(new Vec3(0.0D, height, 0.0D)));
return new Vec3(anchor.x, elevated.y, anchor.z);
} }
private Vec3 getFlightDescentPosition(LivingEntity target) { private Vec3 getFlightDescentPosition(LivingEntity target) {
Vec3 toTarget = target.position().subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 forward = this.getPlaneForward(target.position().subtract(this.position()));
if (toTarget.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
toTarget = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); forward = this.getPlaneForward(this.getViewVector(1.0F));
} }
if (toTarget.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
toTarget = new Vec3(0.0D, 0.0D, 1.0D); forward = this.toWorld(new Vec3(0.0D, 0.0D, 1.0D));
} }
Vec3 forward = toTarget.normalize(); Vec3 right = this.getLocalRight(forward);
Vec3 right = new Vec3(-forward.z, 0.0D, forward.x);
double side = this.tickCount % 20 < 10 ? 1.0D : -1.0D; double side = this.tickCount % 20 < 10 ? 1.0D : -1.0D;
boolean lowProfileTarget = this.isLowProfileFlightTarget(target); boolean lowProfileTarget = this.isLowProfileFlightTarget(target);
double sideOffset = lowProfileTarget ? 1.15D : 0.9D; double sideOffset = lowProfileTarget ? 1.15D : 0.9D;
@@ -1231,33 +1289,29 @@ public class NightmareEntity extends Monster implements GeoEntity {
Vec3 anchor = target.position() Vec3 anchor = target.position()
.subtract(forward.scale(backOffset)) .subtract(forward.scale(backOffset))
.add(right.scale(side * sideOffset)); .add(right.scale(side * sideOffset));
return new Vec3(anchor.x, this.getFlyingAttackTargetY(target), anchor.z); return new Vec3(anchor.x, this.getFlyingAttackTargetPos(target).y, anchor.z);
} }
private boolean isLowProfileFlightTarget(LivingEntity target) { private boolean isLowProfileFlightTarget(LivingEntity target) {
return target.getBbHeight() <= LOW_PROFILE_TARGET_MAX_HEIGHT; return target.getBbHeight() <= LOW_PROFILE_TARGET_MAX_HEIGHT;
} }
private double getFlyingAttackTargetY(LivingEntity target) {
double targetHeight = Mth.clamp(target.getBbHeight() * 0.4D, FLYING_ATTACK_MIN_TARGET_HEIGHT, FLYING_ATTACK_BODY_TARGET_HEIGHT);
return target.getY() + targetHeight;
}
private double horizontalDistanceToSqr(LivingEntity target) { private double horizontalDistanceToSqr(LivingEntity target) {
double dx = target.getX() - this.getX(); Vec3 delta = this.localDeltaTo(target.position());
double dz = target.getZ() - this.getZ(); double dx = delta.x;
double dz = delta.z;
return dx * dx + dz * dz; return dx * dx + dz * dz;
} }
private boolean isInFront(Vec3 position, double minimumDot) { private boolean isInFront(Vec3 position, double minimumDot) {
Vec3 forward = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); Vec3 forward = this.toLocalPlane(this.getViewVector(1.0F));
Vec3 toTarget = position.subtract(this.position()).multiply(1.0D, 0.0D, 1.0D); Vec3 toTarget = this.toLocalPlane(position.subtract(this.position()));
if (forward.lengthSqr() < 1.0E-4D || toTarget.lengthSqr() < 1.0E-4D) return true; if (forward.lengthSqr() < 1.0E-4D || toTarget.lengthSqr() < 1.0E-4D) return true;
return forward.normalize().dot(toTarget.normalize()) >= minimumDot; return forward.normalize().dot(toTarget.normalize()) >= minimumDot;
} }
private void faceTowardTarget(LivingEntity target, float maxTurnDegrees) { private void faceTowardTarget(LivingEntity target, float maxTurnDegrees) {
Vec3 toTarget = target.getEyePosition().subtract(this.getEyePosition()); Vec3 toTarget = this.toLocal(target.getEyePosition().subtract(this.getEyePosition()));
double horizontal = Math.sqrt(toTarget.x * toTarget.x + toTarget.z * toTarget.z); double horizontal = Math.sqrt(toTarget.x * toTarget.x + toTarget.z * toTarget.z);
if (horizontal > 1.0E-4D) { if (horizontal > 1.0E-4D) {
float targetYaw = (float) (Mth.atan2(toTarget.z, toTarget.x) * (180.0D / Math.PI)) - 90.0F; float targetYaw = (float) (Mth.atan2(toTarget.z, toTarget.x) * (180.0D / Math.PI)) - 90.0F;
@@ -1273,35 +1327,41 @@ public class NightmareEntity extends Monster implements GeoEntity {
} }
private boolean isTooCloseToCeiling() { private boolean isTooCloseToCeiling() {
BlockPos current = BlockPos.containing(this.getX(), this.getY(), this.getZ()); Direction gravityUp = AntarchyGravityRotationUtil.getGravityDownDirection(this).getOpposite();
BlockPos current = this.blockPosition();
for (int i = 1; i <= FLIGHT_CEILING_CLEARANCE_BLOCKS; i++) { for (int i = 1; i <= FLIGHT_CEILING_CLEARANCE_BLOCKS; i++) {
if (!this.level().isEmptyBlock(current.above(i))) return true; if (!this.level().isEmptyBlock(current.relative(gravityUp, i))) return true;
} }
return false; return false;
} }
private Vec3 getPortalEntryPosition() { private Vec3 getPortalEntryPosition() {
return this.position().add(this.getViewVector(1.0F).multiply(1.6D, 0.0D, 1.6D)); Vec3 forward = this.getPlaneForward(this.getViewVector(1.0F));
if (forward.lengthSqr() < 1.0E-4D) {
forward = this.toWorld(new Vec3(0.0D, 0.0D, 1.0D));
}
return this.position().add(forward.scale(1.6D));
} }
@Nullable @Nullable
private Vec3 findPortalExitPos(LivingEntity target, Vec3 entryPos) { private Vec3 findPortalExitPos(LivingEntity target, Vec3 entryPos) {
Vec3 forward = target.getLookAngle().multiply(1.0D, 0.0D, 1.0D); Vec3 forward = this.getPlaneForward(target.getLookAngle());
if (forward.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
forward = this.getViewVector(1.0F).multiply(1.0D, 0.0D, 1.0D); forward = this.getPlaneForward(this.getViewVector(1.0F));
} }
if (forward.lengthSqr() < 1.0E-4D) { if (forward.lengthSqr() < 1.0E-4D) {
forward = new Vec3(0.0D, 0.0D, 1.0D); forward = this.toWorld(new Vec3(0.0D, 0.0D, 1.0D));
} }
forward = forward.normalize(); forward = forward.normalize();
Vec3 right = new Vec3(-forward.z, 0.0D, forward.x); Vec3 right = this.getLocalRight(forward);
Vec3 airOffset = this.toWorld(new Vec3(0.0D, PORTAL_EXIT_AIR_HEIGHT, 0.0D));
Vec3[] candidates = new Vec3[] { Vec3[] candidates = new Vec3[] {
target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)), target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)),
target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).add(0.0D, PORTAL_EXIT_AIR_HEIGHT, 0.0D), target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).add(airOffset),
target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).add(right.scale(PORTAL_EXIT_SIDE_OFFSET)), target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).add(right.scale(PORTAL_EXIT_SIDE_OFFSET)),
target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).subtract(right.scale(PORTAL_EXIT_SIDE_OFFSET)), target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).subtract(right.scale(PORTAL_EXIT_SIDE_OFFSET)),
target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).add(right.scale(PORTAL_EXIT_SIDE_OFFSET)).add(0.0D, PORTAL_EXIT_AIR_HEIGHT, 0.0D), target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).add(right.scale(PORTAL_EXIT_SIDE_OFFSET)).add(airOffset),
target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).subtract(right.scale(PORTAL_EXIT_SIDE_OFFSET)).add(0.0D, PORTAL_EXIT_AIR_HEIGHT, 0.0D) target.position().subtract(forward.scale(PORTAL_EXIT_OFFSET)).subtract(right.scale(PORTAL_EXIT_SIDE_OFFSET)).add(airOffset)
}; };
for (Vec3 candidate : candidates) { for (Vec3 candidate : candidates) {
Vec3 adjusted = this.findValidPortalPosition(candidate); Vec3 adjusted = this.findValidPortalPosition(candidate);
@@ -1318,7 +1378,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
private Vec3 findValidPortalPosition(Vec3 base) { private Vec3 findValidPortalPosition(Vec3 base) {
EntityDimensions dimensions = this.getType().getDimensions(); EntityDimensions dimensions = this.getType().getDimensions();
for (int yOffset = 4; yOffset >= -3; yOffset--) { for (int yOffset = 4; yOffset >= -3; yOffset--) {
Vec3 candidate = new Vec3(base.x, base.y + yOffset, base.z); Vec3 candidate = base.add(this.toWorld(new Vec3(0.0D, yOffset, 0.0D)));
AABB box = dimensions.makeBoundingBox(candidate); AABB box = dimensions.makeBoundingBox(candidate);
if (this.level().noCollision(this, box)) { if (this.level().noCollision(this, box)) {
return candidate; return candidate;
@@ -1351,7 +1411,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
} }
private void updateFlightRotation() { private void updateFlightRotation() {
Vec3 velocity = this.getDeltaMovement(); Vec3 velocity = this.toLocal(this.getDeltaMovement());
if (velocity.horizontalDistanceSqr() > 1.0E-4D) { if (velocity.horizontalDistanceSqr() > 1.0E-4D) {
float targetYaw = (float) (Mth.atan2(velocity.z, velocity.x) * (180.0D / Math.PI)) - 90.0F; float targetYaw = (float) (Mth.atan2(velocity.z, velocity.x) * (180.0D / Math.PI)) - 90.0F;
float nextYaw = Mth.approachDegrees(this.getYRot(), targetYaw, 4.0F); float nextYaw = Mth.approachDegrees(this.getYRot(), targetYaw, 4.0F);
@@ -1392,7 +1452,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
this.tickWingFlapSound(); this.tickWingFlapSound();
return; return;
} }
Vec3 horizontalVelocity = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D); Vec3 horizontalVelocity = this.toLocalPlane(this.getDeltaMovement());
if (horizontalVelocity.lengthSqr() > ANIMATION_MOVEMENT_THRESHOLD_SQR) { if (horizontalVelocity.lengthSqr() > ANIMATION_MOVEMENT_THRESHOLD_SQR) {
this.groundMoveTicks = 6; this.groundMoveTicks = 6;
} }
@@ -1617,11 +1677,11 @@ public class NightmareEntity extends Monster implements GeoEntity {
return; return;
} }
if (NightmareEntity.this.onGround() && NightmareEntity.this.distanceToSqr(target) >= FLIGHT_DISENGAGE_RANGE_SQR) { if (NightmareEntity.this.onGround() && NightmareEntity.this.distanceToSqr(target) >= FLIGHT_DISENGAGE_RANGE_SQR) {
NightmareEntity.this.setDeltaMovement(NightmareEntity.this.getDeltaMovement().add(0.0D, 0.38D, 0.0D)); NightmareEntity.this.setDeltaMovement(NightmareEntity.this.getDeltaMovement().add(NightmareEntity.this.toWorld(new Vec3(0.0D, 0.38D, 0.0D))));
NightmareEntity.this.hasImpulse = true; NightmareEntity.this.hasImpulse = true;
} }
double horizontalDistanceSqr = NightmareEntity.this.horizontalDistanceToSqr(target); double horizontalDistanceSqr = NightmareEntity.this.horizontalDistanceToSqr(target);
double overheadGap = NightmareEntity.this.getY() - target.getY(); double overheadGap = NightmareEntity.this.overheadGapTo(target);
if (horizontalDistanceSqr <= ATTACK_COMMIT_HORIZONTAL_RANGE_SQR if (horizontalDistanceSqr <= ATTACK_COMMIT_HORIZONTAL_RANGE_SQR
&& overheadGap > FLYING_ATTACK_MAX_OVERHEAD_COMMIT_HEIGHT) { && overheadGap > FLYING_ATTACK_MAX_OVERHEAD_COMMIT_HEIGHT) {
Vec3 descentPos = NightmareEntity.this.getFlightDescentPosition(target); Vec3 descentPos = NightmareEntity.this.getFlightDescentPosition(target);
@@ -1681,7 +1741,7 @@ public class NightmareEntity extends Monster implements GeoEntity {
LivingEntity target = NightmareEntity.this.getTarget(); LivingEntity target = NightmareEntity.this.getTarget();
if (target != null) { if (target != null) {
double hdSqr = NightmareEntity.this.horizontalDistanceToSqr(target); double hdSqr = NightmareEntity.this.horizontalDistanceToSqr(target);
double vertDelta = NightmareEntity.this.getY() - target.getY(); double vertDelta = NightmareEntity.this.overheadGapTo(target);
if (target.onGround() && hdSqr <= 25.0D && vertDelta > 1.6D) { if (target.onGround() && hdSqr <= 25.0D && vertDelta > 1.6D) {
NightmareEntity.this.tryBreakBlocksToTarget(target); NightmareEntity.this.tryBreakBlocksToTarget(target);
} }
@@ -1716,9 +1776,11 @@ public class NightmareEntity extends Monster implements GeoEntity {
if (NightmareEntity.this.random.nextInt(40) != 0) return false; if (NightmareEntity.this.random.nextInt(40) != 0) return false;
double angle = NightmareEntity.this.random.nextDouble() * Math.PI * 2; double angle = NightmareEntity.this.random.nextDouble() * Math.PI * 2;
double dist = 4 + NightmareEntity.this.random.nextDouble() * 10; double dist = 4 + NightmareEntity.this.random.nextDouble() * 10;
this.x = NightmareEntity.this.getX() + Math.cos(angle) * dist; Vec3 localOffset = new Vec3(Math.cos(angle) * dist, 0.0D, Math.sin(angle) * dist);
this.z = NightmareEntity.this.getZ() + Math.sin(angle) * dist; Vec3 worldOffset = NightmareEntity.this.toWorld(localOffset);
this.y = NightmareEntity.this.getY(); this.x = NightmareEntity.this.getX() + worldOffset.x;
this.y = NightmareEntity.this.getY() + worldOffset.y;
this.z = NightmareEntity.this.getZ() + worldOffset.z;
return true; return true;
} }
@@ -1,6 +1,7 @@
package com.craisinlord.antarchy.content.gravity; package com.craisinlord.antarchy.content.gravity;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
public final class AntarchyGravityApi { public final class AntarchyGravityApi {
public interface GravitySyncDispatcher { public interface GravitySyncDispatcher {
@@ -99,6 +100,122 @@ public final class AntarchyGravityApi {
syncDispatcher.onGravityStateChanged(entity); syncDispatcher.onGravityStateChanged(entity);
} }
public static Vec3 getWorldVelocity(Entity entity) {
return AntarchyGravityRotationUtil.vecPlayerToWorld(entity.getDeltaMovement(), getGravityDirection(entity));
}
public static void setWorldVelocity(Entity entity, Vec3 worldVelocity) {
entity.setDeltaMovement(AntarchyGravityRotationUtil.vecWorldToPlayer(worldVelocity, getGravityDirection(entity)));
}
public static Vec3 getEyeOffset(Entity entity) {
return AntarchyGravityRotationUtil.getEyeOffset(entity, entity.getEyeHeight());
}
public static double eyeX(Entity entity) {
return isGravityInverted(entity) ? entity.getEyePosition().x : entity.getX();
}
public static double eyeY(Entity entity) {
return isGravityInverted(entity) ? entity.getEyePosition().y : entity.getY();
}
public static double eyeZ(Entity entity) {
return isGravityInverted(entity) ? entity.getEyePosition().z : entity.getZ();
}
public static Vec3 deltaMovement(net.minecraft.world.entity.LivingEntity target) {
return isGravityInverted(target) ? getWorldVelocity(target) : target.getDeltaMovement();
}
public static double projectileSpawnX(net.minecraft.world.entity.LivingEntity shooter) {
return projectileSpawnVec(shooter).x;
}
public static double projectileSpawnY(net.minecraft.world.entity.LivingEntity shooter) {
return projectileSpawnVec(shooter).y;
}
public static double projectileSpawnZ(net.minecraft.world.entity.LivingEntity shooter) {
return projectileSpawnVec(shooter).z;
}
public static double rangedBodyTargetX(net.minecraft.world.entity.LivingEntity target) {
if (!isGravityInverted(target)) {
return target.getX();
}
return target.position().add(AntarchyGravityRotationUtil.vecPlayerToWorld(
0.0D,
target.getBbHeight() * 0.3333333333333333D,
0.0D,
getGravityDirection(target)
)).x;
}
public static double rangedBodyTargetY(net.minecraft.world.entity.LivingEntity target, double heightScale) {
if (!isGravityInverted(target)) {
return target.getY(heightScale);
}
return target.position().add(AntarchyGravityRotationUtil.vecPlayerToWorld(
0.0D,
target.getBbHeight() * 0.3333333333333333D,
0.0D,
getGravityDirection(target)
)).y;
}
public static double rangedBodyTargetZ(net.minecraft.world.entity.LivingEntity target) {
if (!isGravityInverted(target)) {
return target.getZ();
}
return target.position().add(AntarchyGravityRotationUtil.vecPlayerToWorld(
0.0D,
target.getBbHeight() * 0.3333333333333333D,
0.0D,
getGravityDirection(target)
)).z;
}
public static double rangedEyeTargetX(net.minecraft.world.entity.LivingEntity target) {
if (!isGravityInverted(target)) {
return target.getX();
}
return target.position().add(AntarchyGravityRotationUtil.vecPlayerToWorld(
0.0D,
target.getEyeHeight() - 1.100000023841858D,
0.0D,
getGravityDirection(target)
)).x;
}
public static double rangedEyeTargetY(net.minecraft.world.entity.LivingEntity target) {
if (!isGravityInverted(target)) {
return target.getEyeY();
}
return target.position().add(AntarchyGravityRotationUtil.vecPlayerToWorld(
0.0D,
target.getEyeHeight() - 1.100000023841858D,
0.0D,
getGravityDirection(target)
)).y + 1.100000023841858D;
}
public static double rangedEyeTargetZ(net.minecraft.world.entity.LivingEntity target) {
if (!isGravityInverted(target)) {
return target.getZ();
}
return target.position().add(AntarchyGravityRotationUtil.vecPlayerToWorld(
0.0D,
target.getEyeHeight() - 1.100000023841858D,
0.0D,
getGravityDirection(target)
)).z;
}
public static double rangedSqrt(double value, net.minecraft.world.entity.LivingEntity target) {
return isGravityInverted(target) ? Math.sqrt(Math.sqrt(value)) : Math.sqrt(value);
}
private static AntarchyGravityAccess access(Entity entity) { private static AntarchyGravityAccess access(Entity entity) {
if (entity instanceof AntarchyGravityAccess access) { if (entity instanceof AntarchyGravityAccess access) {
return access; return access;
@@ -106,4 +223,12 @@ public final class AntarchyGravityApi {
throw new IllegalStateException("Entity " + entity + " is missing Antarchy gravity state"); throw new IllegalStateException("Entity " + entity + " is missing Antarchy gravity state");
} }
private static Vec3 projectileSpawnVec(net.minecraft.world.entity.LivingEntity shooter) {
AntarchyGravityDirection direction = getGravityDirection(shooter);
if (!direction.isInverted()) {
return new Vec3(shooter.getX(), shooter.getEyeY() - 0.1D, shooter.getZ());
}
return shooter.getEyePosition().subtract(AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, 0.1D, 0.0D, direction));
}
} }
@@ -12,6 +12,7 @@ import net.minecraft.world.level.pathfinder.WalkNodeEvaluator;
public class GravityWalkNodeEvaluator extends WalkNodeEvaluator { public class GravityWalkNodeEvaluator extends WalkNodeEvaluator {
private static final Logger LOGGER = LoggerFactory.getLogger("Antarchy/Pathfinding"); private static final Logger LOGGER = LoggerFactory.getLogger("Antarchy/Pathfinding");
private static final int[] START_Y_SEARCH = {0, 1, -1, 2, -2, 3, -3, 4, -4};
private static final int[][] INVERTED_NEIGHBOR_OFFSETS = { private static final int[][] INVERTED_NEIGHBOR_OFFSETS = {
{1, 0, 0}, {1, 0, 0},
{-1, 0, 0}, {-1, 0, 0},
@@ -68,10 +69,10 @@ public class GravityWalkNodeEvaluator extends WalkNodeEvaluator {
int x = Mth.floor(this.mob.getX()); int x = Mth.floor(this.mob.getX());
int z = Mth.floor(this.mob.getZ()); int z = Mth.floor(this.mob.getZ());
int y = Mth.floor(this.mob.getY() + this.mob.getBbHeight()) - 1; int y = Mth.floor(this.mob.getY() + this.mob.getBbHeight()) - 1;
Node node = this.antarchy$findStartNode(x, y, z);
Node node = this.getNode(x, y, z); if (node == null) {
node.type = PathType.WALKABLE; return super.getStart();
node.costMalus = this.mob.getPathfindingMalus(PathType.WALKABLE); }
if (this.antarchy$loggedGetStart < 8) { if (this.antarchy$loggedGetStart < 8) {
LOGGER.debug( LOGGER.debug(
@@ -89,6 +90,43 @@ public class GravityWalkNodeEvaluator extends WalkNodeEvaluator {
return node; return node;
} }
private Node antarchy$findStartNode(int x, int y, int z) {
for (int dy : START_Y_SEARCH) {
int candidateY = y + dy;
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
Node node = this.antarchy$createStartNode(x + dx, candidateY, z + dz);
if (node != null) {
return node;
}
}
}
}
return null;
}
private Node antarchy$createStartNode(int x, int y, int z) {
if (!this.antarchy$hasCeilingSupport(x, y, z)) {
return null;
}
PathType type = this.getPathTypeOfMob(this.currentContext, x, y, z, this.mob);
float malus = this.mob.getPathfindingMalus(type);
if (malus < 0.0F || type == PathType.OPEN) {
return null;
}
Node node = this.getNode(x, y, z);
node.type = type;
node.costMalus = malus;
return node;
}
private boolean antarchy$hasCeilingSupport(int x, int y, int z) {
PathType ceilingType = this.getPathType(this.currentContext, x, y + 1, z);
return this.mob.getPathfindingMalus(ceilingType) < 0.0F;
}
@Override @Override
public PathType getPathTypeOfMob(PathfindingContext context, int x, int y, int z, Mob mob) { public PathType getPathTypeOfMob(PathfindingContext context, int x, int y, int z, Mob mob) {
if (!AntarchyGravityApi.isGravityInverted(mob)) { if (!AntarchyGravityApi.isGravityInverted(mob)) {
@@ -125,8 +125,10 @@ public final class PermanentPortalTeleporter {
} }
BlockPos horizontalPos = preferredPos.offset(xOff, 0, zOff); BlockPos horizontalPos = preferredPos.offset(xOff, 0, zOff);
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, horizontalPos)); if (destination.hasChunkAt(horizontalPos)) {
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, horizontalPos)); addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, horizontalPos));
addCandidate(candidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, horizontalPos));
}
for (int yOff = 0; yOff <= VERTICAL_SEARCH; yOff++) { for (int yOff = 0; yOff <= VERTICAL_SEARCH; yOff++) {
addCandidate(candidates, horizontalPos.above(yOff)); addCandidate(candidates, horizontalPos.above(yOff));
if (yOff > 0) { if (yOff > 0) {
@@ -184,13 +186,22 @@ public final class PermanentPortalTeleporter {
@Nullable @Nullable
private static Vec3 tryFindSafePosition(Entity entity, ServerLevel destination, BlockPos candidate) { private static Vec3 tryFindSafePosition(Entity entity, ServerLevel destination, BlockPos candidate) {
if (!isSafeDismountAreaLoaded(destination, candidate)) {
return null;
}
Vec3 safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate, true); Vec3 safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate, true);
if (safe != null && isValidArrivalPosition(destination, safe)) { if (safe != null && isValidArrivalPosition(destination, safe)) {
return safe; return safe;
} }
for (Direction direction : Direction.Plane.HORIZONTAL) { for (Direction direction : Direction.Plane.HORIZONTAL) {
safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate.relative(direction), true); BlockPos offsetCandidate = candidate.relative(direction);
if (!isSafeDismountAreaLoaded(destination, offsetCandidate)) {
continue;
}
safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, offsetCandidate, true);
if (safe != null && isValidArrivalPosition(destination, safe)) { if (safe != null && isValidArrivalPosition(destination, safe)) {
return safe; return safe;
} }
@@ -281,11 +292,30 @@ public final class PermanentPortalTeleporter {
BlockPos standPos = BlockPos.containing(safePos); BlockPos standPos = BlockPos.containing(safePos);
if (destination.dimension() == AntarchySettings.termiteDestinationDimension() if (destination.dimension() == AntarchySettings.termiteDestinationDimension()
|| destination.dimension() == AntarchySettings.redAntDestinationDimension()) { || destination.dimension() == AntarchySettings.redAntDestinationDimension()) {
if (!destination.hasChunkAt(standPos) || !destination.hasChunkAt(standPos.below())) {
return false;
}
return !destination.getBlockState(standPos.below()).is(net.minecraft.world.level.block.Blocks.BEDROCK); return !destination.getBlockState(standPos.below()).is(net.minecraft.world.level.block.Blocks.BEDROCK);
} }
return true; return true;
} }
private static boolean isSafeDismountAreaLoaded(ServerLevel destination, BlockPos center) {
if (!destination.hasChunkAt(center) || !destination.hasChunkAt(center.above()) || !destination.hasChunkAt(center.below())) {
return false;
}
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos offset = center.relative(direction);
if (!destination.hasChunkAt(offset) || !destination.hasChunkAt(offset.above()) || !destination.hasChunkAt(offset.below())) {
return false;
}
}
return true;
}
@Nullable @Nullable
private static Entity moveEntity(Entity entity, DimensionTransition transition) { private static Entity moveEntity(Entity entity, DimensionTransition transition) {
ServerLevel destination = transition.newLevel(); ServerLevel destination = transition.newLevel();
@@ -11,6 +11,8 @@ import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
* Mixin plugin for compat-gated mixins and optional deps. * Mixin plugin for compat-gated mixins and optional deps.
*/ */
public final class AntarchyMixinPlugin implements IMixinConfigPlugin { public final class AntarchyMixinPlugin implements IMixinConfigPlugin {
private static final AntarchyRangedAttackPatcher RANGED_ATTACK_PATCHER = new AntarchyRangedAttackPatcher();
@Override @Override
public void onLoad(String mixinPackage) { public void onLoad(String mixinPackage) {
Mixins.registerErrorHandlerClass(AntarchyMixinErrorHandler.class.getName()); Mixins.registerErrorHandlerClass(AntarchyMixinErrorHandler.class.getName());
@@ -51,5 +53,6 @@ public final class AntarchyMixinPlugin implements IMixinConfigPlugin {
@Override @Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
RANGED_ATTACK_PATCHER.patch(targetClass);
} }
} }
@@ -0,0 +1,227 @@
package com.craisinlord.antarchy.mixins;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
final class AntarchyRangedAttackPatcher {
private static final String RANGED_ATTACK_DESC = "(Lnet/minecraft/world/entity/LivingEntity;F)V";
private static final String LIVING_DESC = "(Lnet/minecraft/world/entity/LivingEntity;)D";
private static final String LIVING_D_DESC = "(Lnet/minecraft/world/entity/LivingEntity;D)D";
private static final String D_LIVING_DESC = "(DLnet/minecraft/world/entity/LivingEntity;)D";
private static final String DELTA_MOVEMENT_DESC = "(Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/phys/Vec3;";
private static final String API_OWNER = "com/craisinlord/antarchy/content/gravity/AntarchyGravityApi";
private enum AimMode {
BODY,
EYE
}
int patch(ClassNode classNode) {
int total = 0;
for (MethodNode method : classNode.methods) {
if (!RANGED_ATTACK_DESC.equals(method.desc)) {
continue;
}
if (!isPerformRangedAttack(method.name)) {
continue;
}
if (!hasRangedAimSqrt(method)) {
continue;
}
total += applyPatch(method);
}
return total;
}
private boolean isPerformRangedAttack(String methodName) {
return "performRangedAttack".equals(methodName)
|| "m_6504_".equals(methodName)
|| "m_31448_".equals(methodName)
|| "m_31457_".equals(methodName);
}
private boolean hasRangedAimSqrt(MethodNode method) {
for (AbstractInsnNode insn = method.instructions.getFirst(); insn != null; insn = insn.getNext()) {
if (insn instanceof MethodInsnNode call
&& call.getOpcode() == Opcodes.INVOKESTATIC
&& "java/lang/Math".equals(call.owner)
&& "sqrt".equals(call.name)
&& "(D)D".equals(call.desc)) {
return true;
}
}
return false;
}
private AimMode detectAimMode(MethodNode method) {
for (AbstractInsnNode insn = method.instructions.getFirst(); insn != null; insn = insn.getNext()) {
if (!(insn instanceof MethodInsnNode call)) {
continue;
}
int opcode = call.getOpcode();
if (opcode != Opcodes.INVOKEVIRTUAL && opcode != Opcodes.INVOKEINTERFACE) {
continue;
}
if (isGetYScaled(call)) {
return AimMode.BODY;
}
}
return AimMode.EYE;
}
private int applyPatch(MethodNode method) {
AimMode mode = detectAimMode(method);
int total = 0;
int ordX = 0;
int ordZ = 0;
int ordYScaled = 0;
int ordEyeY = 0;
InsnList list = method.instructions;
for (AbstractInsnNode cur = list.getFirst(); cur != null; cur = cur.getNext()) {
if (!(cur instanceof MethodInsnNode call)) {
continue;
}
int opcode = call.getOpcode();
if (opcode != Opcodes.INVOKEVIRTUAL && opcode != Opcodes.INVOKEINTERFACE) {
continue;
}
if (isGetX(call)) {
if (ordX++ != 0) {
continue;
}
list.set(cur, new MethodInsnNode(
Opcodes.INVOKESTATIC,
API_OWNER,
mode == AimMode.BODY ? "rangedBodyTargetX" : "rangedEyeTargetX",
LIVING_DESC,
false
));
total++;
continue;
}
if (isGetZ(call)) {
if (ordZ++ != 0) {
continue;
}
list.set(cur, new MethodInsnNode(
Opcodes.INVOKESTATIC,
API_OWNER,
mode == AimMode.BODY ? "rangedBodyTargetZ" : "rangedEyeTargetZ",
LIVING_DESC,
false
));
total++;
continue;
}
if (mode == AimMode.BODY && isGetYScaled(call)) {
if (ordYScaled++ != 0) {
continue;
}
list.set(cur, new MethodInsnNode(
Opcodes.INVOKESTATIC,
API_OWNER,
"rangedBodyTargetY",
LIVING_D_DESC,
false
));
total++;
continue;
}
if (mode == AimMode.EYE && isGetEyeY(call)) {
if (ordEyeY++ != 0) {
continue;
}
list.set(cur, new MethodInsnNode(
Opcodes.INVOKESTATIC,
API_OWNER,
"rangedEyeTargetY",
LIVING_DESC,
false
));
total++;
}
}
total += patchSqrtAndDelta(method);
return total;
}
private int patchSqrtAndDelta(MethodNode method) {
int total = 0;
InsnList list = method.instructions;
for (AbstractInsnNode cur = list.getFirst(); cur != null; cur = cur.getNext()) {
if (!(cur instanceof MethodInsnNode call)) {
continue;
}
if ((call.getOpcode() == Opcodes.INVOKEVIRTUAL || call.getOpcode() == Opcodes.INVOKEINTERFACE)
&& isGetDeltaMovement(call)
&& isAload1(previousSignificant(cur))) {
list.set(cur, new MethodInsnNode(
Opcodes.INVOKESTATIC,
API_OWNER,
"deltaMovement",
DELTA_MOVEMENT_DESC,
false
));
total++;
continue;
}
if (call.getOpcode() == Opcodes.INVOKESTATIC
&& "java/lang/Math".equals(call.owner)
&& "sqrt".equals(call.name)
&& "(D)D".equals(call.desc)) {
list.insertBefore(cur, new VarInsnNode(Opcodes.ALOAD, 1));
list.set(cur, new MethodInsnNode(
Opcodes.INVOKESTATIC,
API_OWNER,
"rangedSqrt",
D_LIVING_DESC,
false
));
total++;
}
}
return total;
}
private boolean isGetX(MethodInsnNode call) {
return "()D".equals(call.desc) && ("getX".equals(call.name) || "m_20185_".equals(call.name));
}
private boolean isGetZ(MethodInsnNode call) {
return "()D".equals(call.desc) && ("getZ".equals(call.name) || "m_20189_".equals(call.name));
}
private boolean isGetYScaled(MethodInsnNode call) {
return "(D)D".equals(call.desc) && ("getY".equals(call.name) || "m_20227_".equals(call.name));
}
private boolean isGetEyeY(MethodInsnNode call) {
return "()D".equals(call.desc) && ("getEyeY".equals(call.name) || "m_20188_".equals(call.name));
}
private boolean isGetDeltaMovement(MethodInsnNode call) {
return "()Lnet/minecraft/world/phys/Vec3;".equals(call.desc)
&& ("getDeltaMovement".equals(call.name) || "m_20184_".equals(call.name));
}
private boolean isAload1(AbstractInsnNode insn) {
return insn instanceof VarInsnNode varInsn && varInsn.getOpcode() == Opcodes.ALOAD && varInsn.var == 1;
}
private AbstractInsnNode previousSignificant(AbstractInsnNode node) {
AbstractInsnNode previous = node.getPrevious();
while (previous != null) {
int type = previous.getType();
if (type != AbstractInsnNode.LABEL && type != AbstractInsnNode.LINE) {
return previous;
}
previous = previous.getPrevious();
}
return null;
}
}
@@ -5,7 +5,7 @@ import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil; import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -21,10 +21,12 @@ public abstract class AbstractArrowGravityMixin {
@ModifyVariable(method = "tick", at = @At(value = "STORE"), ordinal = 0) @ModifyVariable(method = "tick", at = @At(value = "STORE"), ordinal = 0)
private Vec3 antarchy$fixArrowGravityDroop(Vec3 velocity) { private Vec3 antarchy$fixArrowGravityDroop(Vec3 velocity) {
AbstractArrow self = (AbstractArrow) (Object) this; AbstractArrow self = (AbstractArrow) (Object) this;
if (!AntarchySettings.invertProjectilesFromInvertedPlayers()) return velocity;
Entity owner = self.getOwner(); Entity owner = self.getOwner();
if (!(owner instanceof Player player)) return velocity; if (!(owner instanceof LivingEntity living)) return velocity;
AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(player); if (owner instanceof net.minecraft.world.entity.player.Player && !AntarchySettings.invertProjectilesFromInvertedPlayers()) {
return velocity;
}
AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(living);
if (!direction.isInverted()) return velocity; if (!direction.isInverted()) return velocity;
velocity = new Vec3(velocity.x, velocity.y + 0.05D, velocity.z); velocity = new Vec3(velocity.x, velocity.y + 0.05D, velocity.z);
velocity = AntarchyGravityRotationUtil.vecWorldToPlayer(velocity, direction); velocity = AntarchyGravityRotationUtil.vecWorldToPlayer(velocity, direction);
@@ -0,0 +1,68 @@
package com.craisinlord.antarchy.mixins.gravity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(BehaviorUtils.class)
public abstract class BehaviorUtilsGravityMixin {
@WrapOperation(
method = "throwItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;F)V",
at = @At(
value = "NEW",
target = "(Lnet/minecraft/world/level/Level;DDDLnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/item/ItemEntity;"
)
)
private static ItemEntity antarchy$fixThrownItemSpawn(
Level level,
double x,
double y,
double z,
ItemStack stack,
Operation<ItemEntity> original,
@Local float yOffset,
@Local LivingEntity entity
) {
if (!AntarchyGravityApi.isGravityInverted(entity)) {
return original.call(level, x, y, z, stack);
}
Vec3 eyeOffset = AntarchyGravityRotationUtil.getEyeOffset(entity, entity.getEyeHeight());
Vec3 offset = eyeOffset.normalize().scale(yOffset);
Vec3 itemPos = entity.position().add(eyeOffset).subtract(offset);
ItemEntity itemEntity = original.call(level, itemPos.x(), itemPos.y(), itemPos.z(), stack);
AntarchyGravityApi.setGravityDirection(itemEntity, AntarchyGravityApi.getGravityDirection(entity));
return itemEntity;
}
@WrapOperation(
method = "throwItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;F)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/item/ItemEntity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V"
)
)
private static void antarchy$fixThrownItemVelocity(
ItemEntity itemEntity,
Vec3 deltaMovement,
Operation<Void> original,
@Local LivingEntity entity
) {
if (!AntarchyGravityApi.isGravityInverted(entity)) {
original.call(itemEntity, deltaMovement);
return;
}
AntarchyGravityApi.setWorldVelocity(itemEntity, deltaMovement);
}
}
@@ -7,7 +7,6 @@ import com.craisinlord.antarchy.config.AntarchySettings;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CrossbowItem; import net.minecraft.world.item.CrossbowItem;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -25,7 +24,7 @@ public abstract class CrossbowItemGravityMixin {
at = @At(value = "INVOKE", at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/entity/LivingEntity;getX()D", ordinal = 0)) target = "Lnet/minecraft/world/entity/LivingEntity;getX()D", ordinal = 0))
private static double antarchy$fixCrossbowSpawnX(LivingEntity shooter, Operation<Double> original) { private static double antarchy$fixCrossbowSpawnX(LivingEntity shooter, Operation<Double> original) {
if (!AntarchySettings.invertProjectilesFromInvertedPlayers() || !(shooter instanceof Player)) return original.call(shooter); if (!antarchy$shouldFixProjectileSpawn(shooter)) return original.call(shooter);
AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(shooter); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(shooter);
if (!direction.isInverted()) return original.call(shooter); if (!direction.isInverted()) return original.call(shooter);
Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, BOLT_OFFSET, 0.0D, direction); Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, BOLT_OFFSET, 0.0D, direction);
@@ -36,7 +35,7 @@ public abstract class CrossbowItemGravityMixin {
at = @At(value = "INVOKE", at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/entity/LivingEntity;getEyeY()D", ordinal = 0)) target = "Lnet/minecraft/world/entity/LivingEntity;getEyeY()D", ordinal = 0))
private static double antarchy$fixCrossbowSpawnY(LivingEntity shooter, Operation<Double> original) { private static double antarchy$fixCrossbowSpawnY(LivingEntity shooter, Operation<Double> original) {
if (!AntarchySettings.invertProjectilesFromInvertedPlayers() || !(shooter instanceof Player)) return original.call(shooter); if (!antarchy$shouldFixProjectileSpawn(shooter)) return original.call(shooter);
AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(shooter); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(shooter);
if (!direction.isInverted()) return original.call(shooter); if (!direction.isInverted()) return original.call(shooter);
Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, BOLT_OFFSET, 0.0D, direction); Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, BOLT_OFFSET, 0.0D, direction);
@@ -47,10 +46,15 @@ public abstract class CrossbowItemGravityMixin {
at = @At(value = "INVOKE", at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/entity/LivingEntity;getZ()D", ordinal = 0)) target = "Lnet/minecraft/world/entity/LivingEntity;getZ()D", ordinal = 0))
private static double antarchy$fixCrossbowSpawnZ(LivingEntity shooter, Operation<Double> original) { private static double antarchy$fixCrossbowSpawnZ(LivingEntity shooter, Operation<Double> original) {
if (!AntarchySettings.invertProjectilesFromInvertedPlayers() || !(shooter instanceof Player)) return original.call(shooter); if (!antarchy$shouldFixProjectileSpawn(shooter)) return original.call(shooter);
AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(shooter); AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(shooter);
if (!direction.isInverted()) return original.call(shooter); if (!direction.isInverted()) return original.call(shooter);
Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, BOLT_OFFSET, 0.0D, direction); Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, BOLT_OFFSET, 0.0D, direction);
return shooter.getEyePosition().subtract(offset).z; return shooter.getEyePosition().subtract(offset).z;
} }
private static boolean antarchy$shouldFixProjectileSpawn(LivingEntity shooter) {
return !(shooter instanceof net.minecraft.world.entity.player.Player)
|| AntarchySettings.invertProjectilesFromInvertedPlayers();
}
} }
@@ -51,6 +51,18 @@ public abstract class EntityGravityFrameMixin {
cir.setReturnValue(entity.position().add(AntarchyGravityRotationUtil.getEyeOffset(entity, entity.getEyeHeight())).y); cir.setReturnValue(entity.position().add(AntarchyGravityRotationUtil.getEyeOffset(entity, entity.getEyeHeight())).y);
} }
@Inject(method = "getY(D)D", at = @At("HEAD"), cancellable = true)
private void antarchy$fixScaledY(double scale, CallbackInfoReturnable<Double> cir) {
Entity entity = (Entity) (Object) this;
AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(entity);
if (!direction.isInverted()) {
return;
}
cir.setReturnValue(entity.position().add(
AntarchyGravityRotationUtil.vecPlayerToWorld(0.0D, entity.getBbHeight() * scale, 0.0D, direction)
).y);
}
@Inject(method = "getEyePosition()Lnet/minecraft/world/phys/Vec3;", at = @At("HEAD"), cancellable = true) @Inject(method = "getEyePosition()Lnet/minecraft/world/phys/Vec3;", at = @At("HEAD"), cancellable = true)
private void antarchy$fixEyePosition(CallbackInfoReturnable<Vec3> cir) { private void antarchy$fixEyePosition(CallbackInfoReturnable<Vec3> cir) {
Entity entity = (Entity) (Object) this; Entity entity = (Entity) (Object) this;
@@ -21,16 +21,14 @@ public abstract class GroundPathNavigationMixin {
@Inject(method = "createPathFinder", at = @At("HEAD"), cancellable = true) @Inject(method = "createPathFinder", at = @At("HEAD"), cancellable = true)
private void antarchy$useGravityEvaluator(int maxVisitedNodes, CallbackInfoReturnable<PathFinder> cir) { private void antarchy$useGravityEvaluator(int maxVisitedNodes, CallbackInfoReturnable<PathFinder> cir) {
var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob(); var mob = ((PathNavigationAccessor) (Object) this).antarchy$getMob();
if (!AntarchyGravityApi.isGravityInverted(mob)) { if (AntarchyGravityApi.isGravityInverted(mob)) {
return; LOGGER.debug(
"[Path] swap evaluator mob={} maxVisitedNodes={}",
mob.getClass().getSimpleName(),
maxVisitedNodes
);
} }
LOGGER.debug(
"[Path] swap evaluator mob={} maxVisitedNodes={}",
mob.getClass().getSimpleName(),
maxVisitedNodes
);
cir.setReturnValue(new PathFinder(new GravityWalkNodeEvaluator(), maxVisitedNodes)); cir.setReturnValue(new PathFinder(new GravityWalkNodeEvaluator(), maxVisitedNodes));
} }
} }
@@ -46,6 +46,7 @@
"TigerEyeCamouflageMixin", "TigerEyeCamouflageMixin",
"TigerEyeVisibilityMixin", "TigerEyeVisibilityMixin",
"gravity.AbstractArrowGravityMixin", "gravity.AbstractArrowGravityMixin",
"gravity.BehaviorUtilsGravityMixin",
"gravity.BucketItemGravityMixin", "gravity.BucketItemGravityMixin",
"gravity.ChunkMapAccessor", "gravity.ChunkMapAccessor",
"gravity.CrossbowItemGravityMixin", "gravity.CrossbowItemGravityMixin",
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"discover_stampys_house": { "discover_stampys_house": {
"conditions": { "conditions": {
@@ -0,0 +1,36 @@
{
"parent": "antarchy:visit_cavaryn",
"criteria": {
"kill_horde_common": {
"conditions": {
"entity": {
"type": {
"tag": "antarchy:horde_common"
}
}
},
"trigger": "minecraft:player_killed_entity"
}
},
"display": {
"announce_to_chat": true,
"description": {
"text": "Kill one of Cavaryn's horde-common creatures"
},
"frame": "task",
"icon": {
"count": 1,
"id": "antarchy:creeping_horror_spawn_egg"
},
"show_toast": true,
"title": {
"text": "Anger the Hive Mind"
}
},
"requirements": [
[
"kill_horde_common"
]
],
"sends_telemetry_event": true
}
@@ -0,0 +1,58 @@
{
"parent": "antarchy:visit_elythia",
"criteria": {
"kill_basilisk": {
"conditions": {
"entity": {
"type": "antarchy:basilisk"
}
},
"trigger": "minecraft:player_killed_entity"
},
"kill_toreterror": {
"conditions": {
"entity": {
"type": "antarchy:toreterror"
}
},
"trigger": "minecraft:player_killed_entity"
},
"obtain_brutalfly_elytra": {
"conditions": {
"items": [
{
"items": "antarchy:brutalfly_elytra"
}
]
},
"trigger": "minecraft:inventory_changed"
}
},
"display": {
"announce_to_chat": true,
"description": {
"text": "Defeat Basilisk, Toreterror, and Brutalfly to claim mastery of Elythia"
},
"frame": "challenge",
"icon": {
"count": 1,
"id": "antarchy:brutalfly_elytra"
},
"show_toast": true,
"title": {
"text": "Ant-arch of Elythia"
}
},
"requirements": [
[
"kill_basilisk"
],
[
"kill_toreterror"
],
[
"obtain_brutalfly_elytra"
]
],
"sends_telemetry_event": true
}
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"impossible": { "impossible": {
"trigger": "minecraft:impossible" "trigger": "minecraft:impossible"
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:anger_the_hive_mind",
"criteria": { "criteria": {
"tame_hercules_beetle": { "tame_hercules_beetle": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:herculean_task",
"criteria": { "criteria": {
"obtain_attitude_adjuster": { "obtain_attitude_adjuster": {
"conditions": { "conditions": {
@@ -24,7 +24,7 @@
}, },
"show_toast": true, "show_toast": true,
"title": { "title": {
"translate": "advancements.antarchy.behavioral_correction.title" "text": "Ant-ger Management"
} }
}, },
"requirements": [ "requirements": [
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"brutalfly": { "brutalfly": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:anger_the_hive_mind",
"criteria": { "criteria": {
"eat_cooked_bug_meat": { "eat_cooked_bug_meat": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"kill_alpha_mantis": { "kill_alpha_mantis": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"discover_ruined_arena": { "discover_ruined_arena": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"discover_ruined_prison": { "discover_ruined_prison": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"impossible": { "impossible": {
"trigger": "minecraft:impossible" "trigger": "minecraft:impossible"
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_thoraxis",
"criteria": { "criteria": {
"kill_bed_bug": { "kill_bed_bug": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"impossible": { "impossible": {
"trigger": "minecraft:impossible" "trigger": "minecraft:impossible"
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"discover_castle": { "discover_castle": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_thoraxis",
"criteria": { "criteria": {
"craft_gravity_gun": { "craft_gravity_gun": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:anger_the_hive_mind",
"criteria": { "criteria": {
"kill_hercules_beetle": { "kill_hercules_beetle": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_thoraxis",
"criteria": { "criteria": {
"impossible": { "impossible": {
"trigger": "minecraft:impossible" "trigger": "minecraft:impossible"
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"impossible": { "impossible": {
"trigger": "minecraft:impossible" "trigger": "minecraft:impossible"
@@ -0,0 +1,61 @@
{
"parent": "antarchy:visit_thoraxis",
"criteria": {
"kill_emperor_scorpion": {
"conditions": {
"entity": {
"type": "antarchy:emperor_scorpion"
}
},
"trigger": "minecraft:player_killed_entity"
},
"kill_lucid": {
"conditions": {
"entity": {
"type": "antarchy:lucid"
}
},
"trigger": "minecraft:player_killed_entity"
},
"kill_nightmare": {
"conditions": {
"entity": {
"type": "antarchy:nightmare"
}
},
"trigger": "minecraft:player_killed_entity"
}
},
"display": {
"announce_to_chat": true,
"description": {
"text": "Defeat Emperor Scorpion, Lucid, and Nightmare"
},
"frame": "challenge",
"icon": {
"count": 1,
"id": "minecraft:potion",
"components": {
"minecraft:potion_contents": {
"potion": "antarchy:dread"
}
}
},
"show_toast": true,
"title": {
"text": "I Am the Nightmare"
}
},
"requirements": [
[
"kill_emperor_scorpion"
],
[
"kill_lucid"
],
[
"kill_nightmare"
]
],
"sends_telemetry_event": true
}
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_thoraxis",
"criteria": { "criteria": {
"become_inverted": { "become_inverted": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"kill_toreterror": { "kill_toreterror": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_thoraxis",
"criteria": { "criteria": {
"kill_lucid": { "kill_lucid": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:anger_the_hive_mind",
"criteria": { "criteria": {
"kill_molevore": { "kill_molevore": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:sting_operation",
"criteria": { "criteria": {
"now_watch_me_whip": { "now_watch_me_whip": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"kill_cloud_shark": { "kill_cloud_shark": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:shark_weak",
"criteria": { "criteria": {
"eat_soup": { "eat_soup": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"impossible": { "impossible": {
"trigger": "minecraft:impossible" "trigger": "minecraft:impossible"
@@ -0,0 +1,34 @@
{
"parent": "antarchy:visit_thoraxis",
"criteria": {
"kill_emperor_scorpion": {
"conditions": {
"entity": {
"type": "antarchy:emperor_scorpion"
}
},
"trigger": "minecraft:player_killed_entity"
}
},
"display": {
"announce_to_chat": true,
"description": {
"text": "Defeat the Emperor Scorpion"
},
"frame": "challenge",
"icon": {
"count": 1,
"id": "antarchy:emperor_scorpion_spawn_egg"
},
"show_toast": true,
"title": {
"text": "Sting Operation"
}
},
"requirements": [
[
"kill_emperor_scorpion"
]
],
"sends_telemetry_event": true
}
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"kill_basilisk": { "kill_basilisk": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_thoraxis",
"criteria": { "criteria": {
"kill_nightmare": { "kill_nightmare": {
"conditions": { "conditions": {
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_elythia",
"criteria": { "criteria": {
"discover_lab": { "discover_lab": {
"conditions": { "conditions": {
@@ -1,5 +1,4 @@
{ {
"parent": "minecraft:adventure/root",
"criteria": { "criteria": {
"entered_cavaryn": { "entered_cavaryn": {
"conditions": { "conditions": {
@@ -10,6 +9,7 @@
}, },
"display": { "display": {
"announce_to_chat": true, "announce_to_chat": true,
"background": "antarchy:block/myrmite",
"description": { "description": {
"translate": "advancements.antarchy.visit_cavaryn.description" "translate": "advancements.antarchy.visit_cavaryn.description"
}, },
@@ -1,5 +1,4 @@
{ {
"parent": "minecraft:adventure/root",
"criteria": { "criteria": {
"entered_elythia": { "entered_elythia": {
"conditions": { "conditions": {
@@ -10,6 +9,7 @@
}, },
"display": { "display": {
"announce_to_chat": true, "announce_to_chat": true,
"background": "antarchy:block/ouranwood/mossy_ouranwood_log",
"description": { "description": {
"translate": "advancements.antarchy.visit_elythia.description" "translate": "advancements.antarchy.visit_elythia.description"
}, },
@@ -1,5 +1,4 @@
{ {
"parent": "minecraft:adventure/root",
"criteria": { "criteria": {
"entered_thoraxis": { "entered_thoraxis": {
"conditions": { "conditions": {
@@ -10,6 +9,7 @@
}, },
"display": { "display": {
"announce_to_chat": true, "announce_to_chat": true,
"background": "antarchy:block/nyxite",
"description": { "description": {
"translate": "advancements.antarchy.visit_thoraxis.description" "translate": "advancements.antarchy.visit_thoraxis.description"
}, },
@@ -1,5 +1,5 @@
{ {
"parent": "minecraft:adventure/root", "parent": "antarchy:visit_thoraxis",
"criteria": { "criteria": {
"become_stinky": { "become_stinky": {
"conditions": { "conditions": {
@@ -2,9 +2,7 @@
"replace": false, "replace": false,
"values": [ "values": [
"minecraft:ender_dragon", "minecraft:ender_dragon",
"antarchy:emperor_scorpion",
"antarchy:kraken", "antarchy:kraken",
"antarchy:nightmare",
"antarchy:reverie", "antarchy:reverie",
"antarchy:lucid", "antarchy:lucid",
"antarchy:triffid" "antarchy:triffid"