stinky fly sounds, creeping horror sounds, lurking terror sounds, spit bug, bile interaction with water, termite nests actually added
This commit is contained in:
1 parent
ca77d1b480
commit
eeded21b7d
66 files changed
+1288
-155
No files matched your search
@@ -122,6 +122,14 @@ public final class AntarchySoundEvents {
|
||||
public static Supplier<SoundEvent> BOMBER_WALK = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> BOMBER_KNOCK = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> BOMBER_EXPLODE = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> STINKY_FLY = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> CREEPING_HORROR_GROWL = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> CREEPING_HORROR_HURT = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> CREEPING_HORROR_BITE = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> LURKING_TERROR_SNARL = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> LURKING_TERROR_HURT = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> LURKING_TERROR_BITE = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> LURKING_TERROR_FLY_LOOP = (Supplier<SoundEvent>) UNBOUND;
|
||||
public static Supplier<SoundEvent> DUCT_TAPE_USE = (Supplier<SoundEvent>) UNBOUND;
|
||||
|
||||
private AntarchySoundEvents() {
|
||||
@@ -241,6 +249,14 @@ public final class AntarchySoundEvents {
|
||||
Supplier<SoundEvent> bomberWalk,
|
||||
Supplier<SoundEvent> bomberKnock,
|
||||
Supplier<SoundEvent> bomberExplode,
|
||||
Supplier<SoundEvent> stinkyFly,
|
||||
Supplier<SoundEvent> creepingHorrorGrowl,
|
||||
Supplier<SoundEvent> creepingHorrorHurt,
|
||||
Supplier<SoundEvent> creepingHorrorBite,
|
||||
Supplier<SoundEvent> lurkingTerrorSnarl,
|
||||
Supplier<SoundEvent> lurkingTerrorHurt,
|
||||
Supplier<SoundEvent> lurkingTerrorBite,
|
||||
Supplier<SoundEvent> lurkingTerrorFlyLoop,
|
||||
Supplier<SoundEvent> ductTapeUse
|
||||
) {
|
||||
SQUIDZOOKA_FIRE = squidzookaFire;
|
||||
@@ -356,6 +372,14 @@ public final class AntarchySoundEvents {
|
||||
BOMBER_WALK = bomberWalk;
|
||||
BOMBER_KNOCK = bomberKnock;
|
||||
BOMBER_EXPLODE = bomberExplode;
|
||||
STINKY_FLY = stinkyFly;
|
||||
CREEPING_HORROR_GROWL = creepingHorrorGrowl;
|
||||
CREEPING_HORROR_HURT = creepingHorrorHurt;
|
||||
CREEPING_HORROR_BITE = creepingHorrorBite;
|
||||
LURKING_TERROR_SNARL = lurkingTerrorSnarl;
|
||||
LURKING_TERROR_HURT = lurkingTerrorHurt;
|
||||
LURKING_TERROR_BITE = lurkingTerrorBite;
|
||||
LURKING_TERROR_FLY_LOOP = lurkingTerrorFlyLoop;
|
||||
DUCT_TAPE_USE = ductTapeUse;
|
||||
}
|
||||
}
|
||||
+26
-1
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.block;
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.entity.CreepingHorrorEntity;
|
||||
import com.craisinlord.antarchy.content.block.AmberMossBlock;
|
||||
import com.craisinlord.antarchy.content.block.LurkingTerrorEggBlock;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -127,6 +128,30 @@ public class CreepingHorrorEggBlock extends Block {
|
||||
public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, BlockEntity blockEntity, net.minecraft.world.item.ItemStack stack) {
|
||||
super.playerDestroy(level, player, pos, state, blockEntity, stack);
|
||||
this.decreaseEggs(level, pos, state);
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
panicHatchNearby(serverLevel, pos);
|
||||
}
|
||||
}
|
||||
|
||||
private static void panicHatchNearby(ServerLevel level, BlockPos origin) {
|
||||
int radius = 6;
|
||||
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
|
||||
for (int dx = -radius; dx <= radius; dx++) {
|
||||
for (int dy = -radius; dy <= radius; dy++) {
|
||||
for (int dz = -radius; dz <= radius; dz++) {
|
||||
if (dx == 0 && dy == 0 && dz == 0) continue;
|
||||
mutable.set(origin.getX() + dx, origin.getY() + dy, origin.getZ() + dz);
|
||||
if (level.random.nextFloat() >= 0.4f) continue;
|
||||
BlockState nearby = level.getBlockState(mutable);
|
||||
BlockPos immutable = mutable.immutable();
|
||||
if (nearby.getBlock() instanceof CreepingHorrorEggBlock b) {
|
||||
b.hatchEggs(level, immutable, nearby, level.random);
|
||||
} else if (nearby.getBlock() instanceof LurkingTerrorEggBlock b) {
|
||||
b.hatchEggs(level, immutable, nearby, level.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,7 +175,7 @@ public class CreepingHorrorEggBlock extends Block {
|
||||
this.decreaseEggs(level, pos, state);
|
||||
}
|
||||
|
||||
private void hatchEggs(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) {
|
||||
void hatchEggs(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) {
|
||||
level.removeBlock(pos, false);
|
||||
level.playSound(null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.75F, 0.95F + random.nextFloat() * 0.1F);
|
||||
|
||||
|
||||
+26
-1
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.block;
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.entity.LurkingTerrorEntity;
|
||||
import com.craisinlord.antarchy.content.block.AmberMossBlock;
|
||||
import com.craisinlord.antarchy.content.block.CreepingHorrorEggBlock;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -127,6 +128,30 @@ public class LurkingTerrorEggBlock extends Block {
|
||||
public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, BlockEntity blockEntity, net.minecraft.world.item.ItemStack stack) {
|
||||
super.playerDestroy(level, player, pos, state, blockEntity, stack);
|
||||
this.decreaseEggs(level, pos, state);
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
panicHatchNearby(serverLevel, pos);
|
||||
}
|
||||
}
|
||||
|
||||
private static void panicHatchNearby(ServerLevel level, BlockPos origin) {
|
||||
int radius = 6;
|
||||
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
|
||||
for (int dx = -radius; dx <= radius; dx++) {
|
||||
for (int dy = -radius; dy <= radius; dy++) {
|
||||
for (int dz = -radius; dz <= radius; dz++) {
|
||||
if (dx == 0 && dy == 0 && dz == 0) continue;
|
||||
mutable.set(origin.getX() + dx, origin.getY() + dy, origin.getZ() + dz);
|
||||
if (level.random.nextFloat() >= 0.4f) continue;
|
||||
BlockState nearby = level.getBlockState(mutable);
|
||||
BlockPos immutable = mutable.immutable();
|
||||
if (nearby.getBlock() instanceof LurkingTerrorEggBlock b) {
|
||||
b.hatchEggs(level, immutable, nearby, level.random);
|
||||
} else if (nearby.getBlock() instanceof CreepingHorrorEggBlock b) {
|
||||
b.hatchEggs(level, immutable, nearby, level.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,7 +175,7 @@ public class LurkingTerrorEggBlock extends Block {
|
||||
this.decreaseEggs(level, pos, state);
|
||||
}
|
||||
|
||||
private void hatchEggs(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) {
|
||||
void hatchEggs(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) {
|
||||
level.removeBlock(pos, false);
|
||||
level.playSound(null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.75F, 0.95F + random.nextFloat() * 0.1F);
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.craisinlord.antarchy.content.client.model;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.entity.SpitBugEntity;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
public class SpitBugModel extends GeoModel<SpitBugEntity> {
|
||||
@Override
|
||||
public ResourceLocation getModelResource(SpitBugEntity animatable) {
|
||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/spit_bug.geo.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureResource(SpitBugEntity animatable) {
|
||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/spit_bug.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAnimationResource(SpitBugEntity animatable) {
|
||||
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/spit_bug.animation.json");
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -35,11 +35,10 @@ public class AntCarriedFoodGeoLayer extends BlockAndItemGeoLayer<BaseAntEntity>
|
||||
|
||||
@Override
|
||||
protected void renderStackForBone(PoseStack poseStack, GeoBone bone, ItemStack stack, BaseAntEntity animatable, MultiBufferSource bufferSource, float partialTick, int packedLight, int packedOverlay) {
|
||||
double yOffset = animatable.isDancing() ? -0.055D : -0.04D;
|
||||
poseStack.translate(0.0D, yOffset, -0.42D);
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(90.0F));
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F));
|
||||
poseStack.scale(0.4F, 0.4F, 0.4F);
|
||||
double yOffset = animatable.isDancing() ? 0.58D : 0.15D;
|
||||
poseStack.translate(0.0D, yOffset, -0.50D);
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(90.0F));
|
||||
poseStack.scale(0.5F, 0.5F, 0.5F);
|
||||
super.renderStackForBone(poseStack, bone, stack, animatable, bufferSource, partialTick, packedLight, packedOverlay);
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.ant.BaseAntEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.model.SilverfishModel;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.client.renderer.entity.RenderLayerParent;
|
||||
import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class AntCarriedFoodLayer<T extends BaseAntEntity> extends RenderLayer<T, SilverfishModel<T>> {
|
||||
private final ItemRenderer itemRenderer;
|
||||
|
||||
public AntCarriedFoodLayer(RenderLayerParent<T, SilverfishModel<T>> renderer, ItemRenderer itemRenderer) {
|
||||
super(renderer);
|
||||
this.itemRenderer = itemRenderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(
|
||||
PoseStack poseStack,
|
||||
MultiBufferSource buffer,
|
||||
int packedLight,
|
||||
T ant,
|
||||
float limbSwing,
|
||||
float limbSwingAmount,
|
||||
float partialTick,
|
||||
float ageInTicks,
|
||||
float netHeadYaw,
|
||||
float headPitch
|
||||
) {
|
||||
ItemStack carriedFood = ant.getCarriedFood();
|
||||
if (carriedFood.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(0.0F, 0.08F, -0.06F);
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(90.0F));
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F));
|
||||
poseStack.scale(0.22F, 0.22F, 0.22F);
|
||||
this.itemRenderer.renderStatic(
|
||||
ant,
|
||||
carriedFood,
|
||||
ItemDisplayContext.FIXED,
|
||||
false,
|
||||
poseStack,
|
||||
buffer,
|
||||
ant.level(),
|
||||
packedLight,
|
||||
OverlayTexture.NO_OVERLAY,
|
||||
ant.getId()
|
||||
);
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.SpitBugProjectileEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
public class SpitBugProjectileRenderer extends EntityRenderer<SpitBugProjectileEntity> {
|
||||
private static final ResourceLocation PROJECTILE_TEXTURE =
|
||||
ResourceLocation.withDefaultNamespace("textures/entity/enderdragon/dragon_fireball.png");
|
||||
|
||||
public SpitBugProjectileRenderer(EntityRendererProvider.Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBlockLightLevel(SpitBugProjectileEntity entity, BlockPos pos) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(SpitBugProjectileEntity entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight) {
|
||||
poseStack.pushPose();
|
||||
poseStack.mulPose(this.entityRenderDispatcher.cameraOrientation());
|
||||
|
||||
float scale = entity.getRenderScale(partialTick);
|
||||
poseStack.scale(scale, scale, scale);
|
||||
|
||||
VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.entityTranslucent(PROJECTILE_TEXTURE));
|
||||
PoseStack.Pose pose = poseStack.last();
|
||||
Matrix4f matrix4f = pose.pose();
|
||||
float alpha = entity.isLingering() ? 0.78F : 0.95F;
|
||||
|
||||
addVertex(vertexConsumer, pose, matrix4f, -0.5F, -0.5F, 0.0F, 1.0F, alpha, packedLight);
|
||||
addVertex(vertexConsumer, pose, matrix4f, 0.5F, -0.5F, 1.0F, 1.0F, alpha, packedLight);
|
||||
addVertex(vertexConsumer, pose, matrix4f, 0.5F, 0.5F, 1.0F, 0.0F, alpha, packedLight);
|
||||
addVertex(vertexConsumer, pose, matrix4f, -0.5F, 0.5F, 0.0F, 0.0F, alpha, packedLight);
|
||||
|
||||
poseStack.popPose();
|
||||
super.render(entity, entityYaw, partialTick, poseStack, buffer, packedLight);
|
||||
}
|
||||
|
||||
private static void addVertex(
|
||||
VertexConsumer vertexConsumer,
|
||||
PoseStack.Pose pose,
|
||||
Matrix4f matrix4f,
|
||||
float x,
|
||||
float y,
|
||||
float u,
|
||||
float v,
|
||||
float alpha,
|
||||
int packedLight
|
||||
) {
|
||||
vertexConsumer.addVertex(matrix4f, x, y, 0.0F)
|
||||
.setColor(0.55F, 1.0F, 0.35F, alpha)
|
||||
.setUv(u, v)
|
||||
.setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
.setLight(packedLight)
|
||||
.setNormal(pose, 0.0F, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(SpitBugProjectileEntity entity) {
|
||||
return PROJECTILE_TEXTURE;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.client.model.SpitBugModel;
|
||||
import com.craisinlord.antarchy.content.entity.SpitBugEntity;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import software.bernie.geckolib.renderer.GeoEntityRenderer;
|
||||
|
||||
public class SpitBugRenderer extends GeoEntityRenderer<SpitBugEntity> {
|
||||
public SpitBugRenderer(EntityRendererProvider.Context context) {
|
||||
super(context, new SpitBugModel());
|
||||
this.shadowRadius = 1.6F;
|
||||
this.withScale(0.85F);
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,8 @@ public class BomberEntity extends Monster implements GeoEntity {
|
||||
private static final int DEFAULT_FUSE_TICKS = 120;
|
||||
private static final int EXPLODE_ANIM_START_TICKS = 25;
|
||||
private static final int FLASH_INTERVAL_TICKS = 5;
|
||||
private static final double KNOCKBACK_MULTIPLIER = 3.0D;
|
||||
private static final float EXPLOSION_RADIUS_MULTIPLIER = 0.45F;
|
||||
|
||||
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
||||
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
|
||||
@@ -152,7 +154,13 @@ public class BomberEntity extends Monster implements GeoEntity {
|
||||
this.primeFuse();
|
||||
}
|
||||
|
||||
return super.hurt(source, amount);
|
||||
this.pushAwayFrom(source);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void knockback(double strength, double x, double z) {
|
||||
super.knockback(strength * KNOCKBACK_MULTIPLIER, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -205,6 +213,11 @@ public class BomberEntity extends Monster implements GeoEntity {
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (this.detonating && this.fuseTicks <= EXPLODE_ANIM_START_TICKS) {
|
||||
this.getNavigation().stop();
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
}
|
||||
|
||||
if (!this.level().isClientSide && this.detonating) {
|
||||
if (this.fuseTicks > 0) {
|
||||
this.fuseTicks--;
|
||||
@@ -268,7 +281,7 @@ public class BomberEntity extends Monster implements GeoEntity {
|
||||
double x = this.getX();
|
||||
double y = this.getY(0.0625D);
|
||||
double z = this.getZ();
|
||||
float radius = (float) AntarchySettings.bomberExplosionRadius();
|
||||
float radius = (float) (AntarchySettings.bomberExplosionRadius() * EXPLOSION_RADIUS_MULTIPLIER);
|
||||
serverLevel.playSound(null, x, y, z, SoundEvents.GENERIC_EXPLODE.value(), SoundSource.HOSTILE, 0.55F, 1.0F);
|
||||
serverLevel.explode(
|
||||
this,
|
||||
@@ -306,6 +319,26 @@ public class BomberEntity extends Monster implements GeoEntity {
|
||||
this.discard();
|
||||
}
|
||||
|
||||
private void pushAwayFrom(DamageSource source) {
|
||||
Entity sourceEntity = source.getDirectEntity();
|
||||
if (sourceEntity == null) {
|
||||
sourceEntity = source.getEntity();
|
||||
}
|
||||
if (sourceEntity == null || sourceEntity == this) {
|
||||
return;
|
||||
}
|
||||
|
||||
double dx = this.getX() - sourceEntity.getX();
|
||||
double dz = this.getZ() - sourceEntity.getZ();
|
||||
double distance = Math.sqrt(dx * dx + dz * dz);
|
||||
if (distance < 1.0E-4D) {
|
||||
return;
|
||||
}
|
||||
|
||||
double strength = 0.4D * KNOCKBACK_MULTIPLIER;
|
||||
this.push(dx / distance * strength, 0.08D, dz / distance * strength);
|
||||
}
|
||||
|
||||
private boolean isMovingForAnimation() {
|
||||
return this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-4D || this.getNavigation().isInProgress();
|
||||
}
|
||||
@@ -317,12 +350,12 @@ public class BomberEntity extends Monster implements GeoEntity {
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return super.canUse();
|
||||
return !BomberEntity.this.isDetonating() || BomberEntity.this.getFuseTicks() > EXPLODE_ANIM_START_TICKS && super.canUse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return super.canContinueToUse();
|
||||
return !BomberEntity.this.isDetonating() || BomberEntity.this.getFuseTicks() > EXPLODE_ANIM_START_TICKS && super.canContinueToUse();
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -1,10 +1,12 @@
|
||||
package com.craisinlord.antarchy.content.entity;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.Difficulty;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
@@ -133,12 +135,28 @@ public class CreepingHorrorEntity extends Monster implements GeoEntity {
|
||||
public boolean doHurtTarget(net.minecraft.world.entity.Entity target) {
|
||||
boolean result = super.doHurtTarget(target);
|
||||
if (result) {
|
||||
this.playSound(AntarchySoundEvents.CREEPING_HORROR_BITE.get(), 1.0F, 0.95F + this.random.nextFloat() * 0.1F);
|
||||
attackAnimTicks = 20;
|
||||
this.level().broadcastEntityEvent(this, ATTACK_ANIM_EVENT);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return AntarchySoundEvents.CREEPING_HORROR_GROWL.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getHurtSound(net.minecraft.world.damagesource.DamageSource source) {
|
||||
return AntarchySoundEvents.CREEPING_HORROR_HURT.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getDeathSound() {
|
||||
return AntarchySoundEvents.CREEPING_HORROR_HURT.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEntityEvent(byte id) {
|
||||
if (id == ATTACK_ANIM_EVENT) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.craisinlord.antarchy.content.entity;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
@@ -22,6 +23,7 @@ import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||||
import net.minecraft.world.entity.monster.Monster;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
@@ -129,12 +131,28 @@ public class LurkingTerrorEntity extends Monster implements GeoEntity {
|
||||
public boolean doHurtTarget(net.minecraft.world.entity.Entity target) {
|
||||
boolean result = super.doHurtTarget(target);
|
||||
if (result) {
|
||||
this.playSound(AntarchySoundEvents.LURKING_TERROR_BITE.get(), 1.0F, 0.95F + this.random.nextFloat() * 0.1F);
|
||||
attackAnimTicks = 20;
|
||||
this.level().broadcastEntityEvent(this, ATTACK_ANIM_EVENT);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return AntarchySoundEvents.LURKING_TERROR_SNARL.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getHurtSound(net.minecraft.world.damagesource.DamageSource source) {
|
||||
return AntarchySoundEvents.LURKING_TERROR_HURT.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getDeathSound() {
|
||||
return AntarchySoundEvents.LURKING_TERROR_HURT.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEntityEvent(byte id) {
|
||||
if (id == ATTACK_ANIM_EVENT) {
|
||||
@@ -147,6 +165,9 @@ public class LurkingTerrorEntity extends Monster implements GeoEntity {
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (!this.level().isClientSide() && !this.onGround() && this.tickCount % 40 == 0) {
|
||||
this.playSound(AntarchySoundEvents.LURKING_TERROR_FLY_LOOP.get(), 0.45F, 0.95F + this.random.nextFloat() * 0.1F);
|
||||
}
|
||||
if (attackAnimTicks > 0) attackAnimTicks--;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
package com.craisinlord.antarchy.content.entity;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.Difficulty;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
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.Goal;
|
||||
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
|
||||
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
|
||||
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
|
||||
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
|
||||
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.Level;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
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;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class SpitBugEntity extends Monster implements GeoEntity {
|
||||
private static final EntityDataAccessor<Integer> SPIT_ANIM_TICKS =
|
||||
SynchedEntityData.defineId(SpitBugEntity.class, EntityDataSerializers.INT);
|
||||
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
||||
private static final RawAnimation WALK_ANIM = RawAnimation.begin().thenLoop("walk");
|
||||
private static final RawAnimation SPIT_ANIM = RawAnimation.begin().thenPlay("spit");
|
||||
|
||||
private static final double MAX_HEALTH = 30.0D;
|
||||
private static final double MOVEMENT_SPEED = 0.23D;
|
||||
private static final double ATTACK_DAMAGE = 5.0D;
|
||||
private static final double FOLLOW_RANGE = 24.0D;
|
||||
private static final double SPIT_RANGE_SQR = 14.0D * 14.0D;
|
||||
private static final double MELEE_RANGE_SQR = 3.5D * 3.5D;
|
||||
private static final int SPIT_COOLDOWN_TICKS = 55;
|
||||
private static final int SPIT_ANIMATION_TICKS = 18;
|
||||
private static final int SPIT_RELEASE_TICKS = 8;
|
||||
|
||||
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||
|
||||
private int spitCooldownTicks;
|
||||
private int spitAnimationTicks;
|
||||
private int spitReleaseTicks;
|
||||
|
||||
public SpitBugEntity(EntityType<? extends SpitBugEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
this.xpReward = 10;
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return Mob.createMobAttributes()
|
||||
.add(Attributes.MAX_HEALTH, MAX_HEALTH)
|
||||
.add(Attributes.MOVEMENT_SPEED, MOVEMENT_SPEED)
|
||||
.add(Attributes.ATTACK_DAMAGE, ATTACK_DAMAGE)
|
||||
.add(Attributes.FOLLOW_RANGE, FOLLOW_RANGE)
|
||||
.add(Attributes.ARMOR, 4.0D)
|
||||
.add(Attributes.KNOCKBACK_RESISTANCE, 0.2D);
|
||||
}
|
||||
|
||||
public static boolean canSpawn(EntityType<SpitBugEntity> 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
|
||||
&& level.isEmptyBlock(pos)
|
||||
&& level.isEmptyBlock(pos.above())
|
||||
&& Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
builder.define(SPIT_ANIM_TICKS, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(1, new SpitAttackGoal());
|
||||
this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false));
|
||||
this.goalSelector.addGoal(3, new WaterAvoidingRandomStrollGoal(this, 0.9D));
|
||||
this.goalSelector.addGoal(4, new LookAtPlayerGoal(this, Player.class, 12.0F));
|
||||
this.goalSelector.addGoal(5, new RandomLookAroundGoal(this));
|
||||
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
|
||||
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||
controllers.add(new AnimationController<>(this, "main_controller", 2, this::mainAnimController));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.geoCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (this.level().isClientSide) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.spitCooldownTicks > 0) {
|
||||
this.spitCooldownTicks--;
|
||||
}
|
||||
|
||||
if (this.spitAnimationTicks > 0) {
|
||||
this.spitAnimationTicks--;
|
||||
this.entityData.set(SPIT_ANIM_TICKS, this.spitAnimationTicks);
|
||||
if (this.spitReleaseTicks > 0 && --this.spitReleaseTicks == 0) {
|
||||
this.fireSpitProjectile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doHurtTarget(net.minecraft.world.entity.Entity target) {
|
||||
boolean hurt = super.doHurtTarget(target);
|
||||
if (hurt) {
|
||||
this.playSound(SoundEvents.SPIDER_HURT, 0.7F, 0.8F + this.random.nextFloat() * 0.2F);
|
||||
}
|
||||
return hurt;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return SoundEvents.SPIDER_AMBIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getHurtSound(DamageSource damageSource) {
|
||||
return SoundEvents.SPIDER_HURT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getDeathSound() {
|
||||
return SoundEvents.SPIDER_DEATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playStepSound(BlockPos pos, BlockState blockState) {
|
||||
this.playSound(SoundEvents.SPIDER_STEP, 0.18F, 0.95F);
|
||||
}
|
||||
|
||||
private PlayState mainAnimController(AnimationState<SpitBugEntity> state) {
|
||||
if (this.entityData.get(SPIT_ANIM_TICKS) > 0) {
|
||||
return state.setAndContinue(SPIT_ANIM);
|
||||
}
|
||||
return state.setAndContinue(state.isMoving() ? WALK_ANIM : IDLE_ANIM);
|
||||
}
|
||||
|
||||
private boolean canSpitAt(LivingEntity target) {
|
||||
return this.spitCooldownTicks <= 0
|
||||
&& this.spitAnimationTicks <= 0
|
||||
&& this.hasLineOfSight(target)
|
||||
&& this.distanceToSqr(target) <= SPIT_RANGE_SQR
|
||||
&& this.distanceToSqr(target) > MELEE_RANGE_SQR;
|
||||
}
|
||||
|
||||
private void startSpitAttack() {
|
||||
this.spitCooldownTicks = SPIT_COOLDOWN_TICKS;
|
||||
this.spitAnimationTicks = SPIT_ANIMATION_TICKS;
|
||||
this.spitReleaseTicks = SPIT_RELEASE_TICKS;
|
||||
this.entityData.set(SPIT_ANIM_TICKS, this.spitAnimationTicks);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void fireSpitProjectile() {
|
||||
if (!(this.level() instanceof ServerLevel serverLevel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LivingEntity target = this.getTarget();
|
||||
if (target == null || !target.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityType<SpitBugProjectileEntity> projectileType = (EntityType<SpitBugProjectileEntity>) BuiltInRegistries.ENTITY_TYPE.getOptional(
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "spit_bug_projectile")
|
||||
).orElse(null);
|
||||
if (projectileType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SpitBugProjectileEntity projectile = new SpitBugProjectileEntity(projectileType, this, serverLevel);
|
||||
Vec3 origin = this.position()
|
||||
.add(0.0D, this.getBbHeight() * 0.55D, 0.0D)
|
||||
.add(this.getViewVector(0.0F).scale(1.35D));
|
||||
Vec3 aimPoint = target.getEyePosition().add(target.getDeltaMovement().scale(0.45D));
|
||||
Vec3 direction = aimPoint.subtract(origin).normalize();
|
||||
|
||||
projectile.setPos(origin.x, origin.y, origin.z);
|
||||
projectile.shoot(direction.x, direction.y, direction.z, 1.05F, 0.0F);
|
||||
serverLevel.addFreshEntity(projectile);
|
||||
this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, 0.85F + this.random.nextFloat() * 0.15F);
|
||||
}
|
||||
|
||||
private final class SpitAttackGoal extends Goal {
|
||||
SpitAttackGoal() {
|
||||
this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
LivingEntity target = SpitBugEntity.this.getTarget();
|
||||
return target != null && target.isAlive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return this.canUse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
LivingEntity target = SpitBugEntity.this.getTarget();
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SpitBugEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
||||
|
||||
if (SpitBugEntity.this.canSpitAt(target)) {
|
||||
SpitBugEntity.this.getNavigation().stop();
|
||||
SpitBugEntity.this.startSpitAttack();
|
||||
return;
|
||||
}
|
||||
|
||||
if (SpitBugEntity.this.distanceToSqr(target) > 36.0D || !SpitBugEntity.this.hasLineOfSight(target)) {
|
||||
SpitBugEntity.this.getNavigation().moveTo(target, 1.0D);
|
||||
} else {
|
||||
SpitBugEntity.this.getNavigation().stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
package com.craisinlord.antarchy.content.entity;
|
||||
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class SpitBugProjectileEntity extends ThrowableItemProjectile {
|
||||
private static final EntityDataAccessor<Boolean> LINGERING =
|
||||
SynchedEntityData.defineId(SpitBugProjectileEntity.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final int MAX_FLIGHT_TICKS = 100;
|
||||
private static final int LINGER_DURATION_TICKS = 300;
|
||||
private static final int DIRECT_HIT_DAMAGE = 8;
|
||||
private static final float LINGER_RADIUS = 1.65F;
|
||||
|
||||
private boolean lingering;
|
||||
private int lingeringTicks;
|
||||
|
||||
public SpitBugProjectileEntity(EntityType<? extends SpitBugProjectileEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
}
|
||||
|
||||
public SpitBugProjectileEntity(EntityType<? extends SpitBugProjectileEntity> entityType, LivingEntity owner, Level level) {
|
||||
super(entityType, owner, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||
super.defineSynchedData(builder);
|
||||
builder.define(LINGERING, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item getDefaultItem() {
|
||||
return Items.SLIME_BALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getDefaultGravity() {
|
||||
return 0.03D;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeCollidedWith() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttackable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isLingering() {
|
||||
return this.entityData.get(LINGERING);
|
||||
}
|
||||
|
||||
public float getRenderScale(float partialTick) {
|
||||
if (!this.isLingering()) {
|
||||
return 0.65F;
|
||||
}
|
||||
float progress = Math.min(1.0F, (this.lingeringTicks + partialTick) / 8.0F);
|
||||
return 0.6F + progress * 0.5F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.isLingering()) {
|
||||
this.tickLingering();
|
||||
return;
|
||||
}
|
||||
|
||||
super.tick();
|
||||
if (this.tickCount > MAX_FLIGHT_TICKS) {
|
||||
this.discard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.level().isClientSide) {
|
||||
this.level().addParticle(ParticleTypes.ITEM_SLIME, this.getX(), this.getY(), this.getZ(), 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
private void tickLingering() {
|
||||
this.lingeringTicks++;
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
|
||||
if (this.level().isClientSide) {
|
||||
double radius = 0.4D + this.random.nextDouble() * 0.45D;
|
||||
this.level().addParticle(
|
||||
ParticleTypes.ITEM_SLIME,
|
||||
this.getX() + (this.random.nextDouble() - 0.5D) * radius,
|
||||
this.getY() + 0.04D,
|
||||
this.getZ() + (this.random.nextDouble() - 0.5D) * radius,
|
||||
0.0D,
|
||||
0.0D,
|
||||
0.0D
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.lingeringTicks % 4 == 0) {
|
||||
this.applyLingeringSpit();
|
||||
}
|
||||
|
||||
if (this.lingeringTicks >= LINGER_DURATION_TICKS) {
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
|
||||
private void applyLingeringSpit() {
|
||||
for (LivingEntity target : this.level().getEntitiesOfClass(
|
||||
LivingEntity.class,
|
||||
this.getBoundingBox().inflate(LINGER_RADIUS, 0.6D, LINGER_RADIUS),
|
||||
entity -> entity.isAlive() && entity != this.getOwner()
|
||||
)) {
|
||||
target.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 30, 3, false, true, true));
|
||||
target.makeStuckInBlock(Blocks.HONEY_BLOCK.defaultBlockState(), new Vec3(0.2D, 0.0D, 0.2D));
|
||||
}
|
||||
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
serverLevel.sendParticles(ParticleTypes.ITEM_SLIME, this.getX(), this.getY() + 0.05D, this.getZ(), 3, 0.45D, 0.02D, 0.45D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHitEntity(EntityHitResult result) {
|
||||
if (!this.level().isClientSide && result.getEntity() instanceof LivingEntity livingTarget) {
|
||||
Entity owner = this.getOwner();
|
||||
if (owner instanceof LivingEntity livingOwner) {
|
||||
livingTarget.hurt(this.damageSources().mobProjectile(this, livingOwner), DIRECT_HIT_DAMAGE);
|
||||
} else {
|
||||
livingTarget.hurt(this.damageSources().magic(), DIRECT_HIT_DAMAGE);
|
||||
}
|
||||
livingTarget.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 80, 3, false, true, true));
|
||||
livingTarget.makeStuckInBlock(Blocks.HONEY_BLOCK.defaultBlockState(), new Vec3(0.25D, 0.0D, 0.25D));
|
||||
}
|
||||
|
||||
this.beginLingering(result.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHitBlock(BlockHitResult result) {
|
||||
this.beginLingering(result.getLocation());
|
||||
}
|
||||
|
||||
private void beginLingering(Vec3 location) {
|
||||
if (this.isLingering()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lingering = true;
|
||||
this.entityData.set(LINGERING, true);
|
||||
this.lingeringTicks = 0;
|
||||
this.noPhysics = true;
|
||||
this.setPos(location.x, location.y + 0.05D, location.z);
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.fluid;
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
@@ -11,34 +12,69 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.tags.EntityTypeTags;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.LiquidBlock;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.FlowingFluid;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
public class BileLiquidBlock extends LiquidBlock {
|
||||
private static final ResourceLocation BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "bile");
|
||||
private static final ResourceLocation FLOWING_BILE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "flowing_bile");
|
||||
private static final ResourceLocation BROODSTONE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "broodstone");
|
||||
private static final ResourceLocation MYRMITE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "myrmite");
|
||||
private static final int EFFECT_DURATION_TICKS = 100;
|
||||
|
||||
public BileLiquidBlock(FlowingFluid fluid, BlockBehaviour.Properties properties) {
|
||||
super(fluid, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) {
|
||||
super.neighborChanged(state, level, pos, neighborBlock, neighborPos, movedByPiston);
|
||||
if (!level.isClientSide) {
|
||||
reactWithWater(state, level, pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||
if (!level.isClientSide) {
|
||||
reactWithWater(state, level, pos);
|
||||
}
|
||||
}
|
||||
|
||||
private void reactWithWater(BlockState state, Level level, BlockPos pos) {
|
||||
for (Direction dir : Direction.values()) {
|
||||
FluidState neighbor = level.getFluidState(pos.relative(dir));
|
||||
if (neighbor.is(Fluids.WATER) || neighbor.is(Fluids.FLOWING_WATER)) {
|
||||
boolean isSource = state.getFluidState().isSource();
|
||||
ResourceLocation resultId = isSource ? BROODSTONE_ID : MYRMITE_ID;
|
||||
Block resultBlock = BuiltInRegistries.BLOCK.getOptional(resultId).orElse(null);
|
||||
if (resultBlock != null) {
|
||||
level.setBlock(pos, resultBlock.defaultBlockState(), 3);
|
||||
level.levelEvent(1501, pos, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
|
||||
super.entityInside(state, level, pos, entity);
|
||||
|
||||
if (entity instanceof LivingEntity livingEntity) {
|
||||
if (!level.isClientSide) {
|
||||
if (livingEntity.getType().is(EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS)) {
|
||||
return;
|
||||
}
|
||||
livingEntity.addEffect(new MobEffectInstance(AntarchyObjects.STINKY_EFFECT.get(), EFFECT_DURATION_TICKS, 0, false, true, true));
|
||||
livingEntity.addEffect(new MobEffectInstance(MobEffects.WEAKNESS, EFFECT_DURATION_TICKS, 0, false, true, true));
|
||||
}
|
||||
|
||||
if (livingEntity.getType().is(EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -126,11 +126,10 @@ public class ElythiaBiomeSource extends BiomeSource {
|
||||
return oceanHolder != null ? oceanHolder : seaLevelBiome;
|
||||
}
|
||||
|
||||
// Land column in the shallow-underwater zone: force ocean for surface biomes that
|
||||
// ended up below sea level (e.g. meadow in a depression). Only applies within
|
||||
// 6 quarts (~24 blocks) of sea level — deep underground is unaffected.
|
||||
if (y >= this.seaLevelQuartY - 6 && y <= this.seaLevelQuartY
|
||||
&& oceanHolder != null && !allowedBelowSeaLevel(biome)) {
|
||||
// Land column below sea level: force any non-allowed surface biome to ocean.
|
||||
// Cave sand/decorations are prevented by above_preliminary_surface in the
|
||||
// surface rules, so this is safe to apply unconditionally.
|
||||
if (y <= this.seaLevelQuartY && oceanHolder != null && !allowedBelowSeaLevel(biome)) {
|
||||
return oceanHolder;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user