Giant frying pan

Many fixes
Boogaloo prep
Underside eye stars and moon
Commanded vfx
effect icons
fabric crash fixes
This commit is contained in:
craisinlord committed 2026-09-22 21:28:35 -05:00
1 parent 682bd39001
commit a566c7ffcd
95 files changed
+1738 -107

No files matched your search

@@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.RandomSource;
public interface InfinityCompatBridge {
@@ -26,6 +27,10 @@ public interface InfinityCompatBridge {
return InfinityWarpResult.REJECTED;
}
default InfinityWarpResult requestDimensionCreation(MinecraftServer server, ResourceLocation dimensionId) {
return InfinityWarpResult.REJECTED;
}
/**
* Converts an already-ignited vanilla Nether portal frame at {@code anyPortalBlockPos} into a real, permanent
* Infinite Dimensions portal to {@code dimensionId}, generating the dimension first if it doesn't exist yet.
@@ -156,6 +156,7 @@ public final class AntarchyConfigCatalog {
private static boolean isToolSetting(String name) {
return name.equals("sizeChangingRaysEnabled")
|| name.startsWith("sizeRay")
|| name.startsWith("temporalTuner")
|| name.equals("shrinkingPotionDelta")
|| name.equals("growthPotionDelta")
|| name.startsWith("ultimate")
@@ -30,6 +30,8 @@ public final class AntarchySettings {
private static double sizeRayMinScale = 0.1D;
private static double sizeRayMaxScale = 10.0D;
private static double sizeRayDeltaPerHit = 0.25D;
private static double temporalTunerMinRate = 0.1D;
private static double temporalTunerMaxRate = 3.0D;
private static double shrinkingPotionDelta = 0.3D;
private static double growthPotionDelta = 0.5D;
private static double antDanceRadius = 5.0D;
@@ -229,6 +231,7 @@ public final class AntarchySettings {
private static double royalAssailantLeggingsDoubleDamageChance = 0.07D;
private static double royalAssailantBootsDoubleDamageChance = 0.05D;
private static double royalGuardianSwordAttackDamage = 111.0D;
private static double giantFryingPanAttackDamage = 80.0D;
private static double royalGuardianSwordAttackSpeed = -2.5D;
private static int royalGuardianSwordElementalCooldownTicks = 120;
private static double royalGuardianSwordFirePrimaryDamage = 22.0D;
@@ -758,6 +761,14 @@ public final class AntarchySettings {
return sizeRayDeltaPerHit;
}
public static double temporalTunerMinRate() {
return temporalTunerMinRate;
}
public static double temporalTunerMaxRate() {
return temporalTunerMaxRate;
}
public static double shrinkingPotionDelta() {
return shrinkingPotionDelta;
}
@@ -1385,6 +1396,14 @@ public final class AntarchySettings {
sizeRayDeltaPerHit = value;
}
public static void setTemporalTunerMinRate(double value) {
temporalTunerMinRate = value;
}
public static void setTemporalTunerMaxRate(double value) {
temporalTunerMaxRate = value;
}
public static void setShrinkingPotionDelta(double value) {
shrinkingPotionDelta = value;
}
@@ -2041,6 +2060,8 @@ public final class AntarchySettings {
public static double royalGuardianSwordAttackDamage() { return royalGuardianSwordAttackDamage; }
public static void setRoyalGuardianSwordAttackDamage(double v) { royalGuardianSwordAttackDamage = v; }
public static double giantFryingPanAttackDamage() { return giantFryingPanAttackDamage; }
public static void setGiantFryingPanAttackDamage(double v) { giantFryingPanAttackDamage = v; }
public static double royalGuardianSwordAttackSpeed() { return royalGuardianSwordAttackSpeed; }
public static void setRoyalGuardianSwordAttackSpeed(double v) { royalGuardianSwordAttackSpeed = v; }
@@ -210,6 +210,8 @@ public final class AntarchyObjects {
@SuppressWarnings("unchecked")
public static Supplier<MenuType<com.craisinlord.antarchy.content.menu.RoyalJudgmentMenu>> ROYAL_JUDGMENT_MENU = (Supplier<MenuType<com.craisinlord.antarchy.content.menu.RoyalJudgmentMenu>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<MenuType<com.craisinlord.antarchy.content.menu.GiantFryingPanMenu>> GIANT_FRYING_PAN_MENU = (Supplier<MenuType<com.craisinlord.antarchy.content.menu.GiantFryingPanMenu>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<net.minecraft.world.item.Item> CHEEP_ITEM = (Supplier<net.minecraft.world.item.Item>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Block> DUPLICATOR_LOG = (Supplier<Block>) UNBOUND;
@@ -321,6 +323,10 @@ public final class AntarchyObjects {
public static Supplier<Holder<MobEffect>> GLIMMERING_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
public static Supplier<Holder<MobEffect>> ROYAL_VITALITY_PENALTY_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Holder<MobEffect>> BLEEDING_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Holder<MobEffect>> BLOOD_MOON_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Fluid> LUMEN = (Supplier<Fluid>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Fluid> FLOWING_LUMEN = (Supplier<Fluid>) UNBOUND;
@@ -824,6 +830,14 @@ public final class AntarchyObjects {
ROYAL_VITALITY_PENALTY_EFFECT = supplier;
}
public static void setBleedingEffect(Supplier<Holder<MobEffect>> supplier) {
BLEEDING_EFFECT = supplier;
}
public static void setBloodMoonEffect(Supplier<Holder<MobEffect>> supplier) {
BLOOD_MOON_EFFECT = supplier;
}
public static void setElka(Supplier<EntityType<com.craisinlord.antarchy.content.entity.ElkaEntity>> supplier) {
ELKA = supplier;
}
@@ -916,6 +930,10 @@ public final class AntarchyObjects {
ROYAL_JUDGMENT_MENU = supplier;
}
public static void setGiantFryingPanMenu(Supplier<MenuType<com.craisinlord.antarchy.content.menu.GiantFryingPanMenu>> supplier) {
GIANT_FRYING_PAN_MENU = supplier;
}
public static void setAmericanComponent(Supplier<net.minecraft.core.component.DataComponentType<net.minecraft.util.Unit>> supplier) {
AMERICAN_COMPONENT = supplier;
}
@@ -78,6 +78,7 @@ public final class UnderVaultBlockEntity extends BlockEntity {
@Override
protected void loadAdditional(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries) {
vaultData.loadCustomOnly(tag, registries);
vaultData.setConfig(createConfig());
}
@Override
@@ -1,6 +1,8 @@
package com.craisinlord.antarchy.content.client;
import com.craisinlord.antarchy.content.effect.RoyalEffectHooks;
import com.craisinlord.antarchy.content.item.TemporalTunerItem;
import com.craisinlord.antarchy.content.time.TimeDilationApi;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
@@ -22,22 +24,19 @@ public final class ContractionAfterimages {
}
public static void tick(ClientLevel level) {
Holder<MobEffect> holder = RoyalEffectHooks.contractedHolder();
int now = (int) (level.getGameTime() & 0x7fffffffL);
Iterator<Map.Entry<LivingEntity, Deque<Sample>>> iterator = HISTORY.entrySet().iterator();
while (iterator.hasNext()) {
LivingEntity tracked = iterator.next().getKey();
if (tracked == null || holder == null || tracked.isRemoved() || !tracked.isAlive()
|| !tracked.hasEffect(holder)) {
if (tracked == null || tracked.isRemoved() || !tracked.isAlive() || !isActive(tracked)) {
iterator.remove();
}
}
}
public static void observe(LivingEntity living) {
Holder<MobEffect> holder = RoyalEffectHooks.contractedHolder();
if (holder == null || living.isInvisible() || !living.hasEffect(holder)) {
if (!isActive(living)) {
return;
}
int now = (int) (living.level().getGameTime() & 0x7fffffffL);
@@ -52,6 +51,15 @@ public final class ContractionAfterimages {
return HISTORY.get(entity);
}
public static boolean isActive(LivingEntity living) {
Holder<MobEffect> holder = RoyalEffectHooks.contractedHolder();
boolean contracted = holder != null && living.hasEffect(holder);
boolean tuned = living instanceof net.minecraft.world.entity.player.Player player
&& TemporalTunerItem.isAvailable(player)
&& TimeDilationApi.getRate(living) > 1.0D;
return !living.isInvisible() && (contracted || tuned);
}
public static float fade(Sample sample, int now) {
float elapsed = now - sample.recordedTick;
return Math.max(0.0F, 1.0F - elapsed / SAMPLE_LIFETIME_TICKS);
@@ -0,0 +1,50 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.item.GiantFryingPanItem;
import com.craisinlord.antarchy.content.item.GiantFryingPanStorage;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.model.GeoModel;
import software.bernie.geckolib.renderer.GeoItemRenderer;
public final class GiantFryingPanRenderer extends GeoItemRenderer<GiantFryingPanItem> {
public GiantFryingPanRenderer(GeoModel<GiantFryingPanItem> model) {
super(model);
}
@Override
public void actuallyRender(
PoseStack poseStack,
GiantFryingPanItem animatable,
BakedGeoModel model,
net.minecraft.client.renderer.RenderType renderType,
MultiBufferSource bufferSource,
com.mojang.blaze3d.vertex.VertexConsumer buffer,
boolean isReRender,
float partialTick,
int packedLight,
int packedOverlay,
int colour
) {
super.actuallyRender(poseStack, animatable, model, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, colour);
if (isReRender || this.renderPerspective == ItemDisplayContext.GUI) return;
ItemStack pan = this.getCurrentItemStack();
if (!(Minecraft.getInstance().player instanceof net.minecraft.world.entity.player.Player player)) return;
GiantFryingPanStorage storage = new GiantFryingPanStorage(pan, player);
for (int slot = 0; slot < GiantFryingPanStorage.SLOT_COUNT; slot++) {
ItemStack stack = storage.getItem(slot);
if (stack.isEmpty()) continue;
int row = slot / 3;
int column = slot % 3;
poseStack.pushPose();
poseStack.translate((column - 1) * 0.42D, 1.72D, (row - 1) * 0.42D);
poseStack.scale(0.24F, 0.24F, 0.24F);
Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemDisplayContext.FIXED, packedLight, packedOverlay, poseStack, bufferSource, Minecraft.getInstance().level, 0);
poseStack.popPose();
}
}
}
@@ -3,10 +3,15 @@ package com.craisinlord.antarchy.content.client.renderer;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.LivingEntity;
public final class RoyalIndicatorRenderer {
private static final ResourceLocation COMMANDED_CROWN_TEXTURE = ResourceLocation.fromNamespaceAndPath(
com.craisinlord.antarchy.Antarchy.MODID, "textures/vfx/commanded_vfx_side.png");
private RoyalIndicatorRenderer() {
}
@@ -25,7 +30,7 @@ public final class RoyalIndicatorRenderer {
if (commanded) {
ring(lines, pose, radius, spin, 0.95F, 0.63F, 0.10F, 0.95F, 36);
crownPoints(lines, pose, radius, spin, 1.0F, 0.80F, 0.22F, 0.95F);
crownTexture(poseStack, buffers, LightTexture.FULL_BRIGHT, radius, spin);
}
if (judged) {
float markY = commanded ? -0.13F : 0.08F;
@@ -48,23 +53,38 @@ public final class RoyalIndicatorRenderer {
}
}
private static void crownPoints(VertexConsumer out, PoseStack.Pose pose, float radius, float rotation,
float r, float g, float b, float a) {
final int spikes = 5;
float innerRadius = radius * 0.72F;
for (int i = 0; i < spikes; i++) {
double outerAngle = rotation + Math.PI * 2.0D * i / spikes;
double innerAngle = rotation + Math.PI * 2.0D * (i + 0.5D) / spikes;
float outerX = (float) Math.cos(outerAngle) * radius;
float outerZ = (float) Math.sin(outerAngle) * radius;
float innerX = (float) Math.cos(innerAngle) * innerRadius;
float innerZ = (float) Math.sin(innerAngle) * innerRadius;
float nextOuterX = (float) Math.cos(rotation + Math.PI * 2.0D * (i + 1) / spikes) * radius;
float nextOuterZ = (float) Math.sin(rotation + Math.PI * 2.0D * (i + 1) / spikes) * radius;
line(out, pose, outerX, 0.0F, outerZ, innerX, 0.34F, innerZ, r, g, b, a);
line(out, pose, innerX, 0.34F, innerZ, nextOuterX, 0.0F, nextOuterZ, r, g, b, a);
line(out, pose, outerX, 0.0F, outerZ, nextOuterX, 0.0F, nextOuterZ, r, g, b, a);
private static void crownTexture(PoseStack poseStack, MultiBufferSource buffers, int packedLight,
float radius, float rotation) {
VertexConsumer crown = buffers.getBuffer(RenderType.entityTranslucentEmissive(COMMANDED_CROWN_TEXTURE));
float halfWidth = radius * 0.78F;
float bottom = 0.02F;
float top = 0.40F;
poseStack.pushPose();
poseStack.mulPose(com.mojang.math.Axis.YP.rotation(rotation));
for (int side = 0; side < 4; side++) {
poseStack.pushPose();
poseStack.mulPose(com.mojang.math.Axis.YP.rotationDegrees(side * 90.0F));
PoseStack.Pose pose = poseStack.last();
quad(crown, pose, -halfWidth, bottom, halfWidth, top, halfWidth, packedLight);
poseStack.popPose();
}
poseStack.popPose();
}
private static void quad(VertexConsumer out, PoseStack.Pose pose, float left, float bottom,
float right, float top, float depth, int packedLight) {
out.addVertex(pose, left, bottom, depth).setUv(0.0F, 1.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
out.addVertex(pose, right, bottom, depth).setUv(1.0F, 1.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
out.addVertex(pose, right, top, depth).setUv(1.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
out.addVertex(pose, left, top, depth).setUv(0.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
// Emit the reverse winding as well. The crown is viewed from every angle, and
// a single-sided quad can vanish when the renderer's culling state rejects it.
out.addVertex(pose, left, top, depth).setUv(0.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
out.addVertex(pose, right, top, depth).setUv(1.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
out.addVertex(pose, right, bottom, depth).setUv(1.0F, 1.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
out.addVertex(pose, left, bottom, depth).setUv(0.0F, 1.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
}
private static void brackets(VertexConsumer out, PoseStack.Pose pose, float radius, float rotation) {
@@ -1,7 +1,6 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.client.ContractionAfterimages;
import com.craisinlord.antarchy.content.effect.RoyalEffectHooks;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import java.util.Deque;
@@ -30,8 +29,7 @@ public final class TemporalContractionAfterimageLayer<T extends LivingEntity, M
public void render(PoseStack poseStack, MultiBufferSource buffer, int packedLight, T entity,
float limbSwing, float limbSwingAmount, float partialTick, float ageInTicks, float netHeadYaw,
float headPitch) {
if (entity.isSpectator() || entity.isInvisible() || RoyalEffectHooks.contractedHolder() == null
|| !entity.hasEffect(RoyalEffectHooks.contractedHolder())) {
if (entity.isSpectator() || !ContractionAfterimages.isActive(entity)) {
return;
}
Deque<ContractionAfterimages.Sample> samples = ContractionAfterimages.samples(entity);
@@ -1,7 +1,6 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.client.ContractionAfterimages;
import com.craisinlord.antarchy.content.effect.RoyalEffectHooks;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import java.util.Deque;
@@ -32,8 +31,7 @@ public final class TemporalContractionGeoLayer<T extends GeoAnimatable> extends
MultiBufferSource bufferSource, @Nullable VertexConsumer buffer, float partialTick,
int packedLight, int packedOverlay) {
if (!(animatable instanceof Entity entity) || !(entity instanceof LivingEntity living)
|| living.isInvisible() || RoyalEffectHooks.contractedHolder() == null
|| !living.hasEffect(RoyalEffectHooks.contractedHolder())) {
|| !ContractionAfterimages.isActive(living)) {
return;
}
Deque<ContractionAfterimages.Sample> samples = ContractionAfterimages.samples(living);
@@ -31,8 +31,16 @@ public final class ThoraxisUndersideSkyRenderer {
Registries.DIMENSION,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "thoraxis")
);
private static final ResourceLocation SUN_TEXTURE = ResourceLocation.withDefaultNamespace("textures/environment/sun.png");
private static final ResourceLocation SUN_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/environment/eye_moon.png");
private static final ResourceLocation MOON_TEXTURE = ResourceLocation.withDefaultNamespace("textures/environment/moon_phases.png");
private static final ResourceLocation[] EYE_STAR_TEXTURES = {
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/environment/eye_star1.png"),
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/environment/eye_star2.png"),
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/environment/eye_star3.png"),
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/environment/eye_star4.png"),
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/environment/eye_star5.png")
};
private static final float[] EYE_STAR_SCALES = {1.0F, 0.86F, 0.72F, 0.58F, 0.46F};
private static final float SKY_RADIUS = 100.0F;
private static final float BODY_SIZE = 32.0F;
private static final float SKY_RED = 0.015F;
@@ -40,7 +48,7 @@ public final class ThoraxisUndersideSkyRenderer {
private static final float SKY_BLUE = 0.035F;
@org.jetbrains.annotations.Nullable
private static VertexBuffer redStarBuffer = null;
private static VertexBuffer[] eyeStarBuffers = null;
private ThoraxisUndersideSkyRenderer() {
}
@@ -73,37 +81,57 @@ public final class ThoraxisUndersideSkyRenderer {
float timeOfDay = 0.72F + partialTick * 0.0F;
renderCelestialBodies(poseStack.last().pose(), projectionMatrix, timeOfDay);
renderRedStars(poseStack.last().pose(), projectionMatrix);
renderEyeStars(poseStack.last().pose(), projectionMatrix);
RenderSystem.depthMask(true);
}
private static void renderRedStars(Matrix4f modelViewMatrix, Matrix4f projectionMatrix) {
if (redStarBuffer == null) {
redStarBuffer = buildRedStarBuffer();
private static void renderEyeStars(Matrix4f modelViewMatrix, Matrix4f projectionMatrix) {
if (eyeStarBuffers == null) {
eyeStarBuffers = buildEyeStarBuffers();
}
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.setShaderColor(0.95F, 0.95F, 0.95F, 0.95F);
redStarBuffer.bind();
redStarBuffer.drawWithShader(modelViewMatrix, projectionMatrix, GameRenderer.getPositionColorShader());
VertexBuffer.unbind();
RenderSystem.blendFuncSeparate(
GlStateManager.SourceFactor.ONE,
GlStateManager.DestFactor.ONE,
GlStateManager.SourceFactor.ONE,
GlStateManager.DestFactor.ZERO
);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 0.015F, 0.02F, 1.0F);
RenderSystem.backupProjectionMatrix();
RenderSystem.setProjectionMatrix(projectionMatrix, VertexSorting.DISTANCE_TO_ORIGIN);
for (int i = 0; i < eyeStarBuffers.length; i++) {
RenderSystem.setShaderTexture(0, EYE_STAR_TEXTURES[i]);
eyeStarBuffers[i].bind();
eyeStarBuffers[i].drawWithShader(modelViewMatrix, projectionMatrix, GameRenderer.getPositionTexShader());
VertexBuffer.unbind();
}
RenderSystem.restoreProjectionMatrix();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.defaultBlendFunc();
RenderSystem.disableBlend();
}
private static VertexBuffer buildRedStarBuffer() {
Random random = new Random(552031L);
BufferBuilder builder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
private static VertexBuffer[] buildEyeStarBuffers() {
VertexBuffer[] buffers = new VertexBuffer[EYE_STAR_TEXTURES.length];
for (int textureIndex = 0; textureIndex < EYE_STAR_TEXTURES.length; textureIndex++) {
Random random = new Random(552031L);
BufferBuilder builder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
for (int i = 0; i < 1800; i++) {
double x = random.nextFloat() * 2.0F - 1.0F;
double y = random.nextFloat() * 2.0F - 1.0F;
double z = random.nextFloat() * 2.0F - 1.0F;
double size = (0.52F + random.nextFloat() * 0.36F) * EYE_STAR_SCALES[textureIndex];
double rot = random.nextDouble() * Math.PI * 2.0D;
double lenSq = x * x + y * y + z * z;
if (i % EYE_STAR_TEXTURES.length != textureIndex || lenSq >= 1.0D || lenSq <= 0.01D) {
continue;
}
for (int i = 0; i < 1800; i++) {
double x = random.nextFloat() * 2.0F - 1.0F;
double y = random.nextFloat() * 2.0F - 1.0F;
double z = random.nextFloat() * 2.0F - 1.0F;
double size = 0.13F + random.nextFloat() * 0.12F;
double lenSq = x * x + y * y + z * z;
if (lenSq < 1.0D && lenSq > 0.01D) {
double len = 1.0D / Math.sqrt(lenSq);
x *= len;
y *= len;
@@ -117,12 +145,8 @@ public final class ThoraxisUndersideSkyRenderer {
double pitch = Math.atan2(Math.sqrt(x * x + z * z), y);
double sinPitch = Math.sin(pitch);
double cosPitch = Math.cos(pitch);
double rot = random.nextDouble() * Math.PI * 2.0D;
double sinRot = Math.sin(rot);
double cosRot = Math.cos(rot);
float red = 0.75F + random.nextFloat() * 0.25F;
float green = 0.02F + random.nextFloat() * 0.05F;
float blue = 0.04F + random.nextFloat() * 0.08F;
for (int j = 0; j < 4; j++) {
double u = (j & 2) - 1;
@@ -133,24 +157,26 @@ public final class ThoraxisUndersideSkyRenderer {
double qy = -px * cosPitch;
double rx = qy * sinYaw - py * cosYaw;
double ry = py * sinYaw + qy * cosYaw;
float quadU = (j == 0 || j == 1) ? 0.0F : 1.0F;
float quadV = (j == 0 || j == 3) ? 0.0F : 1.0F;
builder.addVertex((float) (sx + rx * size), (float) (sy + qx * size), (float) (sz + ry * size))
.setColor(red, green, blue, 1.0F);
.setUv(quadU, quadV);
}
}
}
MeshData mesh = builder.buildOrThrow();
VertexBuffer buffer = new VertexBuffer(VertexBuffer.Usage.STATIC);
buffer.bind();
buffer.upload(mesh);
VertexBuffer.unbind();
return buffer;
MeshData mesh = builder.buildOrThrow();
buffers[textureIndex] = new VertexBuffer(VertexBuffer.Usage.STATIC);
buffers[textureIndex].bind();
buffers[textureIndex].upload(mesh);
VertexBuffer.unbind();
}
return buffers;
}
private static void renderCelestialBodies(Matrix4f modelViewMatrix, Matrix4f projectionMatrix, float timeOfDay) {
float t = timeOfDay * 360.0F;
renderBodyGlow(modelViewMatrix, projectionMatrix, t, -10.0F, 0xFF1F18, 86.0F);
renderTexturedBody(modelViewMatrix, projectionMatrix, t, -10.0F, 42.0F, 0xFF1F18, SUN_TEXTURE, false, 0, t * 0.6F);
renderTexturedBody(modelViewMatrix, projectionMatrix, t, -10.0F, 42.0F, 0xFF1F18, SUN_TEXTURE, false, 0, t * 0.6F + 90.0F);
float moonOrbit = t + 180.0F;
renderBodyGlow(modelViewMatrix, projectionMatrix, moonOrbit, 24.0F, 0x8F30FF, 76.0F);
@@ -0,0 +1,24 @@
package com.craisinlord.antarchy.content.client.screen;
import com.craisinlord.antarchy.content.menu.GiantFryingPanMenu;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
public final class GiantFryingPanScreen extends AbstractContainerScreen<GiantFryingPanMenu> {
private static final ResourceLocation INVENTORY_TEXTURE = ResourceLocation.withDefaultNamespace("textures/gui/container/inventory.png");
public GiantFryingPanScreen(GiantFryingPanMenu menu, Inventory inventory, Component title) {
super(menu, inventory, title);
imageWidth = 176;
imageHeight = 132;
inventoryLabelY = 40;
}
@Override
protected void renderBg(GuiGraphics graphics, float partialTick, int mouseX, int mouseY) {
graphics.blit(INVENTORY_TEXTURE, leftPos, topPos, 0, 0, imageWidth, imageHeight);
}
}
@@ -409,6 +409,7 @@ public final class CreativeTabContents {
entry("ultimate_hoe", "tools_and_utilities"),
entry("battle_axe", "combat"),
entry("big_bertha", "combat"),
entry("giant_frying_pan", "combat"),
entry("basilisk_dagger", "combat"),
entry("ultimate_helmet", "combat"),
entry("ultimate_chestplate", "combat"),
@@ -437,6 +438,7 @@ public final class CreativeTabContents {
entry("nightmare_leggings", "combat"),
entry("nightmare_boots", "combat"),
entry("nightmare_sword", "combat"),
entry("blood_gods_blade", "combat"),
entry("blood_crystal_katana", "combat"),
entry("blood_crystal_helmet", "combat"),
entry("blood_crystal_chestplate", "combat"),
@@ -490,6 +492,7 @@ public final class CreativeTabContents {
entry("mud_pie", "ingredients"),
entry("lucid_eye", "ingredients"),
entry("blood_crystal_shard", "ingredients"),
entry("temporal_tuner", "ingredients"),
entry("tigers_eye", "ingredients"),
entry("tigers_eye_block", "building_blocks"),
entry("blood_crystal_apple", "ingredients"),
@@ -0,0 +1,22 @@
package com.craisinlord.antarchy.content.effect;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.entity.LivingEntity;
public final class BleedingMobEffect extends MobEffect {
public BleedingMobEffect() {
super(MobEffectCategory.HARMFUL, 0x8F1020);
}
@Override
public boolean applyEffectTick(LivingEntity entity, int amplifier) {
entity.hurt(entity.damageSources().magic(), 1.0F + amplifier);
return true;
}
@Override
public boolean shouldApplyEffectTickThisTick(int duration, int amplifier) {
return duration % 20 == 0;
}
}
@@ -0,0 +1,10 @@
package com.craisinlord.antarchy.content.effect;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
public final class BloodMoonMobEffect extends MobEffect {
public BloodMoonMobEffect() {
super(MobEffectCategory.BENEFICIAL, 0xB51B2D);
}
}
@@ -93,6 +93,7 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
private UUID staffOwnerId;
private int staffManticoreCount;
private boolean staffManticoreSpawned;
private boolean gauntletVisualOnly;
public DimensionalTearEntity(EntityType<? extends DimensionalTearEntity> entityType, Level level) {
super(entityType, level);
@@ -109,6 +110,12 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
return tear;
}
public static DimensionalTearEntity createGauntletVisual(ServerLevel level, Vec3 pos, float yaw, int lifetimeTicks) {
DimensionalTearEntity tear = create(level, pos, yaw, lifetimeTicks);
tear.gauntletVisualOnly = true;
return tear;
}
public static DimensionalTearEntity createQueenManticoreTear(ServerLevel level, Vec3 pos, float yaw,
int lifetimeTicks, UUID queenId, int count) {
DimensionalTearEntity tear = create(level, pos, yaw, lifetimeTicks);
@@ -161,7 +168,15 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
this.setTearState(TearState.NORMAL);
}
if (this.ageTicks >= this.lifetimeTicks) {
this.removeLinkedPair();
if (this.gauntletVisualOnly) {
this.discard();
} else {
this.removeLinkedPair();
}
return;
}
if (this.gauntletVisualOnly) {
return;
}
@@ -500,6 +515,7 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
tag.putInt("EventTicks", this.eventTicks);
tag.putInt("NextEventTicks", this.nextEventTicks);
tag.putInt("PendingEvent", this.pendingEvent.ordinal());
tag.putBoolean("GauntletVisualOnly", this.gauntletVisualOnly);
if (this.linkedTearId != null) {
tag.putUUID("LinkedTearId", this.linkedTearId);
}
@@ -522,6 +538,7 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
int event = tag.getInt("PendingEvent");
TearState[] states = TearState.values();
this.pendingEvent = event >= 0 && event < states.length ? states[event] : TearState.NORMAL;
this.gauntletVisualOnly = tag.getBoolean("GauntletVisualOnly");
if (tag.hasUUID("LinkedTearId")) {
this.linkedTearId = tag.getUUID("LinkedTearId");
}
@@ -14,6 +14,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.GameRules;
@@ -28,7 +29,7 @@ import org.jetbrains.annotations.Nullable;
public final class RoyalBeamController {
private static final int INITIAL_TRACKING_DELAY_TICKS = 8;
private final Mob owner;
private final LivingEntity owner;
private Vec3 serverTarget;
private Vec3 beamEndPosition;
private int beamTicks;
@@ -39,10 +40,14 @@ public final class RoyalBeamController {
private static final int ICE_MUTATIONS_PER_TICK = 3;
private static final float ICE_IMPACT_RADIUS = 2.0F;
public RoyalBeamController(Mob owner) {
public RoyalBeamController(LivingEntity owner) {
this.owner = owner;
}
public RoyalBeamController(Mob owner) {
this((LivingEntity) owner);
}
public boolean isFiring() {
return this.beamTicks > 0;
}
@@ -164,7 +169,9 @@ public final class RoyalBeamController {
) {
Vec3 direction = beamEnd.subtract(shootFrom).normalize();
double distance = shootFrom.distanceTo(beamEnd);
DamageSource damageSource = this.owner.damageSources().mobAttack(this.owner);
DamageSource damageSource = this.owner instanceof Player player
? player.damageSources().playerAttack(player)
: this.owner.damageSources().mobAttack(this.owner);
this.damagedThisTick.clear();
boolean pathMutates = terrainMode == RoyalBeamTerrainMode.DESTROY;
for (double walked = settings.pathStep(); walked < Math.min(distance, settings.range()); walked += settings.pathStep()) {
@@ -224,7 +231,7 @@ public final class RoyalBeamController {
for (LivingEntity living : entities) {
if (living.is(this.owner)
|| this.owner.isAlliedTo(living)
|| living.getType() == this.owner.getType()
|| !(this.owner instanceof Player) && living.getType() == this.owner.getType()
|| this.owner instanceof RoyalBossEntity royalBoss && !royalBoss.canDamageWithRoyalAttack(living)
|| living.distanceToSqr(center) > radius * radius
|| damagedThisTick.contains(living.getId())
@@ -22,6 +22,16 @@ public record RoyalBeamSettings(
boolean terrainEnabled,
boolean requireLineOfSightForDamage
) {
public static RoyalBeamSettings gauntletPower() {
return new RoyalBeamSettings(64.0D, 0.0D, 2.0D, 18, 4, 50, 0.9F, 1.8F,
9.0F, 0.8F, 1, 64.0D, 0.8F, 1.8F, 6, 1.0F, 1.0F, 50.0F, true, false);
}
public static RoyalBeamSettings gauntletInfinity() {
return new RoyalBeamSettings(64.0D, 0.0D, 1.5D, 24, 4, 1200, 1.25F, 2.5F,
28.0F, 1.8F, 1, 64.0D, 1.0F, 2.0F, 0, 0.0F, 0.0F, 0.0F, false, false);
}
public static RoyalBeamSettings tremorzillaLike(float damage, boolean terrainEnabled) {
return new RoyalBeamSettings(
100.0D,
@@ -0,0 +1,93 @@
package com.craisinlord.antarchy.content.item;
import com.craisinlord.antarchy.content.AntarchyObjects;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.SwordItem;
import net.minecraft.world.item.Tier;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.component.ItemAttributeModifiers;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import org.joml.Vector3f;
public final class BloodGodsBladeItem extends SwordItem {
private static final int BLEEDING_TICKS = 100;
private static final int BLOOD_MOON_TICKS = 200;
private static final int BLOOD_MOON_MAX_TICKS = 300;
private static final int BLOOD_MOON_COOLDOWN_TICKS = 1200;
private static final double BLOOD_MOON_RADIUS = 12.0D;
private static final DustParticleOptions BLOOD_PARTICLES = new DustParticleOptions(new Vector3f(0.65F, 0.02F, 0.05F), 1.6F);
private final Tier tier;
private final int attackDamage;
private final float attackSpeed;
public BloodGodsBladeItem(Tier tier, Item.Properties properties, int attackDamage, float attackSpeed) {
super(tier, properties);
this.tier = tier;
this.attackDamage = attackDamage;
this.attackSpeed = attackSpeed;
}
@Override
public ItemAttributeModifiers getDefaultAttributeModifiers() {
return SwordItem.createAttributes(this.tier, this.attackDamage, this.attackSpeed);
}
@Override
public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
boolean result = super.hurtEnemy(stack, target, attacker);
if (!attacker.level().isClientSide()) {
target.addEffect(new MobEffectInstance(AntarchyObjects.BLEEDING_EFFECT.get(), BLEEDING_TICKS, 0, false, true, true));
if (attacker instanceof Player player && player.hasEffect(AntarchyObjects.BLOOD_MOON_EFFECT.get())) {
player.heal(1.0F);
if (target.isDeadOrDying()) {
MobEffectInstance bloodMoon = player.getEffect(AntarchyObjects.BLOOD_MOON_EFFECT.get());
if (bloodMoon != null) {
player.addEffect(new MobEffectInstance(AntarchyObjects.BLOOD_MOON_EFFECT.get(), Math.min(BLOOD_MOON_MAX_TICKS, bloodMoon.getDuration() + 20), bloodMoon.getAmplifier(), false, true, true));
}
}
}
}
return result;
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
if (player.getCooldowns().isOnCooldown(this)) {
return InteractionResultHolder.fail(stack);
}
if (!level.isClientSide() && level instanceof ServerLevel serverLevel) {
player.getCooldowns().addCooldown(this, BLOOD_MOON_COOLDOWN_TICKS);
player.addEffect(new MobEffectInstance(AntarchyObjects.BLOOD_MOON_EFFECT.get(), BLOOD_MOON_TICKS, 0, false, true, true));
player.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, BLOOD_MOON_TICKS, 0, false, false, true));
for (LivingEntity entity : level.getEntitiesOfClass(LivingEntity.class, player.getBoundingBox().inflate(BLOOD_MOON_RADIUS), entity -> entity != player && entity.isAlive() && !player.isAlliedTo(entity))) {
entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, BLOOD_MOON_TICKS, 0, false, true, true));
entity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, BLOOD_MOON_TICKS, 0, false, true, true));
}
serverLevel.sendParticles(BLOOD_PARTICLES, player.getX(), player.getY() + 1.0D, player.getZ(), 160, 2.5D, 1.2D, 2.5D, 0.08D);
serverLevel.sendParticles(BLOOD_PARTICLES, player.getX(), player.getY() + 8.0D, player.getZ(), 80, 5.0D, 0.2D, 5.0D, 0.02D);
}
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide());
}
@Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
tooltipComponents.add(Component.translatable("tooltip.antarchy.blood_gods_blade.bleeding").withStyle(ChatFormatting.DARK_RED));
tooltipComponents.add(Component.translatable("tooltip.antarchy.blood_gods_blade.blood_moon").withStyle(ChatFormatting.RED));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
}
}
@@ -0,0 +1,150 @@
package com.craisinlord.antarchy.content.item;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel;
import com.craisinlord.antarchy.content.client.renderer.AnimatedHeldItemRenderer;
import com.craisinlord.antarchy.content.client.renderer.GiantFryingPanRenderer;
import java.util.function.Consumer;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.EquipmentSlotGroup;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.SwordItem;
import net.minecraft.world.item.Tier;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.component.ItemAttributeModifiers;
import net.minecraft.network.chat.Component;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import software.bernie.geckolib.animatable.GeoItem;
import software.bernie.geckolib.animatable.client.GeoRenderProvider;
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.animation.AnimatableManager;
import software.bernie.geckolib.util.GeckoLibUtil;
public class GiantFryingPanItem extends SwordItem implements GeoItem {
private static final ResourceLocation MODEL_LOCATION = ResourceLocation.fromNamespaceAndPath("antarchy", "geo/giant_frying_pan.geo.json");
private static final ResourceLocation TEXTURE_LOCATION = ResourceLocation.fromNamespaceAndPath("antarchy", "textures/item/giant_frying_pan/giant_frying_pan_model.png");
private static final ResourceLocation ANIMATION_LOCATION = ResourceLocation.fromNamespaceAndPath("antarchy", "animations/static_item.animation.json");
private static final ResourceLocation REACH_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "giant_frying_pan_reach");
private static final ResourceLocation KNOCKBACK_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "giant_frying_pan_knockback");
private final Tier tier;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
public GiantFryingPanItem(Tier tier, Item.Properties properties) {
super(tier, properties);
this.tier = tier;
GeoItem.registerSyncedAnimatable(this);
}
@Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<net.minecraft.network.chat.Component> tooltipComponents, TooltipFlag tooltipFlag) {
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
tooltipComponents.add(Component.translatable("tooltip.antarchy.giant_frying_pan.insert").withStyle(ChatFormatting.GRAY));
tooltipComponents.add(Component.translatable("tooltip.antarchy.giant_frying_pan.gui").withStyle(ChatFormatting.GRAY));
tooltipComponents.add(Component.translatable("tooltip.antarchy.giant_frying_pan.campfire").withStyle(ChatFormatting.DARK_GRAY));
}
@Override
public ItemAttributeModifiers getDefaultAttributeModifiers() {
return SwordItem.createAttributes(this.tier, (int) Math.round(AntarchySettings.giantFryingPanAttackDamage()), -3.8F)
.withModifierAdded(Attributes.ENTITY_INTERACTION_RANGE,
new AttributeModifier(REACH_MODIFIER_ID, 6.0D, AttributeModifier.Operation.ADD_VALUE),
EquipmentSlotGroup.MAINHAND)
.withModifierAdded(Attributes.ATTACK_KNOCKBACK,
new AttributeModifier(KNOCKBACK_MODIFIER_ID, 2.0D, AttributeModifier.Operation.ADD_VALUE),
EquipmentSlotGroup.MAINHAND);
}
@Override
public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
boolean hurt = super.hurtEnemy(stack, target, attacker);
if (!hurt || attacker.level().isClientSide) {
return hurt;
}
Vec3 direction = target.position().subtract(attacker.position()).multiply(1.0D, 0.0D, 1.0D);
if (direction.lengthSqr() < 1.0E-4D) {
direction = attacker.getLookAngle().multiply(1.0D, 0.0D, 1.0D);
}
if (direction.lengthSqr() >= 1.0E-4D) {
direction = direction.normalize();
Vec3 motion = target.getDeltaMovement();
double x = Math.max(-2.6D, Math.min(2.6D, motion.x + direction.x * 1.8D));
double z = Math.max(-2.6D, Math.min(2.6D, motion.z + direction.z * 1.8D));
target.setDeltaMovement(x, motion.y, z);
target.hurtMarked = true;
}
Level level = attacker.level();
level.playSound(null, target.blockPosition(), SoundEvents.ANVIL_LAND, SoundSource.PLAYERS, 0.8F, 1.25F);
return hurt;
}
@Override
public void inventoryTick(ItemStack stack, Level level, net.minecraft.world.entity.Entity entity, int slotId, boolean isSelected) {
super.inventoryTick(stack, level, entity, slotId, isSelected);
if (entity instanceof Player player) GiantFryingPanStorage.tick(player, stack, level);
}
@Override
public net.minecraft.world.InteractionResultHolder<ItemStack> use(Level level, Player player, net.minecraft.world.InteractionHand hand) {
ItemStack pan = player.getItemInHand(hand);
if (player.isShiftKeyDown()) {
if (!level.isClientSide) {
player.openMenu(new SimpleMenuProvider(
(containerId, inventory, ignored) -> new com.craisinlord.antarchy.content.menu.GiantFryingPanMenu(containerId, inventory),
Component.translatable("item.antarchy.giant_frying_pan")));
}
return net.minecraft.world.InteractionResultHolder.sidedSuccess(pan, level.isClientSide);
}
net.minecraft.world.InteractionHand foodHand = hand == net.minecraft.world.InteractionHand.MAIN_HAND
? net.minecraft.world.InteractionHand.OFF_HAND : net.minecraft.world.InteractionHand.MAIN_HAND;
ItemStack food = player.getItemInHand(foodHand);
if (!GiantFryingPanStorage.isCampfireInput(player, food)) return net.minecraft.world.InteractionResultHolder.pass(pan);
GiantFryingPanStorage storage = new GiantFryingPanStorage(pan, player);
for (int slot = 0; slot < GiantFryingPanStorage.SLOT_COUNT; slot++) {
if (storage.getItem(slot).isEmpty()) {
if (!level.isClientSide) {
storage.setItem(slot, food.copyWithCount(1));
food.shrink(1);
level.playSound(null, player.blockPosition(), SoundEvents.CAMPFIRE_CRACKLE, SoundSource.PLAYERS, 0.8F, 1.0F);
}
return net.minecraft.world.InteractionResultHolder.sidedSuccess(pan, level.isClientSide);
}
}
return net.minecraft.world.InteractionResultHolder.fail(pan);
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
@Override
public void createGeoRenderer(Consumer<GeoRenderProvider> consumer) {
consumer.accept(new GeoRenderProvider() {
private GiantFryingPanRenderer renderer;
@Override
public net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer getGeoItemRenderer() {
if (this.renderer == null) {
this.renderer = new GiantFryingPanRenderer(new ResourceBackedGeoItemModel<>(MODEL_LOCATION, TEXTURE_LOCATION, ANIMATION_LOCATION));
}
return this.renderer;
}
});
}
}
@@ -0,0 +1,174 @@
package com.craisinlord.antarchy.content.item;
import java.util.Optional;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CampfireCookingRecipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.SingleRecipeInput;
import net.minecraft.world.level.Level;
public final class GiantFryingPanStorage implements Container {
public static final int SLOT_COUNT = 9;
private static final String SLOTS = "antarchy.giant_frying_pan_slots";
private static final String SLOT = "Slot";
private static final String ITEM = "Item";
private static final String TIME = "Time";
private final ItemStack pan;
private final Player player;
public GiantFryingPanStorage(ItemStack pan, Player player) {
this.pan = pan;
this.player = player;
}
public static ItemStack findPan(Player player) {
ItemStack selected = player.getMainHandItem();
if (selected.getItem() instanceof GiantFryingPanItem) return selected;
ItemStack offhand = player.getOffhandItem();
if (offhand.getItem() instanceof GiantFryingPanItem) return offhand;
for (ItemStack stack : player.getInventory().items) {
if (stack.getItem() instanceof GiantFryingPanItem) return stack;
}
return ItemStack.EMPTY;
}
public static int findPanSlot(Player player) {
if (player.getMainHandItem().getItem() instanceof GiantFryingPanItem) return player.getInventory().selected;
if (player.getOffhandItem().getItem() instanceof GiantFryingPanItem) return 40;
for (int i = 0; i < player.getInventory().items.size(); i++) {
if (player.getInventory().items.get(i).getItem() instanceof GiantFryingPanItem) return i;
}
return -1;
}
public static void tick(Player player, ItemStack pan, Level level) {
if (level.isClientSide || !(pan.getItem() instanceof GiantFryingPanItem)) return;
GiantFryingPanStorage storage = new GiantFryingPanStorage(pan, player);
for (int slot = 0; slot < SLOT_COUNT; slot++) {
ItemStack input = storage.getItem(slot);
if (input.isEmpty()) continue;
Optional<RecipeHolder<CampfireCookingRecipe>> recipe = level.getServer().getRecipeManager().getRecipeFor(
RecipeType.CAMPFIRE_COOKING, new SingleRecipeInput(input), level);
if (recipe.isEmpty()) {
storage.setCookTime(slot, 0);
continue;
}
int time = storage.getCookTime(slot) + 1;
if (time < 600) {
storage.setCookTime(slot, time);
continue;
}
ItemStack cooked = recipe.get().value().assemble(new SingleRecipeInput(input), level.registryAccess());
input.shrink(1);
storage.setItem(slot, input);
storage.setCookTime(slot, 0);
if (!cooked.isEmpty()) {
var output = new net.minecraft.world.entity.item.ItemEntity(level, player.getX(), player.getY() + 1.2D, player.getZ(), cooked);
output.setDeltaMovement(player.getLookAngle().scale(0.35D).add(0.0D, 0.2D, 0.0D));
output.setPickUpDelay(10);
level.addFreshEntity(output);
}
}
}
public static boolean isCampfireInput(Player player, ItemStack stack) {
return !stack.isEmpty() && (player.getServer() == null || player.getServer().getRecipeManager().getRecipeFor(
RecipeType.CAMPFIRE_COOKING, new SingleRecipeInput(stack), player.level()).isPresent());
}
private ListTag slotList() {
return pan.getOrDefault(net.minecraft.core.component.DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY)
.copyTag().getList(SLOTS, Tag.TAG_COMPOUND);
}
private CompoundTag slotTag(int slot) {
for (Tag raw : slotList()) {
CompoundTag tag = (CompoundTag) raw;
if (tag.getInt(SLOT) == slot) return tag;
}
CompoundTag tag = new CompoundTag();
tag.putInt(SLOT, slot);
return tag;
}
private void writeSlot(int slot, ItemStack stack, int cookTime) {
HolderLookup.Provider registries = player.registryAccess();
net.minecraft.world.item.component.CustomData.update(net.minecraft.core.component.DataComponents.CUSTOM_DATA, pan, root -> {
ListTag list = root.getList(SLOTS, Tag.TAG_COMPOUND);
for (int i = list.size() - 1; i >= 0; i--) {
if (list.getCompound(i).getInt(SLOT) == slot) list.remove(i);
}
if (!stack.isEmpty()) {
CompoundTag tag = new CompoundTag();
tag.putInt(SLOT, slot);
tag.putInt(TIME, cookTime);
tag.put(ITEM, stack.save(registries));
list.add(tag);
}
root.put(SLOTS, list);
});
}
public int getCookTime(int slot) {
return slotTag(slot).getInt(TIME);
}
public void setCookTime(int slot, int value) {
ItemStack stack = getItem(slot);
if (!stack.isEmpty()) writeSlot(slot, stack, value);
}
@Override
public int getContainerSize() { return SLOT_COUNT; }
@Override
public boolean isEmpty() {
for (int i = 0; i < SLOT_COUNT; i++) if (!getItem(i).isEmpty()) return false;
return true;
}
@Override
public ItemStack getItem(int slot) {
CompoundTag tag = slotTag(slot);
if (!tag.contains(ITEM, Tag.TAG_COMPOUND)) return ItemStack.EMPTY;
return ItemStack.parseOptional(player.registryAccess(), tag.getCompound(ITEM));
}
@Override
public ItemStack removeItem(int slot, int amount) {
ItemStack stack = getItem(slot);
if (stack.isEmpty()) return ItemStack.EMPTY;
ItemStack result = stack.split(amount);
writeSlot(slot, stack, 0);
return result;
}
@Override
public ItemStack removeItemNoUpdate(int slot) {
ItemStack result = getItem(slot);
writeSlot(slot, ItemStack.EMPTY, 0);
return result;
}
@Override
public void setItem(int slot, ItemStack stack) { writeSlot(slot, stack, 0); }
@Override
public void setChanged() { }
@Override
public boolean stillValid(Player player) { return player.isAlive(); }
@Override
public void clearContent() {
for (int i = 0; i < SLOT_COUNT; i++) writeSlot(i, ItemStack.EMPTY, 0);
}
}
@@ -78,10 +78,15 @@ public final class RoyalGuardianSwordAbilities {
|| !(swordStack.getItem() instanceof RoyalGuardianSwordItem)
|| !RoyalGuardianSwordItem.isDischargeReady(swordStack, level.getGameTime())) return;
switch (RoyalGuardianSwordItem.getMode(swordStack)) {
RoyalGuardianSwordItem.Mode mode = RoyalGuardianSwordItem.getMode(swordStack);
if (mode == RoyalGuardianSwordItem.Mode.NONE) return;
switch (mode) {
case FIRE -> fireImpact(level, owner, primary);
case FROST -> frostFan(level, owner, primary);
case STORM -> chainLightning(level, owner, primary);
case NONE -> {
}
}
RoyalGuardianSwordItem.startDischargeCooldown(swordStack, level.getGameTime());
}
@@ -94,8 +94,8 @@ public class RoyalGuardianSwordItem extends SwordItem implements GeoItem {
private static void setMode(ItemStack stack, Mode mode) {
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> {
if (mode == Mode.FIRE) tag.remove(MODE_TAG);
else tag.putInt(MODE_TAG, mode.ordinal());
if (mode == Mode.NONE) tag.remove(MODE_TAG);
else tag.putInt(MODE_TAG, mode.id);
});
}
@@ -115,8 +115,8 @@ public class RoyalGuardianSwordItem extends SwordItem implements GeoItem {
}
public static Mode getMode(ItemStack stack) {
int value = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag().getInt(MODE_TAG);
return Mode.values()[Math.floorMod(value, Mode.values().length)];
net.minecraft.nbt.CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
return tag.contains(MODE_TAG) ? Mode.fromId(tag.getInt(MODE_TAG)) : Mode.NONE;
}
public static boolean isDischargeReady(ItemStack stack, long gameTime) {
@@ -130,20 +130,37 @@ public class RoyalGuardianSwordItem extends SwordItem implements GeoItem {
}
public enum Mode {
FIRE("tooltip.antarchy.royal_guardian_sword.mode.fire", "tooltip.antarchy.royal_guardian_sword.fire"),
FROST("tooltip.antarchy.royal_guardian_sword.mode.frost", "tooltip.antarchy.royal_guardian_sword.frost"),
STORM("tooltip.antarchy.royal_guardian_sword.mode.storm", "tooltip.antarchy.royal_guardian_sword.storm");
NONE(-1, "tooltip.antarchy.royal_guardian_sword.mode.none", "tooltip.antarchy.royal_guardian_sword.none"),
FIRE(0, "tooltip.antarchy.royal_guardian_sword.mode.fire", "tooltip.antarchy.royal_guardian_sword.fire"),
FROST(1, "tooltip.antarchy.royal_guardian_sword.mode.frost", "tooltip.antarchy.royal_guardian_sword.frost"),
STORM(2, "tooltip.antarchy.royal_guardian_sword.mode.storm", "tooltip.antarchy.royal_guardian_sword.storm");
private final int id;
private final String translationKey;
private final String tooltipKey;
Mode(String translationKey, String tooltipKey) {
Mode(int id, String translationKey, String tooltipKey) {
this.id = id;
this.translationKey = translationKey;
this.tooltipKey = tooltipKey;
}
public Mode next() {
return values()[(this.ordinal() + 1) % values().length];
return switch (this) {
case NONE -> FIRE;
case FIRE -> FROST;
case FROST -> STORM;
case STORM -> NONE;
};
}
private static Mode fromId(int id) {
for (Mode mode : values()) {
if (mode.id == id) {
return mode;
}
}
return NONE;
}
}
@@ -0,0 +1,86 @@
package com.craisinlord.antarchy.content.item;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.time.TemporalTunerAccess;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.core.component.DataComponents;
import net.minecraft.sounds.SoundEvents;
import java.util.List;
public final class TemporalTunerItem extends Item {
public static final double STEP = 0.1D;
private static final String RATE_TAG = "TemporalTunerRate";
public TemporalTunerItem(Properties properties) {
super(properties.stacksTo(1));
}
public static boolean isAvailable(Player player) {
return player.getInventory().contains(stack -> stack.getItem() instanceof TemporalTunerItem)
&& (player.getMainHandItem().getItem() instanceof TemporalTunerItem
|| player.getOffhandItem().getItem() instanceof TemporalTunerItem
|| hasHotbarTuner(player));
}
private static boolean hasHotbarTuner(Player player) {
for (int slot = 0; slot < 9; slot++) {
if (player.getInventory().getItem(slot).getItem() instanceof TemporalTunerItem) {
return true;
}
}
return false;
}
public static double clampRate(double rate) {
return Math.max(AntarchySettings.temporalTunerMinRate(), Math.min(AntarchySettings.temporalTunerMaxRate(), rate));
}
public static void adjust(Player player, double delta) {
if (!(player instanceof TemporalTunerAccess access) || !isAvailable(player)) {
return;
}
double previousRate = getRate(player);
double updatedRate = clampRate(previousRate + delta);
access.antarchy$setTemporalTunerRate(updatedRate);
if (Math.abs(updatedRate - previousRate) >= 0.001D) {
player.playSound(SoundEvents.NOTE_BLOCK_HAT.value(), 0.6F, 1.0F);
}
syncTooltipRate(player, getRate(player));
}
public static double getRate(Player player) {
return player instanceof TemporalTunerAccess access ? clampRate(access.antarchy$getTemporalTunerRate()) : 1.0D;
}
public static void syncTooltipRate(Player player, double rate) {
for (int slot = 0; slot < 9; slot++) {
updateStackRate(player.getInventory().getItem(slot), rate);
}
updateStackRate(player.getOffhandItem(), rate);
}
private static void updateStackRate(ItemStack stack, double rate) {
if (stack.getItem() instanceof TemporalTunerItem) {
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putDouble(RATE_TAG, rate));
}
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(Component.translatable("tooltip.antarchy.temporal_tuner.description").withStyle(ChatFormatting.RED));
double rate = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag().getDouble(RATE_TAG);
if (rate <= 0.0D) {
rate = 1.0D;
}
tooltip.add(Component.translatable("tooltip.antarchy.temporal_tuner.speed", (int) Math.round(rate * 100.0D)).withStyle(ChatFormatting.GRAY));
tooltip.add(Component.translatable("tooltip.antarchy.temporal_tuner.controls", (int) (AntarchySettings.temporalTunerMinRate() * 100), (int) (AntarchySettings.temporalTunerMaxRate() * 100)).withStyle(ChatFormatting.GRAY));
tooltip.add(Component.translatable("tooltip.antarchy.temporal_tuner.availability").withStyle(ChatFormatting.RED));
}
}
@@ -0,0 +1,54 @@
package com.craisinlord.antarchy.content.menu;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.item.GiantFryingPanItem;
import com.craisinlord.antarchy.content.item.GiantFryingPanStorage;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
public final class GiantFryingPanMenu extends AbstractContainerMenu {
private final GiantFryingPanStorage panStorage;
public GiantFryingPanMenu(int containerId, Inventory inventory) {
super(AntarchyObjects.GIANT_FRYING_PAN_MENU.get(), containerId);
ItemStack pan = GiantFryingPanStorage.findPan(inventory.player);
this.panStorage = new GiantFryingPanStorage(pan, inventory.player);
for (int slot = 0; slot < GiantFryingPanStorage.SLOT_COUNT; slot++) {
this.addSlot(new Slot(panStorage, slot, 8 + slot * 18, 18) {
@Override
public boolean mayPlace(ItemStack stack) {
return GiantFryingPanStorage.isCampfireInput(inventory.player, stack);
}
@Override
public int getMaxStackSize() { return 1; }
});
}
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 9; col++) {
this.addSlot(new Slot(inventory, col + row * 9 + 9, 8 + col * 18, 50 + row * 18));
}
}
for (int col = 0; col < 9; col++) this.addSlot(new Slot(inventory, col, 8 + col * 18, 108));
}
@Override
public boolean stillValid(Player player) { return player.isAlive() && !panStorage.isEmpty() || GiantFryingPanStorage.findPan(player).getItem() instanceof GiantFryingPanItem; }
@Override
public ItemStack quickMoveStack(Player player, int index) {
if (index < 0 || index >= slots.size()) return ItemStack.EMPTY;
Slot slot = slots.get(index);
if (!slot.hasItem()) return ItemStack.EMPTY;
ItemStack original = slot.getItem().copy();
if (index < GiantFryingPanStorage.SLOT_COUNT) {
if (!moveItemStackTo(slot.getItem(), GiantFryingPanStorage.SLOT_COUNT, slots.size(), true)) return ItemStack.EMPTY;
} else if (!moveItemStackTo(slot.getItem(), 0, GiantFryingPanStorage.SLOT_COUNT, false)) return ItemStack.EMPTY;
if (slot.getItem().isEmpty()) slot.setByPlayer(ItemStack.EMPTY);
else slot.setChanged();
return original;
}
}
@@ -0,0 +1,19 @@
package com.craisinlord.antarchy.content.network;
import com.craisinlord.antarchy.Antarchy;
import io.netty.buffer.ByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
public record TemporalTunerScrollPayload(double delta) implements CustomPacketPayload {
public static final Type<TemporalTunerScrollPayload> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "temporal_tuner_scroll"));
public static final StreamCodec<ByteBuf, TemporalTunerScrollPayload> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.DOUBLE, TemporalTunerScrollPayload::delta, TemporalTunerScrollPayload::new);
@Override
public Type<TemporalTunerScrollPayload> type() {
return TYPE;
}
}
@@ -0,0 +1,116 @@
package com.craisinlord.antarchy.content.portal;
import java.util.LinkedHashSet;
import java.util.Set;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.vehicle.DismountHelper;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.portal.DimensionTransition;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
public final class CrossDimensionTravelApi {
private static final int HORIZONTAL_SEARCH_RADIUS = 8;
private static final int VERTICAL_SEARCH_RADIUS = 8;
private CrossDimensionTravelApi() {
}
public static boolean transferToSafePosition(Entity entity, ServerLevel destination, BlockPos preferred) {
if (!entity.isAlive() || !(entity.level() instanceof ServerLevel source)) {
return false;
}
Vec3 arrival = findSafePosition(entity, destination, preferred);
if (arrival == null) {
return false;
}
if (entity instanceof ServerPlayer player) {
player.teleportTo(destination, arrival.x, arrival.y, arrival.z, player.getYRot(), player.getXRot());
player.setPortalCooldown();
return true;
}
if (source == destination) {
entity.teleportTo(arrival.x, arrival.y, arrival.z);
entity.setPortalCooldown();
return true;
}
Entity moved = entity.changeDimension(new DimensionTransition(
destination,
arrival,
Vec3.ZERO,
entity.getYRot(),
entity.getXRot(),
DimensionTransition.PLAY_PORTAL_SOUND
));
if (moved != null) {
moved.setPortalCooldown();
return true;
}
return false;
}
@Nullable
public static Vec3 findSafePosition(Entity entity, ServerLevel destination, BlockPos preferred) {
Set<BlockPos> candidates = new LinkedHashSet<>();
candidates.add(preferred);
for (int radius = 0; radius <= HORIZONTAL_SEARCH_RADIUS; radius++) {
for (int x = -radius; x <= radius; x++) {
for (int z = -radius; z <= radius; z++) {
if (radius > 0 && Math.abs(x) != radius && Math.abs(z) != radius) {
continue;
}
BlockPos column = preferred.offset(x, 0, z);
if (destination.hasChunkAt(column)) {
BlockPos surface = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, column);
candidates.add(surface);
candidates.add(surface.above());
}
for (int y = 0; y <= VERTICAL_SEARCH_RADIUS; y++) {
candidates.add(column.above(y));
if (y > 0) {
candidates.add(column.below(y));
}
}
}
}
}
for (BlockPos candidate : candidates) {
if (!isAreaLoaded(destination, candidate)) {
continue;
}
Vec3 safe = DismountHelper.findSafeDismountLocation(entity.getType(), destination, candidate, true);
if (safe != null && isValidPosition(destination, safe)) {
return safe;
}
}
return null;
}
private static boolean isAreaLoaded(ServerLevel level, BlockPos center) {
if (center.getY() <= level.getMinBuildHeight() || center.getY() >= level.getMaxBuildHeight() - 1
|| !level.getWorldBorder().isWithinBounds(center)) {
return false;
}
for (Direction direction : Direction.values()) {
if (!level.hasChunkAt(center.relative(direction))) {
return false;
}
}
return level.hasChunkAt(center) && level.hasChunkAt(center.above());
}
private static boolean isValidPosition(ServerLevel level, Vec3 position) {
BlockPos feet = BlockPos.containing(position);
BlockPos head = feet.above();
BlockState feetState = level.getBlockState(feet);
BlockState headState = level.getBlockState(head);
return feetState.getFluidState().isEmpty() && headState.getFluidState().isEmpty()
&& feetState.getCollisionShape(level, feet).isEmpty()
&& headState.getCollisionShape(level, head).isEmpty();
}
}
@@ -0,0 +1,7 @@
package com.craisinlord.antarchy.content.time;
public interface TemporalTunerAccess {
double antarchy$getTemporalTunerRate();
void antarchy$setTemporalTunerRate(double rate);
}
@@ -12,6 +12,8 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.entity.player.Player;
import com.craisinlord.antarchy.content.item.TemporalTunerItem;
import com.craisinlord.antarchy.content.effect.DilatedMobEffect;
import com.craisinlord.antarchy.content.effect.ContractedMobEffect;
import com.craisinlord.antarchy.content.effect.RoyalEffectEligibility;
@@ -35,6 +37,9 @@ public final class TimeDilationManager {
}
}
TrackingState tracking = TRACKING.get(level);
for (ServerPlayer player : level.players()) {
trackPotentiallyAffected(player);
}
if (activeFields == null && (tracking == null || tracking.entities.isEmpty())) {
continue;
}
@@ -64,13 +69,15 @@ public final class TimeDilationManager {
if (!(entity.level() instanceof ServerLevel level) || entity instanceof TimeDilationFieldEntity) {
return;
}
boolean hasTuner = entity instanceof Player player && TemporalTunerItem.isAvailable(player);
boolean hasEffect = entity instanceof net.minecraft.world.entity.LivingEntity living
&& ((RoyalEffectHooks.dilatedHolder() != null && living.hasEffect(RoyalEffectHooks.dilatedHolder()))
|| (RoyalEffectHooks.contractedHolder() != null && living.hasEffect(RoyalEffectHooks.contractedHolder())));
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()))))) {
&& !hasTuner && !hasEffect) {
return;
}
TRACKING.computeIfAbsent(level, ignored -> new TrackingState()).entities.add(entity);
@@ -165,6 +172,15 @@ public final class TimeDilationManager {
effectRate = Math.max(effectRate, ContractedMobEffect.rateForAmplifier(effect.getAmplifier()));
}
}
double tunerRate = TimeDilationMath.NORMAL_RATE;
if (entity instanceof Player player && player instanceof TemporalTunerAccess tunerAccess) {
if (TemporalTunerItem.isAvailable(player)) {
tunerRate = TemporalTunerItem.getRate(player);
} else {
tunerAccess.antarchy$setTemporalTunerRate(TimeDilationMath.NORMAL_RATE);
TemporalTunerItem.syncTooltipRate(player, TimeDilationMath.NORMAL_RATE);
}
}
double inheritedRate = access.antarchy$getInheritedTimeDilationRate();
double vehicleRate = TimeDilationApi.getVehicleRate(entity);
if (vehicleRate < TimeDilationMath.NORMAL_RATE) {
@@ -190,6 +206,11 @@ public final class TimeDilationManager {
} else {
fastRate = Math.max(fastRate, effectRate);
}
if (tunerRate < TimeDilationMath.NORMAL_RATE) {
slowRate = Math.min(slowRate, tunerRate);
} else {
fastRate = Math.max(fastRate, tunerRate);
}
if (inheritedRate < TimeDilationMath.NORMAL_RATE) {
slowRate = Math.min(slowRate, inheritedRate);
} else {
@@ -16,7 +16,8 @@ public abstract class AlexsCavesDepthChargeMixin {
@ModifyArg(
method = "tick",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/Vec3;add(DDD)Lnet/minecraft/world/phys/Vec3;"),
index = 1
index = 1,
require = 0
)
private double antarchy$invertManualGravity(double y) {
Projectile self = (Projectile) (Object) this;
@@ -18,7 +18,7 @@ public abstract class LivingEntityTimeDilationMixin {
private void antarchy$trackTemporalEffects(CallbackInfo ci) {
Entity entity = (Entity) (Object) this;
TimeDilationManager.trackPotentiallyAffected(entity);
if (entity.level().isClientSide && RoyalEffectHooks.contractedHolder() != null) {
if (entity.level().isClientSide) {
ContractionAfterimages.observe((LivingEntity) entity);
}
}
@@ -0,0 +1,37 @@
package com.craisinlord.antarchy.mixins.time;
import com.craisinlord.antarchy.content.time.TimeDilationMath;
import com.craisinlord.antarchy.content.time.TemporalTunerAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Player.class)
public abstract class PlayerTemporalTunerMixin implements TemporalTunerAccess {
@Unique
private double antarchy$temporalTunerRate = TimeDilationMath.NORMAL_RATE;
@Override
public double antarchy$getTemporalTunerRate() {
return antarchy$temporalTunerRate;
}
@Override
public void antarchy$setTemporalTunerRate(double rate) {
antarchy$temporalTunerRate = TimeDilationMath.clampRate(rate);
}
@Inject(method = "addAdditionalSaveData", at = @At("TAIL"))
private void antarchy$saveTemporalTunerRate(CompoundTag tag, CallbackInfo ci) {
tag.putDouble("AntarchyTemporalTunerRate", antarchy$temporalTunerRate);
}
@Inject(method = "readAdditionalSaveData", at = @At("TAIL"))
private void antarchy$loadTemporalTunerRate(CompoundTag tag, CallbackInfo ci) {
antarchy$temporalTunerRate = TimeDilationMath.clampRate(tag.getDouble("AntarchyTemporalTunerRate"));
}
}
@@ -107,6 +107,7 @@
"time.EntityDeltaMovementTimeDilationMixin",
"time.EntityMoveTimeDilationMixin",
"time.EntityTimeDilationStateMixin",
"time.PlayerTemporalTunerMixin",
"time.EntityRotationTimeDilationMixin",
"time.EntityCrouchTimeDilationMixin",
"time.LivingEntityKnockbackTimeDilationMixin",
@@ -0,0 +1,110 @@
{
"format_version": "1.21.110",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 128,
"texture_height": 128,
"visible_bounds_width": 4,
"visible_bounds_height": 6,
"visible_bounds_offset": [0, 2, 0]
},
"bones": [
{
"name": "giant_frying_pan",
"pivot": [0, -2, 0],
"cubes": [
{"origin": [-1, 0, -1], "size": [2, 20, 2], "uv": [16, 0]}
]
},
{
"name": "handle",
"parent": "giant_frying_pan",
"pivot": [0, -2, 0],
"cubes": [
{
"origin": [-2, -16, -2],
"size": [4, 16, 4],
"uv": {
"north": {"uv": [4, 4], "uv_size": [4, 16]},
"east": {"uv": [8, 4], "uv_size": [-4, 16]},
"south": {"uv": [4, 4], "uv_size": [4, 16]},
"west": {"uv": [8, 4], "uv_size": [-4, 16]},
"up": {"uv": [4, 0], "uv_size": [4, 4]},
"down": {"uv": [8, 4], "uv_size": [4, -4]}
}
}
]
},
{
"name": "pan_base",
"parent": "giant_frying_pan",
"pivot": [0, 38, 0],
"cubes": [
{
"origin": [-18, 22, 1],
"size": [36, 36, 2],
"uv": {
"north": {"uv": [0, 22], "uv_size": [36, 36]},
"east": {"uv": [26, 66], "uv_size": [2, 36]},
"south": {"uv": [36, 0], "uv_size": [36, 36]},
"west": {"uv": [28, 66], "uv_size": [2, 36]},
"up": {"uv": [102, 64], "uv_size": [-36, -2]},
"down": {"uv": [102, 66], "uv_size": [-36, -2]}
}
},
{
"origin": [18, 22, -3],
"size": [2, 36, 6],
"uv": {
"north": {"uv": [64, 62], "uv_size": [2, 36]},
"east": {"uv": [0, 58], "uv_size": [6, 36]},
"south": {"uv": [24, 66], "uv_size": [2, 36]},
"west": {"uv": [38, 54], "uv_size": [36, -6], "uv_rotation": 90},
"up": {"uv": [26, 10], "uv_size": [-2, -6]},
"down": {"uv": [26, 16], "uv_size": [-2, -6]}
}
},
{
"origin": [-20, 20, -3],
"size": [40, 2, 6],
"uv": {
"north": {"uv": [24, 60], "uv_size": [40, 2]},
"east": {"uv": [74, 48], "uv_size": [2, 6], "uv_rotation": 90},
"south": {"uv": [24, 62], "uv_size": [40, 2]},
"west": {"uv": [38, 54], "uv_size": [-2, -6], "uv_rotation": 90},
"up": {"uv": [76, 42], "uv_size": [-40, -6]},
"down": {"uv": [76, 48], "uv_size": [-40, 6]}
}
},
{
"origin": [-20, 22, -3],
"size": [2, 36, 6],
"uv": {
"north": {"uv": [30, 66], "uv_size": [2, 36]},
"east": {"uv": [38, 48], "uv_size": [36, 6], "uv_rotation": 90},
"south": {"uv": [32, 66], "uv_size": [2, 36]},
"west": {"uv": [18, 58], "uv_size": [6, 36]},
"up": {"uv": [26, 22], "uv_size": [-2, -6]},
"down": {"uv": [28, 10], "uv_size": [-2, -6]}
}
},
{
"origin": [-20, 58, -3],
"size": [40, 2, 6],
"uv": {
"north": {"uv": [24, 64], "uv_size": [40, 2]},
"east": {"uv": [36, 48], "uv_size": [2, 6], "uv_rotation": 90},
"south": {"uv": [64, 60], "uv_size": [40, 2]},
"west": {"uv": [36, 54], "uv_size": [2, -6], "uv_rotation": 90},
"up": {"uv": [76, 54], "uv_size": [-40, -6]},
"down": {"uv": [76, 60], "uv_size": [-40, -6]}
}
}
]
}
]
}
]
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "antarchy:item/blood_gods_blade"
}
}
@@ -321,6 +321,10 @@
"subtitles.antarchy.mantis_attack": "Mantis snaps",
"subtitles.antarchy.mantis_fly_loop": "Mantis wings buzz",
"item.antarchy.big_bertha": "Big Bertha",
"item.antarchy.giant_frying_pan": "Giant Frying Pan",
"tooltip.antarchy.giant_frying_pan.insert": "Right-click with food to add it to the pan.",
"tooltip.antarchy.giant_frying_pan.gui": "Shift-right-click to open the cooking slots.",
"tooltip.antarchy.giant_frying_pan.campfire": "Cooks campfire recipes without fuel.",
"item.antarchy.bluestone": "Bluestone Dust",
"item.antarchy.wasp_nest": "Wasp Nest",
"item.antarchy.stink_bug": "Stink Bug",
@@ -528,6 +532,11 @@
"item.antarchy.blood_crystal_shard": "Blood Crystal Shard",
"item.antarchy.blood_crystal_apple": "Blood Crystal Apple",
"item.antarchy.blood_crystal_katana": "Blood Crystal Katana",
"item.antarchy.blood_gods_blade": "Blood God’s Blade",
"tooltip.antarchy.blood_gods_blade.bleeding": "Hits inflict Bleeding",
"tooltip.antarchy.blood_gods_blade.blood_moon": "Right-click: Summon Blood Moon",
"effect.antarchy.bleeding": "Bleeding",
"effect.antarchy.blood_moon": "Blood Moon",
"item.antarchy.blood_crystal_helmet": "Blood Crystal Helmet",
"item.antarchy.blood_crystal_chestplate": "Blood Crystal Chestplate",
"item.antarchy.blood_crystal_leggings": "Blood Crystal Leggings",
@@ -548,9 +557,11 @@
"item.antarchy.royal_guardian_sword": "Royal Guardian Sword",
"item.antarchy.royal_guardian_shield": "Royal Guardian Shield",
"tooltip.antarchy.royal_guardian_sword.mode": "Mode: %s",
"tooltip.antarchy.royal_guardian_sword.mode.none": "None",
"tooltip.antarchy.royal_guardian_sword.mode.fire": "Fire",
"tooltip.antarchy.royal_guardian_sword.mode.frost": "Frost",
"tooltip.antarchy.royal_guardian_sword.mode.storm": "Storm",
"tooltip.antarchy.royal_guardian_sword.none": "Fully charged hits use the sword's normal damage without an elemental discharge.",
"tooltip.antarchy.royal_guardian_sword.fire": "Fully charged hits erupt in royal flame, burning the target and nearby enemies.",
"tooltip.antarchy.royal_guardian_sword.frost": "Fully charged hits freeze the target and raise a fan of royal ice spikes.",
"tooltip.antarchy.royal_guardian_sword.storm": "Fully charged hits call royal lightning that chains between nearby enemies.",
@@ -577,6 +588,11 @@
"tooltip.antarchy.mantis_claw.wall_cling": "Dual wield to cling to walls and jump upward.",
"item.antarchy.king_scale": "King Scale",
"item.antarchy.queen_scale": "Queen Scale",
"item.antarchy.temporal_tuner": "Temporal Tuner",
"tooltip.antarchy.temporal_tuner.description": "Adjusts your personal time dilation.",
"tooltip.antarchy.temporal_tuner.speed": "Current speed: %s%%",
"tooltip.antarchy.temporal_tuner.controls": "Shift + scroll: %s%% to %s%% speed",
"tooltip.antarchy.temporal_tuner.availability": "Resets when removed from your hotbar and offhand.",
"item.antarchy.jerry_nucleus": "Jerry Nucleus",
"tooltip.antarchy.jerry_nucleus.hatch": "While holding, interact with any bug egg or turtle egg to hatch it instantly.",
"key.antarchy.mount_special": "Mount: Special / Charge",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "antarchy:item/blood_gods_blade"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:item/generated",
"gui_light": "front",
"textures": {
"layer0": "antarchy:item/giant_frying_pan/giant_frying_pan_in_hand"
}
}
@@ -0,0 +1,90 @@
{
"credit": "Made with Blockbench",
"parent": "builtin/entity",
"texture_size": [
128,
128
],
"display": {
"thirdperson_righthand": {
"rotation": [
-25,
-180,
0
],
"translation": [
0,
-4,
3
],
"scale": [
1.2,
1.2,
1.2
]
},
"thirdperson_lefthand": {
"rotation": [
-25,
-180,
0
],
"translation": [
0,
-4,
3
],
"scale": [
1.2,
1.2,
1.2
]
},
"firstperson_righthand": {
"rotation": [
-75,
-180,
15
],
"translation": [
10,
-5,
10
],
"scale": [
0.68,
0.68,
0.68
]
},
"firstperson_lefthand": {
"rotation": [
-75,
-180,
15
],
"translation": [
10,
-5,
10
],
"scale": [
0.68,
0.68,
0.68
]
},
"ground": {
"translation": [
0,
2,
0
],
"scale": [
0.2,
0.2,
0.2
]
}
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "antarchy:item/temporal_tuner"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

@@ -0,0 +1,6 @@
{
"animation": {
"frametime": 5,
"interpolate": true
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -0,0 +1,6 @@
{
"animation": {
"frametime": 5,
"interpolate": true
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1002 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

@@ -124,6 +124,11 @@
"name": "antarchy:music_disc_verdance",
"weight": 2
},
{
"type": "minecraft:item",
"name": "antarchy:blood_gods_blade",
"weight": 1
},
{
"type": "minecraft:item",
"name": "antos:floppy_disk",
@@ -0,0 +1,21 @@
{
"type": "minecraft:crafting_shaped",
"category": "equipment",
"pattern": [
"NNN",
"NNN",
" S "
],
"key": {
"N": {
"item": "minecraft:netherite_block"
},
"S": {
"item": "antarchy:ultimate_shovel"
}
},
"result": {
"id": "antarchy:giant_frying_pan",
"count": 1
}
}
@@ -0,0 +1,24 @@
{
"type": "minecraft:crafting_shaped",
"category": "misc",
"pattern": [
"QSQ",
"QCQ",
"QQQ"
],
"key": {
"S": {
"item": "antarchy:blood_crystal_shard"
},
"Q": {
"item": "antarchy:queen_scale"
},
"C": {
"item": "minecraft:compass"
}
},
"result": {
"id": "antarchy:temporal_tuner",
"count": 1
}
}
@@ -8,6 +8,7 @@
"antarchy:ultimate_sword",
"antarchy:battle_axe",
"antarchy:big_bertha",
"antarchy:giant_frying_pan",
"antarchy:nightmare_sword",
"antarchy:basilisk_dagger",
"antarchy:ultimate_bow",
@@ -23,6 +24,7 @@
"antarchy:nightmare_boots",
"antarchy:moggles",
"antarchy:blood_crystal_katana",
"antarchy:blood_gods_blade",
"antarchy:mantis_claw",
"antarchy:krakens_grasp",
"antarchy:blood_crystal_helmet",
@@ -5,9 +5,11 @@
"antarchy:ultimate_axe",
"antarchy:ultimate_sword",
"antarchy:big_bertha",
"antarchy:giant_frying_pan",
"antarchy:nightmare_sword",
"antarchy:basilisk_dagger",
"antarchy:blood_crystal_katana",
"antarchy:blood_gods_blade",
"antarchy:mantis_claw",
"antarchy:royal_guardian_sword",
"antarchy:royal_assailant_battleaxe"
@@ -5,7 +5,9 @@
"antarchy:nightmare_sword",
"antarchy:basilisk_dagger",
"antarchy:big_bertha",
"antarchy:giant_frying_pan",
"antarchy:blood_crystal_katana",
"antarchy:blood_gods_blade",
"antarchy:mantis_claw",
"antarchy:royal_guardian_sword"
]