finish ant portals
optional flint and steel functionality dorrie
This commit is contained in:
1 parent
4e67661448
commit
f23cf63f4f
15 files changed
+598
-53
No files matched your search
@@ -448,6 +448,7 @@ public final class AntarchySettings {
|
||||
private static int fallenKingCrownArmorValue = 2;
|
||||
private static double fallenKingCrownArmorToughness = 0.0D;
|
||||
private static boolean permanentPortalsEnabled = true;
|
||||
private static boolean permanentPortalsFlintAndSteelEnabled = false;
|
||||
private static boolean elythiaPortalEnabled = true;
|
||||
private static boolean thoraxisPortalEnabled = true;
|
||||
private static boolean cavarynPortalEnabled = true;
|
||||
@@ -965,6 +966,10 @@ public final class AntarchySettings {
|
||||
permanentPortalsEnabled = value;
|
||||
}
|
||||
|
||||
public static void setPermanentPortalsFlintAndSteelEnabled(boolean value) {
|
||||
permanentPortalsFlintAndSteelEnabled = value;
|
||||
}
|
||||
|
||||
public static void setElythiaPortalEnabled(boolean value) {
|
||||
elythiaPortalEnabled = value;
|
||||
}
|
||||
@@ -977,6 +982,12 @@ public final class AntarchySettings {
|
||||
cavarynPortalEnabled = value;
|
||||
}
|
||||
|
||||
public static boolean permanentPortalsEnabled() { return permanentPortalsEnabled; }
|
||||
public static boolean permanentPortalsFlintAndSteelEnabled() { return permanentPortalsFlintAndSteelEnabled; }
|
||||
public static boolean elythiaPortalEnabled() { return elythiaPortalEnabled; }
|
||||
public static boolean thoraxisPortalEnabled() { return thoraxisPortalEnabled; }
|
||||
public static boolean cavarynPortalEnabled() { return cavarynPortalEnabled; }
|
||||
|
||||
public static void setBrownAntRequiresReagent(boolean value) {
|
||||
brownAntRequiresReagent = value;
|
||||
}
|
||||
@@ -2454,11 +2465,6 @@ public final class AntarchySettings {
|
||||
public static double fallenKingCrownArmorToughness() { return fallenKingCrownArmorToughness; }
|
||||
public static void setFallenKingCrownArmorToughness(double value) { fallenKingCrownArmorToughness = value; }
|
||||
|
||||
public static boolean permanentPortalsEnabled() { return permanentPortalsEnabled; }
|
||||
public static boolean elythiaPortalEnabled() { return elythiaPortalEnabled; }
|
||||
public static boolean thoraxisPortalEnabled() { return thoraxisPortalEnabled; }
|
||||
public static boolean cavarynPortalEnabled() { return cavarynPortalEnabled; }
|
||||
|
||||
public static boolean elythiaFireflyParticlesEnabled() { return elythiaFireflyParticlesEnabled; }
|
||||
public static void setElythiaFireflyParticlesEnabled(boolean value) { elythiaFireflyParticlesEnabled = value; }
|
||||
|
||||
|
||||
+19
-2
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.craisinlord.antarchy.content.portal.PermanentPortalManager;
|
||||
import com.craisinlord.antarchy.content.portal.PermanentPortalType;
|
||||
import com.craisinlord.antarchy.content.portal.PermanentPortalTeleporter;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -11,6 +12,7 @@ import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.portal.DimensionTransition;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -27,7 +29,7 @@ import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public final class AntDimensionPortalBlock extends Block {
|
||||
public final class AntDimensionPortalBlock extends Block implements net.minecraft.world.level.block.Portal {
|
||||
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.HORIZONTAL_AXIS;
|
||||
private static final VoxelShape X_SHAPE = Block.box(0.0D, 0.0D, 6.0D, 16.0D, 16.0D, 10.0D);
|
||||
private static final VoxelShape Z_SHAPE = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 16.0D, 16.0D);
|
||||
@@ -85,10 +87,25 @@ public final class AntDimensionPortalBlock extends Block {
|
||||
@Override
|
||||
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
|
||||
if (!level.isClientSide()) {
|
||||
PermanentPortalManager.handleEntityInsidePortal(entity, this.type);
|
||||
entity.setAsInsidePortal(this, pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.level.block.Portal.Transition getLocalTransition() {
|
||||
return net.minecraft.world.level.block.Portal.Transition.CONFUSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPortalTransitionTime(ServerLevel level, Entity entity) {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionTransition getPortalDestination(ServerLevel level, Entity entity, BlockPos pos) {
|
||||
return PermanentPortalTeleporter.createTransition(level, entity, pos, this.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.entity;
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
@@ -12,6 +13,8 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
@@ -26,8 +29,6 @@ import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.control.MoveControl;
|
||||
import net.minecraft.world.entity.ai.control.SmoothSwimmingLookControl;
|
||||
import net.minecraft.world.entity.ai.control.SmoothSwimmingMoveControl;
|
||||
import net.minecraft.world.entity.ai.goal.BreathAirGoal;
|
||||
import net.minecraft.world.entity.ai.goal.FloatGoal;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
|
||||
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
|
||||
@@ -67,11 +68,11 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
SynchedEntityData.defineId(DorrieEntity.class, EntityDataSerializers.INT);
|
||||
|
||||
private static final int MAX_CHARGE_TICKS = 40;
|
||||
private static final float WATER_RIDE_SPEED = 1.26F;
|
||||
private static final float LAND_BEACH_SPEED = 0.04F;
|
||||
private static final float WATER_RIDE_SPEED = 1.84F;
|
||||
private static final float LAND_BEACH_SPEED = 0.10F;
|
||||
private static final int QUIRK_DURATION_TICKS = 65;
|
||||
private static final int MIN_QUIRK_COOLDOWN_TICKS = 180;
|
||||
private static final int MAX_QUIRK_COOLDOWN_TICKS = 320;
|
||||
private static final int MIN_QUIRK_COOLDOWN_TICKS = 140;
|
||||
private static final int MAX_QUIRK_COOLDOWN_TICKS = 260;
|
||||
private static final double MOVING_ANIM_THRESHOLD_SQ = 0.0025D;
|
||||
|
||||
private static final RawAnimation IDLE_GROUND_ANIM = RawAnimation.begin().thenLoop("idle_ground");
|
||||
@@ -127,20 +128,19 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(1, new BreathAirGoal(this));
|
||||
this.goalSelector.addGoal(2, new TryFindWaterGoal(this));
|
||||
this.goalSelector.addGoal(3, new HuntCheepGoal(this));
|
||||
this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0D, 10));
|
||||
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.45D, 60));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
|
||||
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
|
||||
this.goalSelector.addGoal(1, new HuntCheepGoal(this));
|
||||
this.goalSelector.addGoal(2, new DolphinSwimGoal());
|
||||
this.goalSelector.addGoal(3, new RandomSwimmingGoal(this, 1.35D, 8));
|
||||
this.goalSelector.addGoal(4, new WaterAvoidingRandomStrollGoal(this, 0.72D, 40));
|
||||
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return Mob.createMobAttributes()
|
||||
.add(Attributes.MAX_HEALTH, AntarchySettings.dorrieHealth())
|
||||
.add(Attributes.MOVEMENT_SPEED, 1.0D)
|
||||
.add(Attributes.MOVEMENT_SPEED, 1.15D)
|
||||
.add(Attributes.FOLLOW_RANGE, 16.0D)
|
||||
.add(Attributes.ATTACK_DAMAGE, 4.0D);
|
||||
}
|
||||
@@ -255,13 +255,20 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
protected Vec3 getRiddenInput(Player player, Vec3 travelVector) {
|
||||
float forward = player.zza;
|
||||
float strafe = player.xxa * 0.5F;
|
||||
return new Vec3(strafe, 0, forward);
|
||||
float pitch = Mth.clamp(player.getXRot(), -60.0F, 60.0F);
|
||||
double vertical = 0.0D;
|
||||
if (player.zza > 0.02F) {
|
||||
vertical = -pitch / 45.0D;
|
||||
} else if (Math.abs(pitch) > 10.0F) {
|
||||
vertical = -pitch / 60.0D;
|
||||
}
|
||||
return new Vec3(strafe, Mth.clamp(vertical, -1.0D, 1.0D), forward);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getRiddenSpeed(Player player) {
|
||||
float speed = (this.isInWater() || this.isInLava())
|
||||
? WATER_RIDE_SPEED * (1.0F + Math.min(this.swimForwardTicks, 60) * 0.025F)
|
||||
? WATER_RIDE_SPEED * (1.0F + Math.min(this.swimForwardTicks, 60) * 0.03F)
|
||||
: LAND_BEACH_SPEED;
|
||||
return (float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * speed;
|
||||
}
|
||||
@@ -270,6 +277,7 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
public void tick() {
|
||||
super.tick();
|
||||
this.updateNavigationMode();
|
||||
this.setNoGravity(this.isInWater() || this.isInLava());
|
||||
|
||||
if (this.getControllingPassenger() instanceof Player player) {
|
||||
this.setYRot(player.getYRot());
|
||||
@@ -315,13 +323,6 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
this.tickQuirkAnimation();
|
||||
}
|
||||
|
||||
if (this.isInWater() && !isLeaping) {
|
||||
Vec3 mov = this.getDeltaMovement();
|
||||
double push = this.isUnderWater() ? 0.07D : 0.015D;
|
||||
double cappedY = this.isUnderWater() ? 0.3D : 0.05D;
|
||||
this.setDeltaMovement(mov.x, Math.min(mov.y + push, cappedY), mov.z);
|
||||
}
|
||||
|
||||
if (landAnimTicks > 0) {
|
||||
landAnimTicks--;
|
||||
}
|
||||
@@ -342,17 +343,57 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void baseTick() {
|
||||
super.baseTick();
|
||||
if (this.isInWater() || this.isInLava()) {
|
||||
this.setAirSupply(this.getMaxAirSupply());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void travel(Vec3 travelVector) {
|
||||
if (this.getControllingPassenger() instanceof Player rider && this.isVehicle()) {
|
||||
this.setYRot(rider.getYRot());
|
||||
this.yRotO = this.getYRot();
|
||||
this.yBodyRot = this.getYRot();
|
||||
this.yHeadRot = this.getYRot();
|
||||
|
||||
Vec3 riddenInput = this.getRiddenInput(rider, travelVector);
|
||||
this.setSpeed(this.getRiddenSpeed(rider));
|
||||
|
||||
if (this.isInWater() || this.isInLava()) {
|
||||
this.moveRelative(this.getSpeed(), new Vec3(riddenInput.x, 0.0D, riddenInput.z));
|
||||
Vec3 motion = this.getDeltaMovement();
|
||||
double vertical = this.isLeaping ? 0.0D : riddenInput.y * 0.09D;
|
||||
this.setDeltaMovement(
|
||||
motion.x * 0.92D,
|
||||
motion.y * 0.90D + vertical,
|
||||
motion.z * 0.92D
|
||||
);
|
||||
this.move(net.minecraft.world.entity.MoverType.SELF, this.getDeltaMovement());
|
||||
return;
|
||||
}
|
||||
|
||||
this.moveRelative(this.getSpeed(), new Vec3(riddenInput.x, 0.0D, riddenInput.z));
|
||||
this.move(net.minecraft.world.entity.MoverType.SELF, this.getDeltaMovement());
|
||||
return;
|
||||
}
|
||||
|
||||
super.travel(travelVector);
|
||||
}
|
||||
|
||||
public void releaseJump() {
|
||||
if (!this.level().isClientSide && isCharging) {
|
||||
float power = chargeTicks / (float) MAX_CHARGE_TICKS;
|
||||
if (power > 0.05F) {
|
||||
Vec3 look = this.getLookAngle();
|
||||
Vec3 current = this.getDeltaMovement();
|
||||
double forwardAdd = power * 0.5D;
|
||||
double vertical = 0.55D + power * 0.9D;
|
||||
double forwardAdd = 0.18D + power * 0.42D;
|
||||
double vertical = 0.28D + power * 0.62D;
|
||||
this.setDeltaMovement(
|
||||
current.x + look.x * forwardAdd,
|
||||
vertical,
|
||||
current.y + vertical,
|
||||
current.z + look.z * forwardAdd
|
||||
);
|
||||
this.hasImpulse = true;
|
||||
@@ -517,6 +558,7 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
|
||||
private boolean canUseQuirkAnimation() {
|
||||
return this.isInWater()
|
||||
&& !this.isUnderWater()
|
||||
&& this.getControllingPassenger() == null
|
||||
&& !this.isLeaping
|
||||
&& this.landAnimTicks <= 0
|
||||
@@ -524,6 +566,72 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
&& !this.isMovingForAnimation(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Vec3 findWaterSurfaceTarget(double radius, int minYDelta, int maxYDelta) {
|
||||
int baseY = Mth.floor(this.getY());
|
||||
for (int attempt = 0; attempt < 12; attempt++) {
|
||||
double offsetX = (this.random.nextDouble() - 0.5D) * radius * 2.0D;
|
||||
double offsetZ = (this.random.nextDouble() - 0.5D) * radius * 2.0D;
|
||||
int x = Mth.floor(this.getX() + offsetX);
|
||||
int z = Mth.floor(this.getZ() + offsetZ);
|
||||
Vec3 target = this.findWaterSurfaceTarget(x, z, baseY + minYDelta, baseY + maxYDelta);
|
||||
if (target != null) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
return this.findWaterSurfaceTarget(Mth.floor(this.getX()), Mth.floor(this.getZ()),
|
||||
baseY + minYDelta, baseY + maxYDelta);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Vec3 findWaterSurfaceTarget(int x, int z, int minY, int maxY) {
|
||||
int top = Math.min(maxY, this.level().getMaxBuildHeight() - 2);
|
||||
int bottom = Math.max(minY, this.level().getMinBuildHeight() + 1);
|
||||
for (int y = top; y >= bottom; y--) {
|
||||
BlockPos pos = BlockPos.containing(x, y, z);
|
||||
if (!this.isWaterAt(pos) || this.isWaterAt(pos.above())) {
|
||||
continue;
|
||||
}
|
||||
return new Vec3(x + 0.5D, y + 0.85D, z + 0.5D);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Vec3 findSubmergedTarget(double radius, int minYDelta, int maxYDelta) {
|
||||
int baseY = Mth.floor(this.getY());
|
||||
for (int attempt = 0; attempt < 16; attempt++) {
|
||||
double offsetX = (this.random.nextDouble() - 0.5D) * radius * 2.0D;
|
||||
double offsetZ = (this.random.nextDouble() - 0.5D) * radius * 2.0D;
|
||||
int x = Mth.floor(this.getX() + offsetX);
|
||||
int z = Mth.floor(this.getZ() + offsetZ);
|
||||
Vec3 target = this.findSubmergedTarget(x, z, baseY + minYDelta, baseY + maxYDelta);
|
||||
if (target != null) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
return this.findSubmergedTarget(Mth.floor(this.getX()), Mth.floor(this.getZ()),
|
||||
baseY + minYDelta, baseY + maxYDelta);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Vec3 findSubmergedTarget(int x, int z, int minY, int maxY) {
|
||||
int top = Math.min(maxY, this.level().getMaxBuildHeight() - 2);
|
||||
int bottom = Math.max(minY, this.level().getMinBuildHeight() + 1);
|
||||
for (int y = top; y >= bottom; y--) {
|
||||
BlockPos pos = BlockPos.containing(x, y, z);
|
||||
if (!this.isWaterAt(pos) || !this.isWaterAt(pos.below())) {
|
||||
continue;
|
||||
}
|
||||
return new Vec3(x + 0.5D, y + 0.3D, z + 0.5D);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isWaterAt(BlockPos pos) {
|
||||
return this.level().getFluidState(pos).is(FluidTags.WATER);
|
||||
}
|
||||
|
||||
private boolean isMovingForAnimation(@Nullable AnimationState<DorrieEntity> state) {
|
||||
if (state != null && state.isMoving()) {
|
||||
return true;
|
||||
@@ -535,6 +643,147 @@ public class DorrieEntity extends Animal implements GeoEntity {
|
||||
|| this.getNavigation().isInProgress();
|
||||
}
|
||||
|
||||
private class DolphinSwimGoal extends Goal {
|
||||
private static final int COOLDOWN_MIN_TICKS = 120;
|
||||
private static final int COOLDOWN_MAX_TICKS = 240;
|
||||
private static final int DIVE_MIN_TICKS = 50;
|
||||
private static final int DIVE_MAX_TICKS = 110;
|
||||
private static final int ROAM_MIN_TICKS = 70;
|
||||
private static final int ROAM_MAX_TICKS = 140;
|
||||
private static final int TARGET_REFRESH_TICKS = 20;
|
||||
private static final double AQUATIC_SPEED = 1.15D;
|
||||
private static final double SEARCH_RADIUS = 12.0D;
|
||||
|
||||
@Nullable
|
||||
private Vec3 targetPos;
|
||||
private int phaseTicks;
|
||||
private int targetRefreshTicks;
|
||||
private int cooldownTicks;
|
||||
private Phase phase = Phase.ROAM;
|
||||
|
||||
DolphinSwimGoal() {
|
||||
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
if (DorrieEntity.this.level().isClientSide
|
||||
|| DorrieEntity.this.isVehicle()
|
||||
|| DorrieEntity.this.getControllingPassenger() != null
|
||||
|| DorrieEntity.this.isCharging
|
||||
|| DorrieEntity.this.isLeaping
|
||||
|| DorrieEntity.this.landAnimTicks > 0
|
||||
|| DorrieEntity.this.getTarget() != null) {
|
||||
return false;
|
||||
}
|
||||
if (!DorrieEntity.this.isInWater()) {
|
||||
return false;
|
||||
}
|
||||
if (this.cooldownTicks > 0) {
|
||||
this.cooldownTicks--;
|
||||
return false;
|
||||
}
|
||||
if (DorrieEntity.this.random.nextInt(6) != 0) {
|
||||
return false;
|
||||
}
|
||||
this.targetPos = DorrieEntity.this.isUnderWater()
|
||||
? DorrieEntity.this.findSubmergedTarget(SEARCH_RADIUS, -5, 2)
|
||||
: DorrieEntity.this.findSubmergedTarget(SEARCH_RADIUS, -5, 1);
|
||||
return this.targetPos != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return this.targetPos != null
|
||||
&& !DorrieEntity.this.isVehicle()
|
||||
&& DorrieEntity.this.getControllingPassenger() == null
|
||||
&& DorrieEntity.this.isAlive()
|
||||
&& DorrieEntity.this.isInWater();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.phase = DorrieEntity.this.isUnderWater() ? Phase.ROAM : Phase.DIVE;
|
||||
this.phaseTicks = this.phase == Phase.DIVE
|
||||
? DorrieEntity.this.random.nextInt(DIVE_MAX_TICKS - DIVE_MIN_TICKS + 1) + DIVE_MIN_TICKS
|
||||
: DorrieEntity.this.random.nextInt(ROAM_MAX_TICKS - ROAM_MIN_TICKS + 1) + ROAM_MIN_TICKS;
|
||||
this.targetRefreshTicks = 0;
|
||||
if (this.targetPos == null) {
|
||||
this.targetPos = this.pickTargetForPhase();
|
||||
}
|
||||
if (this.targetPos == null) {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.targetPos = null;
|
||||
this.phaseTicks = 0;
|
||||
this.targetRefreshTicks = 0;
|
||||
DorrieEntity.this.getNavigation().stop();
|
||||
this.cooldownTicks = DorrieEntity.this.random.nextInt(COOLDOWN_MAX_TICKS - COOLDOWN_MIN_TICKS + 1) + COOLDOWN_MIN_TICKS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.targetPos == null) {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.phaseTicks > 0) {
|
||||
this.phaseTicks--;
|
||||
}
|
||||
if (this.targetRefreshTicks > 0) {
|
||||
this.targetRefreshTicks--;
|
||||
}
|
||||
|
||||
if (this.phase == Phase.DIVE && this.phaseTicks <= 0) {
|
||||
this.phase = Phase.ROAM;
|
||||
this.phaseTicks = DorrieEntity.this.random.nextInt(ROAM_MAX_TICKS - ROAM_MIN_TICKS + 1) + ROAM_MIN_TICKS;
|
||||
this.targetPos = this.pickTargetForPhase();
|
||||
} else if (this.phase == Phase.ROAM && this.phaseTicks <= 0) {
|
||||
this.phase = Phase.SURFACE;
|
||||
this.phaseTicks = DorrieEntity.this.random.nextInt(DIVE_MAX_TICKS - DIVE_MIN_TICKS + 1) + DIVE_MIN_TICKS;
|
||||
this.targetPos = DorrieEntity.this.findWaterSurfaceTarget(SEARCH_RADIUS, -1, 4);
|
||||
} else if (this.phase == Phase.SURFACE && this.phaseTicks <= 0 && this.isCloseToTarget()) {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.targetPos == null || this.targetRefreshTicks <= 0 || this.isCloseToTarget()) {
|
||||
this.targetPos = this.pickTargetForPhase();
|
||||
this.targetRefreshTicks = TARGET_REFRESH_TICKS;
|
||||
}
|
||||
|
||||
if (this.targetPos == null) {
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
DorrieEntity.this.getLookControl().setLookAt(this.targetPos.x, this.targetPos.y, this.targetPos.z, 25.0F, 20.0F);
|
||||
DorrieEntity.this.getNavigation().moveTo(this.targetPos.x, this.targetPos.y, this.targetPos.z, AQUATIC_SPEED);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Vec3 pickTargetForPhase() {
|
||||
return this.phase == Phase.SURFACE
|
||||
? DorrieEntity.this.findWaterSurfaceTarget(SEARCH_RADIUS, -1, 4)
|
||||
: DorrieEntity.this.findSubmergedTarget(SEARCH_RADIUS, -5, 2);
|
||||
}
|
||||
|
||||
private boolean isCloseToTarget() {
|
||||
return this.targetPos != null && DorrieEntity.this.distanceToSqr(this.targetPos) < 4.0D;
|
||||
}
|
||||
|
||||
private enum Phase {
|
||||
DIVE,
|
||||
ROAM,
|
||||
SURFACE
|
||||
}
|
||||
}
|
||||
|
||||
private static class HuntCheepGoal extends Goal {
|
||||
private static final int COOLDOWN_TICKS = 600;
|
||||
private static final double HUNT_RANGE = 16.0D;
|
||||
|
||||
+9
@@ -108,6 +108,15 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity {
|
||||
.add(Attributes.FOLLOW_RANGE, AntarchySettings.emperorScorpionFollowRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fireImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lavaHurt() {
|
||||
}
|
||||
|
||||
public static boolean canSpawn(EntityType<EmperorScorpionEntity> entityType, ServerLevelAccessor level,
|
||||
MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
|
||||
if (spawnReason == MobSpawnType.SPAWN_EGG
|
||||
|
||||
+22
-5
@@ -11,6 +11,7 @@ import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -34,10 +35,19 @@ public final class PermanentPortalManager {
|
||||
return;
|
||||
}
|
||||
|
||||
shape.fill(serverLevel);
|
||||
Vec3 center = shape.center();
|
||||
serverLevel.playSound(null, center.x, center.y, center.z, SoundEvents.END_PORTAL_SPAWN, SoundSource.BLOCKS, 0.9F, 0.9F);
|
||||
spawnActivationParticles(serverLevel, type, center);
|
||||
activatePortal(serverLevel, type, shape, SoundEvents.END_PORTAL_SPAWN, 0.9F, 0.9F);
|
||||
}
|
||||
|
||||
public static boolean tryIgnitePortal(Level level, BlockPos triggerPos, PermanentPortalType type) {
|
||||
PermanentPortalShape shape = PermanentPortalShape.findInactiveNear(level, triggerPos, type);
|
||||
if (shape == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
activatePortal(serverLevel, type, shape, SoundEvents.FLINTANDSTEEL_USE, 0.9F, 1.0F);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void handleEntityInsidePortal(Entity entity, PermanentPortalType type) {
|
||||
@@ -67,7 +77,7 @@ public final class PermanentPortalManager {
|
||||
WARMUPS.remove(entity.getUUID());
|
||||
PermanentPortalTeleporter.teleport(entity, type);
|
||||
if (entity.level() instanceof ServerLevel currentLevel) {
|
||||
currentLevel.playSound(null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.8F, 1.0F);
|
||||
currentLevel.playSound(null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.PORTAL_TRAVEL, SoundSource.PLAYERS, 0.8F, 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +131,13 @@ public final class PermanentPortalManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static void activatePortal(ServerLevel level, PermanentPortalType type, PermanentPortalShape shape, net.minecraft.sounds.SoundEvent sound, float volume, float pitch) {
|
||||
shape.fill(level);
|
||||
Vec3 center = shape.center();
|
||||
level.playSound(null, center.x, center.y, center.z, sound, SoundSource.BLOCKS, volume, pitch);
|
||||
spawnActivationParticles(level, type, center);
|
||||
}
|
||||
|
||||
private static final class PortalWarmup {
|
||||
private PermanentPortalType type;
|
||||
private long lastSeenTick;
|
||||
|
||||
+86
@@ -8,6 +8,7 @@ import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
@@ -18,6 +19,7 @@ public final class PermanentPortalShape {
|
||||
public static final int MIN_WIDTH = 2;
|
||||
public static final int MIN_HEIGHT = 3;
|
||||
public static final int MAX_SIZE = 21;
|
||||
public static final int ACTIVE_SEARCH_RADIUS = 8;
|
||||
|
||||
private final PermanentPortalType type;
|
||||
private final Direction.Axis axis;
|
||||
@@ -38,12 +40,52 @@ public final class PermanentPortalShape {
|
||||
return find(level, interiorPos, type, axis, state -> state.isAir());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PermanentPortalShape findInactiveNear(BlockGetter level, BlockPos center, PermanentPortalType type) {
|
||||
for (int x = center.getX() - 2; x <= center.getX() + 2; x++) {
|
||||
for (int y = center.getY() - 2; y <= center.getY() + 2; y++) {
|
||||
for (int z = center.getZ() - 2; z <= center.getZ() + 2; z++) {
|
||||
BlockPos candidate = new BlockPos(x, y, z);
|
||||
PermanentPortalShape xShape = findInactive(level, candidate, type, Direction.Axis.X);
|
||||
if (xShape != null) {
|
||||
return xShape;
|
||||
}
|
||||
PermanentPortalShape zShape = findInactive(level, candidate, type, Direction.Axis.Z);
|
||||
if (zShape != null) {
|
||||
return zShape;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PermanentPortalShape findActive(BlockGetter level, BlockPos interiorPos, PermanentPortalType type, Direction.Axis axis) {
|
||||
Block portalBlock = type.portalBlock();
|
||||
return find(level, interiorPos, type, axis, state -> state.is(portalBlock));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PermanentPortalShape findActiveNear(BlockGetter level, BlockPos center, PermanentPortalType type) {
|
||||
for (int x = center.getX() - ACTIVE_SEARCH_RADIUS; x <= center.getX() + ACTIVE_SEARCH_RADIUS; x++) {
|
||||
for (int y = center.getY() - ACTIVE_SEARCH_RADIUS; y <= center.getY() + ACTIVE_SEARCH_RADIUS; y++) {
|
||||
for (int z = center.getZ() - ACTIVE_SEARCH_RADIUS; z <= center.getZ() + ACTIVE_SEARCH_RADIUS; z++) {
|
||||
BlockPos candidate = new BlockPos(x, y, z);
|
||||
PermanentPortalShape xShape = findActive(level, candidate, type, Direction.Axis.X);
|
||||
if (xShape != null) {
|
||||
return xShape;
|
||||
}
|
||||
PermanentPortalShape zShape = findActive(level, candidate, type, Direction.Axis.Z);
|
||||
if (zShape != null) {
|
||||
return zShape;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PermanentPortalShape find(
|
||||
BlockGetter level,
|
||||
@@ -159,6 +201,50 @@ public final class PermanentPortalShape {
|
||||
this.forEachInterior(pos -> level.setBlock(pos, portalState, Block.UPDATE_ALL));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PermanentPortalShape create(ServerLevel level, BlockPos bottomLeft, PermanentPortalType type, Direction.Axis axis) {
|
||||
if (axis == Direction.Axis.Y || !canCreate(level, bottomLeft, type, axis)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BlockState frameState = type.platformBlock().defaultBlockState();
|
||||
BlockState portalState = type.portalBlock().defaultBlockState().setValue(BlockStateProperties.HORIZONTAL_AXIS, axis);
|
||||
Direction widthDirection = axis == Direction.Axis.X ? Direction.EAST : Direction.SOUTH;
|
||||
|
||||
for (int y = -1; y <= 3; y++) {
|
||||
for (int x = -1; x <= 2; x++) {
|
||||
BlockPos pos = bottomLeft.relative(widthDirection, x).above(y);
|
||||
if (x == -1 || x == 2 || y == -1 || y == 3) {
|
||||
level.setBlock(pos, frameState, Block.UPDATE_ALL);
|
||||
} else {
|
||||
level.setBlock(pos, portalState, Block.UPDATE_ALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new PermanentPortalShape(type, axis, bottomLeft.immutable(), 2, 3);
|
||||
}
|
||||
|
||||
private static boolean canCreate(BlockGetter level, BlockPos bottomLeft, PermanentPortalType type, Direction.Axis axis) {
|
||||
Direction widthDirection = axis == Direction.Axis.X ? Direction.EAST : Direction.SOUTH;
|
||||
Block frameBlock = type.platformBlock();
|
||||
for (int y = -1; y <= 3; y++) {
|
||||
for (int x = -1; x <= 2; x++) {
|
||||
BlockPos pos = bottomLeft.relative(widthDirection, x).above(y);
|
||||
BlockState state = level.getBlockState(pos);
|
||||
boolean frameSpot = x == -1 || x == 2 || y == -1 || y == 3;
|
||||
if (frameSpot) {
|
||||
if (!state.isAir() && !state.is(frameBlock) && !state.canBeReplaced()) {
|
||||
return false;
|
||||
}
|
||||
} else if (!state.isAir() && !state.canBeReplaced() && !state.is(Blocks.AIR)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean contains(BlockPos pos) {
|
||||
if (pos.getY() < this.bottomLeft.getY() || pos.getY() >= this.bottomLeft.getY() + this.height) {
|
||||
return false;
|
||||
|
||||
+115
-13
@@ -1,14 +1,17 @@
|
||||
package com.craisinlord.antarchy.content.portal;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.vehicle.DismountHelper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
@@ -28,18 +31,23 @@ public final class PermanentPortalTeleporter {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerLevel destination = resolveDestination(sourceLevel, type);
|
||||
if (destination == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 arrival = findArrivalPosition(entity, destination, entity.blockPosition(), type.platformBlock().defaultBlockState());
|
||||
Entity movedEntity = moveEntity(entity, destination, arrival);
|
||||
DimensionTransition transition = createTransition(sourceLevel, entity, entity.blockPosition(), type);
|
||||
Entity movedEntity = moveEntity(entity, transition);
|
||||
if (movedEntity != null) {
|
||||
movedEntity.setPortalCooldown();
|
||||
}
|
||||
}
|
||||
|
||||
public static DimensionTransition createTransition(ServerLevel sourceLevel, Entity entity, BlockPos portalPos, PermanentPortalType type) {
|
||||
ServerLevel destination = resolveDestination(sourceLevel, type);
|
||||
if (destination == null) {
|
||||
return new DimensionTransition(sourceLevel, entity, DimensionTransition.DO_NOTHING);
|
||||
}
|
||||
|
||||
Vec3 arrival = findArrivalPosition(entity, destination, portalPos, type);
|
||||
return new DimensionTransition(destination, arrival, Vec3.ZERO, entity.getYRot(), entity.getXRot(), DimensionTransition.PLAY_PORTAL_SOUND);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ServerLevel resolveDestination(ServerLevel sourceLevel, PermanentPortalType type) {
|
||||
if (sourceLevel.dimension() == type.primaryDimension()) {
|
||||
@@ -48,13 +56,31 @@ public final class PermanentPortalTeleporter {
|
||||
return sourceLevel.getServer().getLevel(type.primaryDimension());
|
||||
}
|
||||
|
||||
private static Vec3 findArrivalPosition(Entity entity, ServerLevel destination, BlockPos preferredPos, BlockState platformState) {
|
||||
private static Vec3 findArrivalPosition(Entity entity, ServerLevel destination, BlockPos preferredPos, PermanentPortalType type) {
|
||||
PermanentPortalShape active = PermanentPortalShape.findActiveNear(destination, preferredPos, type);
|
||||
if (active != null) {
|
||||
return active.center();
|
||||
}
|
||||
|
||||
Vec3 safe = findSafeArrivalPosition(entity, destination, preferredPos);
|
||||
return safe != null ? safe : createFallbackPlatform(destination, preferredPos, platformState);
|
||||
if (safe != null) {
|
||||
PermanentPortalShape created = createReturnPortal(destination, safe, type);
|
||||
if (created != null) {
|
||||
return created.center();
|
||||
}
|
||||
return safe;
|
||||
}
|
||||
|
||||
return createFallbackPlatform(destination, preferredPos, type.platformBlock().defaultBlockState());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Vec3 findSafeArrivalPosition(Entity entity, ServerLevel destination, BlockPos preferredPos) {
|
||||
int[] yRange = getDimensionYRange(destination);
|
||||
if (yRange != null) {
|
||||
return findSafeArrivalPositionInYRange(entity, destination, preferredPos, yRange[0], yRange[1]);
|
||||
}
|
||||
|
||||
Set<BlockPos> candidates = new LinkedHashSet<>();
|
||||
addCandidate(candidates, preferredPos);
|
||||
|
||||
@@ -88,6 +114,29 @@ public final class PermanentPortalTeleporter {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Vec3 findSafeArrivalPositionInYRange(Entity entity, ServerLevel destination, BlockPos preferredPos, int minY, int maxY) {
|
||||
for (int radius = 0; radius <= SEARCH_RADIUS; radius++) {
|
||||
for (int xOff = -radius; xOff <= radius; xOff++) {
|
||||
for (int zOff = -radius; zOff <= radius; zOff++) {
|
||||
if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int x = preferredPos.getX() + xOff;
|
||||
int z = preferredPos.getZ() + zOff;
|
||||
for (int y = maxY; y >= minY + 1; y--) {
|
||||
Vec3 safePos = tryFindSafePosition(entity, destination, new BlockPos(x, y, z));
|
||||
if (safePos != null && safePos.y >= minY && safePos.y <= maxY) {
|
||||
return safePos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void addCandidate(Set<BlockPos> candidates, @Nullable BlockPos pos) {
|
||||
if (pos == null) {
|
||||
return;
|
||||
@@ -103,13 +152,13 @@ public final class PermanentPortalTeleporter {
|
||||
@Nullable
|
||||
private static Vec3 tryFindSafePosition(Entity entity, ServerLevel destination, BlockPos candidate) {
|
||||
Vec3 safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate, true);
|
||||
if (safe != null) {
|
||||
if (safe != null && isValidArrivalPosition(destination, safe)) {
|
||||
return safe;
|
||||
}
|
||||
|
||||
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
||||
safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate.relative(direction), true);
|
||||
if (safe != null) {
|
||||
if (safe != null && isValidArrivalPosition(destination, safe)) {
|
||||
return safe;
|
||||
}
|
||||
}
|
||||
@@ -134,7 +183,60 @@ public final class PermanentPortalTeleporter {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Entity moveEntity(Entity entity, ServerLevel destination, Vec3 destinationPos) {
|
||||
private static PermanentPortalShape createReturnPortal(ServerLevel destination, Vec3 safePos, PermanentPortalType type) {
|
||||
BlockPos preferred = BlockPos.containing(safePos);
|
||||
int minY = destination.getMinBuildHeight() + 2;
|
||||
int maxY = destination.getMaxBuildHeight() - 4;
|
||||
int clampedY = Mth.clamp(preferred.getY(), minY, maxY);
|
||||
|
||||
for (int radius = 0; radius <= 4; radius++) {
|
||||
for (int xOff = -radius; xOff <= radius; xOff++) {
|
||||
for (int zOff = -radius; zOff <= radius; zOff++) {
|
||||
if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BlockPos anchor = new BlockPos(preferred.getX() + xOff, clampedY, preferred.getZ() + zOff);
|
||||
PermanentPortalShape xShape = PermanentPortalShape.create(destination, anchor, type, Direction.Axis.X);
|
||||
if (xShape != null) {
|
||||
return xShape;
|
||||
}
|
||||
PermanentPortalShape zShape = PermanentPortalShape.create(destination, anchor, type, Direction.Axis.Z);
|
||||
if (zShape != null) {
|
||||
return zShape;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static int[] getDimensionYRange(ServerLevel destination) {
|
||||
ResourceKey<Level> dim = destination.dimension();
|
||||
if (dim == AntarchySettings.termiteDestinationDimension()) {
|
||||
return new int[]{100, 200};
|
||||
}
|
||||
if (dim == AntarchySettings.brownAntDestinationDimension()) {
|
||||
return new int[]{75, 120};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isValidArrivalPosition(ServerLevel destination, Vec3 safePos) {
|
||||
BlockPos standPos = BlockPos.containing(safePos);
|
||||
if (destination.dimension() == AntarchySettings.termiteDestinationDimension()
|
||||
|| destination.dimension() == AntarchySettings.redAntDestinationDimension()) {
|
||||
return !destination.getBlockState(standPos.below()).is(net.minecraft.world.level.block.Blocks.BEDROCK);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Entity moveEntity(Entity entity, DimensionTransition transition) {
|
||||
ServerLevel destination = transition.newLevel();
|
||||
Vec3 destinationPos = transition.pos();
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
player.teleportTo(destination, destinationPos.x, destinationPos.y, destinationPos.z, player.getYRot(), player.getXRot());
|
||||
return player;
|
||||
@@ -145,6 +247,6 @@ public final class PermanentPortalTeleporter {
|
||||
return entity;
|
||||
}
|
||||
|
||||
return entity.changeDimension(new DimensionTransition(destination, destinationPos, Vec3.ZERO, entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING));
|
||||
return entity.changeDimension(transition);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.portal.PermanentPortalManager;
|
||||
import com.craisinlord.antarchy.content.portal.PermanentPortalType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.item.FlintAndSteelItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(FlintAndSteelItem.class)
|
||||
public abstract class FlintAndSteelPortalIgnitionMixin {
|
||||
@Inject(method = "useOn", at = @At("HEAD"), cancellable = true)
|
||||
private void antarchy$ignitePermanentPortal(UseOnContext context, CallbackInfoReturnable<InteractionResult> cir) {
|
||||
if (!AntarchySettings.permanentPortalsEnabled() || !AntarchySettings.permanentPortalsFlintAndSteelEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Level level = context.getLevel();
|
||||
BlockPos clickedPos = context.getClickedPos();
|
||||
BlockState clickedState = level.getBlockState(clickedPos);
|
||||
|
||||
for (PermanentPortalType type : PermanentPortalType.values()) {
|
||||
if (!type.isEnabled() || !clickedState.is(type.frameTag())) {
|
||||
continue;
|
||||
}
|
||||
if (!PermanentPortalManager.tryIgnitePortal(level, clickedPos, type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!level.isClientSide() && context.getPlayer() != null) {
|
||||
ItemStack stack = context.getItemInHand();
|
||||
stack.hurtAndBreak(1, context.getPlayer(), handToSlot(context.getHand()));
|
||||
}
|
||||
|
||||
cir.setReturnValue(InteractionResult.sidedSuccess(level.isClientSide()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static EquipmentSlot handToSlot(InteractionHand hand) {
|
||||
return hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
"DreamSandLowGravityMixin",
|
||||
"FireVisualBaseFireBlockMixin",
|
||||
"FireVisualEntityMixin",
|
||||
"FlintAndSteelPortalIgnitionMixin",
|
||||
"GlowVinesUnderLeavesMixin",
|
||||
"NightmareSwordDamageMixin",
|
||||
"ServerPlayerGameModeMixin",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"description": {
|
||||
"identifier": "geometry.unknown",
|
||||
"texture_width": 128,
|
||||
"texture_height": 128,
|
||||
"texture_height": 256,
|
||||
"visible_bounds_width": 7,
|
||||
"visible_bounds_height": 4.5,
|
||||
"visible_bounds_offset": [0, 1.75, 0]
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Reference in new issue
Block a user