stinky, attribute fix native, new kraken, and a bunch of other random bs

This commit is contained in:
craisinlord committed 2026-06-25 15:10:24 -05:00
1 parent cd2972a208
commit 36b7530104
130 files changed
+21935 -10706

No files matched your search

@@ -1,5 +1,6 @@
package com.craisinlord.antarchy;
import com.craisinlord.antarchy.content.AttributeRangeInit;
import com.craisinlord.integrated_api.events.lifecycle.ServerGoingToStartEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -10,6 +11,7 @@ public class Antarchy {
public static final Logger LOGGER = LogManager.getLogger();
public static void init() {
AttributeRangeInit.apply();
ServerGoingToStartEvent.EVENT.addListener(Antarchy::serverAboutToStart);
}
private static void serverAboutToStart(final ServerGoingToStartEvent event) {
@@ -5,7 +5,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
public final class AntarchySettings {
private static boolean disableInfinityBookPortalCreation = false;
private static boolean disableInfinityBookPortalCreation = true;
private static boolean easterBunnyEnabled = true;
private static int easterBunnyNaturalSpawnChancePercent = 1;
private static boolean rainbowAntsLeadToInfinityDimensions = true;
@@ -6,6 +6,7 @@ import com.craisinlord.antarchy.content.entity.ButterflyEntity;
import com.craisinlord.antarchy.content.entity.CaterpillarEntity;
import com.craisinlord.antarchy.content.entity.EasterBunnyEntity;
import com.craisinlord.antarchy.content.entity.HushProjectileEntity;
import com.craisinlord.antarchy.content.entity.StinkBugEntity;
import com.craisinlord.antarchy.content.entity.WaterBombEntity;
import com.craisinlord.antarchy.content.entity.TriffidEntity;
import com.craisinlord.antarchy.content.entity.CreepingHorrorEntity;
@@ -27,6 +28,7 @@ import com.craisinlord.antarchy.content.block.entity.DreamCampfireBlockEntity;
import com.craisinlord.antarchy.content.block.entity.WaspNestBlockEntity;
import java.util.function.Supplier;
import net.minecraft.core.Holder;
import net.minecraft.core.particles.SimpleParticleType;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.EntityType;
@@ -85,6 +87,8 @@ public final class AntarchyObjects {
@SuppressWarnings("unchecked")
public static Supplier<EntityType<LurkingTerrorEntity>> LURKING_TERROR = (Supplier<EntityType<LurkingTerrorEntity>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<EntityType<StinkBugEntity>> STINK_BUG = (Supplier<EntityType<StinkBugEntity>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Block> DUPLICATOR_LOG = (Supplier<Block>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Block> DUPLICATOR_SAPLING = (Supplier<Block>) UNBOUND;
@@ -165,6 +169,8 @@ public final class AntarchyObjects {
@SuppressWarnings("unchecked")
public static Supplier<Item> REVERIE_BOTTLE = (Supplier<Item>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Item> STINK_BUG_ITEM = (Supplier<Item>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Holder<MobEffect>> DREAD = (Supplier<Holder<MobEffect>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Holder<Attribute>> DOUBLE_DAMAGE_CHANCE = (Supplier<Holder<Attribute>>) UNBOUND;
@@ -177,6 +183,8 @@ public final class AntarchyObjects {
@SuppressWarnings("unchecked")
public static Supplier<Holder<MobEffect>> INVERTED_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Holder<MobEffect>> STINKY_EFFECT = (Supplier<Holder<MobEffect>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Block> OURANWOOD_ACORN_BLOCK = (Supplier<Block>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<Block> MOSSY_OURANWOOD_LOG = (Supplier<Block>) UNBOUND;
@@ -208,6 +216,8 @@ public final class AntarchyObjects {
public static Supplier<BlockEntityType<WaspNestBlockEntity>> WASP_NEST_BLOCK_ENTITY = (Supplier<BlockEntityType<WaspNestBlockEntity>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<BlockEntityType<HushweedBlockEntity>> HUSHWEED_BLOCK_ENTITY = (Supplier<BlockEntityType<HushweedBlockEntity>>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier<SimpleParticleType> STINKY_GAS = (Supplier<SimpleParticleType>) UNBOUND;
private AntarchyObjects() {
}
@@ -234,6 +244,7 @@ public final class AntarchyObjects {
Supplier<EntityType<WaterBombEntity>> waterBomb,
Supplier<EntityType<CreepingHorrorEntity>> creepingHorror,
Supplier<EntityType<LurkingTerrorEntity>> lurkingTerror,
Supplier<EntityType<StinkBugEntity>> stinkBug,
Supplier<Block> duplicatorLog,
Supplier<Block> duplicatorSapling,
Supplier<Block> ductTape,
@@ -274,9 +285,11 @@ public final class AntarchyObjects {
Supplier<Item> krakenTooth,
Supplier<Item> moggles,
Supplier<Item> reverieBottle,
Supplier<Item> stinkBugItem,
Supplier<Holder<MobEffect>> dread,
Supplier<Holder<MobEffect>> paralyzedEffect,
Supplier<Holder<MobEffect>> invertedEffect,
Supplier<Holder<MobEffect>> stinkyEffect,
Supplier<Block> ouranwoodAcornBlock,
Supplier<Block> mossyOuranwoodLog,
Supplier<Block> mossyOuranwoodWood,
@@ -293,6 +306,7 @@ public final class AntarchyObjects {
Supplier<BlockEntityType<DreamCampfireBlockEntity>> dreamCampfireBlockEntity,
Supplier<BlockEntityType<WaspNestBlockEntity>> waspNestBlockEntity,
Supplier<BlockEntityType<HushweedBlockEntity>> hushweedBlockEntity,
Supplier<SimpleParticleType> stinkyGas,
Supplier<Holder<Attribute>> doubleDamageChance,
Supplier<Holder<Attribute>> bloodglassMaxHearts,
Supplier<Holder<MobEffect>> bloodglassWard
@@ -318,6 +332,7 @@ public final class AntarchyObjects {
WATER_BOMB = waterBomb;
CREEPING_HORROR = creepingHorror;
LURKING_TERROR = lurkingTerror;
STINK_BUG = stinkBug;
DUPLICATOR_LOG = duplicatorLog;
DUPLICATOR_SAPLING = duplicatorSapling;
DUCT_TAPE = ductTape;
@@ -358,9 +373,11 @@ public final class AntarchyObjects {
KRAKEN_TOOTH = krakenTooth;
MOGGLES = moggles;
REVERIE_BOTTLE = reverieBottle;
STINK_BUG_ITEM = stinkBugItem;
DREAD = dread;
PARALYZED_EFFECT = paralyzedEffect;
INVERTED_EFFECT = invertedEffect;
STINKY_EFFECT = stinkyEffect;
OURANWOOD_ACORN_BLOCK = ouranwoodAcornBlock;
MOSSY_OURANWOOD_LOG = mossyOuranwoodLog;
MOSSY_OURANWOOD_WOOD = mossyOuranwoodWood;
@@ -377,6 +394,7 @@ public final class AntarchyObjects {
DREAM_CAMPFIRE_BLOCK_ENTITY = dreamCampfireBlockEntity;
WASP_NEST_BLOCK_ENTITY = waspNestBlockEntity;
HUSHWEED_BLOCK_ENTITY = hushweedBlockEntity;
STINKY_GAS = stinkyGas;
DOUBLE_DAMAGE_CHANCE = doubleDamageChance;
BLOODGLASS_MAX_HEARTS = bloodglassMaxHearts;
BLOODGLASS_WARD = bloodglassWard;
@@ -55,6 +55,7 @@ public final class AntarchyTags {
public static final TagKey<EntityType<?>> PARALYSIS_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("paralysis_immune"));
public static final TagKey<EntityType<?>> HUSHWEED_TARGETS = TagKey.create(Registries.ENTITY_TYPE, id("hushweed_targets"));
public static final TagKey<EntityType<?>> TRIFFID_PREY = TagKey.create(Registries.ENTITY_TYPE, id("triffid_prey"));
public static final TagKey<EntityType<?>> STINKY_REPELLED_HOSTILES = TagKey.create(Registries.ENTITY_TYPE, id("stinky_repelled_hostiles"));
public static final TagKey<EntityType<?>> SCORPION_WHIP_IMMUNE = TagKey.create(Registries.ENTITY_TYPE, id("scorpion_whip_immune"));
public static final TagKey<EntityType<?>> SCORPION_WHIP_BLACKLIST = TagKey.create(Registries.ENTITY_TYPE, id("scorpion_whip_blacklist"));
@@ -0,0 +1,34 @@
package com.craisinlord.antarchy.content;
import com.craisinlord.antarchy.mixins.AccessorRangedAttribute;
import com.google.common.collect.ImmutableSet;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.RangedAttribute;
import java.util.Set;
public class AttributeRangeInit {
private static final double MAX = 11_000_000D;
private static final Set<ResourceLocation> TARGETS = ImmutableSet.of(
ResourceLocation.fromNamespaceAndPath("minecraft", "generic.max_health"),
ResourceLocation.fromNamespaceAndPath("minecraft", "generic.armor"),
ResourceLocation.fromNamespaceAndPath("minecraft", "generic.armor_toughness"),
ResourceLocation.fromNamespaceAndPath("minecraft", "generic.attack_damage"),
ResourceLocation.fromNamespaceAndPath("minecraft", "generic.attack_knockback")
);
public static void apply() {
for (ResourceLocation id : TARGETS) {
Attribute attribute = BuiltInRegistries.ATTRIBUTE.get(id);
if (attribute instanceof RangedAttribute ranged && ranged instanceof AccessorRangedAttribute accessor) {
if (ranged.getMaxValue() < MAX) {
accessor.antarchyAttributefix$setMaxValue(MAX);
}
}
}
}
}
@@ -0,0 +1,170 @@
package com.craisinlord.antarchy.content;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.EntityTypeTags;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.entity.monster.Enemy;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
public final class StinkyBehavior {
public static final int STINKY_EFFECT_DURATION_TICKS = 60;
public static final double STINK_BUG_AURA_RADIUS = 5.0D;
public static final double STINKY_NAUSEA_RADIUS = 4.0D;
private static final int TRAIL_INTERVAL_TICKS = 4;
private static final int REACTION_INTERVAL_TICKS = 10;
private static final double ARTHROPOD_ALERT_RADIUS = 28.0D;
private static final double FLEE_RADIUS = 10.0D;
private static final double FLEE_DISTANCE = 8.0D;
private static final int STINKY_NAUSEA_DURATION_TICKS = 60;
private static final int STINK_BUG_BURST_NAUSEA_DURATION_TICKS = 100;
private StinkyBehavior() {
}
public static void tickStinkyTrail(LivingEntity entity) {
if (!(entity.level() instanceof ServerLevel serverLevel)) {
return;
}
if (!entity.isAlive() || entity.tickCount % TRAIL_INTERVAL_TICKS != 0 || !entity.hasEffect(AntarchyObjects.STINKY_EFFECT.get())) {
return;
}
Vec3 motion = entity.getDeltaMovement();
Vec3 horizontalMotion = new Vec3(motion.x, 0.0D, motion.z);
Vec3 direction = horizontalMotion.lengthSqr() > 1.0E-4D
? horizontalMotion.normalize()
: entity.getLookAngle().multiply(1.0D, 0.0D, 1.0D);
if (direction.lengthSqr() <= 1.0E-4D) {
direction = new Vec3(0.0D, 0.0D, 1.0D);
} else {
direction = direction.normalize();
}
Vec3 origin = entity.position()
.subtract(direction.scale(0.35D))
.add(0.0D, Math.max(0.15D, entity.getBbHeight() * 0.2D), 0.0D);
serverLevel.sendParticles(
AntarchyObjects.STINKY_GAS.get(),
origin.x,
origin.y,
origin.z,
2,
entity.getBbWidth() * 0.12D,
0.04D,
entity.getBbWidth() * 0.12D,
0.005D
);
applyNearbyNausea(entity, STINKY_NAUSEA_RADIUS, STINKY_NAUSEA_DURATION_TICKS);
if (entity.tickCount % REACTION_INTERVAL_TICKS == 0) {
reactToStinkySource(entity);
}
}
public static void emitBurst(LivingEntity entity, int count) {
if (!(entity.level() instanceof ServerLevel serverLevel)) {
return;
}
serverLevel.sendParticles(
AntarchyObjects.STINKY_GAS.get(),
entity.getX(),
entity.getY(0.45D),
entity.getZ(),
count,
entity.getBbWidth() * 0.35D,
entity.getBbHeight() * 0.25D,
entity.getBbWidth() * 0.35D,
0.045D
);
applyNearbyNausea(entity, STINK_BUG_AURA_RADIUS, STINK_BUG_BURST_NAUSEA_DURATION_TICKS);
}
public static void applyNearbyNausea(LivingEntity source, double radius, int durationTicks) {
if (source.level().isClientSide()) {
return;
}
for (Player player : source.level().getEntitiesOfClass(
Player.class,
source.getBoundingBox().inflate(radius),
player -> player.isAlive() && !player.isSpectator() && player != source
)) {
player.addEffect(new MobEffectInstance(MobEffects.CONFUSION, durationTicks, 0, false, true, true));
}
}
private static void reactToStinkySource(LivingEntity source) {
if (source.level().isClientSide() || !source.isAlive()) {
return;
}
for (Mob mob : source.level().getEntitiesOfClass(
Mob.class,
source.getBoundingBox().inflate(ARTHROPOD_ALERT_RADIUS),
mob -> mob.isAlive() && mob != source
)) {
if (mob.getType().is(EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS)) {
attractArthropod(mob, source);
continue;
}
if (shouldRepelMob(mob, source)) {
repelPassiveOrNeutralMob(mob, source);
}
}
}
private static void attractArthropod(Mob mob, LivingEntity source) {
if (!isValidStinkySourceForMob(mob, source)) {
return;
}
LivingEntity currentTarget = mob.getTarget();
if (currentTarget != null && currentTarget.isAlive() && currentTarget.hasEffect(AntarchyObjects.STINKY_EFFECT.get())
&& mob.distanceToSqr(currentTarget) <= ARTHROPOD_ALERT_RADIUS * ARTHROPOD_ALERT_RADIUS) {
return;
}
mob.setTarget(source);
}
private static void repelPassiveOrNeutralMob(Mob mob, LivingEntity source) {
if (!(mob instanceof PathfinderMob pathfinderMob) || !isValidStinkySourceForMob(mob, source)) {
return;
}
Vec3 away = mob.position().subtract(source.position());
if (away.lengthSqr() < 1.0E-4D) {
away = new Vec3(mob.getRandom().nextDouble() - 0.5D, 0.0D, mob.getRandom().nextDouble() - 0.5D);
}
Vec3 escapeTarget = mob.position().add(away.normalize().scale(FLEE_DISTANCE));
pathfinderMob.setTarget(null);
pathfinderMob.getNavigation().moveTo(escapeTarget.x, escapeTarget.y, escapeTarget.z, 1.2D);
}
private static boolean shouldRepelMob(Mob mob, LivingEntity source) {
if (mob.hasEffect(AntarchyObjects.STINKY_EFFECT.get()) || mob.distanceToSqr(source) > FLEE_RADIUS * FLEE_RADIUS) {
return false;
}
if (mob.getType().is(AntarchyTags.Entities.STINKY_REPELLED_HOSTILES)) {
return true;
}
return !(mob instanceof Enemy);
}
private static boolean isValidStinkySourceForMob(Mob mob, LivingEntity source) {
if (source == mob || !source.isAlive() || !source.hasEffect(AntarchyObjects.STINKY_EFFECT.get())) {
return false;
}
if (source instanceof Player player && (player.isCreative() || player.isSpectator())) {
return false;
}
return !mob.isAlliedTo(source);
}
}
@@ -0,0 +1,38 @@
package com.craisinlord.antarchy.content.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
public class AmberMossBlock extends Block implements BonemealableBlock {
public static final MapCodec<AmberMossBlock> CODEC = Block.simpleCodec(AmberMossBlock::new);
public AmberMossBlock(BlockBehaviour.Properties properties) {
super(properties);
}
@Override
public MapCodec<AmberMossBlock> codec() {
return CODEC;
}
@Override
public boolean isValidBonemealTarget(LevelReader level, BlockPos pos, BlockState state) {
return false;
}
@Override
public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) {
return false;
}
@Override
public void performBonemeal(net.minecraft.server.level.ServerLevel level, RandomSource random, BlockPos pos, BlockState state) {
}
}
@@ -96,7 +96,7 @@ public class BedBugEggBlock extends Block {
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!this.shouldUpdateHatchLevel(level) || !hasHatchSupport(level, pos)) {
if (!this.shouldUpdateHatchLevel(level)) {
return;
}
@@ -87,7 +87,7 @@ public class CreepingHorrorEggBlock extends Block {
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!this.shouldUpdateHatchLevel(level) || !hasHatchSupport(level, pos)) {
if (!this.shouldUpdateHatchLevel(level)) {
return;
}
@@ -87,7 +87,7 @@ public class LurkingTerrorEggBlock extends Block {
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!this.shouldUpdateHatchLevel(level) || !hasHatchSupport(level, pos)) {
if (!this.shouldUpdateHatchLevel(level)) {
return;
}
@@ -0,0 +1,23 @@
package com.craisinlord.antarchy.content.client.model;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.entity.StinkBugEntity;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.model.GeoModel;
public class StinkBugModel extends GeoModel<StinkBugEntity> {
@Override
public ResourceLocation getModelResource(StinkBugEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/stink_bug.geo.json");
}
@Override
public ResourceLocation getTextureResource(StinkBugEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/stink_bug.png");
}
@Override
public ResourceLocation getAnimationResource(StinkBugEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/stink_bug.animation.json");
}
}
@@ -15,6 +15,7 @@ public class CreepingHorrorRenderer extends GeoEntityRenderer<CreepingHorrorEnti
public CreepingHorrorRenderer(EntityRendererProvider.Context context) {
super(context, new CreepingHorrorModel());
this.shadowRadius = 0.5F;
this.withScale(0.85F);
}
@Override
@@ -9,5 +9,6 @@ public class LurkingTerrorRenderer extends GeoEntityRenderer<LurkingTerrorEntity
public LurkingTerrorRenderer(EntityRendererProvider.Context context) {
super(context, new LurkingTerrorModel());
this.shadowRadius = 0.5F;
this.withScale(0.85F);
}
}
@@ -0,0 +1,35 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.client.model.StinkBugModel;
import com.craisinlord.antarchy.content.entity.StinkBugEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import org.jetbrains.annotations.Nullable;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.renderer.GeoEntityRenderer;
public class StinkBugRenderer extends GeoEntityRenderer<StinkBugEntity> {
private static final float ADULT_SCALE = 0.75F;
private static final float BABY_SCALE = 0.50F;
private static final float ADULT_SHADOW_RADIUS = 0.6F;
public StinkBugRenderer(EntityRendererProvider.Context context) {
super(context, new StinkBugModel());
this.shadowRadius = ADULT_SHADOW_RADIUS;
this.withScale(ADULT_SCALE);
}
@Override
public void preRender(PoseStack poseStack, StinkBugEntity animatable, BakedGeoModel model, @Nullable MultiBufferSource bufferSource, @Nullable VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, int colour) {
super.preRender(poseStack, animatable, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, colour);
if (animatable.isBaby()) {
poseStack.scale(BABY_SCALE, BABY_SCALE, BABY_SCALE);
this.shadowRadius = ADULT_SHADOW_RADIUS * BABY_SCALE;
} else {
this.shadowRadius = ADULT_SHADOW_RADIUS;
}
}
}
@@ -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 StinkyMobEffect extends MobEffect {
public StinkyMobEffect() {
super(MobEffectCategory.HARMFUL, 0x66773A);
}
}
@@ -57,7 +57,7 @@ public class CreepingHorrorEntity extends Monster implements GeoEntity {
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, AntarchySettings.creepingHorrorHealth())
.add(Attributes.MOVEMENT_SPEED, 0.30D)
.add(Attributes.MOVEMENT_SPEED, 0.38D)
.add(Attributes.ATTACK_DAMAGE, AntarchySettings.creepingHorrorAttackDamage())
.add(Attributes.FOLLOW_RANGE, 16.0D);
}
@@ -3,6 +3,9 @@ package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.content.entity.trades.DrTrayaurusTradeManager;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.AgeableMob;
@@ -80,6 +83,21 @@ public class DrTrayaurusEntity extends AbstractVillager {
this.overrideXp(1);
}
@Override
protected SoundEvent getAmbientSound() {
return SoundEvents.VILLAGER_AMBIENT;
}
@Override
protected SoundEvent getHurtSound(DamageSource damageSource) {
return SoundEvents.VILLAGER_HURT;
}
@Override
protected SoundEvent getDeathSound() {
return SoundEvents.VILLAGER_DEATH;
}
@Override
public InteractionResult mobInteract(Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
@@ -58,31 +58,23 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
SynchedEntityData.defineId(JumpyBugEntity.class, EntityDataSerializers.BOOLEAN);
private static final EntityDataAccessor<Boolean> CLINGING_TO_CEILING =
SynchedEntityData.defineId(JumpyBugEntity.class, EntityDataSerializers.BOOLEAN);
private static final EntityDataAccessor<Integer> LATCHED_TARGET_ID =
SynchedEntityData.defineId(JumpyBugEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> ATTACK_STATE =
SynchedEntityData.defineId(JumpyBugEntity.class, EntityDataSerializers.INT);
private static final String POUNCE_COOLDOWN_KEY = "PounceCooldown";
private static final String LATCH_COOLDOWN_KEY = "LatchCooldown";
private static final String LATCH_TICKS_KEY = "LatchTicksRemaining";
private static final String BITE_COOLDOWN_KEY = "BiteCooldown";
private static final String RECOVERY_TICKS_KEY = "RecoveryTicks";
private static final String POUNCE_TICKS_KEY = "PounceTicks";
private static final double DEFAULT_MOVEMENT_SPEED = 0.25D;
private static final double DEFAULT_FOLLOW_RANGE = 16.0D;
private static final double DEFAULT_POUNCE_RANGE = 8.0D;
private static final int DEFAULT_LATCH_DURATION = 80;
private static final int DEFAULT_BITE_INTERVAL = 15;
private static final double MELEE_WALK_RANGE = 4.0D;
private static final int DEFAULT_POUNCE_COOLDOWN = 60;
private static final int DEFAULT_LATCH_COOLDOWN = 80;
private static final int DEFAULT_RECOVERY_TICKS = 20;
private static final double POUNCE_HORIZONTAL_SPEED = 0.92D;
private static final double POUNCE_UPWARD_SPEED = 0.45D;
private static final double POUNCE_UPWARD_SPEED = 0.75D;
private static final double QUICK_MOVE_SQR = 0.14D * 0.14D;
private static final double CLING_SEARCH_RANGE = 1.5D;
private static final double LATCH_CHECK_RANGE = 0.85D;
private static final double POUNCE_LAND_DAMAGE_RANGE = 5.0D;
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
@@ -92,9 +84,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
private int pounceCooldownTicks;
private int latchCooldownTicks;
private int latchTicksRemaining;
private int biteCooldownTicks;
private int recoveryTicks;
private int pounceTicks;
private float visualAlpha = 1.0F;
@@ -127,20 +116,18 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
super.defineSynchedData(builder);
builder.define(CAMOUFLAGED, false);
builder.define(CLINGING_TO_CEILING, false);
builder.define(LATCHED_TARGET_ID, -1);
builder.define(ATTACK_STATE, AttackState.GROUND.id());
}
@Override
protected void registerGoals() {
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(1, new LatchedGoal());
this.goalSelector.addGoal(2, new PounceAttackGoal());
this.goalSelector.addGoal(3, new CeilingClingGoal());
this.goalSelector.addGoal(4, new ChaseTargetGoal());
this.goalSelector.addGoal(5, new WanderGoal());
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 10.0F));
this.goalSelector.addGoal(7, new RandomLookAroundGoal(this));
this.goalSelector.addGoal(1, new PounceAttackGoal());
this.goalSelector.addGoal(2, new CeilingClingGoal());
this.goalSelector.addGoal(3, new ChaseTargetGoal());
this.goalSelector.addGoal(4, new WanderGoal());
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 10.0F));
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
}
@@ -159,9 +146,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
public void addAdditionalSaveData(CompoundTag tag) {
super.addAdditionalSaveData(tag);
tag.putInt(POUNCE_COOLDOWN_KEY, this.pounceCooldownTicks);
tag.putInt(LATCH_COOLDOWN_KEY, this.latchCooldownTicks);
tag.putInt(LATCH_TICKS_KEY, this.latchTicksRemaining);
tag.putInt(BITE_COOLDOWN_KEY, this.biteCooldownTicks);
tag.putInt(RECOVERY_TICKS_KEY, this.recoveryTicks);
tag.putInt(POUNCE_TICKS_KEY, this.pounceTicks);
}
@@ -170,9 +154,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
public void readAdditionalSaveData(CompoundTag tag) {
super.readAdditionalSaveData(tag);
this.pounceCooldownTicks = tag.getInt(POUNCE_COOLDOWN_KEY);
this.latchCooldownTicks = tag.getInt(LATCH_COOLDOWN_KEY);
this.latchTicksRemaining = tag.getInt(LATCH_TICKS_KEY);
this.biteCooldownTicks = tag.getInt(BITE_COOLDOWN_KEY);
this.recoveryTicks = tag.getInt(RECOVERY_TICKS_KEY);
this.pounceTicks = tag.getInt(POUNCE_TICKS_KEY);
}
@@ -198,19 +179,11 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
if (this.pounceCooldownTicks > 0) {
this.pounceCooldownTicks--;
}
if (this.latchCooldownTicks > 0) {
this.latchCooldownTicks--;
}
if (this.biteCooldownTicks > 0) {
this.biteCooldownTicks--;
}
if (this.recoveryTicks > 0) {
this.recoveryTicks--;
}
if (this.isLatched()) {
this.tickLatched();
} else if (this.isClingingToCeiling()) {
if (this.isClingingToCeiling()) {
this.tickClinging();
} else if (this.isPouncing()) {
this.tickPouncing();
@@ -227,7 +200,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
@Override
public void travel(Vec3 travelVector) {
if (this.isLatched() || this.isClingingToCeiling()) {
if (this.isClingingToCeiling()) {
this.setDeltaMovement(Vec3.ZERO);
return;
}
@@ -243,9 +216,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
this.setCamouflaged(false);
this.recoveryTicks = Math.max(this.recoveryTicks, DEFAULT_RECOVERY_TICKS);
if (this.isLatched()) {
this.detachFromTarget(true);
}
if (this.isClingingToCeiling()) {
this.stopClinging();
}
@@ -288,14 +258,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
return this.entityData.get(CLINGING_TO_CEILING);
}
public boolean isLatched() {
return this.entityData.get(LATCHED_TARGET_ID) != -1;
}
public boolean isLatchedTo(LivingEntity entity) {
return this.entityData.get(LATCHED_TARGET_ID) == entity.getId();
}
public boolean isPouncing() {
return this.getAttackState() == AttackState.POUNCING;
}
@@ -326,7 +288,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
private PlayState mainAnimController(AnimationState<JumpyBugEntity> state) {
AttackState attackState = this.getAttackState();
if (attackState == AttackState.POUNCING || attackState == AttackState.LATCHED || attackState == AttackState.CLINGING) {
if (attackState == AttackState.POUNCING || attackState == AttackState.CLINGING) {
return state.setAndContinue(JUMP_ANIM);
}
if (attackState == AttackState.RECOVERING) {
@@ -356,54 +318,18 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
this.setAttackState(AttackState.POUNCING);
this.setCamouflaged(false);
this.pounceTicks++;
LivingEntity target = this.getTarget();
if (target != null && target.isAlive() && this.distanceToSqr(target) <= (this.getBbWidth() + target.getBbWidth() + LATCH_CHECK_RANGE) * (this.getBbWidth() + target.getBbWidth() + LATCH_CHECK_RANGE)) {
if (this.tryLatch(target)) {
return;
}
}
if (this.onGround() && this.pounceTicks > 4) {
if (this.onGround() && this.pounceTicks > 8) {
LivingEntity target = this.getTarget();
if (target != null && target.isAlive() && this.distanceToSqr(target) <= POUNCE_LAND_DAMAGE_RANGE * POUNCE_LAND_DAMAGE_RANGE) {
target.hurt(this.damageSources().mobAttack(this), (float) AntarchySettings.jumpyBugPounceDamage());
}
this.finishPounce(false);
}
}
private void tickLatched() {
LivingEntity target = this.getLatchedTarget();
if (target == null || !target.isAlive() || target.level() != this.level() || target.isRemoved() || target.isInWater()) {
this.detachFromTarget(false);
return;
}
this.setAttackState(AttackState.LATCHED);
this.setCamouflaged(false);
this.setNoGravity(true);
this.noPhysics = true;
this.getNavigation().stop();
this.setDeltaMovement(Vec3.ZERO);
Vec3 latchPos = this.getLatchPosition(target);
this.setPos(latchPos.x, latchPos.y, latchPos.z);
this.yRotO = this.getYRot();
this.setYRot(target.getYHeadRot());
this.setYBodyRot(target.getYHeadRot());
this.setYHeadRot(target.getYHeadRot());
this.setXRot(-20.0F);
if (--this.latchTicksRemaining <= 0) {
this.detachFromTarget(true);
return;
}
if (this.biteCooldownTicks <= 0) {
target.hurt(this.damageSources().mobAttack(this), (float) AntarchySettings.jumpyBugLatchDamage());
this.biteCooldownTicks = DEFAULT_BITE_INTERVAL;
this.playSound(SoundEvents.SPIDER_HURT, 0.35F, 1.5F + this.random.nextFloat() * 0.2F);
}
}
private void updateCamouflage() {
if (this.isLatched() || this.isPouncing()) {
if (this.isPouncing()) {
this.setCamouflaged(false);
return;
}
@@ -415,63 +341,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
this.setCamouflaged(shouldCamouflage);
}
private boolean tryLatch(LivingEntity target) {
if (!(target instanceof Player) || this.latchCooldownTicks > 0 || this.isLatched()) {
return false;
}
if (this.level().getEntitiesOfClass(JumpyBugEntity.class, target.getBoundingBox().inflate(0.75D),
bug -> bug != this && bug.isLatchedTo(target)).isEmpty()) {
this.entityData.set(LATCHED_TARGET_ID, target.getId());
this.latchTicksRemaining = DEFAULT_LATCH_DURATION;
this.biteCooldownTicks = 0;
this.pounceTicks = 0;
this.setAttackState(AttackState.LATCHED);
this.setTarget(target);
target.hurt(this.damageSources().mobAttack(this), (float) AntarchySettings.jumpyBugPounceDamage());
return true;
}
return false;
}
private void detachFromTarget(boolean knockAway) {
LivingEntity target = this.getLatchedTarget();
this.entityData.set(LATCHED_TARGET_ID, -1);
this.latchTicksRemaining = 0;
this.biteCooldownTicks = DEFAULT_BITE_INTERVAL;
this.latchCooldownTicks = DEFAULT_LATCH_COOLDOWN;
this.setAttackState(AttackState.RECOVERING);
this.recoveryTicks = DEFAULT_RECOVERY_TICKS;
this.setNoGravity(false);
this.noPhysics = false;
if (knockAway && target != null) {
Vec3 away = this.position().subtract(target.position());
if (away.lengthSqr() < 1.0E-4D) {
away = target.getLookAngle().scale(-1.0D);
}
away = away.normalize();
this.setDeltaMovement(away.x * 0.35D, 0.25D, away.z * 0.35D);
this.hasImpulse = true;
}
}
@Nullable
private LivingEntity getLatchedTarget() {
int entityId = this.entityData.get(LATCHED_TARGET_ID);
if (entityId == -1) {
return null;
}
Entity entity = this.level().getEntity(entityId);
return entity instanceof LivingEntity livingEntity ? livingEntity : null;
}
private Vec3 getLatchPosition(LivingEntity target) {
Vec3 eyePos = target.position().add(0.0D, target.getEyeHeight() - 0.15D, 0.0D);
Vec3 backOffset = target.getLookAngle().normalize().scale(-0.16D);
return eyePos.add(backOffset).add(0.0D, -0.18D, 0.0D);
}
@Nullable
private BlockPos findClingBlockPos() {
BlockPos origin = this.blockPosition();
@@ -537,18 +406,15 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
}
private boolean canUseAmbush() {
return !this.isLatched()
&& !this.isPouncing()
&& this.recoveryTicks <= 0
&& this.latchCooldownTicks <= 0;
return !this.isPouncing()
&& this.recoveryTicks <= 0;
}
private enum AttackState implements StringRepresentable {
GROUND(0, "ground"),
CLINGING(1, "clinging"),
POUNCING(2, "pouncing"),
LATCHED(3, "latched"),
RECOVERING(4, "recovering");
RECOVERING(3, "recovering");
private static final IntFunction<AttackState> BY_ID = ByIdMap.continuous(AttackState::id, values(), ByIdMap.OutOfBoundsStrategy.ZERO);
public static final Codec<AttackState> CODEC = StringRepresentable.fromEnum(AttackState::values);
@@ -571,27 +437,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
}
}
private final class LatchedGoal extends Goal {
private LatchedGoal() {
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK, Flag.JUMP));
}
@Override
public boolean canUse() {
return JumpyBugEntity.this.isLatched();
}
@Override
public boolean canContinueToUse() {
return JumpyBugEntity.this.isLatched();
}
@Override
public void tick() {
JumpyBugEntity.this.getNavigation().stop();
}
}
private final class PounceAttackGoal extends Goal {
private PounceAttackGoal() {
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK, Flag.JUMP));
@@ -604,7 +449,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
&& target.isAlive()
&& JumpyBugEntity.this.canUseAmbush()
&& JumpyBugEntity.this.pounceCooldownTicks <= 0
&& JumpyBugEntity.this.distanceToSqr(target) <= DEFAULT_POUNCE_RANGE * DEFAULT_POUNCE_RANGE
&& (JumpyBugEntity.this.hasLineOfSight(target) || JumpyBugEntity.this.distanceToSqr(target) <= 9.0D);
}
@@ -638,7 +482,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
return JumpyBugEntity.this.random.nextInt(40) == 0 && JumpyBugEntity.this.canClingHere();
}
return JumpyBugEntity.this.distanceToSqr(target) <= (DEFAULT_POUNCE_RANGE + CLING_SEARCH_RANGE) * (DEFAULT_POUNCE_RANGE + CLING_SEARCH_RANGE)
return JumpyBugEntity.this.distanceToSqr(target) <= (DEFAULT_FOLLOW_RANGE + CLING_SEARCH_RANGE) * (DEFAULT_FOLLOW_RANGE + CLING_SEARCH_RANGE)
&& JumpyBugEntity.this.canClingHere();
}
@@ -668,7 +512,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
JumpyBugEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
if (JumpyBugEntity.this.pounceCooldownTicks <= 0
&& JumpyBugEntity.this.distanceToSqr(target) <= DEFAULT_POUNCE_RANGE * DEFAULT_POUNCE_RANGE
&& (JumpyBugEntity.this.hasLineOfSight(target) || JumpyBugEntity.this.distanceToSqr(target) <= 4.0D)) {
JumpyBugEntity.this.stopClinging();
JumpyBugEntity.this.beginPounce(target);
@@ -686,7 +529,6 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
LivingEntity target = JumpyBugEntity.this.getTarget();
return target != null
&& target.isAlive()
&& !JumpyBugEntity.this.isLatched()
&& !JumpyBugEntity.this.isClingingToCeiling()
&& !JumpyBugEntity.this.isPouncing()
&& JumpyBugEntity.this.recoveryTicks <= 0;
@@ -705,7 +547,8 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
}
JumpyBugEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
if (JumpyBugEntity.this.distanceToSqr(target) > DEFAULT_POUNCE_RANGE * DEFAULT_POUNCE_RANGE) {
// Only walk when close; at range, pounce is the primary approach
if (JumpyBugEntity.this.distanceToSqr(target) <= MELEE_WALK_RANGE * MELEE_WALK_RANGE) {
JumpyBugEntity.this.getNavigation().moveTo(target, 1.05D);
} else {
JumpyBugEntity.this.getNavigation().stop();
@@ -720,8 +563,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
@Override
public boolean canUse() {
return !JumpyBugEntity.this.isLatched()
&& !JumpyBugEntity.this.isClingingToCeiling()
return !JumpyBugEntity.this.isClingingToCeiling()
&& !JumpyBugEntity.this.isPouncing()
&& JumpyBugEntity.this.getTarget() == null
&& super.canUse();
@@ -729,8 +571,7 @@ public class JumpyBugEntity extends Monster implements GeoEntity {
@Override
public boolean canContinueToUse() {
return !JumpyBugEntity.this.isLatched()
&& !JumpyBugEntity.this.isClingingToCeiling()
return !JumpyBugEntity.this.isClingingToCeiling()
&& !JumpyBugEntity.this.isPouncing()
&& super.canContinueToUse();
}
@@ -30,6 +30,7 @@ import software.bernie.geckolib.util.GeckoLibUtil;
public class LurkingTerrorEntity extends Monster implements GeoEntity {
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
private static final RawAnimation FLY_ANIM = RawAnimation.begin().thenLoop("fly");
private static final RawAnimation ATTACK_LAND_ANIM = RawAnimation.begin().thenLoop("attackland");
private static final RawAnimation ATTACK_AIR_ANIM = RawAnimation.begin().thenLoop("attackair");
private static final byte ATTACK_ANIM_EVENT = 5;
@@ -45,10 +46,10 @@ public class LurkingTerrorEntity extends Monster implements GeoEntity {
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, AntarchySettings.lurkingTerrorHealth())
.add(Attributes.MOVEMENT_SPEED, 0.25D)
.add(Attributes.MOVEMENT_SPEED, 0.35D)
.add(Attributes.ATTACK_DAMAGE, AntarchySettings.lurkingTerrorAttackDamage())
.add(Attributes.FOLLOW_RANGE, 16.0D)
.add(Attributes.FLYING_SPEED, 0.4D);
.add(Attributes.FLYING_SPEED, 0.55D);
}
@Override
@@ -84,7 +85,7 @@ public class LurkingTerrorEntity extends Monster implements GeoEntity {
return state.setAndContinue(ATTACK_LAND_ANIM);
}
if (state.isMoving()) {
return state.setAndContinue(WALK_ANIM);
return state.setAndContinue(this.onGround() ? WALK_ANIM : FLY_ANIM);
}
return state.setAndContinue(IDLE_ANIM);
}
@@ -62,6 +62,7 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
private static final String LAUNCH_OWNER_KEY = "LaunchOwner";
private static final String ARMED_AFTER_LANDING_KEY = "ArmedAfterLanding";
private static final String ACTION_ANIM_TICKS_KEY = "ActionAnimTicks";
private static final String SPAWNED_BY_KRAKEN_KEY = "SpawnedByKraken";
private static final double AGGRO_SPEED = 0.5D;
private static final double PATROL_SPEED = 0.28D;
private static final double ATTACH_RANGE_SQR = 2.25D;
@@ -86,6 +87,7 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
private int attachedTargetId = -1;
private boolean launchedFromSquidzooka;
private boolean armedAfterLanding;
private boolean spawnedByKraken;
@Nullable
private UUID launchOwnerUuid;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
@@ -298,6 +300,7 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
tag.putBoolean(LAUNCHED_FROM_SQUIDZOOKA_KEY, this.launchedFromSquidzooka);
tag.putBoolean(ARMED_AFTER_LANDING_KEY, this.armedAfterLanding);
tag.putInt(ACTION_ANIM_TICKS_KEY, this.actionAnimationTicks);
tag.putBoolean(SPAWNED_BY_KRAKEN_KEY, this.spawnedByKraken);
if (this.launchOwnerUuid != null) {
tag.putUUID(LAUNCH_OWNER_KEY, this.launchOwnerUuid);
}
@@ -311,10 +314,19 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
this.launchedFromSquidzooka = tag.getBoolean(LAUNCHED_FROM_SQUIDZOOKA_KEY);
this.armedAfterLanding = tag.getBoolean(ARMED_AFTER_LANDING_KEY);
this.actionAnimationTicks = Math.max(0, tag.getInt(ACTION_ANIM_TICKS_KEY));
this.spawnedByKraken = tag.getBoolean(SPAWNED_BY_KRAKEN_KEY);
this.launchOwnerUuid = tag.hasUUID(LAUNCH_OWNER_KEY) ? tag.getUUID(LAUNCH_OWNER_KEY) : null;
this.updateAnimationState();
}
public boolean isSpawnedByKraken() {
return this.spawnedByKraken;
}
public void setSpawnedByKraken(boolean spawnedByKraken) {
this.spawnedByKraken = spawnedByKraken;
}
private void tickAggroMovement(LivingEntity target) {
this.patrolTarget = null;
this.getLookControl().setLookAt(target, 30.0F, 30.0F);
@@ -0,0 +1,125 @@
package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.StinkyBehavior;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.Difficulty;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.tags.EntityTypeTags;
import net.minecraft.world.entity.AgeableMob;
import net.minecraft.world.entity.EntityType;
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.FloatGoal;
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.ServerLevelAccessor;
import org.jetbrains.annotations.Nullable;
import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.animation.AnimatableManager;
import software.bernie.geckolib.animation.AnimationController;
import software.bernie.geckolib.animation.AnimationState;
import software.bernie.geckolib.animation.PlayState;
import software.bernie.geckolib.animation.RawAnimation;
import software.bernie.geckolib.util.GeckoLibUtil;
public class StinkBugEntity extends Animal implements GeoEntity {
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
private static final int STINK_BURST_PARTICLES = 32;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
public StinkBugEntity(EntityType<? extends StinkBugEntity> entityType, Level level) {
super(entityType, level);
this.xpReward = 2;
}
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, 6.0D)
.add(Attributes.MOVEMENT_SPEED, 0.24D)
.add(Attributes.FOLLOW_RANGE, 8.0D);
}
public static boolean canSpawn(EntityType<StinkBugEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
return level.getDifficulty() != Difficulty.PEACEFUL
&& Animal.checkAnimalSpawnRules(entityType, level, spawnReason, pos, random);
}
@Override
protected void registerGoals() {
this.goalSelector.addGoal(0, new FloatGoal(this));
this.goalSelector.addGoal(1, new WaterAvoidingRandomStrollGoal(this, 0.9D));
this.goalSelector.addGoal(2, new LookAtPlayerGoal(this, Player.class, 6.0F));
this.goalSelector.addGoal(3, new RandomLookAroundGoal(this));
}
@Override
public void tick() {
super.tick();
if (this.level().isClientSide || this.tickCount % 10 != 0) {
return;
}
for (var target : this.level().getEntitiesOfClass(
net.minecraft.world.entity.LivingEntity.class,
this.getBoundingBox().inflate(StinkyBehavior.STINK_BUG_AURA_RADIUS),
entity -> entity != this
&& entity.isAlive()
&& !entity.getType().is(EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS)
)) {
target.addEffect(new MobEffectInstance(AntarchyObjects.STINKY_EFFECT.get(), StinkyBehavior.STINKY_EFFECT_DURATION_TICKS, 0, false, true, true));
}
}
@Override
public boolean hurt(DamageSource source, float amount) {
boolean hurt = super.hurt(source, amount);
if (hurt) {
StinkyBehavior.emitBurst(this, STINK_BURST_PARTICLES);
}
return hurt;
}
@Override
public boolean isFood(ItemStack stack) {
return false;
}
@Override
@Nullable
public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) {
return AntarchyObjects.STINK_BUG.get().create(level);
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
controllers.add(new AnimationController<>(this, "main_controller", 2, this::mainAnimController));
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
private <T extends StinkBugEntity> PlayState mainAnimController(AnimationState<T> animationState) {
animationState.setAnimation(animationState.isMoving() ? WALK_ANIM : IDLE_ANIM);
return PlayState.CONTINUE;
}
}
@@ -12,6 +12,8 @@ import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.ThrowableProjectile;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.material.Fluids;
@@ -98,21 +100,32 @@ public class WaterBombEntity extends ThrowableProjectile {
living.push(knockDir.x * knockback, 0.3D, knockDir.z * knockback);
living.hurtMarked = true;
}
living.clearFire();
}
@Override
protected void onHitBlock(BlockHitResult result) {
BlockPos hitPos = result.getBlockPos().relative(result.getDirection());
BlockPos blockPos = result.getBlockPos();
BlockPos hitPos = blockPos.relative(result.getDirection());
Level level = this.level();
if (level.getBlockState(blockPos).getBlock() instanceof CampfireBlock campfire && level.getBlockState(blockPos).getValue(CampfireBlock.LIT)) {
level.setBlock(blockPos, level.getBlockState(blockPos).setValue(CampfireBlock.LIT, false), 3);
this.discard();
return;
}
if (this.isHuge()) {
for (BlockPos pos : BlockPos.betweenClosed(hitPos.offset(-1, 0, -1), hitPos.offset(1, 0, 1))) {
if (level.isEmptyBlock(pos)) {
if (level.getBlockState(pos).getBlock() instanceof BaseFireBlock) {
level.removeBlock(pos, false);
} else if (level.isEmptyBlock(pos)) {
level.setBlock(pos, Blocks.WATER.defaultBlockState(), 3);
level.scheduleTick(pos, Fluids.WATER, 2);
}
}
} else {
if (level.isEmptyBlock(hitPos) && level.getBlockState(hitPos.below()).isSolid()) {
if (level.getBlockState(hitPos).getBlock() instanceof BaseFireBlock) {
level.removeBlock(hitPos, false);
} else if (level.isEmptyBlock(hitPos) && level.getBlockState(hitPos.below()).isSolid()) {
level.setBlock(hitPos, Blocks.WATER.defaultBlockState().setValue(LiquidBlock.LEVEL, 1), 3);
level.scheduleTick(hitPos, Fluids.WATER, 2);
}
@@ -786,6 +786,7 @@ public class KrakenEntity extends Monster implements GeoEntity {
}
missileSquid.setCanFly(true);
missileSquid.setSpawnedByKraken(true);
missileSquid.moveTo(spawnPos.x, spawnPos.y, spawnPos.z, this.getYRot(), 0.0F);
serverLevel.addFreshEntity(missileSquid);
if (launched) {
@@ -7,6 +7,7 @@ import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel;
import com.craisinlord.antarchy.content.entity.MissileSquidEntity;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
@@ -21,7 +22,11 @@ import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ProjectileWeaponItem;
import net.minecraft.world.item.UseAnim;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec2;
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;
@@ -55,17 +60,10 @@ public class SquidzookaItem extends ProjectileWeaponItem implements GeoItem {
}
if (!level.isClientSide()) {
MissileSquidEntity projectileSquid = AntarchyObjects.MISSILE_SQUID.get().create(level);
if (projectileSquid != null) {
projectileSquid.moveTo(
player.getX(),
player.getEyeY() - 0.2D,
player.getZ(),
player.getYRot(),
player.getXRot()
);
projectileSquid.launchFromSquidzooka(player, (float) AntarchySettings.squidzookaLaunchVelocity());
level.addFreshEntity(projectileSquid);
fireSquid(level, player, 0.0F);
if (hasMultishot(itemStack)) {
fireSquid(level, player, -10.0F);
fireSquid(level, player, 10.0F);
}
spawnFireParticles((ServerLevel) level, player);
itemStack.hurtAndBreak(1, player, usedHand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND);
@@ -115,6 +113,16 @@ public class SquidzookaItem extends ProjectileWeaponItem implements GeoItem {
projectile.shootFromRotation(livingEntity, livingEntity.getXRot(), livingEntity.getYRot(), angle, velocity, inaccuracy);
}
@Override
public boolean isEnchantable(ItemStack stack) {
return stack.getCount() == 1;
}
@Override
public int getEnchantmentValue() {
return 1;
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
controllers.add(new AnimationController<>(this, FIRE_CONTROLLER, state -> PlayState.STOP)
@@ -147,6 +155,32 @@ public class SquidzookaItem extends ProjectileWeaponItem implements GeoItem {
triggerAnim(livingEntity, animatableId, FIRE_CONTROLLER, FIRE_ANIMATION);
}
private static void fireSquid(Level level, Player player, float yawOffset) {
MissileSquidEntity projectileSquid = AntarchyObjects.MISSILE_SQUID.get().create(level);
if (projectileSquid == null) {
return;
}
float yaw = player.getYRot() + yawOffset;
Vec3 direction = Vec3.directionFromRotation(new Vec2(player.getXRot(), yaw));
projectileSquid.moveTo(
player.getX(),
player.getEyeY() - 0.2D,
player.getZ(),
yaw,
player.getXRot()
);
projectileSquid.launchAsProjectile(player, direction.scale(AntarchySettings.squidzookaLaunchVelocity()).add(player.getDeltaMovement()));
level.addFreshEntity(projectileSquid);
}
private static boolean hasMultishot(ItemStack stack) {
return stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY)
.keySet()
.stream()
.anyMatch(holder -> holder.is(Enchantments.MULTISHOT));
}
private static void spawnFireParticles(ServerLevel level, Player player) {
double lookX = player.getLookAngle().x;
double lookY = player.getLookAngle().y;
@@ -0,0 +1,18 @@
package com.craisinlord.antarchy.mixins;
import net.minecraft.world.entity.ai.attributes.RangedAttribute;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(RangedAttribute.class)
public interface AccessorRangedAttribute {
@Accessor("minValue")
@Mutable
void antarchyAttributefix$setMinValue(double minValue);
@Accessor("maxValue")
@Mutable
void antarchyAttributefix$setMaxValue(double maxValue);
}
@@ -0,0 +1,20 @@
package com.craisinlord.antarchy.mixins;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.StinkyBehavior;
import net.minecraft.world.entity.LivingEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LivingEntity.class)
public abstract class StinkyLivingEntityMixin {
@Inject(method = "tick", at = @At("TAIL"))
private void antarchy$tickStinkyTrail(CallbackInfo ci) {
LivingEntity livingEntity = (LivingEntity) (Object) this;
if (livingEntity.hasEffect(AntarchyObjects.STINKY_EFFECT.get())) {
StinkyBehavior.tickStinkyTrail(livingEntity);
}
}
}