Fix Bugs And Add Particle Effects To Glowing Obsidian
All checks were successful
Twine/pipeline/head This commit looks good
All checks were successful
Twine/pipeline/head This commit looks good
This commit is contained in:
parent
38f16baa75
commit
fec445e22a
@ -46,6 +46,9 @@ public class Twine implements ModInitializer {
|
|||||||
public static final int STAGE_COUNT = 6;
|
public static final int STAGE_COUNT = 6;
|
||||||
public static final int STAGE_TIME = 24000;
|
public static final int STAGE_TIME = 24000;
|
||||||
|
|
||||||
|
public static final int AI_RANGE = 16;
|
||||||
|
public static final int AI_MAX_Y_DIFFERENCE = 4;
|
||||||
|
|
||||||
public static ScreenHandlerType<? extends GenericContainerScreenHandler> BACKPACK_SCREEN_TYPE;
|
public static ScreenHandlerType<? extends GenericContainerScreenHandler> BACKPACK_SCREEN_TYPE;
|
||||||
public static ScreenHandlerType<? extends CraftingScreenHandler> BOAT_CRAFTING_SCREEN_TYPE;
|
public static ScreenHandlerType<? extends CraftingScreenHandler> BOAT_CRAFTING_SCREEN_TYPE;
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ import net.minecraft.entity.LivingEntity;
|
|||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.entity.mob.Monster;
|
import net.minecraft.entity.mob.Monster;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.BlockView;
|
import net.minecraft.world.BlockView;
|
||||||
@ -27,13 +29,14 @@ public class GlowingObsidianBlock extends Block {
|
|||||||
@Override
|
@Override
|
||||||
public void onSteppedOn(World world, BlockPos pos, Entity entity) {
|
public void onSteppedOn(World world, BlockPos pos, Entity entity) {
|
||||||
super.onSteppedOn(world, pos, entity);
|
super.onSteppedOn(world, pos, entity);
|
||||||
if (entity instanceof LivingEntity && entity.age % 5 == 0) {
|
if (!world.isClient() && entity instanceof LivingEntity && entity.age % 10 == 0) {
|
||||||
final float amount = 2f;
|
final float amount = 2f;
|
||||||
if (entity instanceof Monster) {
|
if (entity instanceof Monster) {
|
||||||
((LivingEntity) entity).heal(amount);
|
((LivingEntity) entity).heal(amount);
|
||||||
} else {
|
} else {
|
||||||
entity.damage(DamageSource.MAGIC, amount);
|
entity.damage(DamageSource.MAGIC, amount);
|
||||||
}
|
}
|
||||||
|
((ServerWorld) world).spawnParticles(ParticleTypes.SMOKE, pos.getX() + 0.5d, pos.getY() + 1d, pos.getZ() + 0.5d, 12 + world.getRandom().nextInt(12), 0.1d, 0.5d, 0.1d,0.01d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import net.minecraft.world.chunk.ChunkStatus;
|
|||||||
|
|
||||||
public class ExplodeArtificialBlockGoal extends MoveToTargetPosGoal {
|
public class ExplodeArtificialBlockGoal extends MoveToTargetPosGoal {
|
||||||
public ExplodeArtificialBlockGoal(MobEntityWithAi mob) {
|
public ExplodeArtificialBlockGoal(MobEntityWithAi mob) {
|
||||||
super(mob, 1d, 24, 4);
|
super(mob, 1d, Twine.AI_RANGE, Twine.AI_MAX_Y_DIFFERENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,4 +62,13 @@ public class ExplodeArtificialBlockGoal extends MoveToTargetPosGoal {
|
|||||||
|
|
||||||
return stage >= StageUtil.CREEPERS_TARGET_ARTIFICIAL_BLOCKS && super.canStart();
|
return stage >= StageUtil.CREEPERS_TARGET_ARTIFICIAL_BLOCKS && super.canStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean findTargetPos() {
|
||||||
|
if (targetPos != null && isTargetPos(mob.world, targetPos)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return super.findTargetPos();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.thebrokenrail.twine.entity;
|
package com.thebrokenrail.twine.entity;
|
||||||
|
|
||||||
|
import com.thebrokenrail.twine.Twine;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.entity.ai.TargetFinder;
|
import net.minecraft.entity.ai.TargetFinder;
|
||||||
import net.minecraft.entity.ai.goal.Goal;
|
import net.minecraft.entity.ai.goal.Goal;
|
||||||
@ -12,9 +13,6 @@ import net.minecraft.world.chunk.Chunk;
|
|||||||
import net.minecraft.world.chunk.ChunkStatus;
|
import net.minecraft.world.chunk.ChunkStatus;
|
||||||
|
|
||||||
public class FleeEndRodGoal extends Goal {
|
public class FleeEndRodGoal extends Goal {
|
||||||
private static final int RANGE = 16;
|
|
||||||
private static final int MAX_Y_DIFFERENCE = 7;
|
|
||||||
|
|
||||||
private final MobEntityWithAi mob;
|
private final MobEntityWithAi mob;
|
||||||
private Vec3d targetPos;
|
private Vec3d targetPos;
|
||||||
private Path fleePath;
|
private Path fleePath;
|
||||||
@ -37,8 +35,8 @@ public class FleeEndRodGoal extends Goal {
|
|||||||
BlockPos blockPos = mob.getBlockPos();
|
BlockPos blockPos = mob.getBlockPos();
|
||||||
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
||||||
|
|
||||||
for (int k = 0; k <= MAX_Y_DIFFERENCE; k = k > 0 ? -k : 1 - k) {
|
for (int k = 0; k <= Twine.AI_MAX_Y_DIFFERENCE; k = k > 0 ? -k : 1 - k) {
|
||||||
for (int l = 0; l < RANGE; ++l) {
|
for (int l = 0; l < Twine.AI_RANGE; ++l) {
|
||||||
for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) {
|
for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) {
|
||||||
for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) {
|
for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) {
|
||||||
mutable.set(blockPos, m, k - 1, n);
|
mutable.set(blockPos, m, k - 1, n);
|
||||||
@ -64,7 +62,7 @@ public class FleeEndRodGoal extends Goal {
|
|||||||
@Override
|
@Override
|
||||||
public boolean canStart() {
|
public boolean canStart() {
|
||||||
if (findTargetPos()) {
|
if (findTargetPos()) {
|
||||||
Vec3d vec3d = TargetFinder.findTargetAwayFrom(mob, RANGE * 2, MAX_Y_DIFFERENCE * 2, targetPos);
|
Vec3d vec3d = TargetFinder.findTargetAwayFrom(mob, Twine.AI_RANGE * 2, Twine.AI_MAX_Y_DIFFERENCE * 2, targetPos);
|
||||||
if (vec3d == null) {
|
if (vec3d == null) {
|
||||||
return false;
|
return false;
|
||||||
} else if (squaredDistanceTo(vec3d) < mob.squaredDistanceTo(targetPos)) {
|
} else if (squaredDistanceTo(vec3d) < mob.squaredDistanceTo(targetPos)) {
|
||||||
@ -98,7 +96,7 @@ public class FleeEndRodGoal extends Goal {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
if (squaredDistanceTo(mob.getPos()) < (RANGE / 2d)) {
|
if (squaredDistanceTo(mob.getPos()) < (Twine.AI_RANGE / 2d)) {
|
||||||
mob.getNavigation().setSpeed(FAST_SPEED);
|
mob.getNavigation().setSpeed(FAST_SPEED);
|
||||||
} else {
|
} else {
|
||||||
mob.getNavigation().setSpeed(SLOW_SPEED);
|
mob.getNavigation().setSpeed(SLOW_SPEED);
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
package com.thebrokenrail.twine.entity;
|
|
||||||
|
|
||||||
import com.thebrokenrail.twine.Twine;
|
|
||||||
import net.minecraft.entity.ai.goal.MoveToTargetPosGoal;
|
|
||||||
import net.minecraft.entity.mob.MobEntityWithAi;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.world.WorldView;
|
|
||||||
import net.minecraft.world.chunk.Chunk;
|
|
||||||
import net.minecraft.world.chunk.ChunkStatus;
|
|
||||||
|
|
||||||
public class StandOnGlowingObsidian extends MoveToTargetPosGoal {
|
|
||||||
public StandOnGlowingObsidian(MobEntityWithAi mob) {
|
|
||||||
super(mob, 1d, 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isTargetPos(WorldView world, BlockPos pos) {
|
|
||||||
Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false);
|
|
||||||
if (chunk == null) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return chunk.getBlockState(pos).isOf(Twine.GLOWING_OBSIDIAN) && chunk.getBlockState(pos.up()).isAir() && chunk.getBlockState(pos.up(2)).isAir();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canStart() {
|
|
||||||
return super.canStart() && (mob.getHealth() / mob.getMaxHealth()) <= 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.thebrokenrail.twine.entity;
|
||||||
|
|
||||||
|
import com.thebrokenrail.twine.Twine;
|
||||||
|
import net.minecraft.entity.ai.goal.Goal;
|
||||||
|
import net.minecraft.entity.ai.pathing.Path;
|
||||||
|
import net.minecraft.entity.mob.MobEntityWithAi;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.WorldView;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.ChunkStatus;
|
||||||
|
|
||||||
|
public class StandOnGlowingObsidianGoal extends Goal {
|
||||||
|
private final MobEntityWithAi mob;
|
||||||
|
private Vec3d targetPos;
|
||||||
|
private Path path;
|
||||||
|
|
||||||
|
public StandOnGlowingObsidianGoal(MobEntityWithAi mob) {
|
||||||
|
super();
|
||||||
|
this.mob = mob;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean findTargetPos() {
|
||||||
|
BlockPos blockPos = mob.getBlockPos();
|
||||||
|
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
||||||
|
|
||||||
|
for (int k = 0; k <= Twine.AI_MAX_Y_DIFFERENCE; k = k > 0 ? -k : 1 - k) {
|
||||||
|
for (int l = 0; l < Twine.AI_RANGE; ++l) {
|
||||||
|
for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) {
|
||||||
|
for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) {
|
||||||
|
mutable.set(blockPos, m, k - 1, n);
|
||||||
|
if (mob.isInWalkTargetRange(mutable) && isTargetPos(mob.world, mutable)) {
|
||||||
|
targetPos = new Vec3d(mutable.getX() + 0.5d, mutable.getY(), mutable.getZ() + 0.5d);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canStart() {
|
||||||
|
if ((mob.getHealth() / mob.getMaxHealth()) <= 0.5f && findTargetPos()) {
|
||||||
|
path = mob.getNavigation().findPathTo(targetPos.x, targetPos.y, targetPos.z, 0);
|
||||||
|
return path != null;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldContinue() {
|
||||||
|
return !mob.getNavigation().isIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
mob.getNavigation().startMovingAlong(path, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
targetPos = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTargetPos(WorldView world, BlockPos pos) {
|
||||||
|
Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false);
|
||||||
|
if (chunk == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return chunk.getBlockState(pos).isOf(Twine.GLOWING_OBSIDIAN) && chunk.getBlockState(pos.up()).isAir() && chunk.getBlockState(pos.up(2)).isAir();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -93,7 +93,7 @@ public class MixinBoatEntity implements BoatUtil {
|
|||||||
player.getEntityWorld().playSound(null, ((BoatEntity) (Object) this).getBlockPos(), SoundEvents.ITEM_ARMOR_EQUIP_GENERIC, ((BoatEntity) (Object) this).getSoundCategory(), 1f, 1f);
|
player.getEntityWorld().playSound(null, ((BoatEntity) (Object) this).getBlockPos(), SoundEvents.ITEM_ARMOR_EQUIP_GENERIC, ((BoatEntity) (Object) this).getSoundCategory(), 1f, 1f);
|
||||||
}
|
}
|
||||||
info.setReturnValue(ActionResult.SUCCESS);
|
info.setReturnValue(ActionResult.SUCCESS);
|
||||||
} else if (player.isSneaking()) {
|
} else if (player.shouldCancelInteraction()) {
|
||||||
if (!player.getEntityWorld().isClient()) {
|
if (!player.getEntityWorld().isClient()) {
|
||||||
openInventory(player);
|
openInventory(player);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import com.thebrokenrail.twine.component.StageDataComponent;
|
|||||||
import com.thebrokenrail.twine.entity.ExplodeArtificialBlockGoal;
|
import com.thebrokenrail.twine.entity.ExplodeArtificialBlockGoal;
|
||||||
import com.thebrokenrail.twine.entity.FleeEndRodGoal;
|
import com.thebrokenrail.twine.entity.FleeEndRodGoal;
|
||||||
import com.thebrokenrail.twine.entity.FollowPassiveEntityGoal;
|
import com.thebrokenrail.twine.entity.FollowPassiveEntityGoal;
|
||||||
import com.thebrokenrail.twine.entity.StandOnGlowingObsidian;
|
import com.thebrokenrail.twine.entity.StandOnGlowingObsidianGoal;
|
||||||
import com.thebrokenrail.twine.util.StageUtil;
|
import com.thebrokenrail.twine.util.StageUtil;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.ai.goal.FollowTargetGoal;
|
import net.minecraft.entity.ai.goal.FollowTargetGoal;
|
||||||
@ -44,7 +44,7 @@ public class MixinMobEntity {
|
|||||||
if (world != null && !world.isClient()) {
|
if (world != null && !world.isClient()) {
|
||||||
if (this instanceof Monster) {
|
if (this instanceof Monster) {
|
||||||
if ((Object) this instanceof MobEntityWithAi) {
|
if ((Object) this instanceof MobEntityWithAi) {
|
||||||
goalSelector.add(1, new StandOnGlowingObsidian((MobEntityWithAi) (Object) this));
|
goalSelector.add(1, new StandOnGlowingObsidianGoal((MobEntityWithAi) (Object) this));
|
||||||
goalSelector.add(3, new FleeEndRodGoal((MobEntityWithAi) (Object) this));
|
goalSelector.add(3, new FleeEndRodGoal((MobEntityWithAi) (Object) this));
|
||||||
if ((Object) this instanceof CreeperEntity) {
|
if ((Object) this instanceof CreeperEntity) {
|
||||||
goalSelector.add(3, new ExplodeArtificialBlockGoal((MobEntityWithAi) (Object) this));
|
goalSelector.add(3, new ExplodeArtificialBlockGoal((MobEntityWithAi) (Object) this));
|
||||||
|
Reference in New Issue
Block a user