fix king and queen attack anim bug
stabalize RainbowAntEntity dims patch config inconsitency fixed undervault performance improvements
This commit is contained in:
1 parent
377f3785af
commit
37e941915d
47 files changed
+778
-225
No files matched your search
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.craisinlord.antarchy.compat.infinity;
|
||||
|
||||
public enum InfinityWarpResult {
|
||||
REJECTED,
|
||||
PENDING,
|
||||
READY,
|
||||
FAILED_GENERATION,
|
||||
TIMEOUT
|
||||
}
|
||||
+23
@@ -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 <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
|
||||
if (this.blockEntityType == null || type != this.blockEntityType.get()) {
|
||||
|
||||
+5
@@ -163,4 +163,9 @@ public final class ClientTimeDilationTicker {
|
||||
public static void applyFields(List<TimeDilationFieldSnapshot> fields) {
|
||||
activeFields = List.copyOf(fields);
|
||||
}
|
||||
|
||||
public static boolean hasActiveDilation() {
|
||||
return !activeFields.isEmpty()
|
||||
|| com.craisinlord.antarchy.content.time.TimeDilationApi.hasSyncedClientRates();
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -33,21 +33,20 @@ public final class ContractionAfterimages {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (holder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Entity entity : level.entitiesForRendering()) {
|
||||
if (!(entity instanceof LivingEntity living) || living.isInvisible() || !living.hasEffect(holder)) {
|
||||
continue;
|
||||
public static void observe(LivingEntity living) {
|
||||
Holder<MobEffect> holder = RoyalEffectHooks.contractedHolder();
|
||||
if (holder == null || living.isInvisible() || !living.hasEffect(holder)) {
|
||||
return;
|
||||
}
|
||||
int now = (int) (living.level().getGameTime() & 0x7fffffffL);
|
||||
Deque<Sample> samples = HISTORY.computeIfAbsent(living, ignored -> new ArrayDeque<>());
|
||||
samples.addFirst(new Sample(living, now));
|
||||
while (samples.size() > MAX_SAMPLES) {
|
||||
samples.removeLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Deque<Sample> samples(LivingEntity entity) {
|
||||
return HISTORY.get(entity);
|
||||
|
||||
-33
@@ -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<RoyalBossEntity> {
|
||||
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<RoyalBossEntity> {
|
||||
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
|
||||
|
||||
+24
@@ -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<RoyalMountEntity> {
|
||||
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<RoyalMountEntity> {
|
||||
public ResourceLocation getAnimationResource(RoyalMountEntity animatable) {
|
||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/" + animatable.geoNameForRender() + ".animation.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomAnimations(RoyalMountEntity animatable, long instanceId,
|
||||
AnimationState<RoyalMountEntity> 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);
|
||||
}
|
||||
}
|
||||
+26
@@ -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));
|
||||
}
|
||||
}
|
||||
+80
-38
@@ -25,22 +25,28 @@ import software.bernie.geckolib.util.Color;
|
||||
public class RoyalBossRenderer extends GeoEntityRenderer<RoyalBossEntity> {
|
||||
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<RoyalBossEntity> {
|
||||
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<RoyalBossEntity> {
|
||||
|
||||
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<RoyalBossEntity> {
|
||||
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<RoyalBossEntity> {
|
||||
}
|
||||
|
||||
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<RoyalBossEntity> {
|
||||
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<RoyalBossEntity> {
|
||||
.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);
|
||||
}
|
||||
}
|
||||
+79
-22
@@ -19,16 +19,20 @@ import software.bernie.geckolib.renderer.GeoEntityRenderer;
|
||||
public class RoyalMountRenderer extends GeoEntityRenderer<RoyalMountEntity> {
|
||||
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<RoyalMountEntity> {
|
||||
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<RoyalMountEntity> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
+9
-5
@@ -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,10 +383,8 @@ public class RainbowAntEntity extends BaseAntEntity implements GeoEntity {
|
||||
.resolve(dimensionId.getPath());
|
||||
|
||||
this.deletePathRecursively(datapackPath);
|
||||
if (dimensionPath != null) {
|
||||
this.deletePathRecursively(dimensionPath);
|
||||
}
|
||||
}
|
||||
|
||||
private void deletePathRecursively(Path path) {
|
||||
if (!Files.exists(path)) {
|
||||
|
||||
+4
-3
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
-26
@@ -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
|
||||
|
||||
+34
-4
@@ -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) {
|
||||
|
||||
+41
-10
@@ -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<UUID, Vec3> 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");
|
||||
|
||||
+4
@@ -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) {
|
||||
|
||||
+35
-4
@@ -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);
|
||||
|
||||
+15
-1
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
+16
-5
@@ -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));
|
||||
|
||||
-7
@@ -106,7 +106,6 @@ public class WindVortexEntity extends Entity {
|
||||
|
||||
public WindVortexEntity(EntityType<? extends WindVortexEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
this.noCulling = true;
|
||||
}
|
||||
|
||||
public static WindVortexEntity create(Level level, EntityType<? extends WindVortexEntity> 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<Map.Entry<UUID, Double>> iterator = this.carriedProgress.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<UUID, Double> entry = iterator.next();
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
+1
@@ -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()) {
|
||||
|
||||
+56
-12
@@ -19,14 +19,29 @@ import com.craisinlord.antarchy.content.effect.RoyalEffectHooks;
|
||||
|
||||
public final class TimeDilationManager {
|
||||
private static final Map<ServerLevel, TrackingState> TRACKING = new WeakHashMap<>();
|
||||
private static final Map<ServerLevel, Set<TimeDilationFieldEntity>> ACTIVE_FIELDS = new WeakHashMap<>();
|
||||
|
||||
private TimeDilationManager() {
|
||||
}
|
||||
|
||||
public static void tickServer(MinecraftServer server) {
|
||||
for (ServerLevel level : server.getAllLevels()) {
|
||||
List<TimeDilationFieldEntity> fields = collectFields(level);
|
||||
TrackingState tracking = TRACKING.computeIfAbsent(level, ignored -> new TrackingState());
|
||||
Set<TimeDilationFieldEntity> 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<TimeDilationFieldEntity> 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<TimeDilationFieldEntity> fields, TrackingState tracking) {
|
||||
List<TimeDilationFieldSnapshot> snapshots = fields.stream()
|
||||
.filter(field -> !field.isChronosphere())
|
||||
@@ -71,16 +119,6 @@ public final class TimeDilationManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<TimeDilationFieldEntity> collectFields(ServerLevel level) {
|
||||
List<TimeDilationFieldEntity> 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<TimeDilationFieldEntity> 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
|
||||
|
||||
+62
@@ -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<Vec3> 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<VoxelShape> collisions,
|
||||
Operation<Vec3> 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(),
|
||||
|
||||
+7
-1
@@ -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)
|
||||
|
||||
+18
@@ -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<SoundInstance, ChannelAccess.ChannelHandle> 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());
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "antarchy:cornea_stalk",
|
||||
"name": "antarchy:cornea_ear",
|
||||
"weight": 8,
|
||||
"functions": [
|
||||
{
|
||||
|
||||
+6
-1
@@ -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",
|
||||
|
||||
+6
-1
@@ -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",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"minecraft:slime_ball",
|
||||
"antarchy:flytrap_goo"
|
||||
"minecraft:slime_ball"
|
||||
]
|
||||
}
|
||||
+8
-2
@@ -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
|
||||
|
||||
+6
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.craisinlord.antarchy.fabric;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public final class InfinityGenerationFailure {
|
||||
private static final ThreadLocal<ResourceLocation> 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);
|
||||
}
|
||||
}
|
||||
+17
-5
@@ -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());
|
||||
|
||||
+34
@@ -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<Level> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1036,10 +1036,10 @@ public final class AntarchyFabricItems {
|
||||
public static final DeferredItem<Item> HERCULES_HORN = ITEMS.registerSimpleItem("hercules_horn", new Item.Properties().rarity(Rarity.UNCOMMON));
|
||||
|
||||
|
||||
public static final DeferredItem<Item> KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE));
|
||||
public static final DeferredItem<Item> KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant());
|
||||
|
||||
|
||||
public static final DeferredItem<Item> QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE));
|
||||
public static final DeferredItem<Item> QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant());
|
||||
|
||||
|
||||
public static final DeferredItem<Item> CHITIN = ITEMS.registerSimpleItem("chitin", new Item.Properties().rarity(Rarity.UNCOMMON));
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"entity.MultipartEntityLevelRegistryMixin",
|
||||
"WoodTypeInvoker",
|
||||
"infinity.PortalCreatorMixin",
|
||||
"infinity.WarpLogicMixin",
|
||||
"infinity.AmendmentRareOresMixin"
|
||||
],
|
||||
"client": [
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.craisinlord.antarchy.neoforge;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public final class InfinityGenerationFailure {
|
||||
private static final ThreadLocal<ResourceLocation> 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);
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-5
@@ -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<Entity> 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;
|
||||
|
||||
-5
@@ -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(
|
||||
|
||||
+35
@@ -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<Level> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+28
-10
@@ -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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -717,8 +717,8 @@ public final class AntarchyNeoforgeItems {
|
||||
public static final DeferredItem<MantisClawItem> MANTIS_CLAW = ITEMS.register("mantis_claw",
|
||||
() -> new MantisClawItem(Tiers.IRON, new Item.Properties().stacksTo(1).durability(50).rarity(Rarity.UNCOMMON)));
|
||||
public static final DeferredItem<Item> HERCULES_HORN = ITEMS.registerSimpleItem("hercules_horn", new Item.Properties().rarity(Rarity.UNCOMMON));
|
||||
public static final DeferredItem<Item> KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE));
|
||||
public static final DeferredItem<Item> QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE));
|
||||
public static final DeferredItem<Item> KING_SCALE = ITEMS.registerSimpleItem("king_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant());
|
||||
public static final DeferredItem<Item> QUEEN_SCALE = ITEMS.registerSimpleItem("queen_scale", new Item.Properties().rarity(Rarity.RARE).fireResistant());
|
||||
public static final DeferredItem<Item> CHITIN = ITEMS.registerSimpleItem("chitin", new Item.Properties().rarity(Rarity.UNCOMMON));
|
||||
public static final DeferredItem<Item> JERRY_NUCLEUS = ITEMS.register("jerry_nucleus",
|
||||
() -> new com.craisinlord.antarchy.content.item.JerryNucleusItem(new Item.Properties().rarity(Rarity.UNCOMMON)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"infinity.AmendmentRareOresMixin",
|
||||
"infinity.ConfigGenInvocationMixin",
|
||||
"infinity.PortalCreatorMixin",
|
||||
"infinity.WarpLogicMixin",
|
||||
"level.ClientLevelPartEntitiesAccessor",
|
||||
"level.ServerLevelPartEntitiesAccessor"
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user