From ae763037163de9b9b4d5d87671813ca0277f12f3 Mon Sep 17 00:00:00 2001 From: craisinlord Date: Tue, 7 Jul 2026 13:02:01 -0500 Subject: [PATCH] swing through grass fix ruined arena structure kraken multipart fix logspam elythia worldgen fix rolly polly bonemeal --- .../antarchy/config/AntarchySettings.java | 15 +- .../antarchy/config/ConfigResetGuard.java | 2 +- .../antarchy/content/block/BigBushBlock.java | 7 +- .../content/block/BigBushPartBlock.java | 4 +- .../content/entity/AlphaMantisEntity.java | 23 ++ .../content/entity/EmperorScorpionEntity.java | 239 +++++-------- .../antarchy/content/entity/MantisEntity.java | 41 ++- .../content/entity/RollyPollyEntity.java | 336 +++++++++++++++++- .../content/entity/kraken/KrakenEntity.java | 23 +- .../entity/kraken/KrakenMultipartLayout.java | 54 ++- .../entity/multipart/MultipartFramework.java | 12 + .../content/item/WaterCannonItem.java | 2 +- .../worldgen/elythia/ElythiaFloraFeature.java | 33 +- .../GameRendererSwingThroughGrassMixin.java | 131 +++++++ .../resources/antarchy-common.mixins.json | 1 + .../animations/toreterror.animation.json | 7 +- .../chests/ruined_arena/generic.json | 91 ++--- .../spawners/ruined_arena/hard.json | 68 +++- .../spawners/ruined_arena/medium.json | 45 ++- .../structure/ruined_arena/ruined_arena.nbt | Bin 0 -> 267168 bytes .../has_structure/ruined_arena_biomes.json | 6 + .../worldgen/biome/elythia_meadow.json | 4 +- .../density_function/elythia_surface.json | 5 + .../worldgen/noise_settings/elythia.json | 319 ++++++++++------- .../elythia_meadow_large_tuff_boulders.json | 19 + .../elythia_meadow_tuff_boulders.json | 19 + .../worldgen/structure/ruined_arena.json | 22 ++ .../worldgen/structure_set/elythia_rare.json | 4 + .../ruined_arena/ruined_arena.json | 22 ++ .../structure/larger_locate_search.json | 1 + .../fabric/AntarchyConfigModuleFabric.java | 1 + .../fabric/AntarchyFabricContent.java | 2 +- .../antarchy/fabric/AntarchyFabricEvents.java | 3 + .../AntarchyConfigModuleNeoforge.java | 1 + .../antarchy/neoforge/AntarchyMiscConfig.java | 3 + .../antarchy/neoforge/AntarchyMobsConfig.java | 4 +- .../registry/AntarchyNeoForgeEvents.java | 3 + .../AntarchyNeoforgeCreativeModeTabs.java | 1 + .../registry/AntarchyNeoforgeEntites.java | 2 +- 39 files changed, 1121 insertions(+), 454 deletions(-) create mode 100644 common/src/main/java/com/craisinlord/antarchy/mixins/client/GameRendererSwingThroughGrassMixin.java create mode 100644 common/src/main/resources/data/antarchy/structure/ruined_arena/ruined_arena.nbt create mode 100644 common/src/main/resources/data/antarchy/tags/worldgen/biome/has_structure/ruined_arena_biomes.json create mode 100644 common/src/main/resources/data/antarchy/worldgen/placed_feature/elythia_meadow_large_tuff_boulders.json create mode 100644 common/src/main/resources/data/antarchy/worldgen/placed_feature/elythia_meadow_tuff_boulders.json create mode 100644 common/src/main/resources/data/antarchy/worldgen/structure/ruined_arena.json create mode 100644 common/src/main/resources/data/antarchy/worldgen/template_pool/ruined_arena/ruined_arena.json diff --git a/common/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java b/common/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java index 3855fb0b..09881a9e 100644 --- a/common/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java +++ b/common/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java @@ -17,6 +17,7 @@ public final class AntarchySettings { private static boolean duplicatorTreeEnabled = true; private static boolean glowingTorchflowers = true; private static boolean glowVinesUnderLeaves = true; + private static boolean swingThroughGrassEnabled = true; private static boolean sizeChangingRaysEnabled = true; private static double sizeRayMinScale = 0.1D; private static double sizeRayMaxScale = 10.0D; @@ -100,9 +101,9 @@ public final class AntarchySettings { private static double mantisMovementSpeed = 0.42D; private static double mantisFlyingSpeed = 0.77D; private static boolean mantisIgnoreLightLevel = false; - private static double alphaMantisHealth = 500.0D; + private static double alphaMantisHealth = 250.0D; private static double alphaMantisAttackDamage = 18.0D; - private static double alphaMantisMovementSpeed = 0.42D; + private static double alphaMantisMovementSpeed = 0.546D; private static double alphaMantisFlyingSpeed = 0.77D; private static int alphaMantisSummonIntervalTicks = 300; private static int alphaMantisMaxMinions = 4; @@ -240,7 +241,7 @@ public final class AntarchySettings { private static final int reverieAmbientPulseIntervalMaxTicks = 19; private static double emperorScorpionHealth = 400.0D; private static double emperorScorpionAttackDamage = 28.0D; - private static double emperorScorpionMovementSpeed = 0.32D; + private static double emperorScorpionMovementSpeed = 0.384D; private static double emperorScorpionArmor = 25.0D; private static double emperorScorpionKnockbackResistance = 0.8D; private static double emperorScorpionFollowRange = 40.0D; @@ -540,6 +541,10 @@ public final class AntarchySettings { return glowVinesUnderLeaves; } + public static boolean swingThroughGrassEnabled() { + return swingThroughGrassEnabled; + } + public static boolean sizeChangingRaysEnabled() { return sizeChangingRaysEnabled; } @@ -984,6 +989,10 @@ public final class AntarchySettings { glowVinesUnderLeaves = value; } + public static void setSwingThroughGrassEnabled(boolean value) { + swingThroughGrassEnabled = value; + } + public static void setSizeChangingRaysEnabled(boolean value) { sizeChangingRaysEnabled = value; } diff --git a/common/src/main/java/com/craisinlord/antarchy/config/ConfigResetGuard.java b/common/src/main/java/com/craisinlord/antarchy/config/ConfigResetGuard.java index b80fcf06..c0ef9b88 100644 --- a/common/src/main/java/com/craisinlord/antarchy/config/ConfigResetGuard.java +++ b/common/src/main/java/com/craisinlord/antarchy/config/ConfigResetGuard.java @@ -6,7 +6,7 @@ import java.nio.file.Files; import java.nio.file.Path; public final class ConfigResetGuard { - public static final int RESET_GENERATION = 1; + public static final int RESET_GENERATION = 2; private static final String MARKER_FILE_NAME = ".config_generation"; private ConfigResetGuard() { diff --git a/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushBlock.java b/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushBlock.java index a2ce8ee8..ef1d89ca 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushBlock.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushBlock.java @@ -33,7 +33,7 @@ import java.util.List; import java.util.Set; /** - * Multiblock bush grown with bonemeal. The origin block (this one) carries the + * Multiblock bush grown with bonemeal. The origin block carries the * loot/age; the rest of the footprint is filled with invisible * {@link BigBushPartBlock}s. * @@ -75,7 +75,7 @@ public class BigBushBlock extends BushBlock implements BonemealableBlock { return state.getValue(AGE) == 0 ? SMALL_SHAPE : Shapes.block(); } - /** All part positions belonging to a bush with the given origin state/pos (origin itself excluded). */ + /** All part positions belonging to a bush with the given origin state/pos */ public static List partPositions(BlockState state, BlockPos origin) { List positions = new ArrayList<>(); int age = state.getValue(AGE); @@ -106,7 +106,7 @@ public class BigBushBlock extends BushBlock implements BonemealableBlock { return positions; } - /** Ground-level columns of the footprint; each needs a sturdy block below it. */ + /** Ground columns of the footprint, each needs a sturdy block below it. */ public static List supportColumns(BlockState state, BlockPos origin) { List columns = new ArrayList<>(); int age = state.getValue(AGE); @@ -247,7 +247,6 @@ public class BigBushBlock extends BushBlock implements BonemealableBlock { return; } if (!target.origin().equals(pos)) { - // Relocating the origin: removing it cascades and clears the old parts. level.removeBlock(pos, false); } placeStage(level, target.origin(), target.state()); diff --git a/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushPartBlock.java b/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushPartBlock.java index 51ea6e3b..e9ea7036 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushPartBlock.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/block/BigBushPartBlock.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; * Invisible filler block for the grown {@link BigBushBlock} footprint. Breaking a * part destroys the whole bush (drops come from the origin's loot table). The one * part directly two above the origin of a stage-3 bush renders the top slice of - * the oversized cross model (CAP=true). + * the oversized cross model */ public class BigBushPartBlock extends Block { public static final MapCodec CODEC = Block.simpleCodec(BigBushPartBlock::new); @@ -113,8 +113,6 @@ public class BigBushPartBlock extends Block { level.removeBlock(pos, false); return; } - // Grown bushes need sturdy support under the whole footprint; break with - // drops if any of it is gone (mirrors plants popping when their dirt breaks). BlockState originState = level.getBlockState(origin); if (!originState.canSurvive(level, origin)) { level.destroyBlock(origin, true); diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/AlphaMantisEntity.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/AlphaMantisEntity.java index e82d97fd..fdddadf9 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/entity/AlphaMantisEntity.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/AlphaMantisEntity.java @@ -19,6 +19,7 @@ import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerLevelAccessor; @@ -91,6 +92,16 @@ public class AlphaMantisEntity extends MantisEntity { return false; } + @Override + protected MeleeAttackGoal createCombatGoal() { + return new MeleeAttackGoal(this, this.getCombatSpeed(), true); + } + + @Override + protected double getCombatSpeed() { + return 1.05D; + } + @Override public void tick() { super.tick(); @@ -155,6 +166,18 @@ public class AlphaMantisEntity extends MantisEntity { this.playSound(com.craisinlord.antarchy.content.AntarchySoundEvents.MANTIS_AMBIENT.get(), 2.0F, 0.6F); } + @Override + protected void onActiveTarget(LivingEntity target) { + if (this.flyBurstTicks > 0 || this.flyCooldownTicks > 0) { + this.stopFlightBurst(); + } + } + + @Override + protected boolean shouldStartFlightBurst() { + return false; + } + @Override public void setTarget(@Nullable LivingEntity target) { super.setTarget(target); diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/EmperorScorpionEntity.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/EmperorScorpionEntity.java index 8ac5a93b..7f815a30 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/entity/EmperorScorpionEntity.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/EmperorScorpionEntity.java @@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.entity; import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.content.AntarchyObjects; +import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; @@ -25,18 +26,17 @@ import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.goal.FloatGoal; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; import net.minecraft.world.entity.ai.goal.RandomStrollGoal; import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; import net.minecraft.world.entity.monster.Monster; -import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.phys.Vec3; +import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.Nullable; import software.bernie.geckolib.animatable.GeoEntity; import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache; @@ -84,15 +84,12 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity { new ServerBossEvent(this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS); private int attackAnimTicks = 0; - private int attackHitTick = 0; - private int attackCooldownTicks = 0; private int stingCooldownTicks = 0; private int agroAnimTicks = 0; private int summonCooldown = 0; private boolean attackDamageApplied = false; private boolean stingAttackActive = false; private boolean hasAgroed = false; - @Nullable private LivingEntity attackTarget; public EmperorScorpionEntity(EntityType entityType, Level level) { super(entityType, level); @@ -102,13 +99,13 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity { public static AttributeSupplier.Builder createAttributes() { return Monster.createMonsterAttributes() - .add(Attributes.MAX_HEALTH, 400.0D) - .add(Attributes.MOVEMENT_SPEED, 0.32D) - .add(Attributes.ATTACK_DAMAGE, 28.0D) - .add(Attributes.ARMOR, 25.0D) + .add(Attributes.MAX_HEALTH, AntarchySettings.emperorScorpionHealth()) + .add(Attributes.MOVEMENT_SPEED, AntarchySettings.emperorScorpionMovementSpeed()) + .add(Attributes.ATTACK_DAMAGE, AntarchySettings.emperorScorpionAttackDamage()) + .add(Attributes.ARMOR, AntarchySettings.emperorScorpionArmor()) .add(Attributes.ARMOR_TOUGHNESS, 10.0D) - .add(Attributes.KNOCKBACK_RESISTANCE, 0.8D) - .add(Attributes.FOLLOW_RANGE, 40.0D); + .add(Attributes.KNOCKBACK_RESISTANCE, AntarchySettings.emperorScorpionKnockbackResistance()) + .add(Attributes.FOLLOW_RANGE, AntarchySettings.emperorScorpionFollowRange()); } public static boolean canSpawn(EntityType entityType, ServerLevelAccessor level, @@ -128,10 +125,40 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity { @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); - this.goalSelector.addGoal(1, new EmperorScorpionAttackGoal()); - this.goalSelector.addGoal(5, new RandomStrollGoal(this, 0.8D)); - this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 12.0F)); - this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.2D, true)); + this.goalSelector.addGoal(5, new RandomStrollGoal(this, 0.8D) { + @Override + public boolean canUse() { + return !EmperorScorpionEntity.this.isInCombat() && super.canUse(); + } + + @Override + public boolean canContinueToUse() { + return !EmperorScorpionEntity.this.isInCombat() && super.canContinueToUse(); + } + }); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 12.0F) { + @Override + public boolean canUse() { + return !EmperorScorpionEntity.this.isInCombat() && super.canUse(); + } + + @Override + public boolean canContinueToUse() { + return !EmperorScorpionEntity.this.isInCombat() && super.canContinueToUse(); + } + }); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this) { + @Override + public boolean canUse() { + return !EmperorScorpionEntity.this.isInCombat() && super.canUse(); + } + + @Override + public boolean canContinueToUse() { + return !EmperorScorpionEntity.this.isInCombat() && super.canContinueToUse(); + } + }); this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); } @@ -150,19 +177,14 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity { public void tick() { super.tick(); this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); - if (this.attackCooldownTicks > 0) { - this.attackCooldownTicks--; - } if (this.stingCooldownTicks > 0) { this.stingCooldownTicks--; } if (this.attackAnimTicks > 0) { - if (!this.level().isClientSide) { - this.tickAttackWindup(); - } this.attackAnimTicks--; if (this.attackAnimTicks <= 0) { - this.resetAttackState(); + this.attackDamageApplied = false; + this.stingAttackActive = false; } } if (this.agroAnimTicks > 0) { @@ -226,123 +248,63 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity { @Override public boolean doHurtTarget(Entity target) { - return this.performSnapAttack(target); - } - - private boolean performSnapAttack(Entity target) { boolean hurt = super.doHurtTarget(target); if (hurt) { - this.playSound(AntarchySoundEvents.EMPEROR_SCORPION_ATTACK.get(), 0.9F, 0.95F + this.random.nextFloat() * 0.08F); + boolean usedSting = false; + if (target instanceof LivingEntity livingTarget && this.shouldUseSting(livingTarget)) { + this.stingAttackActive = true; + this.attackAnimTicks = STING_ATTACK_ANIM_TICKS; + this.attackDamageApplied = false; + this.level().broadcastEntityEvent(this, STING_ATTACK_ANIM_EVENT); + usedSting = this.performStingAttack(livingTarget); + if (usedSting) { + this.stingCooldownTicks = STING_ATTACK_COOLDOWN_TICKS; + } + } else { + this.stingAttackActive = false; + this.attackAnimTicks = SNAP_ATTACK_ANIM_TICKS; + this.attackDamageApplied = false; + this.level().broadcastEntityEvent(this, SNAP_ATTACK_ANIM_EVENT); + } + if (!usedSting) { + this.playSound(AntarchySoundEvents.EMPEROR_SCORPION_ATTACK.get(), 0.9F, 0.95F + this.random.nextFloat() * 0.08F); + } } return hurt; } private boolean performStingAttack(Entity target) { + if (!(target instanceof LivingEntity living)) { + return false; + } if (!(this.level() instanceof ServerLevel serverLevel)) { return false; } - boolean hurtAny = false; - for (LivingEntity living : serverLevel.getEntitiesOfClass(LivingEntity.class, - this.getBoundingBox().inflate(STING_AOE_RADIUS), - entity -> entity != this - && entity.isAlive() - && !(entity instanceof EmperorScorpionEntity) - && !(entity instanceof ScorpionEntity))) { - if (living.hurt(AntarchyDamageSources.emperorScorpionSting(serverLevel, this), STING_DAMAGE)) { - hurtAny = true; - int poisonDuration = this.level().getDifficulty() == Difficulty.HARD - ? POISON_DURATION_TICKS * 2 : POISON_DURATION_TICKS; - living.addEffect(new MobEffectInstance(MobEffects.POISON, poisonDuration, 1)); - living.addEffect(new MobEffectInstance(MobEffects.WEAKNESS, WEAKNESS_DURATION_TICKS, 0)); - } - } - if (hurtAny) { + boolean hurt = living.hurt(AntarchyDamageSources.emperorScorpionSting(serverLevel, this), STING_DAMAGE); + if (hurt) { + int poisonDuration = this.level().getDifficulty() == Difficulty.HARD + ? POISON_DURATION_TICKS * 2 : POISON_DURATION_TICKS; + living.addEffect(new MobEffectInstance(MobEffects.POISON, poisonDuration, 1)); + living.addEffect(new MobEffectInstance(MobEffects.WEAKNESS, WEAKNESS_DURATION_TICKS, 0)); this.playSound(AntarchySoundEvents.EMPEROR_SCORPION_ATTACK.get(), 1.0F, 0.9F + this.random.nextFloat() * 0.08F); } - return hurtAny; - } - - private void beginSnapAttack(LivingEntity target) { - this.attackTarget = target; - this.attackAnimTicks = SNAP_ATTACK_ANIM_TICKS; - this.attackHitTick = SNAP_ATTACK_HIT_TICK; - this.attackCooldownTicks = SNAP_ATTACK_COOLDOWN_TICKS; - this.attackDamageApplied = false; - this.stingAttackActive = false; - this.getNavigation().stop(); - this.level().broadcastEntityEvent(this, SNAP_ATTACK_ANIM_EVENT); - this.commitLunge(target, 0.42D, 0.10D); - } - - private void beginStingAttack(LivingEntity target) { - this.attackTarget = target; - this.attackAnimTicks = STING_ATTACK_ANIM_TICKS; - this.attackHitTick = STING_ATTACK_HIT_TICK; - this.attackCooldownTicks = STING_ATTACK_COOLDOWN_TICKS; - this.stingCooldownTicks = STING_ATTACK_COOLDOWN_TICKS; - this.attackDamageApplied = false; - this.stingAttackActive = true; - this.getNavigation().stop(); - this.level().broadcastEntityEvent(this, STING_ATTACK_ANIM_EVENT); - this.commitLunge(target, 0.55D, 0.14D); - } - - private void tickAttackWindup() { - if (this.attackTarget == null || !this.attackTarget.isAlive()) { - this.resetAttackState(); - return; - } - - this.getLookControl().setLookAt(this.attackTarget, 30.0F, 30.0F); - if (!this.attackDamageApplied && this.attackAnimTicks == this.attackHitTick) { - if (this.stingAttackActive) { - this.attackDamageApplied = true; - this.performStingAttack(this.attackTarget); - } else if (this.distanceToSqr(this.attackTarget) <= this.getAttackReachSqr(this.attackTarget)) { - this.attackDamageApplied = true; - this.performSnapAttack(this.attackTarget); - } - } - - if (this.attackAnimTicks <= 0) { - this.resetAttackState(); - } - } - - private double getAttackReachSqr(LivingEntity target) { - double reach = this.getBbWidth() * 1.9D + target.getBbWidth(); - return reach * reach + 1.5D; - } - - private void resetAttackState() { - this.attackAnimTicks = 0; - this.attackHitTick = 0; - this.attackDamageApplied = false; - this.stingAttackActive = false; - this.attackTarget = null; - } - - private void commitLunge(LivingEntity target, double horizontalSpeed, double verticalSpeed) { - Vec3 lunge = target.position().subtract(this.position()); - Vec3 horizontal = new Vec3(lunge.x, 0.0D, lunge.z); - if (horizontal.lengthSqr() < 1.0E-4D) { - return; - } - horizontal = horizontal.normalize().scale(horizontalSpeed); - this.setDeltaMovement(this.getDeltaMovement().add(horizontal.x, verticalSpeed, horizontal.z)); - this.hasImpulse = true; + return hurt; } private boolean shouldUseSting(LivingEntity target) { return this.stingCooldownTicks <= 0 - && this.distanceToSqr(target) <= this.getAttackReachSqr(target) + 2.0D - && (this.getHealth() <= this.getMaxHealth() * 0.6F || this.random.nextFloat() < 0.45F); + && target.isAlive() + && (this.getHealth() <= this.getMaxHealth() * 0.8F || this.random.nextFloat() < 0.35F); } private boolean isAttackLocked() { return this.attackAnimTicks > 0 || this.agroAnimTicks > 0; } + private boolean isInCombat() { + return this.getTarget() != null || this.isAttackLocked(); + } + @Override public void handleEntityEvent(byte id) { if (id == SNAP_ATTACK_ANIM_EVENT) { @@ -442,43 +404,4 @@ public class EmperorScorpionEntity extends Monster implements GeoEntity { super.remove(reason); this.bossEvent.removeAllPlayers(); } - - private final class EmperorScorpionAttackGoal extends MeleeAttackGoal { - private EmperorScorpionAttackGoal() { - super(EmperorScorpionEntity.this, 1.15D, true); - } - - @Override - public void tick() { - if (EmperorScorpionEntity.this.attackTarget != null) { - EmperorScorpionEntity.this.getLookControl().setLookAt( - EmperorScorpionEntity.this.attackTarget, 30.0F, 30.0F); - } - super.tick(); - } - - @Override - public boolean canContinueToUse() { - return EmperorScorpionEntity.this.isAttackLocked() || super.canContinueToUse(); - } - - @Override - protected void checkAndPerformAttack(LivingEntity enemy) { - if (EmperorScorpionEntity.this.isAttackLocked()) { - return; - } - if (this.canPerformAttack(enemy) - && this.isTimeToAttack() - && EmperorScorpionEntity.this.attackCooldownTicks <= 0) { - this.resetAttackCooldown(); - if (EmperorScorpionEntity.this.shouldUseSting(enemy)) { - EmperorScorpionEntity.this.beginStingAttack(enemy); - } else { - EmperorScorpionEntity.this.beginSnapAttack(enemy); - } - return; - } - super.checkAndPerformAttack(enemy); - } - } } diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java index 90995178..4e435a6e 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/MantisEntity.java @@ -64,9 +64,9 @@ public class MantisEntity extends Monster implements GeoEntity { net.minecraft.network.syncher.SynchedEntityData.defineId(MantisEntity.class, net.minecraft.network.syncher.EntityDataSerializers.INT); private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); - private int attackAnimationTicks; - private int flyBurstTicks; - private int flyCooldownTicks; + protected int attackAnimationTicks; + protected int flyBurstTicks; + protected int flyCooldownTicks; private int debugLogTicks = 0; public MantisEntity(EntityType entityType, Level level) { @@ -147,8 +147,8 @@ public class MantisEntity extends Monster implements GeoEntity { @Override protected void registerGoals() { this.goalSelector.addGoal(1, new FloatGoal(this)); - this.goalSelector.addGoal(2, new MeleeAttackGoal(this, COMBAT_SPEED, true)); - this.goalSelector.addGoal(3, new WaterAvoidingRandomStrollGoal(this, WANDER_SPEED)); + this.goalSelector.addGoal(2, this.createCombatGoal()); + this.goalSelector.addGoal(3, this.createIdleStrollGoal()); HurtByTargetGoal hurtByTargetGoal = new HurtByTargetGoal(this); this.targetSelector.addGoal(1, hurtByTargetGoal); @@ -156,6 +156,14 @@ public class MantisEntity extends Monster implements GeoEntity { this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 5, true, false, null)); } + protected MeleeAttackGoal createCombatGoal() { + return new MeleeAttackGoal(this, this.getCombatSpeed(), true); + } + + protected WaterAvoidingRandomStrollGoal createIdleStrollGoal() { + return new WaterAvoidingRandomStrollGoal(this, WANDER_SPEED); + } + @Override protected PathNavigation createNavigation(Level level) { GroundPathNavigation navigation = new GroundPathNavigation(this, level); @@ -206,8 +214,9 @@ public class MantisEntity extends Monster implements GeoEntity { LivingEntity target = this.getTarget(); if (target != null && target.isAlive()) { + this.onActiveTarget(target); this.getLookControl().setLookAt(target, 30.0F, 30.0F); - } else if (this.flyBurstTicks <= 0 && this.flyCooldownTicks <= 0 && this.onGround() && this.random.nextInt(180) == 0) { + } else if (this.shouldStartFlightBurst()) { this.startFlightBurst(); } @@ -264,6 +273,26 @@ public class MantisEntity extends Monster implements GeoEntity { super.setYBodyRot(yBodyRot); } + protected double getCombatSpeed() { + return COMBAT_SPEED; + } + + protected void onActiveTarget(LivingEntity target) { + } + + protected boolean shouldStartFlightBurst() { + return this.flyBurstTicks <= 0 + && this.flyCooldownTicks <= 0 + && this.onGround() + && this.random.nextInt(180) == 0; + } + + protected void stopFlightBurst() { + this.flyBurstTicks = 0; + this.flyCooldownTicks = 0; + this.setNoGravity(false); + } + private void startFlightBurst() { this.flyBurstTicks = 40 + this.random.nextInt(30); this.flyCooldownTicks = 160 + this.random.nextInt(80); diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/RollyPollyEntity.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/RollyPollyEntity.java index 85643b28..7a51d572 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/entity/RollyPollyEntity.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/RollyPollyEntity.java @@ -5,6 +5,9 @@ import com.craisinlord.antarchy.content.AntarchyTags; import java.util.EnumSet; import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; @@ -21,21 +24,29 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.TamableAnimal; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.goal.FloatGoal; import net.minecraft.world.entity.ai.goal.Goal; import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; +import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; import net.minecraft.world.entity.ai.goal.PanicGoal; import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; import net.minecraft.world.entity.ai.goal.TemptGoal; import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.ai.util.DefaultRandomPos; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.BedBlock; +import net.minecraft.world.level.block.ComposterBlock; +import net.minecraft.world.level.block.CropBlock; +import net.minecraft.world.level.block.LevelEvent; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; @@ -55,7 +66,6 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { private static final RawAnimation ROLLING_ANIM = RawAnimation.begin().thenLoop("roll"); private static final RawAnimation UNROLL_ANIM = RawAnimation.begin().thenPlay("normal_mode"); - // ANIMATION_STATE only syncs the roll transitions; idle/walk/rolling are derived client-side private static final int ANIM_NONE = 0; private static final int ANIM_ROLL_UP = 2; private static final int ANIM_UNROLL = 4; @@ -77,6 +87,7 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { private boolean unrolling; private int defensiveCurlTicks; private int tumbleTicks; + private boolean hasCompost; public RollyPollyEntity(EntityType entityType, Level level) { super(entityType, level); @@ -106,21 +117,24 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { return !RollyPollyEntity.this.isRolled() && !RollyPollyEntity.this.isTame() && super.canUse(); } }); - this.goalSelector.addGoal(2, new SnuggleOnBedGoal()); - this.goalSelector.addGoal(3, new TemptGoal(this, 1.1D, Ingredient.of(AntarchyTags.Items.ROLLY_POLLY_FOOD), false) { + this.goalSelector.addGoal(2, new FertilizeCropGoal()); + this.goalSelector.addGoal(3, new EatCompostItemGoal()); + this.goalSelector.addGoal(4, new SnuggleOnBedGoal()); + this.goalSelector.addGoal(5, new TemptGoal(this, 1.1D, Ingredient.of(AntarchyTags.Items.ROLLY_POLLY_FOOD), false) { @Override public boolean canUse() { return !RollyPollyEntity.this.isRolled() && super.canUse(); } }); - this.goalSelector.addGoal(4, new WaterAvoidingRandomStrollGoal(this, 1.0D) { + this.goalSelector.addGoal(6, new RollingStrollGoal()); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D) { @Override public boolean canUse() { return !RollyPollyEntity.this.isRolled() && !RollyPollyEntity.this.isVehicle() && super.canUse(); } }); - this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 8.0F)); - this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); } @Override @@ -132,7 +146,7 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); - if (this.isFood(stack)) { + if (this.isFood(stack) && (!this.isTame() || this.getHealth() < this.getMaxHealth())) { if (!this.level().isClientSide) { if (!player.getAbilities().instabuild) { stack.shrink(1); @@ -147,7 +161,7 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { } else { this.level().broadcastEntityEvent(this, (byte) 6); } - } else if (this.getHealth() < this.getMaxHealth()) { + } else { this.heal(4.0F); this.level().broadcastEntityEvent(this, (byte) 7); } @@ -155,6 +169,21 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { return InteractionResult.sidedSuccess(this.level().isClientSide); } + if (!this.hasCompost && isCompostable(stack)) { + if (!this.level().isClientSide) { + ItemStack eaten = stack.copyWithCount(1); + if (!player.getAbilities().instabuild) { + stack.shrink(1); + } + this.eatCompost(eaten); + } + return InteractionResult.sidedSuccess(this.level().isClientSide); + } + + if (this.isFood(stack)) { + return InteractionResult.sidedSuccess(this.level().isClientSide); + } + if (this.isTame() && stack.isEmpty() && !player.isShiftKeyDown() && !player.isPassengerOfSameVehicle(this)) { if (!this.level().isClientSide) { player.startRiding(this); @@ -171,6 +200,19 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { return null; } + private static boolean isCompostable(ItemStack stack) { + return !stack.isEmpty() && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem()); + } + + private void eatCompost(ItemStack eaten) { + this.hasCompost = true; + this.playSound(this.getEatingSound(eaten), 0.9F, 1.2F); + if (this.level() instanceof ServerLevel serverLevel) { + serverLevel.sendParticles(new ItemParticleOption(ParticleTypes.ITEM, eaten), + this.getX(), this.getY(0.6D), this.getZ(), 6, 0.1D, 0.1D, 0.1D, 0.05D); + } + } + public boolean isRolled() { return this.entityData.get(ROLLED); } @@ -357,6 +399,18 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { return super.causeFallDamage(fallDistance, multiplier, damageSource); } + @Override + public void addAdditionalSaveData(CompoundTag tag) { + super.addAdditionalSaveData(tag); + tag.putBoolean("HasCompost", this.hasCompost); + } + + @Override + public void readAdditionalSaveData(CompoundTag tag) { + super.readAdditionalSaveData(tag); + this.hasCompost = tag.getBoolean("HasCompost"); + } + @Override public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { controllers.add(new AnimationController<>(this, "main_controller", 2, this::mainAnimController)); @@ -381,11 +435,9 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { return state.setAndContinue(ROLLING_ANIM); } if (controller.getCurrentAnimation() == null) { - // Just loaded in while rolled — snap into the held ball pose controller.setAnimationSpeed(1.0D); return state.setAndContinue(ROLL_UP_ANIM); } - // Stationary while rolled: freeze on the current ball frame instead of spinning in place controller.setAnimationSpeed(0.0D); return PlayState.CONTINUE; } @@ -399,7 +451,262 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { return this.geoCache; } - /** Like a cat, a tamed rolly polly wanders over and curls up on the bed while its owner sleeps. */ + private class EatCompostItemGoal extends Goal { + @Nullable + private ItemEntity targetItem; + private int scanCooldown; + + EatCompostItemGoal() { + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + + @Override + public boolean canUse() { + if (RollyPollyEntity.this.hasCompost + || RollyPollyEntity.this.isRolled() + || RollyPollyEntity.this.isVehicle() + || RollyPollyEntity.this.defensiveCurlTicks > 0) { + return false; + } + if (this.scanCooldown > 0) { + this.scanCooldown--; + return false; + } + this.scanCooldown = 20; + this.targetItem = this.findNearestCompostItem(); + return this.targetItem != null; + } + + @Override + public boolean canContinueToUse() { + return !RollyPollyEntity.this.hasCompost + && !RollyPollyEntity.this.isRolled() + && !RollyPollyEntity.this.isVehicle() + && this.targetItem != null + && this.targetItem.isAlive() + && isCompostable(this.targetItem.getItem()); + } + + @Override + public void start() { + if (this.targetItem != null) { + RollyPollyEntity.this.getNavigation().moveTo(this.targetItem, 1.1D); + } + } + + @Override + public void stop() { + this.targetItem = null; + RollyPollyEntity.this.getNavigation().stop(); + } + + @Override + public void tick() { + if (this.targetItem == null) { + return; + } + RollyPollyEntity.this.getLookControl().setLookAt(this.targetItem); + if (RollyPollyEntity.this.tickCount % 10 == 0) { + RollyPollyEntity.this.getNavigation().moveTo(this.targetItem, 1.1D); + } + if (RollyPollyEntity.this.distanceToSqr(this.targetItem) < 2.0D) { + ItemStack stack = this.targetItem.getItem(); + ItemStack eaten = stack.copyWithCount(1); + stack.shrink(1); + if (stack.isEmpty()) { + this.targetItem.discard(); + } else { + this.targetItem.setItem(stack.copy()); + } + RollyPollyEntity.this.eatCompost(eaten); + } + } + + @Nullable + private ItemEntity findNearestCompostItem() { + ItemEntity nearest = null; + double nearestDist = Double.MAX_VALUE; + for (ItemEntity item : RollyPollyEntity.this.level().getEntitiesOfClass(ItemEntity.class, + RollyPollyEntity.this.getBoundingBox().inflate(8.0D, 4.0D, 8.0D), + item -> item.isAlive() && isCompostable(item.getItem()))) { + double dist = RollyPollyEntity.this.distanceToSqr(item); + if (dist < nearestDist) { + nearest = item; + nearestDist = dist; + } + } + return nearest; + } + } + + private class FertilizeCropGoal extends MoveToBlockGoal { + private static final int ROLL_ON_CROP_TICKS = 20; + + private int rollTicks; + + FertilizeCropGoal() { + super(RollyPollyEntity.this, 1.1D, 8, 2); + } + + @Override + public boolean canUse() { + return RollyPollyEntity.this.hasCompost + && !RollyPollyEntity.this.isRolled() + && !RollyPollyEntity.this.isVehicle() + && RollyPollyEntity.this.defensiveCurlTicks <= 0 + && super.canUse(); + } + + @Override + public boolean canContinueToUse() { + return RollyPollyEntity.this.hasCompost + && !RollyPollyEntity.this.isVehicle() + && super.canContinueToUse(); + } + + @Override + protected int nextStartTick(PathfinderMob mob) { + return reducedTickDelay(40 + mob.getRandom().nextInt(40)); + } + + @Override + protected boolean isValidTarget(LevelReader level, BlockPos pos) { + BlockState state = level.getBlockState(pos); + return state.getBlock() instanceof CropBlock crop && !crop.isMaxAge(state); + } + + @Override + protected BlockPos getMoveToTarget() { + return this.blockPos; + } + + @Override + public double acceptedDistance() { + return 1.75D; + } + + @Override + public void start() { + this.rollTicks = 0; + super.start(); + } + + @Override + public void stop() { + super.stop(); + if (RollyPollyEntity.this.isRolled() && RollyPollyEntity.this.rollTransitionTicks <= 0) { + RollyPollyEntity.this.startUnroll(); + } + } + + @Override + public void tick() { + super.tick(); + if (!this.isReachedTarget()) { + this.rollTicks = 0; + return; + } + RollyPollyEntity.this.getNavigation().stop(); + if (!RollyPollyEntity.this.isRolled()) { + if (RollyPollyEntity.this.rollTransitionTicks <= 0) { + RollyPollyEntity.this.startRollUp(); + } + return; + } + if (RollyPollyEntity.this.rollTransitionTicks > 0) { + return; + } + if (++this.rollTicks >= ROLL_ON_CROP_TICKS) { + this.fertilize(); + } + } + + private void fertilize() { + if (RollyPollyEntity.this.level() instanceof ServerLevel serverLevel) { + BlockState state = serverLevel.getBlockState(this.blockPos); + if (state.getBlock() instanceof CropBlock crop && !crop.isMaxAge(state)) { + crop.performBonemeal(serverLevel, RollyPollyEntity.this.random, this.blockPos, state); + serverLevel.levelEvent(LevelEvent.PARTICLES_AND_SOUND_PLANT_GROWTH, this.blockPos, 15); + } + } + RollyPollyEntity.this.hasCompost = false; + RollyPollyEntity.this.startUnroll(); + } + } + + private class RollingStrollGoal extends Goal { + @Nullable + private Vec3 targetPos; + private int rollingTicks; + private int maxRollingTicks; + private boolean startedMoving; + private boolean finished; + + RollingStrollGoal() { + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + + @Override + public boolean canUse() { + if (RollyPollyEntity.this.isRolled() + || RollyPollyEntity.this.isVehicle() + || RollyPollyEntity.this.defensiveCurlTicks > 0 + || RollyPollyEntity.this.hasCompost + || RollyPollyEntity.this.rollTransitionTicks > 0) { + return false; + } + if (RollyPollyEntity.this.getRandom().nextInt(reducedTickDelay(240)) != 0) { + return false; + } + this.targetPos = DefaultRandomPos.getPos(RollyPollyEntity.this, 16, 4); + return this.targetPos != null; + } + + @Override + public boolean canContinueToUse() { + return !this.finished + && this.rollingTicks < this.maxRollingTicks + && !RollyPollyEntity.this.isVehicle() + && !RollyPollyEntity.this.hasCompost; + } + + @Override + public void start() { + this.rollingTicks = 0; + this.maxRollingTicks = this.adjustedTickDelay(140 + RollyPollyEntity.this.getRandom().nextInt(100)); + this.startedMoving = false; + this.finished = false; + RollyPollyEntity.this.startRollUp(); + } + + @Override + public void stop() { + this.targetPos = null; + RollyPollyEntity.this.getNavigation().stop(); + if (RollyPollyEntity.this.isRolled() && RollyPollyEntity.this.rollTransitionTicks <= 0) { + RollyPollyEntity.this.startUnroll(); + } + } + + @Override + public void tick() { + if (RollyPollyEntity.this.rollTransitionTicks > 0 || this.targetPos == null) { + return; + } + this.rollingTicks++; + if (RollyPollyEntity.this.getNavigation().isDone()) { + if (this.startedMoving) { + this.finished = true; + } else { + RollyPollyEntity.this.getNavigation().moveTo( + this.targetPos.x, this.targetPos.y, this.targetPos.z, + AntarchySettings.rollyPollyRollSpeedMultiplier()); + this.startedMoving = true; + } + } + } + } + private class SnuggleOnBedGoal extends Goal { @Nullable private Player ownerPlayer; @@ -428,7 +735,6 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { return false; } this.ownerPlayer = player; - // Aim for the pillow end of the bed, next to the sleeper's head this.bedPos = stateAt.getOptionalValue(BedBlock.FACING) .map(direction -> pos.relative(direction.getOpposite())) .orElse(pos); @@ -467,7 +773,11 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity { } if (RollyPollyEntity.this.distanceToSqr(this.ownerPlayer) > 2.5D) { this.onBedTicks = 0; - if (!RollyPollyEntity.this.isRolled()) { + if (RollyPollyEntity.this.isRolled()) { + if (RollyPollyEntity.this.rollTransitionTicks <= 0) { + RollyPollyEntity.this.startUnroll(); + } + } else { RollyPollyEntity.this.getNavigation().moveTo( this.bedPos.getX() + 0.5D, this.bedPos.getY() + 1.0D, this.bedPos.getZ() + 0.5D, 1.1D); } diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenEntity.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenEntity.java index 5a5b93c5..be235d48 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenEntity.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenEntity.java @@ -6,6 +6,8 @@ import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.damage.AntarchyDamageSources; import com.craisinlord.antarchy.content.entity.MissileSquidEntity; import com.craisinlord.antarchy.content.entity.OctopusBombEntity; +import com.craisinlord.antarchy.content.entity.multipart.MultipartEntityOwner; +import com.craisinlord.antarchy.content.entity.multipart.MultipartLayout; import com.craisinlord.antarchy.content.damage.AntarchyDamageTypes; import java.util.List; @@ -60,7 +62,7 @@ import software.bernie.geckolib.animation.RawAnimation; import software.bernie.geckolib.animation.keyframe.event.builtin.AutoPlayingSoundKeyframeHandler; import software.bernie.geckolib.util.GeckoLibUtil; -public class KrakenEntity extends Monster implements GeoEntity { +public class KrakenEntity extends Monster implements GeoEntity, MultipartEntityOwner { private static final EntityDataAccessor ATTACK_STATE = SynchedEntityData.defineId(KrakenEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor ROARING = SynchedEntityData.defineId(KrakenEntity.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor PHASE_TWO = SynchedEntityData.defineId(KrakenEntity.class, EntityDataSerializers.BOOLEAN); @@ -127,6 +129,9 @@ public class KrakenEntity extends Monster implements GeoEntity { private float orbitDirection = 1.0F; private boolean stormActive; + @Nullable + private Entity[] multipartParts; + public KrakenEntity(EntityType entityType, Level level) { super(entityType, level); this.moveControl = new FlyingMoveControl(this, 20, true); @@ -149,6 +154,22 @@ public class KrakenEntity extends Monster implements GeoEntity { return level.getFluidState(pos).is(FluidTags.WATER) && level.getFluidState(pos.above()).is(FluidTags.WATER); } + @Override + public MultipartLayout antarchy$getMultipartLayout() { + return KrakenMultipartLayout.INSTANCE; + } + + @Override + @Nullable + public Entity[] antarchy$getMultipartParts() { + return this.multipartParts; + } + + @Override + public void antarchy$setMultipartParts(@Nullable Entity[] parts) { + this.multipartParts = parts; + } + @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenMultipartLayout.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenMultipartLayout.java index 4ed41801..e4058999 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenMultipartLayout.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakenMultipartLayout.java @@ -6,43 +6,67 @@ import com.craisinlord.antarchy.content.entity.multipart.MultipartPartDefinition public final class KrakenMultipartLayout implements MultipartLayout { public static final KrakenMultipartLayout INSTANCE = new KrakenMultipartLayout(); + public static final MultipartPartDefinition TENTACLE_MASS = new MultipartPartDefinition( + "tentacle_mass", + 7.5F, + 14.0F, + 0.90F, + -0.35D, + 14.00D, + 0.00D, + true + ); + public static final MultipartPartDefinition HEAD = new MultipartPartDefinition( "head", - 3.0F, - 2.8F, + 9.0F, + 4.0F, 1.00F, - 2.15D, - 5.35D, + 1.50D, + 28.00D, 0.00D, true ); public static final MultipartPartDefinition BACK_HEAD = new MultipartPartDefinition( "back_head", - 4.8F, - 4.4F, + 5.5F, + 4.5F, 1.10F, 0.70D, - 6.55D, + 31.00D, 0.00D, true ); - public static final MultipartPartDefinition TENTACLE_MASS = new MultipartPartDefinition( - "tentacle_mass", - 8.5F, - 3.4F, - 0.90F, - -0.35D, - 1.70D, + public static final MultipartPartDefinition MANTLE = new MultipartPartDefinition( + "mantle", + 8.0F, + 7.0F, + 1.00F, + 0.60D, + 34.50D, + 0.00D, + true + ); + + public static final MultipartPartDefinition CREST = new MultipartPartDefinition( + "crest", + 4.5F, + 4.0F, + 1.10F, + 0.55D, + 41.50D, 0.00D, true ); private static final MultipartPartDefinition[] PARTS = { + TENTACLE_MASS, HEAD, BACK_HEAD, - TENTACLE_MASS + MANTLE, + CREST }; private KrakenMultipartLayout() { diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/multipart/MultipartFramework.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/multipart/MultipartFramework.java index 9bc6c5da..7f36e286 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/entity/multipart/MultipartFramework.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/multipart/MultipartFramework.java @@ -7,6 +7,9 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; public final class MultipartFramework { + private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(MultipartFramework.class); + private static boolean warnedMissingFactory; + public interface PartFactory { Entity create(MultipartEntityOwner owner, int partIndex, MultipartPartDefinition spec); } @@ -43,6 +46,15 @@ public final class MultipartFramework { } public static Entity[] createMultipartParts(MultipartEntityOwner owner) { + if (partFactory == null) { + if (!warnedMissingFactory) { + warnedMissingFactory = true; + LOGGER.warn("Multipart part factory has not been bootstrapped on this platform; " + + "multipart entities will fall back to their base hitbox only"); + } + return new Entity[0]; + } + MultipartLayout layout = owner.antarchy$getMultipartLayout(); MultipartPartDefinition[] parts = layout.parts(); Entity[] created = new Entity[parts.length]; diff --git a/common/src/main/java/com/craisinlord/antarchy/content/item/WaterCannonItem.java b/common/src/main/java/com/craisinlord/antarchy/content/item/WaterCannonItem.java index ec158ce5..be1a7d7a 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/item/WaterCannonItem.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/item/WaterCannonItem.java @@ -66,7 +66,7 @@ public class WaterCannonItem extends ProjectileWeaponItem implements GeoItem { level.playSound(null, player.getX(), player.getY(), player.getZ(), AntarchySoundEvents.WATER_CANNON_FIRE.get(), SoundSource.PLAYERS, - 0.8F, 0.9F + level.getRandom().nextFloat() * 0.2F); + 0.22F, 0.9F + level.getRandom().nextFloat() * 0.2F); if (!level.isClientSide()) { WaterBombEntity bomb = new WaterBombEntity(level, player); diff --git a/common/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaFloraFeature.java b/common/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaFloraFeature.java index d6ae046b..00a17a11 100644 --- a/common/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaFloraFeature.java +++ b/common/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaFloraFeature.java @@ -36,8 +36,8 @@ public class ElythiaFloraFeature extends Feature { RandomSource random = context.random(); BlockPos origin = context.origin(); int attempts = switch (this.variant) { - case FOREST -> 240; - case MEADOW -> 110; + case FOREST -> 185; + case MEADOW -> 95; case TORCHFLOWER_FIELDS -> 60; case BUTTERFLY_FIELDS -> 150; case FLOWER_FOREST_MILKWEED -> 14; @@ -171,33 +171,30 @@ public class ElythiaFloraFeature extends Feature { float roll = random.nextFloat(); if (this.variant == Variant.MEADOW) { - if (roll < 0.40F) { + if (roll < 0.34F) { return placeSingle(level, plantPos, Blocks.SHORT_GRASS); } - if (roll < 0.80F) { + if (roll < 0.78F) { return placeSingle(level, plantPos, veryShortGrass()); } - if (roll < 0.88F) { - return placeVeryTall(level, plantPos, veryTallGrass()); - } - if (roll < 0.98F) { + if (roll < 0.81F) { return placeDouble(level, plantPos, Blocks.TALL_GRASS.defaultBlockState()); } - return placeSingle(level, plantPos, Blocks.SHORT_GRASS); - } - if (roll < 0.24F) { - return placeSingle(level, plantPos, Blocks.SHORT_GRASS); - } - if (roll < 0.60F) { return placeSingle(level, plantPos, veryShortGrass()); } - if (roll < 0.74F) { + if (roll < 0.14F) { + return placeSingle(level, plantPos, Blocks.SHORT_GRASS); + } + if (roll < 0.52F) { + return placeSingle(level, plantPos, veryShortGrass()); + } + if (roll < 0.72F) { return placeSingle(level, plantPos, Blocks.FERN); } - if (roll < 0.84F) { + if (roll < 0.80F) { return placeDouble(level, plantPos, Blocks.TALL_GRASS.defaultBlockState()); } - if (roll < 0.96F) { + if (roll < 0.84F) { return placeVeryTall(level, plantPos, veryTallGrass()); } return placeDouble(level, plantPos, Blocks.LARGE_FERN.defaultBlockState()); @@ -220,7 +217,7 @@ public class ElythiaFloraFeature extends Feature { } boolean placed = false; - int bushAttempts = 10 + random.nextInt(6); + int bushAttempts = 12 + random.nextInt(7); for (int i = 0; i < bushAttempts; i++) { int x = origin.getX() + random.nextInt(radius * 2 + 1) - radius; int z = origin.getZ() + random.nextInt(radius * 2 + 1) - radius; diff --git a/common/src/main/java/com/craisinlord/antarchy/mixins/client/GameRendererSwingThroughGrassMixin.java b/common/src/main/java/com/craisinlord/antarchy/mixins/client/GameRendererSwingThroughGrassMixin.java new file mode 100644 index 00000000..a29867dc --- /dev/null +++ b/common/src/main/java/com/craisinlord/antarchy/mixins/client/GameRendererSwingThroughGrassMixin.java @@ -0,0 +1,131 @@ +package com.craisinlord.antarchy.mixins.client; + +import com.craisinlord.antarchy.config.AntarchySettings; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(GameRenderer.class) +public abstract class GameRendererSwingThroughGrassMixin { + @Shadow + private Minecraft minecraft; + + @Shadow + private static HitResult filterHitResult(HitResult hitResult, Vec3 eyePosition, double range) { + throw new AssertionError(); + } + + @Unique + private Double antarchy$swingThroughReachSq; + + @Inject( + method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/HitResult;getLocation()Lnet/minecraft/world/phys/Vec3;" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void antarchy$cacheSwingThroughReach( + Entity entity, + double blockInteractionRange, + double entityInteractionRange, + float partialTick, + CallbackInfoReturnable cir, + double maxRange, + double maxRangeSq, + Vec3 eyePosition, + HitResult hitResult + ) { + this.antarchy$swingThroughReachSq = null; + if (!AntarchySettings.swingThroughGrassEnabled()) { + return; + } + + if (!(hitResult instanceof BlockHitResult blockHitResult) || hitResult.getType() != HitResult.Type.BLOCK) { + return; + } + + ClientLevel level = this.minecraft.level; + if (level == null) { + return; + } + + BlockPos blockPos = blockHitResult.getBlockPos(); + if (level.getBlockState(blockPos).getCollisionShape(level, blockPos).isEmpty()) { + this.antarchy$swingThroughReachSq = maxRangeSq; + } + } + + @ModifyArg( + method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/projectile/ProjectileUtil;getEntityHitResult(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;D)Lnet/minecraft/world/phys/EntityHitResult;" + ), + index = 5 + ) + private double antarchy$useOriginalReachForEntityRaycast(double rangeSq) { + return this.antarchy$swingThroughReachSq == null ? rangeSq : this.antarchy$swingThroughReachSq; + } + + @Inject( + method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/phys/EntityHitResult;getLocation()Lnet/minecraft/world/phys/Vec3;" + ), + cancellable = true, + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void antarchy$preferAttackableEntityBehindGrass( + Entity entity, + double blockInteractionRange, + double entityInteractionRange, + float partialTick, + CallbackInfoReturnable cir, + double maxRange, + double maxRangeSq, + Vec3 eyePosition, + HitResult blockHitResult, + double blockHitDistanceSq, + Vec3 viewVector, + Vec3 reachEnd, + float unused, + AABB aabb, + EntityHitResult entityHitResult + ) { + if (this.antarchy$swingThroughReachSq == null || entityHitResult == null) { + return; + } + + Entity hitEntity = entityHitResult.getEntity(); + if (!(hitEntity instanceof LivingEntity) + || hitEntity.isSpectator() + || !hitEntity.isAttackable() + || this.minecraft.player == null + || hitEntity == this.minecraft.player.getVehicle()) { + return; + } + + if (eyePosition.distanceToSqr(hitEntity.position()) < this.antarchy$swingThroughReachSq) { + cir.setReturnValue(filterHitResult(entityHitResult, eyePosition, entityInteractionRange)); + } + } +} diff --git a/common/src/main/resources/antarchy-common.mixins.json b/common/src/main/resources/antarchy-common.mixins.json index 6376b525..c4e08990 100644 --- a/common/src/main/resources/antarchy-common.mixins.json +++ b/common/src/main/resources/antarchy-common.mixins.json @@ -53,6 +53,7 @@ "client.CavarynSkyMixin", "client.ElythiaSkyMixin", "client.ElytraModelAccessor", + "client.GameRendererSwingThroughGrassMixin", "client.LightningBoltRendererMixin", "client.LivingEntityRendererBigBushMixin", "client.MountedVehicleCameraMixin", diff --git a/common/src/main/resources/assets/antarchy/animations/toreterror.animation.json b/common/src/main/resources/assets/antarchy/animations/toreterror.animation.json index d0a2525b..cbafcff7 100644 --- a/common/src/main/resources/assets/antarchy/animations/toreterror.animation.json +++ b/common/src/main/resources/assets/antarchy/animations/toreterror.animation.json @@ -2136,6 +2136,11 @@ "spin_attack": { "loop": true, "animation_length": 0.2917, + "sound_effects": { + "0.0": { + "effect": "antarchy:toreterror_spin|1.1|0.95" + } + }, "bones": { "R_arm": { "rotation": { @@ -3357,4 +3362,4 @@ } } } -} \ No newline at end of file +} diff --git a/common/src/main/resources/data/antarchy/loot_table/chests/ruined_arena/generic.json b/common/src/main/resources/data/antarchy/loot_table/chests/ruined_arena/generic.json index 5f5a748e..c60f316d 100644 --- a/common/src/main/resources/data/antarchy/loot_table/chests/ruined_arena/generic.json +++ b/common/src/main/resources/data/antarchy/loot_table/chests/ruined_arena/generic.json @@ -3,22 +3,6 @@ "pools": [ { "entries": [ - { - "type": "minecraft:item", - "name": "minecraft:iron_sword", - "weight": 18, - "functions": [ - { - "function": "minecraft:enchant_with_levels", - "levels": { - "type": "minecraft:uniform", - "min": 5.0, - "max": 18.0 - }, - "options": "#minecraft:on_random_loot" - } - ] - }, { "type": "minecraft:item", "name": "minecraft:bow", @@ -35,32 +19,6 @@ } ] }, - { - "type": "minecraft:item", - "name": "minecraft:crossbow", - "weight": 15, - "functions": [ - { - "function": "minecraft:enchant_with_levels", - "levels": { - "type": "minecraft:uniform", - "min": 6.0, - "max": 20.0 - }, - "options": "#minecraft:on_random_loot" - } - ] - }, - { - "type": "minecraft:item", - "name": "antarchy:battle_axe", - "weight": 10 - }, - { - "type": "minecraft:item", - "name": "antarchy:scorpion_whip", - "weight": 8 - }, { "type": "minecraft:item", "name": "minecraft:shield", @@ -141,21 +99,6 @@ } ] }, - { - "type": "minecraft:item", - "name": "minecraft:amethyst_shard", - "weight": 8, - "functions": [ - { - "function": "minecraft:set_count", - "count": { - "type": "minecraft:uniform", - "min": 2.0, - "max": 6.0 - } - } - ] - }, { "type": "minecraft:item", "name": "minecraft:experience_bottle", @@ -180,7 +123,7 @@ "function": "minecraft:set_components", "components": { "minecraft:potion_contents": { - "potion": "minecraft:swiftness" + "potion": "antarchy:shrinking" } } } @@ -210,7 +153,7 @@ "function": "minecraft:set_components", "components": { "minecraft:potion_contents": { - "potion": "minecraft:regeneration" + "potion": "antarchy:inverted" } } } @@ -251,6 +194,36 @@ } } ] + }, + { + "type": "minecraft:item", + "name": "antarchy:uranium_nugget", + "weight": 3, + "functions": [ + { + "function": "minecraft:set_count", + "count": { + "type": "minecraft:uniform", + "min": 1.0, + "max": 2.0 + } + } + ] + }, + { + "type": "minecraft:item", + "name": "antarchy:titanium_nugget", + "weight": 3, + "functions": [ + { + "function": "minecraft:set_count", + "count": { + "type": "minecraft:uniform", + "min": 1.0, + "max": 2.0 + } + } + ] } ], "rolls": { diff --git a/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/hard.json b/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/hard.json index fabf7cf7..7b3f4bb0 100644 --- a/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/hard.json +++ b/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/hard.json @@ -6,27 +6,17 @@ { "type": "minecraft:item", "name": "antarchy:ultimate_sword", - "weight": 8 + "weight": 2 }, { "type": "minecraft:item", "name": "antarchy:ultimate_bow", - "weight": 8 + "weight": 2 }, { "type": "minecraft:item", "name": "antarchy:ultimate_crossbow", - "weight": 8 - }, - { - "type": "minecraft:item", - "name": "antarchy:battle_axe", - "weight": 14 - }, - { - "type": "minecraft:item", - "name": "antarchy:scorpion_whip", - "weight": 12 + "weight": 2 }, { "type": "minecraft:item", @@ -206,6 +196,58 @@ } } ] + }, + { + "type": "minecraft:item", + "name": "antarchy:uranium_nugget", + "weight": 4, + "functions": [ + { + "function": "minecraft:set_count", + "count": { + "type": "minecraft:uniform", + "min": 1.0, + "max": 2.0 + } + } + ] + }, + { + "type": "minecraft:item", + "name": "antarchy:titanium_nugget", + "weight": 4, + "functions": [ + { + "function": "minecraft:set_count", + "count": { + "type": "minecraft:uniform", + "min": 1.0, + "max": 2.0 + } + } + ] + }, + { + "type": "minecraft:item", + "name": "antarchy:uranium_ingot", + "weight": 2, + "functions": [ + { + "function": "minecraft:set_count", + "count": 1 + } + ] + }, + { + "type": "minecraft:item", + "name": "antarchy:titanium_ingot", + "weight": 2, + "functions": [ + { + "function": "minecraft:set_count", + "count": 1 + } + ] } ], "rolls": { diff --git a/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/medium.json b/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/medium.json index 7e3adfb0..75182308 100644 --- a/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/medium.json +++ b/common/src/main/resources/data/antarchy/loot_table/spawners/ruined_arena/medium.json @@ -195,6 +195,36 @@ } } ] + }, + { + "type": "minecraft:item", + "name": "antarchy:uranium_nugget", + "weight": 4, + "functions": [ + { + "function": "minecraft:set_count", + "count": { + "type": "minecraft:uniform", + "min": 1.0, + "max": 2.0 + } + } + ] + }, + { + "type": "minecraft:item", + "name": "antarchy:titanium_nugget", + "weight": 4, + "functions": [ + { + "function": "minecraft:set_count", + "count": { + "type": "minecraft:uniform", + "min": 1.0, + "max": 2.0 + } + } + ] } ], "rolls": { @@ -205,21 +235,6 @@ }, { "entries": [ - { - "type": "minecraft:item", - "name": "antarchy:ultimate_sword", - "weight": 2 - }, - { - "type": "minecraft:item", - "name": "antarchy:ultimate_bow", - "weight": 2 - }, - { - "type": "minecraft:item", - "name": "antarchy:ultimate_crossbow", - "weight": 2 - }, { "type": "minecraft:item", "name": "minecraft:diamond_sword", diff --git a/common/src/main/resources/data/antarchy/structure/ruined_arena/ruined_arena.nbt b/common/src/main/resources/data/antarchy/structure/ruined_arena/ruined_arena.nbt new file mode 100644 index 0000000000000000000000000000000000000000..d59f43224cd5795a0870399ec803d72da7c3523a GIT binary patch literal 267168 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, EntityType> ALPHA_MANTIS = ENTITY_TYPES.register("alpha_mantis", () -> EntityType.Builder.of(AlphaMantisEntity::new, MobCategory.MONSTER) - .sized(4.0F, 3.25F) + .sized(4.25F, 3.35F) .clientTrackingRange(10) .build("alpha_mantis")); public static final DeferredHolder, EntityType> ROLLY_POLLY = ENTITY_TYPES.register("rolly_polly", diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java index 70d25f9f..a151c550 100644 --- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java +++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricEvents.java @@ -53,8 +53,11 @@ public final class AntarchyFabricEvents { ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.UMBRAL_MOSS_CARPET.get().asItem(), 0.3f); ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.AMBER_MOSS_BLOCK.get().asItem(), 0.65f); ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.AMBER_MOSS_CARPET.get().asItem(), 0.3f); + ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.BIG_BUSH.get().asItem(), 0.65f); ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.CREEPVINE.get().asItem(), 0.3f); ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.HUSHWEED.get().asItem(), 0.65f); + ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.VERY_SHORT_GRASS.get().asItem(), 0.3f); + ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.VERY_TALL_GRASS.get().asItem(), 0.5f); ComposterBlock.COMPOSTABLES.put(AntarchyFabricContent.CORNEA_EAR.get(), 0.65f); ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> { diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java index b5f5680d..0e77f432 100644 --- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java +++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java @@ -350,6 +350,7 @@ public final class AntarchyConfigModuleNeoforge { AntarchySettings.setDuplicatorTreeEnabled(AntarchyMiscConfig.duplicatorTreeEnabled()); AntarchySettings.setGlowingTorchflowers(AntarchyMiscConfig.glowingTorchflowers()); AntarchySettings.setGlowVinesUnderLeaves(AntarchyMiscConfig.glowVinesUnderLeaves()); + AntarchySettings.setSwingThroughGrassEnabled(AntarchyMiscConfig.swingThroughGrassEnabled()); AntarchySettings.setEntitySpecificFireOverlayEnabled(AntarchyMiscConfig.entitySpecificFireOverlayEnabled()); AntarchySettings.setBloodCrystalArmorShieldRechargeTicks(AntarchyToolsConfig.bloodCrystalArmorShieldRechargeTicks()); diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java index c8d6ddf0..322fa099 100644 --- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java +++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java @@ -40,6 +40,7 @@ public final class AntarchyMiscConfig { private static final ModConfigSpec.BooleanValue DUPLICATOR_TREE_ENABLED; private static final ModConfigSpec.BooleanValue GLOWING_TORCHFLOWERS; private static final ModConfigSpec.BooleanValue GLOW_VINES_UNDER_LEAVES; + private static final ModConfigSpec.BooleanValue SWING_THROUGH_GRASS_ENABLED; private static final ModConfigSpec.BooleanValue ENTITY_SPECIFIC_FIRE_OVERLAY_ENABLED; static { @@ -120,6 +121,7 @@ public final class AntarchyMiscConfig { DUPLICATOR_TREE_ENABLED = b.comment("If false, duplicator trees do not generate and duplicator saplings produce nothing.").define("duplicatorTreeEnabled", true); GLOWING_TORCHFLOWERS = b.comment("Whether fully-grown torchflower blocks emit light.") .define("glowingTorchflowers", true); GLOW_VINES_UNDER_LEAVES = b.comment("Whether glow vines can be placed and survive when attached under leaf blocks.") .define("glowVinesUnderLeaves", true); + SWING_THROUGH_GRASS_ENABLED = b.comment("If true, empty collision plants like grass do not block melee target picking.") .define("swingThroughGrassEnabled", true); ENTITY_SPECIFIC_FIRE_OVERLAY_ENABLED = b.comment("If true, burning entities use soul fire / dream fire overlays where appropriate.") .define("entitySpecificFireOverlayEnabled", true); b.pop(); @@ -141,6 +143,7 @@ public final class AntarchyMiscConfig { static boolean duplicatorTreeEnabled() { return DUPLICATOR_TREE_ENABLED.get(); } static boolean glowingTorchflowers() { return GLOWING_TORCHFLOWERS.get(); } static boolean glowVinesUnderLeaves() { return GLOW_VINES_UNDER_LEAVES.get(); } + static boolean swingThroughGrassEnabled() { return SWING_THROUGH_GRASS_ENABLED.get(); } static boolean entitySpecificFireOverlayEnabled() { return ENTITY_SPECIFIC_FIRE_OVERLAY_ENABLED.get(); } static double hushweedSporeLifetimeSeconds() { return HUSHWEED_SPORE_LIFETIME_SECONDS.get(); } diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java index 68c2ab5e..d22259cc 100644 --- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java +++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java @@ -390,9 +390,9 @@ public final class AntarchyMobsConfig { // Alpha Mantis b.push("alphaMantis"); - ALPHA_MANTIS_HEALTH = b.comment("Base max health.") .defineInRange("health", 500.0D, 1.0D, 32768.0D); + ALPHA_MANTIS_HEALTH = b.comment("Base max health.") .defineInRange("health", 250.0D, 1.0D, 32768.0D); ALPHA_MANTIS_ATTACK_DAMAGE = b.comment("Base attack damage.") .defineInRange("attackDamage", 18.0D, 0.0D, 1024.0D); - ALPHA_MANTIS_MOVEMENT_SPEED = b.comment("Base movement speed.") .defineInRange("movementSpeed", 0.42D, 0.0D, 10.0D); + ALPHA_MANTIS_MOVEMENT_SPEED = b.comment("Base movement speed.") .defineInRange("movementSpeed", 0.546D, 0.0D, 10.0D); ALPHA_MANTIS_FLYING_SPEED = b.comment("Base flying speed.") .defineInRange("flyingSpeed", 0.77D, 0.0D, 10.0D); ALPHA_MANTIS_SUMMON_INTERVAL_TICKS = b.comment("Ticks between mantis minion summons while in combat.") .defineInRange("summonIntervalTicks", 300, 20, 72000); ALPHA_MANTIS_MAX_MINIONS = b.comment("Maximum summoned mantises alive near the alpha at once.") .defineInRange("maxMinions", 4, 0, 32); diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java index 4db16c61..4c95ded9 100644 --- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java +++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoForgeEvents.java @@ -1115,8 +1115,11 @@ public final class AntarchyNeoForgeEvents { ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.UMBRAL_MOSS_CARPET.get().asItem(), 0.3f); ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.AMBER_MOSS_BLOCK.get().asItem(), 0.65f); ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.AMBER_MOSS_CARPET.get().asItem(), 0.3f); + ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.BIG_BUSH.get().asItem(), 0.65f); ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.CREEPVINE.get().asItem(), 0.3f); ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.HUSHWEED.get().asItem(), 0.65f); + ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.VERY_SHORT_GRASS.get().asItem(), 0.3f); + ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeBlocks.VERY_TALL_GRASS.get().asItem(), 0.5f); ComposterBlock.COMPOSTABLES.put(AntarchyNeoforgeItems.CORNEA_EAR.get(), 0.65f); }); } diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java index c8d8e664..57d460de 100644 --- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java +++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java @@ -98,6 +98,7 @@ public class AntarchyNeoforgeCreativeModeTabs { event.accept(AntarchyNeoforgeItems.TORCHFLOWER_BUSH_ITEM.get()); event.accept(AntarchyNeoforgeItems.BIG_BUSH_ITEM.get()); event.accept(AntarchyNeoforgeItems.VERY_SHORT_GRASS_ITEM.get()); + event.accept(AntarchyNeoforgeItems.VERY_TALL_GRASS_ITEM.get()); event.accept(AntarchyNeoforgeItems.HUSHWEED_ITEM.get()); event.accept(AntarchyNeoforgeItems.AMBER_LICHEN_ITEM.get()); event.accept(AntarchyNeoforgeItems.CREEPVINE_ITEM.get()); diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java index 1ab5b1f4..35501ae8 100644 --- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java +++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java @@ -97,7 +97,7 @@ public final class AntarchyNeoforgeEntites { .build("mantis")); public static final DeferredHolder, EntityType> ALPHA_MANTIS = ENTITY_TYPES.register("alpha_mantis", () -> EntityType.Builder.of(AlphaMantisEntity::new, MobCategory.MONSTER) - .sized(4.0F, 3.25F) + .sized(4.25F, 3.35F) .clientTrackingRange(10) .build("alpha_mantis")); public static final DeferredHolder, EntityType> ROLLY_POLLY = ENTITY_TYPES.register("rolly_polly",