From 37e941915d4056f92c62a3425167e797e4f6fa35 Mon Sep 17 00:00:00 2001 From: craisinlord Date: Sat, 12 Sep 2026 23:58:24 -0500 Subject: [PATCH] fix king and queen attack anim bug stabalize RainbowAntEntity dims patch config inconsitency fixed undervault performance improvements --- .../compat/infinity/InfinityCompatBridge.java | 4 +- .../compat/infinity/InfinityWarpResult.java | 9 ++ .../content/block/UnderVaultBlock.java | 23 ++++ .../client/ClientTimeDilationTicker.java | 5 + .../client/ContractionAfterimages.java | 21 ++-- .../content/client/model/RoyalBossModel.java | 33 ----- .../content/client/model/RoyalMountModel.java | 24 ++++ .../client/renderer/RoyalBeamRenderTypes.java | 26 ++++ .../client/renderer/RoyalBossRenderer.java | 118 ++++++++++++------ .../client/renderer/RoyalMountRenderer.java | 101 +++++++++++---- .../content/entity/ant/RainbowAntEntity.java | 16 ++- .../content/entity/lucid/LucidEntity.java | 7 +- .../entity/portal/DimensionalTearEntity.java | 26 ---- .../content/entity/royal/KingEntity.java | 38 +++++- .../content/entity/royal/QueenEntity.java | 51 ++++++-- .../content/entity/royal/RoyalBoltEntity.java | 4 + .../content/entity/royal/RoyalBossEntity.java | 39 +++++- .../entity/royal/RoyalMountEntity.java | 16 ++- .../entity/royal/RoyalMountSpitGoal.java | 4 +- .../royal/beam/RoyalBeamController.java | 21 +++- .../entity/vortex/WindVortexEntity.java | 7 -- .../content/time/TimeDilationApi.java | 9 ++ .../content/time/TimeDilationFieldEntity.java | 1 + .../content/time/TimeDilationManager.java | 68 ++++++++-- .../mixins/gravity/EntityMoveMixin.java | 62 +++++++++ .../time/LivingEntityTimeDilationMixin.java | 8 +- .../time/SoundEngineTimeDilationMixin.java | 18 +++ .../loot_table/spawners/undertrial.json | 2 +- .../worldgen/structure/underside_castle.json | 7 +- .../worldgen/structure/underside_ruins.json | 7 +- .../resources/data/c/tags/item/stones.json | 3 +- .../antarchy/fabric/AntarchyFabricEvents.java | 10 +- .../antarchy/fabric/FabricInfinityCompat.java | 9 +- .../fabric/InfinityGenerationFailure.java | 20 +++ .../entity/multipart/MultipartPartEntity.java | 22 +++- .../fabric/mixin/infinity/WarpLogicMixin.java | 34 +++++ .../fabric/registry/AntarchyFabricItems.java | 4 +- .../resources/antarchy-fabric.mixins.json | 1 + .../neoforge/InfinityGenerationFailure.java | 20 +++ .../neoforge/NeoForgeInfinityCompat.java | 9 +- .../entity/multipart/MultipartPartEntity.java | 22 +++- .../infinity/ConfigGenInvocationMixin.java | 5 - .../mixins/infinity/WarpLogicMixin.java | 35 ++++++ .../neoforge/network/MultipartNetworking.java | 3 +- .../registry/AntarchyNeoForgeEvents.java | 38 ++++-- .../registry/AntarchyNeoforgeItems.java | 4 +- .../resources/antarchy-neoforge.mixins.json | 1 + 47 files changed, 784 insertions(+), 231 deletions(-) create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityWarpResult.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBeamRenderTypes.java create mode 100644 fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/InfinityGenerationFailure.java create mode 100644 fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/infinity/WarpLogicMixin.java create mode 100644 neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/InfinityGenerationFailure.java create mode 100644 neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/WarpLogicMixin.java diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityCompatBridge.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityCompatBridge.java index 73a35c87..72e7e9ae 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityCompatBridge.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityCompatBridge.java @@ -22,8 +22,8 @@ public interface InfinityCompatBridge { return getRandomDimensionId(random); } - default boolean requestWarp(ServerPlayer player, ResourceLocation dimensionId) { - return false; + default InfinityWarpResult requestWarp(ServerPlayer player, ResourceLocation dimensionId) { + return InfinityWarpResult.REJECTED; } /** diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityWarpResult.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityWarpResult.java new file mode 100644 index 00000000..096a3832 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/compat/infinity/InfinityWarpResult.java @@ -0,0 +1,9 @@ +package com.craisinlord.antarchy.compat.infinity; + +public enum InfinityWarpResult { + REJECTED, + PENDING, + READY, + FAILED_GENERATION, + TIMEOUT +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/UnderVaultBlock.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/UnderVaultBlock.java index ecf820fb..d0a4d372 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/UnderVaultBlock.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/block/UnderVaultBlock.java @@ -5,6 +5,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; @@ -16,6 +19,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.phys.BlockHitResult; import java.util.function.Supplier; @@ -60,6 +64,25 @@ public final class UnderVaultBlock extends VaultBlock { return new UnderVaultBlockEntity(pos, state, blockEntityType); } + @Override + public ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, + net.minecraft.world.entity.player.Player player, InteractionHand hand, + BlockHitResult hitResult) { + if (stack.isEmpty() || state.getValue(STATE) != net.minecraft.world.level.block.entity.vault.VaultState.ACTIVE) { + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } + if (level instanceof ServerLevel serverLevel + && level.getBlockEntity(pos) instanceof UnderVaultBlockEntity underVault) { + net.minecraft.world.level.block.entity.vault.VaultBlockEntity.Server.tryInsertKey( + serverLevel, pos, state, underVault.getVaultData().getConfig(), + underVault.getVaultData().getServerData(), underVault.getVaultData().getSharedData(), + player, stack); + return ItemInteractionResult.SUCCESS; + } + return level.isClientSide ? ItemInteractionResult.CONSUME + : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } + @Override public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { if (this.blockEntityType == null || type != this.blockEntityType.get()) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ClientTimeDilationTicker.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ClientTimeDilationTicker.java index 25d91b6c..aed3199f 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ClientTimeDilationTicker.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ClientTimeDilationTicker.java @@ -163,4 +163,9 @@ public final class ClientTimeDilationTicker { public static void applyFields(List fields) { activeFields = List.copyOf(fields); } + + public static boolean hasActiveDilation() { + return !activeFields.isEmpty() + || com.craisinlord.antarchy.content.time.TimeDilationApi.hasSyncedClientRates(); + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ContractionAfterimages.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ContractionAfterimages.java index bb40e63a..99daa251 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ContractionAfterimages.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/ContractionAfterimages.java @@ -33,19 +33,18 @@ public final class ContractionAfterimages { iterator.remove(); } } - if (holder == null) { + } + + public static void observe(LivingEntity living) { + Holder holder = RoyalEffectHooks.contractedHolder(); + if (holder == null || living.isInvisible() || !living.hasEffect(holder)) { return; } - - for (Entity entity : level.entitiesForRendering()) { - if (!(entity instanceof LivingEntity living) || living.isInvisible() || !living.hasEffect(holder)) { - continue; - } - Deque samples = HISTORY.computeIfAbsent(living, ignored -> new ArrayDeque<>()); - samples.addFirst(new Sample(living, now)); - while (samples.size() > MAX_SAMPLES) { - samples.removeLast(); - } + int now = (int) (living.level().getGameTime() & 0x7fffffffL); + Deque samples = HISTORY.computeIfAbsent(living, ignored -> new ArrayDeque<>()); + samples.addFirst(new Sample(living, now)); + while (samples.size() > MAX_SAMPLES) { + samples.removeLast(); } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalBossModel.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalBossModel.java index acdbdbde..f3ea5c20 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalBossModel.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalBossModel.java @@ -4,7 +4,6 @@ import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.content.entity.royal.RoyalBossEntity; import com.craisinlord.antarchy.content.entity.royal.RoyalHead; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import software.bernie.geckolib.animation.AnimationState; @@ -15,11 +14,6 @@ public class RoyalBossModel extends GeoModel { private static final String[] BEAM_ANCHORS = { "beam_anchor_left", "beam_anchor_center", "beam_anchor_right" }; - private static final String[][] AIM_CHAINS = { - {"L_neck", "L_neck2", "L_neck3"}, - {"neck", "neck3", "neck4"}, - {"R_neck", "R_neck2", "R_neck3"} - }; @Override public ResourceLocation getModelResource(RoyalBossEntity animatable) { @@ -45,33 +39,6 @@ public class RoyalBossModel extends GeoModel { this.getBone(anchor).ifPresent(bone -> bone.setTrackingMatrices(true)); } - float partialTick = animationState.getPartialTick(); - for (RoyalHead.Slot slot : RoyalHead.Slot.values()) { - Vec3 beamEnd = animatable.getRoyalBeamEndPosition(slot); - if (!animatable.isFiringRoyalBeam(slot) || beamEnd == null) continue; - Vec3 origin = animatable.getRoyalBeamShootFrom(slot, partialTick); - Vec3 direction = com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil.vecWorldToPlayer( - beamEnd.subtract(origin), - com.craisinlord.antarchy.content.gravity.AntarchyGravityApi.getGravityDirection(animatable)); - double horizontal = Math.sqrt(direction.x * direction.x + direction.z * direction.z); - if (direction.lengthSqr() < 1.0E-6D || horizontal < 1.0E-4D) continue; - - float desiredYaw = (float) (Mth.atan2(-direction.x, direction.z) * Mth.RAD_TO_DEG); - float bodyYaw = Mth.rotLerp(partialTick, animatable.yRotO, animatable.getYRot()); - float relativeYaw = Mth.clamp(Mth.wrapDegrees(desiredYaw - bodyYaw), -55.0F, 55.0F) * Mth.DEG_TO_RAD; - float pitch = Mth.clamp((float) -Mth.atan2(direction.y, horizontal) * Mth.RAD_TO_DEG, - -45.0F, 45.0F) * Mth.DEG_TO_RAD; - - String[] chain = AIM_CHAINS[slot.ordinal()]; - float yawPerBone = relativeYaw / chain.length; - float pitchPerBone = pitch / chain.length; - for (String boneName : chain) { - this.getBone(boneName).ifPresent(bone -> { - bone.setRotY(yawPerBone); - bone.setRotX(pitchPerBone); - }); - } - } } @Nullable diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalMountModel.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalMountModel.java index dbba6168..731eb9c3 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalMountModel.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/RoyalMountModel.java @@ -3,9 +3,15 @@ package com.craisinlord.antarchy.content.client.model; import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.content.entity.royal.RoyalMountEntity; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; +import software.bernie.geckolib.animation.AnimationState; +import software.bernie.geckolib.cache.object.GeoBone; import software.bernie.geckolib.model.GeoModel; public class RoyalMountModel extends GeoModel { + private static final String[] HEADS = {"head_left", "head", "head_right"}; + @Override public ResourceLocation getModelResource(RoyalMountEntity animatable) { return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/" + animatable.geoNameForRender() + ".geo.json"); @@ -20,4 +26,22 @@ public class RoyalMountModel extends GeoModel { public ResourceLocation getAnimationResource(RoyalMountEntity animatable) { return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/" + animatable.geoNameForRender() + ".animation.json"); } + + @Override + public void setCustomAnimations(RoyalMountEntity animatable, long instanceId, + AnimationState animationState) { + super.setCustomAnimations(animatable, instanceId, animationState); + for (String head : HEADS) { + this.getBone(head).ifPresent(bone -> bone.setTrackingMatrices(true)); + } + } + + @Nullable + public Vec3 getTrackedBeamAnchor(int head) { + if (head < 0 || head >= HEADS.length) return null; + GeoBone bone = this.getBone(HEADS[head]).orElse(null); + if (bone == null || !bone.isTrackingMatrices()) return null; + org.joml.Vector3d position = bone.getWorldPosition(); + return new Vec3(position.x, position.y, position.z); + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBeamRenderTypes.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBeamRenderTypes.java new file mode 100644 index 00000000..ed243204 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBeamRenderTypes.java @@ -0,0 +1,26 @@ +package com.craisinlord.antarchy.content.client.renderer; + +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.RenderStateShard; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.resources.ResourceLocation; + +public class RoyalBeamRenderTypes extends RenderType { + public RoyalBeamRenderTypes(String name, VertexFormat format, VertexFormat.Mode mode, int bufferSize, + boolean affectsCrumbling, boolean sortOnUpload, Runnable setupState, Runnable clearState) { + super(name, format, mode, bufferSize, affectsCrumbling, sortOnUpload, setupState, clearState); + } + + public static RenderType beam(ResourceLocation texture) { + return create("royal_beam", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, true, true, + CompositeState.builder() + .setTextureState(new TextureStateShard(texture, false, false)) + .setShaderState(RenderStateShard.RENDERTYPE_ENERGY_SWIRL_SHADER) + .setTransparencyState(RenderStateShard.TRANSLUCENT_TRANSPARENCY) + .setCullState(RenderStateShard.NO_CULL) + .setLightmapState(RenderStateShard.LIGHTMAP) + .setOutputState(RenderStateShard.ITEM_ENTITY_TARGET) + .createCompositeState(false)); + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java index d8a380af..2efa79d5 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java @@ -25,22 +25,28 @@ import software.bernie.geckolib.util.Color; public class RoyalBossRenderer extends GeoEntityRenderer { private static final ResourceLocation QUEEN_PURPLE_BEAM_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_outer.png"); private static final ResourceLocation QUEEN_PURPLE_BEAM_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_inner.png"); - private static final ResourceLocation QUEEN_PURPLE_BEAM_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_end_1.png"); + private static final ResourceLocation QUEEN_PURPLE_BEAM_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_end_1.png"); + private static final ResourceLocation QUEEN_PURPLE_BEAM_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_end_2.png"); private static final ResourceLocation QUEEN_RED_BEAM_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_red_beam_outer.png"); private static final ResourceLocation QUEEN_RED_BEAM_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_red_beam_inner.png"); - private static final ResourceLocation QUEEN_RED_BEAM_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_red_beam_end_1.png"); + private static final ResourceLocation QUEEN_RED_BEAM_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_red_beam_end_1.png"); + private static final ResourceLocation QUEEN_RED_BEAM_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_red_beam_end_2.png"); private static final ResourceLocation QUEEN_BLACK_BEAM_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_black_beam_outer.png"); private static final ResourceLocation QUEEN_BLACK_BEAM_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_black_beam_inner.png"); - private static final ResourceLocation QUEEN_BLACK_BEAM_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_black_beam_end_1.png"); + private static final ResourceLocation QUEEN_BLACK_BEAM_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_black_beam_end_1.png"); + private static final ResourceLocation QUEEN_BLACK_BEAM_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_black_beam_end_2.png"); private static final ResourceLocation KING_FIRE_BEAM_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_outer.png"); private static final ResourceLocation KING_FIRE_BEAM_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_inner.png"); - private static final ResourceLocation KING_FIRE_BEAM_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_end_1.png"); + private static final ResourceLocation KING_FIRE_BEAM_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_end_1.png"); + private static final ResourceLocation KING_FIRE_BEAM_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_end_2.png"); private static final ResourceLocation KING_LIGHTNING_BEAM_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_outer.png"); private static final ResourceLocation KING_LIGHTNING_BEAM_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_inner.png"); - private static final ResourceLocation KING_LIGHTNING_BEAM_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_end_1.png"); + private static final ResourceLocation KING_LIGHTNING_BEAM_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_end_1.png"); + private static final ResourceLocation KING_LIGHTNING_BEAM_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_end_2.png"); private static final ResourceLocation KING_ICE_BEAM_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_outer.png"); private static final ResourceLocation KING_ICE_BEAM_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_inner.png"); - private static final ResourceLocation KING_ICE_BEAM_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_end_1.png"); + private static final ResourceLocation KING_ICE_BEAM_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_end_1.png"); + private static final ResourceLocation KING_ICE_BEAM_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_end_2.png"); public RoyalBossRenderer(EntityRendererProvider.Context context) { super(context, new RoyalBossModel()); this.shadowRadius = 8.0F; @@ -110,10 +116,8 @@ public class RoyalBossRenderer extends GeoEntityRenderer { this.shadowRadius = 8.0F * RoyalBossEntity.MODEL_RENDER_SCALE; } - private static final float BEAM_OUTER_RADIUS = 0.55F; - private static final float BEAM_INNER_RADIUS = 0.32F; - private static final float BEAM_TILE_BLOCKS = 3.0F; - private static final float BEAM_SCROLL_SPEED = 0.32F; + private static final float BEAM_OUTER_RADIUS = 1.75F; + private static final float BEAM_INNER_RADIUS = 1.5F; @Override public void render(RoyalBossEntity entity, float entityYaw, float partialTick, PoseStack poseStack, @@ -152,23 +156,23 @@ public class RoyalBossRenderer extends GeoEntityRenderer { ResourceLocation outer = QUEEN_PURPLE_BEAM_OUTER; ResourceLocation inner = QUEEN_PURPLE_BEAM_INNER; - ResourceLocation endTexture = QUEEN_PURPLE_BEAM_END; + ResourceLocation[] endTextures = {QUEEN_PURPLE_BEAM_END_1, QUEEN_PURPLE_BEAM_END_2}; if (entity instanceof KingEntity) { switch (entity.getRoyalBeamElement()) { case FIRE -> { outer = KING_FIRE_BEAM_OUTER; inner = KING_FIRE_BEAM_INNER; - endTexture = KING_FIRE_BEAM_END; + endTextures = new ResourceLocation[]{KING_FIRE_BEAM_END_1, KING_FIRE_BEAM_END_2}; } case LIGHTNING -> { outer = KING_LIGHTNING_BEAM_OUTER; inner = KING_LIGHTNING_BEAM_INNER; - endTexture = KING_LIGHTNING_BEAM_END; + endTextures = new ResourceLocation[]{KING_LIGHTNING_BEAM_END_1, KING_LIGHTNING_BEAM_END_2}; } case ICE -> { outer = KING_ICE_BEAM_OUTER; inner = KING_ICE_BEAM_INNER; - endTexture = KING_ICE_BEAM_END; + endTextures = new ResourceLocation[]{KING_ICE_BEAM_END_1, KING_ICE_BEAM_END_2}; } case GENERIC -> { } @@ -178,12 +182,12 @@ public class RoyalBossRenderer extends GeoEntityRenderer { case QUEEN_RED -> { outer = QUEEN_RED_BEAM_OUTER; inner = QUEEN_RED_BEAM_INNER; - endTexture = QUEEN_RED_BEAM_END; + endTextures = new ResourceLocation[]{QUEEN_RED_BEAM_END_1, QUEEN_RED_BEAM_END_2}; } case QUEEN_BLACK -> { outer = QUEEN_BLACK_BEAM_OUTER; inner = QUEEN_BLACK_BEAM_INNER; - endTexture = QUEEN_BLACK_BEAM_END; + endTextures = new ResourceLocation[]{QUEEN_BLACK_BEAM_END_1, QUEEN_BLACK_BEAM_END_2}; } default -> { } @@ -191,34 +195,53 @@ public class RoyalBossRenderer extends GeoEntityRenderer { } float time = entity.tickCount + partialTick; - float tiles = (float) (length / BEAM_TILE_BLOCKS); - float scroll = -time * BEAM_SCROLL_SPEED; + float outerV = -time * 0.25F; var pose = poseStack.last().pose(); - VertexConsumer outerBuffer = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(outer)); - drawBeamPlane(outerBuffer, pose, start, finish, side1.scale(BEAM_OUTER_RADIUS), scroll, scroll + tiles); - drawBeamPlane(outerBuffer, pose, start, finish, side2.scale(BEAM_OUTER_RADIUS), scroll, scroll + tiles); + float innerV = -time * 0.25F * 0.5F; + VertexConsumer innerBuffer = bufferSource.getBuffer(RoyalBeamRenderTypes.beam(inner)); + drawBeamTube(innerBuffer, pose, start, finish, side1, side2, BEAM_INNER_RADIUS, 4, innerV, 0.0F, 0.55F, 0.5F, 255); - float innerScroll = -time * BEAM_SCROLL_SPEED * 1.6F; - VertexConsumer innerBuffer = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(inner)); - drawBeamPlane(innerBuffer, pose, start, finish, side1.scale(BEAM_INNER_RADIUS), innerScroll, innerScroll + tiles); - drawBeamPlane(innerBuffer, pose, start, finish, side2.scale(BEAM_INNER_RADIUS), innerScroll, innerScroll + tiles); + VertexConsumer outerBuffer = bufferSource.getBuffer(RoyalBeamRenderTypes.beam(outer)); + // Tremorzilla's outer shell stays fully visible all the way to the impact; + // fading the far ring makes the beam look like a translucent cone. + drawBeamTube(outerBuffer, pose, start, finish, side1, side2, BEAM_OUTER_RADIUS, 8, outerV, 0.0F, 0.55F, 0.15F, 255); - float impactSize = 1.1F + 0.35F * Mth.sin(time * 0.6F); - Vec3 camLeft = new Vec3(this.entityRenderDispatcher.camera.getLeftVector()); - Vec3 camUp = new Vec3(this.entityRenderDispatcher.camera.getUpVector()); - VertexConsumer endBuffer = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(endTexture)); - drawBillboard(endBuffer, pose, finish, camLeft.scale(impactSize), camUp.scale(impactSize)); + float impactSize = 1.5F + 0.35F * Mth.sin(time * 0.6F); + ResourceLocation endTexture = endTextures[(entity.tickCount / 2) % endTextures.length]; + VertexConsumer endBuffer = bufferSource.getBuffer(RoyalBeamRenderTypes.beam(endTexture)); + drawBeamImpact(endBuffer, pose, finish.subtract(dir.scale(1.5D)), dir, side1, side2, impactSize); } - private static void drawBeamPlane(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 start, Vec3 end, Vec3 half, - float startV, float endV) { - emitQuad(vertices, pose, - start.subtract(half), start.add(half), end.add(half), end.subtract(half), - 0.0F, startV, 1.0F, endV); - emitQuad(vertices, pose, - start.add(half), start.subtract(half), end.subtract(half), end.add(half), - 0.0F, startV, 1.0F, endV); + private static void drawBeamTube(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 start, Vec3 end, + Vec3 side1, Vec3 side2, float radius, int sections, float scroll, float phase, + float startScale, float uvLengthScale, int endAlpha) { + Vec3[] startRing = new Vec3[sections]; + Vec3[] endRing = new Vec3[sections]; + for (int i = 0; i < sections; i++) { + double angle = Math.PI * 2.0D * i / sections + phase; + Vec3 offset = side1.scale(Math.cos(angle) * radius).add(side2.scale(Math.sin(angle) * radius)); + startRing[i] = start.add(offset.scale(startScale)); + endRing[i] = end.add(offset); + } + float endV = scroll + (float) start.distanceTo(end) * uvLengthScale; + for (int i = 0; i < sections; i++) { + int next = (i + 1) % sections; + // Alex's beam renderer intentionally uses section indices for U rather + // than normalizing them. This is part of the authored 16x16 texture + // pattern and keeps the strip continuous around the tube. + emitBeamQuad(vertices, pose, startRing[i], endRing[i], endRing[next], startRing[next], + i, scroll, next, endV, endAlpha); + } + } + + private static void emitBeamQuad(VertexConsumer vertices, org.joml.Matrix4f pose, + Vec3 a, Vec3 b, Vec3 c, Vec3 d, + float minU, float minV, float maxU, float maxV, int endAlpha) { + beamVertex(vertices, pose, a, minU, minV, 255); + beamVertex(vertices, pose, b, maxU, minV, endAlpha); + beamVertex(vertices, pose, c, maxU, maxV, endAlpha); + beamVertex(vertices, pose, d, minU, maxV, 255); } private static void drawBillboard(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 center, Vec3 left, Vec3 up) { @@ -232,6 +255,17 @@ public class RoyalBossRenderer extends GeoEntityRenderer { 0.0F, 0.0F, 1.0F, 1.0F); } + private static void drawBeamImpact(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 center, Vec3 direction, + Vec3 side1, Vec3 side2, float size) { + // The end textures are atlas textures used by Tremorzilla's crossed flame + // planes, not a texture meant to be repeated on eight radial billboards. + // Two crossed planes preserve the same readable four-point impact without + // stretching the atlas into the noisy starburst the old code produced. + drawBillboard(vertices, pose, center, side1.scale(size), side2.scale(size)); + drawBillboard(vertices, pose, center.subtract(direction.scale(size * 0.35D)), + side1.scale(size * 0.82D), direction.scale(size * 0.82D)); + } + private static void emitQuad(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 a, Vec3 b, Vec3 c, Vec3 d, float minU, float minV, float maxU, float maxV) { @@ -248,4 +282,12 @@ public class RoyalBossRenderer extends GeoEntityRenderer { .setLight(0x00F000F0) .setNormal(0.0F, 1.0F, 0.0F); } + + private static void beamVertex(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 pos, float u, float v, int alpha) { + vertices.addVertex(pose, (float) pos.x, (float) pos.y, (float) pos.z) + .setColor(255, 255, 255, alpha).setUv(u, v) + .setOverlay(OverlayTexture.NO_OVERLAY) + .setLight(0x00F000F0) + .setNormal(0.0F, -1.0F, 0.0F); + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalMountRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalMountRenderer.java index ca9463c6..d8728a4a 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalMountRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalMountRenderer.java @@ -19,16 +19,20 @@ import software.bernie.geckolib.renderer.GeoEntityRenderer; public class RoyalMountRenderer extends GeoEntityRenderer { private static final ResourceLocation QUEEN_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_outer.png"); private static final ResourceLocation QUEEN_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_inner.png"); - private static final ResourceLocation QUEEN_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_end_1.png"); + private static final ResourceLocation QUEEN_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_end_1.png"); + private static final ResourceLocation QUEEN_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/queen/queen_purple_beam_end_2.png"); private static final ResourceLocation KING_FIRE_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_outer.png"); private static final ResourceLocation KING_FIRE_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_inner.png"); - private static final ResourceLocation KING_FIRE_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_end_1.png"); + private static final ResourceLocation KING_FIRE_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_end_1.png"); + private static final ResourceLocation KING_FIRE_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/fire_beam_end_2.png"); private static final ResourceLocation KING_LIGHTNING_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_outer.png"); private static final ResourceLocation KING_LIGHTNING_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_inner.png"); - private static final ResourceLocation KING_LIGHTNING_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_end_1.png"); + private static final ResourceLocation KING_LIGHTNING_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_end_1.png"); + private static final ResourceLocation KING_LIGHTNING_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/lightning_beam_end_2.png"); private static final ResourceLocation KING_ICE_OUTER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_outer.png"); private static final ResourceLocation KING_ICE_INNER = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_inner.png"); - private static final ResourceLocation KING_ICE_END = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_end_1.png"); + private static final ResourceLocation KING_ICE_END_1 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_end_1.png"); + private static final ResourceLocation KING_ICE_END_2 = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/entity/king/ice_beam_end_2.png"); public RoyalMountRenderer(EntityRendererProvider.Context context) { super(context, new RoyalMountModel()); this.shadowRadius = 1.1F; @@ -58,7 +62,9 @@ public class RoyalMountRenderer extends GeoEntityRenderer { double x = Mth.lerp(partialTick, entity.xo, entity.getX()); double y = Mth.lerp(partialTick, entity.yo, entity.getY()); double z = Mth.lerp(partialTick, entity.zo, entity.getZ()); - Vec3 start = entity.beamShootFrom().subtract(x, y, z); + int beamHead = entity.getBeamHead(); + Vec3 trackedAnchor = ((RoyalMountModel) this.getGeoModel()).getTrackedBeamAnchor(beamHead); + Vec3 start = (trackedAnchor != null ? trackedAnchor : entity.beamShootFrom()).subtract(x, y, z); Vec3 finish = end.subtract(x, y, z); Vec3 axis = finish.subtract(start); double length = axis.length(); @@ -69,39 +75,90 @@ public class RoyalMountRenderer extends GeoEntityRenderer { side = side.normalize(); ResourceLocation outer = QUEEN_OUTER; ResourceLocation inner = QUEEN_INNER; - ResourceLocation endTexture = QUEEN_END; + ResourceLocation[] endTextures = {QUEEN_END_1, QUEEN_END_2}; if (entity instanceof PrinceEntity) { switch (entity.getBeamElement()) { - case FIRE -> { outer = KING_FIRE_OUTER; inner = KING_FIRE_INNER; endTexture = KING_FIRE_END; } - case ICE -> { outer = KING_ICE_OUTER; inner = KING_ICE_INNER; endTexture = KING_ICE_END; } - default -> { outer = KING_LIGHTNING_OUTER; inner = KING_LIGHTNING_INNER; endTexture = KING_LIGHTNING_END; } + case FIRE -> { outer = KING_FIRE_OUTER; inner = KING_FIRE_INNER; endTextures = new ResourceLocation[]{KING_FIRE_END_1, KING_FIRE_END_2}; } + case ICE -> { outer = KING_ICE_OUTER; inner = KING_ICE_INNER; endTextures = new ResourceLocation[]{KING_ICE_END_1, KING_ICE_END_2}; } + default -> { outer = KING_LIGHTNING_OUTER; inner = KING_LIGHTNING_INNER; endTextures = new ResourceLocation[]{KING_LIGHTNING_END_1, KING_LIGHTNING_END_2}; } } } float time = entity.tickCount + partialTick; - float tiles = (float) (length / 3.0D); + float outerV = -time * 0.25F; org.joml.Matrix4f pose = poseStack.last().pose(); - drawBeam(bufferSource.getBuffer(RenderType.entityTranslucentEmissive(outer)), pose, start, finish, side.scale(0.24D), -time * 0.32F, -time * 0.32F + tiles); - drawBeam(bufferSource.getBuffer(RenderType.entityTranslucentEmissive(inner)), pose, start, finish, side.scale(0.13D), -time * 0.5F, -time * 0.5F + tiles); - Vec3 up = new Vec3(this.entityRenderDispatcher.camera.getUpVector()).scale(0.55D); - Vec3 left = new Vec3(this.entityRenderDispatcher.camera.getLeftVector()).scale(0.55D); - drawQuad(bufferSource.getBuffer(RenderType.entityTranslucentEmissive(endTexture)), pose, finish.add(left).add(up), finish.subtract(left).add(up), finish.subtract(left).subtract(up), finish.add(left).subtract(up)); + Vec3 side2 = dir.cross(side).normalize(); + VertexConsumer outerBuffer = bufferSource.getBuffer(RoyalBeamRenderTypes.beam(outer)); + drawBeamTube(outerBuffer, pose, start, finish, side, side2, 0.44F, 8, outerV, 0.0F, 0.55F, 0.15F, 0); + float innerV = -time * 0.25F * 0.5F; + VertexConsumer innerBuffer = bufferSource.getBuffer(RoyalBeamRenderTypes.beam(inner)); + drawBeamTube(innerBuffer, pose, start, finish, side, side2, 0.375F, 4, innerV, 1.0F, 0.55F, 0.5F, 255); + float impactSize = 0.375F + 0.09F * Mth.sin(time * 0.6F); + ResourceLocation endTexture = endTextures[(entity.tickCount / 2) % endTextures.length]; + VertexConsumer endBuffer = bufferSource.getBuffer(RoyalBeamRenderTypes.beam(endTexture)); + drawBeamImpact(endBuffer, pose, finish.subtract(dir.scale(0.375D)), dir, side, side2, impactSize); } - private static void drawBeam(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 start, Vec3 end, Vec3 half, float startV, float endV) { - drawQuad(vertices, pose, start.subtract(half), start.add(half), end.add(half), end.subtract(half), startV, endV); - drawQuad(vertices, pose, start.add(half), start.subtract(half), end.subtract(half), end.add(half), startV, endV); + private static void drawBeamTube(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 start, Vec3 end, + Vec3 side1, Vec3 side2, float radius, int sections, float scroll, float phase, + float startScale, float uvLengthScale, int endAlpha) { + Vec3[] startRing = new Vec3[sections]; + Vec3[] endRing = new Vec3[sections]; + for (int i = 0; i < sections; i++) { + double angle = Math.PI * 2.0D * i / sections + phase; + Vec3 offset = side1.scale(Math.cos(angle) * radius).add(side2.scale(Math.sin(angle) * radius)); + startRing[i] = start.add(offset.scale(startScale)); + endRing[i] = end.add(offset); + } + float endV = scroll + (float) start.distanceTo(end) * uvLengthScale; + for (int i = 0; i < sections; i++) { + int next = (i + 1) % sections; + emitBeamQuad(vertices, pose, startRing[i], endRing[i], endRing[next], startRing[next], + i / (float) sections, scroll, next / (float) sections, endV, endAlpha); + } } - private static void drawQuad(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 a, Vec3 b, Vec3 c, Vec3 d) { - drawQuad(vertices, pose, a, b, c, d, 0.0F, 1.0F); + private static void emitBeamQuad(VertexConsumer vertices, org.joml.Matrix4f pose, + Vec3 a, Vec3 b, Vec3 c, Vec3 d, + float minU, float minV, float maxU, float maxV, int endAlpha) { + beamVertex(vertices, pose, a, minU, minV, 255); + beamVertex(vertices, pose, b, maxU, minV, endAlpha); + beamVertex(vertices, pose, c, maxU, maxV, endAlpha); + beamVertex(vertices, pose, d, minU, maxV, 255); } - private static void drawQuad(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 a, Vec3 b, Vec3 c, Vec3 d, float startV, float endV) { - vertex(vertices, pose, a, 0.0F, startV); vertex(vertices, pose, b, 1.0F, startV); vertex(vertices, pose, c, 1.0F, endV); vertex(vertices, pose, d, 0.0F, endV); + private static void drawBeamImpact(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 center, Vec3 direction, + Vec3 side1, Vec3 side2, float size) { + drawBillboard(vertices, pose, center, side1.scale(size), side2.scale(size)); + for (int i = 0; i < 8; i++) { + double angle = (i + 0.5D) * Math.PI * 0.25D; + Vec3 radial = side1.scale(Math.cos(angle)).add(side2.scale(Math.sin(angle))).scale(size); + Vec3 back = direction.scale(size * (i % 2 == 0 ? 1.5D : 1.0D)); + emitQuad(vertices, pose, center.add(radial), center.subtract(radial), + center.subtract(radial).subtract(back), center.add(radial).subtract(back)); + } + } + + private static void drawBillboard(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 center, Vec3 left, Vec3 up) { + emitQuad(vertices, pose, center.add(left).add(up), center.subtract(left).add(up), + center.subtract(left).subtract(up), center.add(left).subtract(up)); + emitQuad(vertices, pose, center.subtract(left).add(up), center.add(left).add(up), + center.add(left).subtract(up), center.subtract(left).subtract(up)); + } + + private static void emitQuad(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 a, Vec3 b, Vec3 c, Vec3 d) { + vertex(vertices, pose, a, 0.0F, 0.0F); + vertex(vertices, pose, b, 1.0F, 0.0F); + vertex(vertices, pose, c, 1.0F, 1.0F); + vertex(vertices, pose, d, 0.0F, 1.0F); } private static void vertex(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 pos, float u, float v) { vertices.addVertex(pose, (float) pos.x, (float) pos.y, (float) pos.z).setColor(255, 255, 255, 255).setUv(u, v) .setOverlay(net.minecraft.client.renderer.texture.OverlayTexture.NO_OVERLAY).setLight(0x00F000F0).setNormal(0.0F, 1.0F, 0.0F); } + + private static void beamVertex(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 pos, float u, float v, int alpha) { + vertices.addVertex(pose, (float) pos.x, (float) pos.y, (float) pos.z).setColor(255, 255, 255, alpha).setUv(u, v) + .setOverlay(net.minecraft.client.renderer.texture.OverlayTexture.NO_OVERLAY).setLight(0x00F000F0).setNormal(0.0F, -1.0F, 0.0F); + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/RainbowAntEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/RainbowAntEntity.java index 7a50da07..e642d24c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/RainbowAntEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ant/RainbowAntEntity.java @@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.entity.ant; import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.compat.infinity.InfinityCompat; +import com.craisinlord.antarchy.compat.infinity.InfinityWarpResult; import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.portal.RainbowPortalIgniter; @@ -62,7 +63,8 @@ public class RainbowAntEntity extends BaseAntEntity implements GeoEntity { return AntTeleportHelper.teleportPlayerToDimension(player, AntarchySettings.rainbowAntNonInfinityFallbackDimension()); } - if (!InfinityCompat.get().requestWarp(player, dimensionId)) { + InfinityWarpResult result = InfinityCompat.get().requestWarp(player, dimensionId); + if (result == InfinityWarpResult.REJECTED) { player.displayClientMessage(Component.translatable("message.antarchy.rainbow_ant_failed_dimension_create"), true); return InteractionResult.CONSUME; } @@ -356,9 +358,13 @@ public class RainbowAntEntity extends BaseAntEntity implements GeoEntity { } private boolean teleportToInfinity(ServerPlayer player, ResourceLocation dimensionId) { - if (!InfinityCompat.get().requestWarp(player, dimensionId)) { + InfinityWarpResult result = InfinityCompat.get().requestWarp(player, dimensionId); + if (result == InfinityWarpResult.FAILED_GENERATION) { this.deleteGeneratedArtifacts(player.server, dimensionId); - this.markForRerollOnNextReagent(); + player.displayClientMessage(Component.translatable("message.antarchy.rainbow_ant_failed_dimension_create"), true); + return false; + } + if (result == InfinityWarpResult.REJECTED) { player.displayClientMessage(Component.translatable("message.antarchy.rainbow_ant_failed_dimension_create"), true); return false; } @@ -377,9 +383,7 @@ public class RainbowAntEntity extends BaseAntEntity implements GeoEntity { .resolve(dimensionId.getPath()); this.deletePathRecursively(datapackPath); - if (dimensionPath != null) { - this.deletePathRecursively(dimensionPath); - } + this.deletePathRecursively(dimensionPath); } private void deletePathRecursively(Path path) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/lucid/LucidEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/lucid/LucidEntity.java index 5fa7de73..52f2bb4c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/lucid/LucidEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/lucid/LucidEntity.java @@ -33,6 +33,7 @@ import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import software.bernie.geckolib.animatable.GeoEntity; @@ -75,6 +76,8 @@ public class LucidEntity extends Monster implements GeoEntity { private static final double MIN_HOVER_RANGE = 6.5D; private static final double CLOSE_RANGE = 4.5D; private static final double DEFAULT_HOVER_HEIGHT = 2.75D; + private static final double NATURAL_SPAWN_LIMIT_RADIUS = 64.0D; + private static final int NATURAL_SPAWN_LIMIT = 5; private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle"); private static final RawAnimation FLY_ANIM = RawAnimation.begin().thenLoop("fly"); @@ -118,6 +121,7 @@ public class LucidEntity extends Monster implements GeoEntity { return level.getDifficulty() != Difficulty.PEACEFUL; } return level.getDifficulty() != Difficulty.PEACEFUL + && level.getEntitiesOfClass(LucidEntity.class, new AABB(pos).inflate(NATURAL_SPAWN_LIMIT_RADIUS), lucid -> lucid.isAlive()).size() < NATURAL_SPAWN_LIMIT && pos.getY() <= 250 && level.isEmptyBlock(pos) && level.isEmptyBlock(pos.above()) @@ -571,6 +575,3 @@ public class LucidEntity extends Monster implements GeoEntity { } - - - diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java index bbedb277..67ae7bdc 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java @@ -1,6 +1,5 @@ package com.craisinlord.antarchy.content.entity.portal; -import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchySoundEvents; @@ -181,13 +180,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { DimensionalTearEntity linked = this.findLinkedTear(); if (linked == null || !linked.isAlive()) { - Antarchy.LOGGER.warn( - "[antarchy-dimensional-tear] discarding unlinked tear uuid={} pos=({}, {}, {}) dim={} linkedTearId={} fallback=({}, {}, {}) ageTicks={} lifetimeTicks={}", - this.getUUID(), this.getX(), this.getY(), this.getZ(), this.level().dimension().location(), - this.linkedTearId, - this.linkedFallbackPos.x, this.linkedFallbackPos.y, this.linkedFallbackPos.z, - this.ageTicks, this.lifetimeTicks - ); this.discard(); return; } @@ -360,7 +352,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { private void teleportEntity(Entity entity, DimensionalTearEntity destination) { Vec3 motion = entity.getDeltaMovement(); - Vec3 startPos = entity.position(); Vec3 exitPos = destination.exitPosition(); TELEPORT_COOLDOWNS.put(entity.getUUID(), this.level().getGameTime() + TELEPORT_COOLDOWN_TICKS); @@ -374,13 +365,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { entity.hasImpulse = true; if (entity instanceof LivingEntity living) { int invertedDuration = AntarchySettings.dimensionalTearInvertedDurationTicks(); - Antarchy.LOGGER.debug( - "[antarchy-dimensional-tear] applying inverted effect targetType={} uuid={} fromTear={} toTear={} startPos=({}, {}, {}) exitPos=({}, {}, {}) dim={} durationTicks={}", - living.getType(), living.getUUID(), this.getUUID(), destination.getUUID(), - startPos.x, startPos.y, startPos.z, - exitPos.x, exitPos.y, exitPos.z, - this.level().dimension().location(), invertedDuration - ); living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), invertedDuration, 0)); } this.level().playSound(null, this.blockPosition(), SoundEvents.ENDERMAN_TELEPORT, SoundSource.NEUTRAL, 0.7F, 0.65F + this.random.nextFloat() * 0.2F); @@ -550,16 +534,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { this.queenManticoreCount = tag.getInt("QueenManticoreCount"); this.queenManticoreSpawned = tag.getBoolean("QueenManticoreSpawned"); } - if (!this.level().isClientSide) { - Antarchy.LOGGER.info( - "[antarchy-dimensional-tear] loaded tear uuid={} pos=({}, {}, {}) dim={} linkedTearId={} fallback=({}, {}, {}) ageTicks={} lifetimeTicks={} eventTicks={} nextEventTicks={} pendingEvent={} queenOwner={} queenManticoreCount={} queenManticoreSpawned={}", - this.getUUID(), this.getX(), this.getY(), this.getZ(), this.level().dimension().location(), - this.linkedTearId, - this.linkedFallbackPos.x, this.linkedFallbackPos.y, this.linkedFallbackPos.z, - this.ageTicks, this.lifetimeTicks, this.eventTicks, this.nextEventTicks, this.pendingEvent, - this.queenOwnerId, this.queenManticoreCount, this.queenManticoreSpawned - ); - } } @Override diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java index 28398935..bba9cd6e 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java @@ -114,6 +114,7 @@ public class KingEntity extends RoyalBossEntity { @Nullable private ServerPlayer exileTarget; private int exileTicks; + private boolean exileWingAnimationPending; @Nullable private ServerPlayer titheTarget; private int titheTicks; @@ -364,6 +365,7 @@ public class KingEntity extends RoyalBossEntity { return; } this.tickRoyalPunishment(); + this.tickPendingExileAnimation(); long gameTime = this.level().getGameTime(); this.judgmentCooldowns.entrySet().removeIf(entry -> entry.getValue() <= gameTime); this.lastPlayerDamageTime.entrySet().removeIf(entry -> gameTime - entry.getValue() > 600L); @@ -489,8 +491,25 @@ public class KingEntity extends RoyalBossEntity { away = away.normalize(); this.exileTarget.setDeltaMovement(away.x * 2.6D, 1.35D, away.z * 2.6D); this.exileTarget.hasImpulse = true; - this.triggerAnim("wing_action", "wing_gust"); this.playRoyalSound(AntarchySoundEvents.KING_WING_FLAP.get(), 0.82F); + this.exileWingAnimationPending = true; + } + } + + private void tickPendingExileAnimation() { + if (!this.exileWingAnimationPending + || !this.attackScheduler.ready("exile_wing_animation", RoyalAttackLane.BODY)) { + return; + } + if (this.beginRoyalAttack("exile_wing_animation", RoyalAttackLane.BODY, 1, 0, 1, + this.animationRecovery(55, 0, 1, 0), new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() { + @Override + public void onStart() { + KingEntity.this.exileWingAnimationPending = false; + KingEntity.this.triggerAnim("wing_action", "wing_gust"); + } + })) { + this.exileWingAnimationPending = false; } } @@ -551,6 +570,7 @@ public class KingEntity extends RoyalBossEntity { } this.exileTarget = null; this.exileTicks = 0; + this.exileWingAnimationPending = false; } private void clearTithe() { @@ -763,7 +783,7 @@ public class KingEntity extends RoyalBossEntity { } else if (this.attackScheduler.ready("wing_gust", RoyalAttackLane.BODY) && distance <= WING_GUST_RADIUS && (forceFar || this.random.nextInt(3) == 0) && this.beginRoyalAttack("wing_gust", RoyalAttackLane.BODY, WING_GUST_COOLDOWN_TICKS, - WING_GUST_WINDUP_TICKS, 1, 16, new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() { + WING_GUST_WINDUP_TICKS, 1, this.animationRecovery(55, WING_GUST_WINDUP_TICKS, 1, 16), new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() { @Override public void onStart() { KingEntity.this.triggerAnim("wing_action", "wing_gust"); KingEntity.this.playRoyalSound(AntarchySoundEvents.KING_WING_FLAP.get(), 0.85F); @@ -777,7 +797,8 @@ public class KingEntity extends RoyalBossEntity { && (forceFar || this.random.nextInt(4) == 0) && this.beginRoyalAttack("royal_muster", RoyalAttackLane.BODY, AntarchySettings.kingRoyalMusterCooldownTicks(), - AntarchySettings.kingRoyalMusterWindupTicks(), 1, 20, + AntarchySettings.kingRoyalMusterWindupTicks(), 1, + this.animationRecovery(59, AntarchySettings.kingRoyalMusterWindupTicks(), 1, 20), new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() { @Override public void onStart() { KingEntity.this.triggerAnim("body_action", "minion_spawn"); @@ -971,6 +992,15 @@ public class KingEntity extends RoyalBossEntity { } private void tickDecree(ServerLevel level, LivingEntity target) { + if (!(target instanceof ServerPlayer player) || !target.isAlive() || target.level() != level) { + if (this.activeDecree != null) { + this.endDecree(target); + } + this.activeDecree = null; + this.activeDecreeTicks = 0; + this.decreeRetreatPressure = false; + return; + } if (this.activeDecree == null) { if (this.decreeCooldownTicks-- > 0) { return; @@ -985,7 +1015,7 @@ public class KingEntity extends RoyalBossEntity { this.playRoyalSound(AntarchySoundEvents.KING_DECREE_CAST.get(), 0.9F + this.random.nextFloat() * 0.15F); this.playRoyalSound(AntarchySoundEvents.KING_ROAR.get(), 0.8F + this.random.nextFloat() * 0.12F); this.projectRoyalSound(AntarchySoundEvents.KING_DECREE.get(), 4.0F, 1.0F, target); - if (target instanceof ServerPlayer player) this.sendDecreeTitle(player); + this.sendDecreeTitle(player); } int countdown = this.activeDecree.countdownTicks(target); if (countdown > 0 && countdown <= 100 && this.tickCount % 20 == 0) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java index 53a3aa16..9021b0c9 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java @@ -76,6 +76,7 @@ public class QueenEntity extends RoyalBossEntity { private int blackHoleCooldownTicks; private final int[] dreamFireballCooldownTicks = new int[3]; private int idleWanderCooldownTicks; + private boolean manticoreAnimationPending; private final RoyalEffectController royalEffects = new RoyalEffectController(); private final Map frozenVelocities = new HashMap<>(); private long naturalTrailSiteId = Long.MIN_VALUE; @@ -229,6 +230,7 @@ public class QueenEntity extends RoyalBossEntity { this.tickIdleWander(); } this.tickManticoreSummon(); + this.tickPendingManticoreAnimation(); this.tickQueenAbilities(); this.tickDreamFireballs(); this.tickFinalAcceleration(); @@ -370,13 +372,30 @@ public class QueenEntity extends RoyalBossEntity { ? this.cooldown(Math.max(20, AntarchySettings.queenManticoreSummonCooldownTicks())) : FAILED_SUMMON_RETRY_TICKS; if (spawned > 0) { - this.triggerAnim("body_action", "minion_spawn"); + this.manticoreAnimationPending = true; this.playRoyalSound(AntarchySoundEvents.QUEEN_ROAR.get(), 0.8F + this.random.nextFloat() * 0.12F); serverLevel.sendParticles(ParticleTypes.PORTAL, this.getX(), this.getY() + 2.0D, this.getZ(), 36, 3.0D, 2.0D, 3.0D, 0.15D); } } + private void tickPendingManticoreAnimation() { + if (!this.manticoreAnimationPending + || !this.attackScheduler.ready("manticore_summon_animation", RoyalAttackLane.BODY)) { + return; + } + if (this.beginRoyalAttack("manticore_summon_animation", RoyalAttackLane.BODY, 1, 0, 1, + this.animationRecovery(59, 0, 1, 0), + new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() { + @Override public void onStart() { + QueenEntity.this.manticoreAnimationPending = false; + QueenEntity.this.triggerAnim("body_action", "minion_spawn"); + } + })) { + this.manticoreAnimationPending = false; + } + } + private int spawnManticoreTears(ServerLevel level, LivingEntity target, int count) { int pairs = Math.max(1, Math.min(3, (count + 1) / 2)); int created = 0; @@ -387,18 +406,26 @@ public class QueenEntity extends RoyalBossEntity { towardTarget = towardTarget.normalize(); Vec3 behindTarget = target.position().add(towardTarget.scale(8.0D)); Vec3 lateral = new Vec3(-towardTarget.z, 0.0D, towardTarget.x); + float tearYaw = (float) Math.toDegrees(Math.atan2(-towardTarget.x, towardTarget.z)); double vertical = AntarchyGravityApi.isGravityInverted(this) ? -2.0D : 2.0D; for (int i = 0; i < pairs; i++) { - double angle = this.random.nextDouble() * Mth.TWO_PI; - double distance = Math.max(8.0D, AntarchySettings.queenManticoreSummonRange() * 0.65D); - double spread = (i - (pairs - 1) * 0.5D) * 5.0D; - Vec3 pairCenter = behindTarget.add(lateral.scale(spread)).add(0.0D, vertical, 0.0D); - Vec3 firstPos = pairCenter.add(lateral.scale(3.0D)); - Vec3 secondPos = pairCenter.add(lateral.scale(-3.0D)); + double forwardScatter = 3.0D + this.random.nextDouble() * 9.0D; + double lateralScatter = (this.random.nextDouble() * 2.0D - 1.0D) * 11.0D; + double heightScatter = (this.random.nextDouble() * 2.0D - 1.0D) * 3.0D; + Vec3 pairCenter = behindTarget + .add(towardTarget.scale(forwardScatter)) + .add(lateral.scale(lateralScatter)) + .add(0.0D, vertical + heightScatter, 0.0D); + double pairAngle = this.random.nextDouble() * Mth.TWO_PI; + Vec3 pairDirection = towardTarget.scale(Math.cos(pairAngle)) + .add(lateral.scale(Math.sin(pairAngle))); + double pairSeparation = 3.5D + this.random.nextDouble() * 3.0D; + Vec3 firstPos = pairCenter.add(pairDirection.scale(pairSeparation)); + Vec3 secondPos = pairCenter.add(pairDirection.scale(-pairSeparation)); DimensionalTearEntity first = DimensionalTearEntity.createQueenManticoreTear(level, firstPos, - (float) Math.toDegrees(angle), 240, this.getUUID(), Math.min(3, count)); + tearYaw, 240, this.getUUID(), Math.min(3, count)); DimensionalTearEntity second = DimensionalTearEntity.createQueenManticoreTear(level, secondPos, - (float) Math.toDegrees(angle + Math.PI), 240, this.getUUID(), Math.min(3, count)); + tearYaw, 240, this.getUUID(), Math.min(3, count)); first.linkTo(second); second.linkTo(first); level.addFreshEntity(first); @@ -446,8 +473,12 @@ public class QueenEntity extends RoyalBossEntity { default -> ACCELERATION_COOLDOWN; }; RoyalAttackLane lane = "black_hole".equals(selected) ? RoyalAttackLane.CENTER_HEAD : RoyalAttackLane.HAZARD; + int actionWindup = 10; + int actionRecovery = "momentum_lock".equals(selected) + ? this.animationRecovery(55, actionWindup, 1, 14) + : this.animationRecovery(25, actionWindup, 1, 14); if (!this.beginRoyalAttack(selected, lane, this.cooldown(cooldown), - 10, 1, 14, new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() { + actionWindup, 1, actionRecovery, new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() { @Override public void onStart() { if ("gravity_stomp".equals(selected)) { QueenEntity.this.triggerAnim("body_action", "stomp"); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBoltEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBoltEntity.java index 4fdf081d..2cc46c0c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBoltEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBoltEntity.java @@ -93,6 +93,10 @@ public class RoyalBoltEntity extends AbstractHurtingProjectile { if (target == owner || (owner != null && target == owner.getVehicle())) { return; } + if (owner instanceof RoyalMountEntity royal && target instanceof RoyalMountEntity other + && royal.isTame() && other.isTame()) { + return; + } float damage = (float) AntarchySettings.royalBoltDamage(); target.hurt(this.damageSources().mobProjectile(this, owner instanceof LivingEntity le ? le : null), damage); if (target instanceof LivingEntity living) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java index bf96825b..860043df 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java @@ -64,7 +64,7 @@ import software.bernie.geckolib.util.GeckoLibUtil; public abstract class RoyalBossEntity extends Monster implements GeoEntity, MultipartEntityOwner { public static final float MODEL_RENDER_SCALE = 2.0F; - public static final float GAMEPLAY_WIDTH = 30.0F; + public static final float GAMEPLAY_WIDTH = 28.0F; public static final float GAMEPLAY_HEIGHT = 15.0F; public enum Phase { @@ -515,6 +515,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult } controller.tick( this.beamAnchor(head), + this.beamDirection(head), beamTarget, this.royalBeamSettings(), this.royalBeamTerrainMode(head), @@ -535,7 +536,8 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult if (!head.readyToAttack() || this.attackScheduler.laneBusy(this.headLane(head)) || target == null || !this.canAttack(target) || this.distanceTo(target) < this.royalBeamMinimumRange() - || this.headWithinBiteReach(head, target)) { + || this.headWithinBiteReach(head, target) + || !this.targetInBeamLine(head, target)) { continue; } RoyalBeamSettings beamSettings = this.royalBeamSettings(); @@ -588,7 +590,6 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult int index = head.slot().ordinal(); head.setBeamActive(false); head.stopShoot(); - this.stopTriggeredAnim(head.slot().controllerName(), null); this.beamControllers[index].stop(); this.entityData.set(BEAM_ACTIVE[index], false); this.entityData.set(BEAM_ELEMENT[index], RoyalBeamElement.GENERIC.ordinal()); @@ -656,7 +657,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult ? new Vec3(-dx / horizontalDistance, 0.0D, -dz / horizontalDistance) : this.getViewVector(1.0F).multiply(-1.0D, 0.0D, -1.0D).normalize(); double standoff = Math.max(this.getBbWidth() * 0.55D, - BEAM_MUZZLE_FORWARD - this.biteReach() * 0.65D); + BEAM_MUZZLE_FORWARD - this.biteReach() * 0.65D + 1.0D); Vec3 wanted = target.position().add(awayFromTarget.scale(standoff)); boolean atStandoff = this.position().multiply(1.0D, 0.0D, 1.0D) .distanceToSqr(wanted.multiply(1.0D, 0.0D, 1.0D)) <= 4.0D; @@ -827,6 +828,10 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult return this.attackScheduler.start(id, lane, cooldownTicks, windupTicks, activeTicks, protectedRecovery, action); } + protected int animationRecovery(int animationTicks, int windupTicks, int activeTicks, int recoveryTicks) { + return Math.max(recoveryTicks, animationTicks - Math.max(0, windupTicks) - Math.max(1, activeTicks)); + } + private void applyBiteHit(RoyalHead head) { if (this.level().isClientSide) { return; @@ -889,6 +894,26 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult return beamAnchor(head.slot(), this.getX(), this.getY(), this.getZ(), this.getYRot()); } + protected Vec3 beamDirection(RoyalHead head) { + float yaw = this.getYRot() * Mth.DEG_TO_RAD; + Vec3 localDirection = new Vec3(-Math.sin(yaw), 0.0D, Math.cos(yaw)); + return AntarchyGravityRotationUtil.vecPlayerToWorld(localDirection, + AntarchyGravityApi.getGravityDirection(this)).normalize(); + } + + private boolean targetInBeamLine(RoyalHead head, LivingEntity target) { + Vec3 origin = this.beamAnchor(head); + Vec3 direction = this.beamDirection(head); + Vec3 toTarget = target.getEyePosition().subtract(origin); + double forwardDistance = toTarget.dot(direction); + if (forwardDistance <= 0.0D) { + return false; + } + Vec3 perpendicular = toTarget.subtract(direction.scale(forwardDistance)); + double tolerance = Math.max(1.5D, target.getBbWidth() * 1.5D); + return perpendicular.lengthSqr() <= tolerance * tolerance; + } + private Vec3 beamAnchor(RoyalHead.Slot slot, double x, double y, double z, float yaw) { double yawRadians = yaw * Mth.DEG_TO_RAD; Vec3 forward = new Vec3(-Math.sin(yawRadians), 0.0D, Math.cos(yawRadians)); @@ -936,6 +961,9 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult this.setRoyalFlying(false); this.getNavigation().stop(); this.setDeltaMovement(Vec3.ZERO); + this.setXRot(0.0F); + this.setYHeadRot(this.getYRot()); + this.yBodyRot = this.getYRot(); } super.die(damageSource); } @@ -967,6 +995,9 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult protected void tickDeath() { this.deathTime++; this.setNoGravity(false); + this.setXRot(0.0F); + this.setYHeadRot(this.getYRot()); + this.yBodyRot = this.getYRot(); Vec3 movement = this.getDeltaMovement(); if (this.onGround()) { this.setDeltaMovement(movement.x * 0.6D, 0.0D, movement.z * 0.6D); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountEntity.java index 9c0be45e..9004cc5f 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountEntity.java @@ -445,6 +445,11 @@ public abstract class RoyalMountEntity extends TamableAnimal implements GeoEntit return; } + LivingEntity target = this.getTarget(); + if (target != null && !this.canAttack(target)) { + this.setTarget(null); + } + if (this.spitCooldown > 0) { this.spitCooldown--; } @@ -625,11 +630,17 @@ public abstract class RoyalMountEntity extends TamableAnimal implements GeoEntit if (target == null && this.getControllingPassenger() instanceof Player) { target = this.frontTarget(); } - if (target != null && target.distanceTo(this) < 5.0D) { + if (target != null && this.canAttack(target) && target.distanceTo(this) < 5.0D) { target.hurt(this.damageSources().mobAttack(this), (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE)); } } + @Override + public boolean canAttack(LivingEntity target) { + return !(target instanceof RoyalMountEntity other && this.isTame() && other.isTame()) + && super.canAttack(target); + } + @Nullable private LivingEntity frontTarget() { Vec3 look = this.getLookAngle(); @@ -640,6 +651,9 @@ public abstract class RoyalMountEntity extends TamableAnimal implements GeoEntit if (candidate == this || candidate == this.getControllingPassenger() || candidate == this.getOwner()) { continue; } + if (!this.canAttack(candidate)) { + continue; + } Vec3 to = candidate.getEyePosition().subtract(eye); double dist = to.length(); if (dist > 6.0D || dist < 1.0E-3D) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountSpitGoal.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountSpitGoal.java index 8c745920..1dfa4f6b 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountSpitGoal.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalMountSpitGoal.java @@ -17,7 +17,7 @@ public class RoyalMountSpitGoal extends Goal { return false; } LivingEntity target = this.mount.getTarget(); - if (target == null || !target.isAlive()) { + if (target == null || !target.isAlive() || !this.mount.canAttack(target)) { return false; } double distance = this.mount.distanceTo(target); @@ -32,7 +32,7 @@ public class RoyalMountSpitGoal extends Goal { @Override public void tick() { LivingEntity target = this.mount.getTarget(); - if (target == null) { + if (target == null || !this.mount.canAttack(target)) { return; } this.mount.getLookControl().setLookAt(target, 30.0F, 30.0F); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java index 96987cd3..0b0cb3fc 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java @@ -77,6 +77,17 @@ public final class RoyalBeamController { RoyalBeamSettings settings, RoyalBeamTerrainMode terrainMode, Consumer<@Nullable Vec3> syncedEndPosition + ) { + this.tick(shootFrom, owner.getLookAngle(), target, settings, terrainMode, syncedEndPosition); + } + + public void tick( + Vec3 shootFrom, + Vec3 shootDirection, + @Nullable LivingEntity target, + RoyalBeamSettings settings, + RoyalBeamTerrainMode terrainMode, + Consumer<@Nullable Vec3> syncedEndPosition ) { if (this.beamTicks <= 0) { syncedEndPosition.accept(null); @@ -100,11 +111,11 @@ public final class RoyalBeamController { return; } - Vec3 direction = this.serverTarget.subtract(shootFrom).normalize(); - if (direction.lengthSqr() < 1.0E-7D) { - direction = this.owner.getLookAngle(); - } - double committedDistance = Math.min(settings.range(), shootFrom.distanceTo(this.serverTarget)); + Vec3 direction = shootDirection.lengthSqr() < 1.0E-7D + ? this.owner.getLookAngle().normalize() + : shootDirection.normalize(); + double committedDistance = Math.min(settings.range(), Math.max(settings.pathStep(), + this.serverTarget.subtract(shootFrom).dot(direction))); double travelProgress = Mth.clamp(this.beamAgeTicks / (double) settings.travelTicks(), 0.0D, 1.0D); double currentRange = Math.max(settings.pathStep(), committedDistance * travelProgress); Vec3 clipEnd = shootFrom.add(direction.scale(currentRange)); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/vortex/WindVortexEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/vortex/WindVortexEntity.java index 6cb4341d..043e6b0e 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/vortex/WindVortexEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/vortex/WindVortexEntity.java @@ -106,7 +106,6 @@ public class WindVortexEntity extends Entity { public WindVortexEntity(EntityType entityType, Level level) { super(entityType, level); - this.noCulling = true; } public static WindVortexEntity create(Level level, EntityType type, Vec3 position, @@ -379,12 +378,6 @@ public class WindVortexEntity extends Entity { return; } - for (ServerPlayer player : serverLevel.players()) { - if (area.intersects(player.getBoundingBox())) { - this.captureEntity(player, height, basis, mode); - } - } - Iterator> iterator = this.carriedProgress.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationApi.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationApi.java index 1e9f99ee..325c2f28 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationApi.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationApi.java @@ -62,6 +62,11 @@ public final class TimeDilationApi { return getRate(entity) < TimeDilationMath.NORMAL_RATE; } + public static double getVehicleRate(Entity entity) { + Entity vehicle = entity.getVehicle(); + return vehicle == null ? TimeDilationMath.NORMAL_RATE : getRate(vehicle); + } + public static void enterRotationBypass() { ROTATION_BYPASS_DEPTH.set(ROTATION_BYPASS_DEPTH.get() + 1); } @@ -112,6 +117,10 @@ public final class TimeDilationApi { SYNCED_CLIENT_RATES.clear(); } + public static boolean hasSyncedClientRates() { + return !SYNCED_CLIENT_RATES.isEmpty(); + } + public static void syncEntityRate(Entity entity, double rate) { syncDispatcher.accept(entity, TimeDilationMath.clampRate(rate)); } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java index 3424521c..610db543 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java @@ -114,6 +114,7 @@ public class TimeDilationFieldEntity extends Entity { if (this.level().isClientSide) { return; } + TimeDilationManager.registerActiveField(this); if (this.anchorId != null && this.level() instanceof ServerLevel level) { Entity anchor = level.getEntity(this.anchorId); if (anchor != null && anchor.isAlive()) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationManager.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationManager.java index be0f88aa..67d39367 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationManager.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationManager.java @@ -19,14 +19,29 @@ import com.craisinlord.antarchy.content.effect.RoyalEffectHooks; public final class TimeDilationManager { private static final Map TRACKING = new WeakHashMap<>(); + private static final Map> ACTIVE_FIELDS = new WeakHashMap<>(); private TimeDilationManager() { } public static void tickServer(MinecraftServer server) { for (ServerLevel level : server.getAllLevels()) { - List fields = collectFields(level); - TrackingState tracking = TRACKING.computeIfAbsent(level, ignored -> new TrackingState()); + Set activeFields = ACTIVE_FIELDS.get(level); + if (activeFields != null) { + activeFields.removeIf(field -> !field.isAlive() || field.isRemoved()); + if (activeFields.isEmpty()) { + ACTIVE_FIELDS.remove(level); + activeFields = null; + } + } + TrackingState tracking = TRACKING.get(level); + if (activeFields == null && (tracking == null || tracking.entities.isEmpty())) { + continue; + } + List fields = activeFields == null ? List.of() : List.copyOf(activeFields); + if (tracking == null) { + tracking = TRACKING.computeIfAbsent(level, ignored -> new TrackingState()); + } discoverFieldEntities(level, fields, tracking); syncFieldSnapshots(level, fields, tracking); updateEntities(level, fields, tracking); @@ -39,6 +54,12 @@ public final class TimeDilationManager { } } + public static void registerActiveField(TimeDilationFieldEntity field) { + if (field.level() instanceof ServerLevel level) { + ACTIVE_FIELDS.computeIfAbsent(level, ignored -> Collections.newSetFromMap(new IdentityHashMap<>())).add(field); + } + } + public static void trackPotentiallyAffected(Entity entity) { if (!(entity.level() instanceof ServerLevel level) || entity instanceof TimeDilationFieldEntity) { return; @@ -46,6 +67,7 @@ public final class TimeDilationManager { if (entity instanceof TimeDilationEntityAccess access && Math.abs(access.antarchy$getTimeDilationRate() - TimeDilationMath.NORMAL_RATE) < 0.001D && Math.abs(access.antarchy$getInheritedTimeDilationRate() - TimeDilationMath.NORMAL_RATE) < 0.001D + && Math.abs(TimeDilationApi.getVehicleRate(entity) - TimeDilationMath.NORMAL_RATE) < 0.001D && (!(entity instanceof net.minecraft.world.entity.LivingEntity living) || ((RoyalEffectHooks.dilatedHolder() == null || !living.hasEffect(RoyalEffectHooks.dilatedHolder())) && (RoyalEffectHooks.contractedHolder() == null || !living.hasEffect(RoyalEffectHooks.contractedHolder()))))) { @@ -54,6 +76,32 @@ public final class TimeDilationManager { TRACKING.computeIfAbsent(level, ignored -> new TrackingState()).entities.add(entity); } + public static void resyncPersistentEffects(ServerPlayer player) { + if (!(player instanceof TimeDilationEntityAccess access)) { + return; + } + + double targetRate = TimeDilationMath.NORMAL_RATE; + if (RoyalEffectHooks.dilatedHolder() != null) { + var effect = player.getEffect(RoyalEffectHooks.dilatedHolder()); + if (effect != null) { + targetRate = Math.min(targetRate, DilatedMobEffect.rateForAmplifier(effect.getAmplifier())); + } + } + if (RoyalEffectHooks.contractedHolder() != null) { + var effect = player.getEffect(RoyalEffectHooks.contractedHolder()); + if (effect != null && targetRate >= TimeDilationMath.NORMAL_RATE) { + targetRate = Math.max(targetRate, ContractedMobEffect.rateForAmplifier(effect.getAmplifier())); + } + } + + if (Math.abs(targetRate - TimeDilationMath.NORMAL_RATE) >= 0.001D) { + access.antarchy$setTimeDilationRate(targetRate); + TimeDilationApi.syncEntityRate(player, targetRate); + } + trackPotentiallyAffected(player); + } + private static void syncFieldSnapshots(ServerLevel level, List fields, TrackingState tracking) { List snapshots = fields.stream() .filter(field -> !field.isChronosphere()) @@ -71,16 +119,6 @@ public final class TimeDilationManager { } } - private static List collectFields(ServerLevel level) { - List fields = new ArrayList<>(); - for (Entity entity : level.getAllEntities()) { - if (entity instanceof TimeDilationFieldEntity field && field.isAlive()) { - fields.add(field); - } - } - return fields; - } - private static void discoverFieldEntities(ServerLevel level, List fields, TrackingState tracking) { for (TimeDilationFieldEntity field : fields) { double radius = field.influenceRadius(); @@ -128,6 +166,12 @@ public final class TimeDilationManager { } } double inheritedRate = access.antarchy$getInheritedTimeDilationRate(); + double vehicleRate = TimeDilationApi.getVehicleRate(entity); + if (vehicleRate < TimeDilationMath.NORMAL_RATE) { + inheritedRate = Math.min(inheritedRate, vehicleRate); + } else { + inheritedRate = Math.max(inheritedRate, vehicleRate); + } if (entity instanceof Projectile projectile && projectile.getOwner() != null) { double ownerRate = TimeDilationApi.getRate(projectile.getOwner()); inheritedRate = ownerRate < TimeDilationMath.NORMAL_RATE diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java index f2ca3e7c..6d06cd49 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/gravity/EntityMoveMixin.java @@ -18,6 +18,8 @@ import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -35,6 +37,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; * Fixes move/landing logic that assumes down is always down. */ public abstract class EntityMoveMixin { + @Unique + private static final Logger ANTARCHY_STEP_LOGGER = LoggerFactory.getLogger("Antarchy/GravityStep"); + @Unique + private boolean antarchy$loggedInvertedCollide; + @Unique + private boolean antarchy$loggedHorizontalBlock; + @Unique + private boolean antarchy$loggedInvertedMove; @Unique private double antarchy$lastWorldMoveY = 0.0; @Unique @@ -49,6 +59,12 @@ public abstract class EntityMoveMixin { Entity entity = (Entity) (Object) this; this.antarchy$moveStartBox = entity.getBoundingBox(); this.antarchy$lastPlayerMoveY = movement.y; + if (AntarchyGravityApi.isGravityInverted(entity) && !this.antarchy$loggedInvertedMove) { + this.antarchy$loggedInvertedMove = true; + ANTARCHY_STEP_LOGGER.warn( + "Inverted move entered: entity={} movement={} noPhysics={} onGround={} box={}", + entity.getClass().getSimpleName(), movement, entity.noPhysics, entity.onGround(), entity.getBoundingBox()); + } } @ModifyVariable(method = "move", at = @At("HEAD"), ordinal = 0, argsOnly = true) @@ -149,6 +165,13 @@ public abstract class EntityMoveMixin { @Inject(method = "collide", at = @At("HEAD")) private void antarchy$captureCollideWorldMovement(Vec3 movement, CallbackInfoReturnable cir) { this.antarchy$collideWorldMovement = movement; + Entity entity = (Entity) (Object) this; + if (AntarchyGravityApi.isGravityInverted(entity) && !this.antarchy$loggedInvertedCollide) { + this.antarchy$loggedInvertedCollide = true; + ANTARCHY_STEP_LOGGER.warn( + "Inverted collide entered: entity={} movement={} onGround={} maxUpStep={} box={}", + entity.getClass().getSimpleName(), movement, entity.onGround(), entity.maxUpStep(), entity.getBoundingBox()); + } } /* @@ -239,6 +262,36 @@ public abstract class EntityMoveMixin { return AntarchyGravityRotationUtil.vecWorldToPlayer(worldResult, direction); } + /* + * Vanilla uses collideWithShapes directly for each step-height candidate, + * bypassing collideBoundingBox. At this point collide() is operating in the + * gravity-local frame, so leaving this call untouched makes an inverted + * entity test the candidate in the opposite horizontal and vertical world + * directions. The candidate consequently never beats the blocked movement. + */ + @WrapOperation( + method = "collide", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/Entity;collideWithShapes(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/List;)Lnet/minecraft/world/phys/Vec3;" + ) + ) + private Vec3 antarchy$collideStepCandidateInLocalFrame( + Vec3 localMovement, + AABB box, + List collisions, + Operation original + ) { + Entity entity = (Entity) (Object) this; + AntarchyGravityDirection direction = AntarchyGravityApi.getGravityDirection(entity); + if (!direction.isInverted()) { + return original.call(localMovement, box, collisions); + } + Vec3 worldMovement = AntarchyGravityRotationUtil.vecPlayerToWorld(localMovement, direction); + Vec3 worldResult = original.call(worldMovement, box, collisions); + return AntarchyGravityRotationUtil.vecWorldToPlayer(worldResult, direction); + } + @Redirect( method = "collide", at = @At( @@ -287,6 +340,15 @@ public abstract class EntityMoveMixin { return; } Vec3 worldResult = AntarchyGravityRotationUtil.vecPlayerToWorld(cir.getReturnValue(), direction); + Vec3 localMovement = AntarchyGravityRotationUtil.vecWorldToPlayer(this.antarchy$collideWorldMovement, direction); + if (!this.antarchy$loggedHorizontalBlock + && (localMovement.x != cir.getReturnValue().x || localMovement.z != cir.getReturnValue().z)) { + this.antarchy$loggedHorizontalBlock = true; + ANTARCHY_STEP_LOGGER.warn( + "Inverted horizontal block: localMovement={} localResult={} worldMovement={} worldResult={} onGround={} maxUpStep={} box={}", + localMovement, cir.getReturnValue(), this.antarchy$collideWorldMovement, worldResult, + entity.onGround(), entity.maxUpStep(), entity.getBoundingBox()); + } cir.setReturnValue(PortalGunCollisionHelper.resolveCollision( entity, entity.getBoundingBox(), diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/LivingEntityTimeDilationMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/LivingEntityTimeDilationMixin.java index 84e54b67..6b08ba28 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/LivingEntityTimeDilationMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/LivingEntityTimeDilationMixin.java @@ -2,6 +2,8 @@ package com.craisinlord.antarchy.mixins.time; import com.craisinlord.antarchy.content.time.TimeDilationApi; import com.craisinlord.antarchy.content.time.TimeDilationManager; +import com.craisinlord.antarchy.content.client.ContractionAfterimages; +import com.craisinlord.antarchy.content.effect.RoyalEffectHooks; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; @@ -14,7 +16,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public abstract class LivingEntityTimeDilationMixin { @Inject(method = "tickEffects", at = @At("HEAD")) private void antarchy$trackTemporalEffects(CallbackInfo ci) { - TimeDilationManager.trackPotentiallyAffected((Entity) (Object) this); + Entity entity = (Entity) (Object) this; + TimeDilationManager.trackPotentiallyAffected(entity); + if (entity.level().isClientSide && RoyalEffectHooks.contractedHolder() != null) { + ContractionAfterimages.observe((LivingEntity) entity); + } } @Inject(method = "updateSwingTime", at = @At("HEAD"), cancellable = true) diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/SoundEngineTimeDilationMixin.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/SoundEngineTimeDilationMixin.java index feb4ff35..d226c288 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/SoundEngineTimeDilationMixin.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/mixins/time/SoundEngineTimeDilationMixin.java @@ -9,15 +9,33 @@ import com.craisinlord.antarchy.content.effect.RoyalEffectHooks; import com.craisinlord.antarchy.mixins.client.EntityBoundSoundInstanceAccessor; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.client.sounds.ChannelAccess; import net.minecraft.client.sounds.SoundEngine; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Map; @Mixin(SoundEngine.class) public abstract class SoundEngineTimeDilationMixin { + @Shadow @Final private Map instanceToChannel; + + @Inject(method = "tickNonPaused", at = @At("TAIL")) + private void antarchy$refreshActiveSoundPitches(CallbackInfo ci) { + if (!ClientTimeDilationTicker.hasActiveDilation()) { + return; + } + this.instanceToChannel.forEach((sound, channel) -> + channel.execute(audioChannel -> audioChannel.setPitch(this.antarchy$dilatePitch(sound.getPitch(), sound)))); + } + @ModifyReturnValue(method = "calculatePitch", at = @At("RETURN")) private float antarchy$dilatePitch(float pitch, SoundInstance sound) { double rate = ClientTimeDilationTicker.rateAt(sound.getX(), sound.getY(), sound.getZ()); diff --git a/common-1.21.1/src/main/resources/data/antarchy/loot_table/spawners/undertrial.json b/common-1.21.1/src/main/resources/data/antarchy/loot_table/spawners/undertrial.json index d656a234..6e105225 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/loot_table/spawners/undertrial.json +++ b/common-1.21.1/src/main/resources/data/antarchy/loot_table/spawners/undertrial.json @@ -26,7 +26,7 @@ }, { "type": "minecraft:item", - "name": "antarchy:cornea_stalk", + "name": "antarchy:cornea_ear", "weight": 8, "functions": [ { diff --git a/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_castle.json b/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_castle.json index 5de325a1..b58b7c96 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_castle.json +++ b/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_castle.json @@ -10,7 +10,12 @@ "biomes": "#antarchy:has_structure/underside_castle_biomes", "step": "underground_structures", "enhanced_terrain_adaptation": { - "type": "integrated_api:none" + "type": "integrated_api:custom", + "carves": true, + "beards": true, + "kernel_size": 35, + "kernel_distance": 35, + "direction": "up" }, "start_height": { "type": "minecraft:constant", diff --git a/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_ruins.json b/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_ruins.json index a0b424d2..a2a448d5 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_ruins.json +++ b/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/underside_ruins.json @@ -10,7 +10,12 @@ "biomes": "#antarchy:has_structure/underside_ruins_biomes", "step": "underground_structures", "enhanced_terrain_adaptation": { - "type": "integrated_api:none" + "type": "integrated_api:custom", + "carves": true, + "beards": true, + "kernel_size": 35, + "kernel_distance": 35, + "direction": "up" }, "start_height": { "type": "minecraft:constant", diff --git a/common-1.21.1/src/main/resources/data/c/tags/item/stones.json b/common-1.21.1/src/main/resources/data/c/tags/item/stones.json index 21acb8ee..e471d6fe 100644 --- a/common-1.21.1/src/main/resources/data/c/tags/item/stones.json +++ b/common-1.21.1/src/main/resources/data/c/tags/item/stones.json @@ -1,7 +1,6 @@ { "replace": false, "values": [ - "minecraft:slime_ball", - "antarchy:flytrap_goo" + "minecraft:slime_ball" ] } diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java index 7a6b83b5..f676c83d 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java @@ -72,8 +72,14 @@ public final class AntarchyFabricEvents { } public static void register() { - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> ChronosphereManager.refresh(handler.player)); - ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> ChronosphereManager.refresh(newPlayer)); + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + ChronosphereManager.refresh(handler.player); + TimeDilationManager.resyncPersistentEffects(handler.player); + }); + ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> { + ChronosphereManager.refresh(newPlayer); + TimeDilationManager.resyncPersistentEffects(newPlayer); + }); ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.register((player, origin, destination) -> ChronosphereManager.refresh(player)); net.fabricmc.fabric.api.networking.v1.EntityTrackingEvents.START_TRACKING.register((trackedEntity, player) -> { if (trackedEntity instanceof com.craisinlord.antarchy.content.time.TimeDilationEntityAccess access diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/FabricInfinityCompat.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/FabricInfinityCompat.java index c4b87547..5950cb2a 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/FabricInfinityCompat.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/FabricInfinityCompat.java @@ -2,6 +2,7 @@ package com.craisinlord.antarchy.fabric; import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.compat.infinity.InfinityCompatBridge; +import com.craisinlord.antarchy.compat.infinity.InfinityWarpResult; import net.lerariemann.infinity.util.InfinityMethods; import net.lerariemann.infinity.util.teleport.PortalCreator; import net.lerariemann.infinity.util.teleport.WarpLogic; @@ -38,13 +39,15 @@ public final class FabricInfinityCompat implements InfinityCompatBridge { } @Override - public boolean requestWarp(ServerPlayer player, ResourceLocation dimensionId) { + public InfinityWarpResult requestWarp(ServerPlayer player, ResourceLocation dimensionId) { try { WarpLogic.requestWarp(player, dimensionId, false); - return true; + return InfinityWarpResult.PENDING; } catch (Throwable throwable) { Antarchy.LOGGER.error("[Antarchy] Failed to request an Infinity warp to {}", dimensionId, throwable); - return false; + return InfinityGenerationFailure.consume(dimensionId) + ? InfinityWarpResult.FAILED_GENERATION + : InfinityWarpResult.REJECTED; } } diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/InfinityGenerationFailure.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/InfinityGenerationFailure.java new file mode 100644 index 00000000..65273889 --- /dev/null +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/InfinityGenerationFailure.java @@ -0,0 +1,20 @@ +package com.craisinlord.antarchy.fabric; + +import net.minecraft.resources.ResourceLocation; + +public final class InfinityGenerationFailure { + private static final ThreadLocal FAILURE = new ThreadLocal<>(); + + private InfinityGenerationFailure() { + } + + public static void mark(ResourceLocation dimensionId) { + FAILURE.set(dimensionId); + } + + public static boolean consume(ResourceLocation dimensionId) { + ResourceLocation failed = FAILURE.get(); + FAILURE.remove(); + return dimensionId.equals(failed); + } +} diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/entity/multipart/MultipartPartEntity.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/entity/multipart/MultipartPartEntity.java index 2402dfd8..4558ff17 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/entity/multipart/MultipartPartEntity.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/entity/multipart/MultipartPartEntity.java @@ -4,6 +4,8 @@ import com.craisinlord.antarchy.content.entity.multipart.MultipartEntityOwner; import com.craisinlord.antarchy.content.entity.multipart.MultipartFramework; import com.craisinlord.antarchy.content.entity.multipart.MultipartPartAccess; import com.craisinlord.antarchy.content.entity.multipart.MultipartPartDefinition; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -64,17 +66,27 @@ public class MultipartPartEntity extends Entity implements MultipartPartAccess { return; } + AntarchyGravityApi.applySyncedState( + this, + AntarchyGravityApi.getGravityDirection(parent), + AntarchyGravityApi.getPrevGravityDirection(parent), + AntarchyGravityApi.isGravityForced(parent), + AntarchyGravityApi.getTransitionDuration(parent), + AntarchyGravityApi.getTransitionRemaining(parent) + ); + double oldX = this.getX(); double oldY = this.getY(); double oldZ = this.getZ(); double yawRadians = Math.toRadians(parent.getYRot()); Vec3 forward = new Vec3(-Math.sin(yawRadians), 0.0D, Math.cos(yawRadians)); Vec3 right = new Vec3(forward.z, 0.0D, -forward.x); - Vec3 position = new Vec3( - parent.getX() + forward.x * definition.forwardOffset() + right.x * definition.lateralOffset(), - parent.getY() + definition.yOffset(), - parent.getZ() + forward.z * definition.forwardOffset() + right.z * definition.lateralOffset() - ); + Vec3 localOffset = new Vec3( + forward.x * definition.forwardOffset() + right.x * definition.lateralOffset(), + definition.yOffset() + (AntarchyGravityApi.isGravityInverted(parent) ? definition.height() : 0.0D), + forward.z * definition.forwardOffset() + right.z * definition.lateralOffset()); + Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(localOffset, AntarchyGravityApi.getGravityDirection(parent)); + Vec3 position = parent.position().add(offset); this.setPos(position.x, position.y, position.z); this.setYRot(parent.getYRot()); this.setXRot(parent.getXRot()); diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/infinity/WarpLogicMixin.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/infinity/WarpLogicMixin.java new file mode 100644 index 00000000..6876fad3 --- /dev/null +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/infinity/WarpLogicMixin.java @@ -0,0 +1,34 @@ +package com.craisinlord.antarchy.fabric.mixin.infinity; + +import com.craisinlord.antarchy.fabric.InfinityGenerationFailure; +import net.lerariemann.infinity.access.MinecraftServerAccess; +import net.lerariemann.infinity.util.teleport.PortalCreator; +import net.lerariemann.infinity.util.teleport.WarpLogic; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(WarpLogic.class) +public interface WarpLogicMixin { + @Redirect( + method = "requestWarp(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/resources/ResourceLocation;Z)V", + at = @At(value = "INVOKE", target = "Lnet/lerariemann/infinity/util/teleport/PortalCreator;tryAddInfinityDimension(Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/resources/ResourceLocation;)Z") + ) + private static boolean antarchy$queuedDimensionCountsAsNew(MinecraftServer server, ResourceLocation dimensionId) throws Throwable { + ResourceKey key = ResourceKey.create(Registries.DIMENSION, dimensionId); + if (server instanceof MinecraftServerAccess access && access.infinity$hasToAdd(key)) { + return true; + } + try { + return PortalCreator.tryAddInfinityDimension(server, dimensionId); + } catch (Throwable throwable) { + InfinityGenerationFailure.mark(dimensionId); + throw throwable; + } + } +} diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java index a2702838..257bbe66 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java @@ -1036,10 +1036,10 @@ public final class AntarchyFabricItems { public static final DeferredItem HERCULES_HORN = ITEMS.registerSimpleItem("hercules_horn", new Item.Properties().rarity(Rarity.UNCOMMON)); - public static final DeferredItem KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE)); + public static final DeferredItem KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant()); - public static final DeferredItem QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE)); + public static final DeferredItem QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant()); public static final DeferredItem CHITIN = ITEMS.registerSimpleItem("chitin", new Item.Properties().rarity(Rarity.UNCOMMON)); diff --git a/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json b/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json index 6def395f..09089132 100644 --- a/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json +++ b/fabric-1.21.1/src/main/resources/antarchy-fabric.mixins.json @@ -21,6 +21,7 @@ "entity.MultipartEntityLevelRegistryMixin", "WoodTypeInvoker", "infinity.PortalCreatorMixin", + "infinity.WarpLogicMixin", "infinity.AmendmentRareOresMixin" ], "client": [ diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/InfinityGenerationFailure.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/InfinityGenerationFailure.java new file mode 100644 index 00000000..1691059e --- /dev/null +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/InfinityGenerationFailure.java @@ -0,0 +1,20 @@ +package com.craisinlord.antarchy.neoforge; + +import net.minecraft.resources.ResourceLocation; + +public final class InfinityGenerationFailure { + private static final ThreadLocal FAILURE = new ThreadLocal<>(); + + private InfinityGenerationFailure() { + } + + public static void mark(ResourceLocation dimensionId) { + FAILURE.set(dimensionId); + } + + public static boolean consume(ResourceLocation dimensionId) { + ResourceLocation failed = FAILURE.get(); + FAILURE.remove(); + return dimensionId.equals(failed); + } +} diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/NeoForgeInfinityCompat.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/NeoForgeInfinityCompat.java index 166f9b99..11184f41 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/NeoForgeInfinityCompat.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/NeoForgeInfinityCompat.java @@ -2,6 +2,7 @@ package com.craisinlord.antarchy.neoforge; import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.compat.infinity.InfinityCompatBridge; +import com.craisinlord.antarchy.compat.infinity.InfinityWarpResult; import net.lerariemann.infinity.InfinityMod; import net.lerariemann.infinity.util.InfinityMethods; import net.lerariemann.infinity.util.teleport.PortalCreator; @@ -69,13 +70,15 @@ public final class NeoForgeInfinityCompat implements InfinityCompatBridge { } @Override - public boolean requestWarp(ServerPlayer player, ResourceLocation dimensionId) { + public InfinityWarpResult requestWarp(ServerPlayer player, ResourceLocation dimensionId) { try { WarpLogic.requestWarp(player, dimensionId, false); - return true; + return InfinityWarpResult.PENDING; } catch (Throwable throwable) { Antarchy.LOGGER.error("[Antarchy] Failed to request an Infinity warp to {}", dimensionId, throwable); - return false; + return InfinityGenerationFailure.consume(dimensionId) + ? InfinityWarpResult.FAILED_GENERATION + : InfinityWarpResult.REJECTED; } } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/entity/multipart/MultipartPartEntity.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/entity/multipart/MultipartPartEntity.java index 554ec3ed..7693bb21 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/entity/multipart/MultipartPartEntity.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/entity/multipart/MultipartPartEntity.java @@ -4,6 +4,8 @@ import com.craisinlord.antarchy.content.entity.multipart.MultipartEntityOwner; import com.craisinlord.antarchy.content.entity.multipart.MultipartFramework; import com.craisinlord.antarchy.content.entity.multipart.MultipartPartAccess; import com.craisinlord.antarchy.content.entity.multipart.MultipartPartDefinition; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; +import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -67,17 +69,27 @@ public class MultipartPartEntity extends PartEntity implements OwnableEn return; } + AntarchyGravityApi.applySyncedState( + this, + AntarchyGravityApi.getGravityDirection(parent), + AntarchyGravityApi.getPrevGravityDirection(parent), + AntarchyGravityApi.isGravityForced(parent), + AntarchyGravityApi.getTransitionDuration(parent), + AntarchyGravityApi.getTransitionRemaining(parent) + ); + double oldX = this.getX(); double oldY = this.getY(); double oldZ = this.getZ(); double yawRadians = Math.toRadians(parent.getYRot()); Vec3 forward = new Vec3(-Math.sin(yawRadians), 0.0D, Math.cos(yawRadians)); Vec3 right = new Vec3(forward.z, 0.0D, -forward.x); - Vec3 position = new Vec3( - parent.getX() + forward.x * this.definition.forwardOffset() + right.x * this.definition.lateralOffset(), - parent.getY() + this.definition.yOffset(), - parent.getZ() + forward.z * this.definition.forwardOffset() + right.z * this.definition.lateralOffset() - ); + Vec3 localOffset = new Vec3( + forward.x * this.definition.forwardOffset() + right.x * this.definition.lateralOffset(), + this.definition.yOffset() + (AntarchyGravityApi.isGravityInverted(parent) ? this.definition.height() : 0.0D), + forward.z * this.definition.forwardOffset() + right.z * this.definition.lateralOffset()); + Vec3 offset = AntarchyGravityRotationUtil.vecPlayerToWorld(localOffset, AntarchyGravityApi.getGravityDirection(parent)); + Vec3 position = parent.position().add(offset); this.setPos(position.x, position.y, position.z); this.setRot(parent.getYRot(), parent.getXRot()); this.xo = oldX; diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/ConfigGenInvocationMixin.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/ConfigGenInvocationMixin.java index 3e00b4a2..9288ebb3 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/ConfigGenInvocationMixin.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/ConfigGenInvocationMixin.java @@ -9,11 +9,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(value = ConfigGenInvocation.class, remap = false) -/* - * Guards against a NPE in Infinite Dimensions' SurfaceRuleScanner when another mod - * registers a surface rule with a missing "biome_is" field. Without this, the crash - * propagates up through PlayerList.placeNewPlayer and kicks the player on login - */ public class ConfigGenInvocationMixin { @Redirect( diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/WarpLogicMixin.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/WarpLogicMixin.java new file mode 100644 index 00000000..27a0666e --- /dev/null +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/mixins/infinity/WarpLogicMixin.java @@ -0,0 +1,35 @@ +package com.craisinlord.antarchy.neoforge.mixins.infinity; + +import com.craisinlord.antarchy.neoforge.InfinityGenerationFailure; +import net.lerariemann.infinity.access.MinecraftServerAccess; +import net.lerariemann.infinity.util.teleport.PortalCreator; +import net.lerariemann.infinity.util.teleport.WarpLogic; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(value = WarpLogic.class, remap = false) +public interface WarpLogicMixin { + @Redirect( + method = "requestWarp(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/resources/ResourceLocation;Z)V", + at = @At(value = "INVOKE", target = "Lnet/lerariemann/infinity/util/teleport/PortalCreator;tryAddInfinityDimension(Lnet/minecraft/server/MinecraftServer;Lnet/minecraft/resources/ResourceLocation;)Z"), + remap = false + ) + private static boolean antarchy$queuedDimensionCountsAsNew(MinecraftServer server, ResourceLocation dimensionId) throws Throwable { + ResourceKey key = ResourceKey.create(Registries.DIMENSION, dimensionId); + if (server instanceof MinecraftServerAccess access && access.infinity$hasToAdd(key)) { + return true; + } + try { + return PortalCreator.tryAddInfinityDimension(server, dimensionId); + } catch (Throwable throwable) { + InfinityGenerationFailure.mark(dimensionId); + throw throwable; + } + } +} diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/MultipartNetworking.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/MultipartNetworking.java index 2287c37f..212df5e6 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/MultipartNetworking.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/network/MultipartNetworking.java @@ -57,8 +57,7 @@ public final class MultipartNetworking { return; } - DamageSource source = serverPlayer.level().damageSources().playerAttack(serverPlayer); - owner.antarchy$hurtMultipartPart(part, source, payload.damage()); + serverPlayer.attack(part); }); } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java index d260c3ec..52ecfb0d 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java @@ -143,6 +143,8 @@ public final class AntarchyNeoForgeEvents { NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleBloodglassPlayerDeath); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleBloodglassRespawn); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleBloodglassLogin); + NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleTimeDilationLogin); + NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleTimeDilationRespawn); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleCavarynHordeKill); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::handleCavarynHordeBlockBreak); NeoForge.EVENT_BUS.addListener(AntarchyNeoForgeEvents::tickCavarynHordes); @@ -213,7 +215,8 @@ public final class AntarchyNeoForgeEvents { && tickEnd > 0L && now - tickEnd >= SERVER_IDLE_BUSY_WARN_NANOS && state != Thread.State.WAITING - && state != Thread.State.TIMED_WAITING; + && state != Thread.State.TIMED_WAITING + && !antarchy$isServerThreadIdleWait(tickThread); if (idleBusy) { antarchy$dumpServerThreadWatchdog( "server thread busy outside active tick", @@ -238,6 +241,18 @@ public final class AntarchyNeoForgeEvents { } } + private static boolean antarchy$isServerThreadIdleWait(Thread tickThread) { + for (StackTraceElement element : tickThread.getStackTrace()) { + String method = element.getMethodName(); + if (method.equals("waitUntilNextTick") + || method.equals("waitForTasks") + || method.equals("managedBlock")) { + return true; + } + } + return false; + } + static void onVillagerTrades(VillagerTradesEvent event) { if (event.getType() == VillagerProfession.FARMER) { event.getTrades().get(1).add(emeraldForItems(AntarchyObjects.CORN.get(), 20, 16, 2)); @@ -384,6 +399,18 @@ public final class AntarchyNeoForgeEvents { } } + static void handleTimeDilationLogin(PlayerEvent.PlayerLoggedInEvent event) { + if (event.getEntity() instanceof ServerPlayer player) { + TimeDilationManager.resyncPersistentEffects(player); + } + } + + static void handleTimeDilationRespawn(PlayerEvent.PlayerRespawnEvent event) { + if (event.getEntity() instanceof ServerPlayer player) { + TimeDilationManager.resyncPersistentEffects(player); + } + } + static void handleTigerEyeLogout(PlayerEvent.PlayerLoggedOutEvent event) { if (event.getEntity() instanceof ServerPlayer player) { TigerEyeCamouflageController.deactivate(player, false); @@ -561,15 +588,6 @@ public final class AntarchyNeoForgeEvents { } if (existingInverted == null || existingInverted.getDuration() <= ANTIMETAL_INVERTED_REFRESH_THRESHOLD_TICKS) { - if (livingEntity instanceof Player || livingEntity.level().dimension().location().toString().equals("antarchy:thoraxis")) { - Antarchy.LOGGER.info( - "[antarchy-gravity] overhead antimetal applying inverted effect targetType={} uuid={} pos=({}, {}, {}) dim={} existingDuration={} gameTime={}", - livingEntity.getType(), livingEntity.getUUID(), livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), - livingEntity.level().dimension().location(), - existingInverted != null ? existingInverted.getDuration() : -1, - gameTime - ); - } livingEntity.addEffect(new MobEffectInstance(AntarchyNeoforgeMisc.INVERTED, ANTIMETAL_INVERTED_REFRESH_TICKS, 0, false, false, false)); spawnAntimetalInversionParticles(livingEntity); } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java index f63da2c6..064e3775 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java @@ -717,8 +717,8 @@ public final class AntarchyNeoforgeItems { public static final DeferredItem MANTIS_CLAW = ITEMS.register("mantis_claw", () -> new MantisClawItem(Tiers.IRON, new Item.Properties().stacksTo(1).durability(50).rarity(Rarity.UNCOMMON))); public static final DeferredItem HERCULES_HORN = ITEMS.registerSimpleItem("hercules_horn", new Item.Properties().rarity(Rarity.UNCOMMON)); - public static final DeferredItem KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE)); - public static final DeferredItem QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE)); + public static final DeferredItem KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant()); + public static final DeferredItem QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant()); public static final DeferredItem CHITIN = ITEMS.registerSimpleItem("chitin", new Item.Properties().rarity(Rarity.UNCOMMON)); public static final DeferredItem JERRY_NUCLEUS = ITEMS.register("jerry_nucleus", () -> new com.craisinlord.antarchy.content.item.JerryNucleusItem(new Item.Properties().rarity(Rarity.UNCOMMON) diff --git a/neoforge-1.21.1/src/main/resources/antarchy-neoforge.mixins.json b/neoforge-1.21.1/src/main/resources/antarchy-neoforge.mixins.json index 0f558385..bdf8ea3c 100644 --- a/neoforge-1.21.1/src/main/resources/antarchy-neoforge.mixins.json +++ b/neoforge-1.21.1/src/main/resources/antarchy-neoforge.mixins.json @@ -12,6 +12,7 @@ "infinity.AmendmentRareOresMixin", "infinity.ConfigGenInvocationMixin", "infinity.PortalCreatorMixin", + "infinity.WarpLogicMixin", "level.ClientLevelPartEntitiesAccessor", "level.ServerLevelPartEntitiesAccessor" ],