From de15c4b6c595c6d50e82132f4047d22578c94618 Mon Sep 17 00:00:00 2001 From: Konstantin Shandurenko Date: Mon, 1 Mar 2021 12:59:16 +0300 Subject: [PATCH] Rewriting projectiles --- .../entity/ai/goal/RangedAttackGoal.java | 19 ++-- .../entity/metadata/ProjectileMeta.java | 13 +++ .../entity/metadata/arrow/ArrowMeta.java | 5 +- .../metadata/arrow/SpectralArrowMeta.java | 5 +- .../entity/metadata/item/FireballMeta.java | 5 +- .../metadata/item/SmallFireballMeta.java | 5 +- .../metadata/other/DragonFireballMeta.java | 5 +- .../metadata/other/FireworkRocketMeta.java | 5 +- .../metadata/other/WitherSkullMeta.java | 5 +- .../server/entity/type/Projectile.java | 67 -------------- .../type/projectile/AbstractProjectile.java | 26 ------ .../entity/type/projectile/EntityArrow.java | 18 ---- .../type/projectile/EntityEyeOfEnder.java | 4 +- .../entity/type/projectile/EntityPotion.java | 4 +- ...stractArrow.java => EntityProjectile.java} | 90 +++++++++++++++++-- .../type/projectile/EntitySpectralArrow.java | 17 ---- .../server/event/entity/EntityShootEvent.java | 9 +- src/test/java/demo/commands/ShootCommand.java | 26 +++--- 18 files changed, 156 insertions(+), 172 deletions(-) create mode 100644 src/main/java/net/minestom/server/entity/metadata/ProjectileMeta.java delete mode 100644 src/main/java/net/minestom/server/entity/type/Projectile.java delete mode 100644 src/main/java/net/minestom/server/entity/type/projectile/AbstractProjectile.java delete mode 100644 src/main/java/net/minestom/server/entity/type/projectile/EntityArrow.java rename src/main/java/net/minestom/server/entity/type/projectile/{EntityAbstractArrow.java => EntityProjectile.java} (59%) delete mode 100644 src/main/java/net/minestom/server/entity/type/projectile/EntitySpectralArrow.java diff --git a/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java b/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java index ae3b979ae..c8b8c7dbf 100644 --- a/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java +++ b/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java @@ -2,17 +2,17 @@ package net.minestom.server.entity.ai.goal; import net.minestom.server.entity.Entity; import net.minestom.server.entity.EntityCreature; +import net.minestom.server.entity.EntityType; import net.minestom.server.entity.ai.GoalSelector; import net.minestom.server.entity.pathfinding.Navigator; -import net.minestom.server.entity.type.Projectile; -import net.minestom.server.entity.type.projectile.EntityArrow; +import net.minestom.server.entity.type.projectile.EntityProjectile; import net.minestom.server.utils.Position; import net.minestom.server.utils.time.CooldownUtils; import net.minestom.server.utils.time.TimeUnit; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; -import java.util.function.BiFunction; +import java.util.function.Function; public class RangedAttackGoal extends GoalSelector { @@ -25,7 +25,7 @@ public class RangedAttackGoal extends GoalSelector { private final double power; private final double spread; - private BiFunction projectileGenerator; + private Function projectileGenerator; private boolean stop; private Entity cachedTarget; @@ -52,7 +52,7 @@ public class RangedAttackGoal extends GoalSelector { Check.argCondition(desirableRange > attackRange, "Desirable range can not exceed attack range!"); } - public void setProjectileGenerator(BiFunction projectileGenerator) { + public void setProjectileGenerator(Function projectileGenerator) { this.projectileGenerator = projectileGenerator; } @@ -87,13 +87,14 @@ public class RangedAttackGoal extends GoalSelector { if (this.entityCreature.hasLineOfSight(target)) { Position to = target.getPosition().clone().add(0D, target.getEyeHeight(), 0D); - BiFunction projectileGenerator = this.projectileGenerator; + Function projectileGenerator = this.projectileGenerator; if (projectileGenerator == null) { - projectileGenerator = EntityArrow::new; + projectileGenerator = shooter -> new EntityProjectile(shooter, EntityType.ARROW); } - Projectile projectile = projectileGenerator.apply(this.entityCreature, new Position(0D, 0D, 0D)); + EntityProjectile projectile = projectileGenerator.apply(this.entityCreature); + projectile.setInstance(this.entityCreature.getInstance(), this.entityCreature.getPosition()); - Projectile.shoot(projectile, this.entityCreature, to, this.power, this.spread); + projectile.shoot(to, this.power, this.spread); this.lastShot = time; } else { comeClose = this.comeClose; diff --git a/src/main/java/net/minestom/server/entity/metadata/ProjectileMeta.java b/src/main/java/net/minestom/server/entity/metadata/ProjectileMeta.java new file mode 100644 index 000000000..d5c4a0585 --- /dev/null +++ b/src/main/java/net/minestom/server/entity/metadata/ProjectileMeta.java @@ -0,0 +1,13 @@ +package net.minestom.server.entity.metadata; + +import net.minestom.server.entity.Entity; +import org.jetbrains.annotations.Nullable; + +public interface ProjectileMeta { + + @Nullable + Entity getShooter(); + + void setShooter(@Nullable Entity shooter); + +} diff --git a/src/main/java/net/minestom/server/entity/metadata/arrow/ArrowMeta.java b/src/main/java/net/minestom/server/entity/metadata/arrow/ArrowMeta.java index d02f96cdc..31f8bdf84 100644 --- a/src/main/java/net/minestom/server/entity/metadata/arrow/ArrowMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/arrow/ArrowMeta.java @@ -3,10 +3,11 @@ package net.minestom.server.entity.metadata.arrow; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.ObjectDataProvider; +import net.minestom.server.entity.metadata.ProjectileMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class ArrowMeta extends AbstractArrowMeta implements ObjectDataProvider { +public class ArrowMeta extends AbstractArrowMeta implements ObjectDataProvider, ProjectileMeta { private Entity shooter; @@ -22,11 +23,13 @@ public class ArrowMeta extends AbstractArrowMeta implements ObjectDataProvider { super.metadata.setIndex((byte) 9, Metadata.VarInt(value)); } + @Override @Nullable public Entity getShooter() { return this.shooter; } + @Override public void setShooter(@Nullable Entity shooter) { this.shooter = shooter; } diff --git a/src/main/java/net/minestom/server/entity/metadata/arrow/SpectralArrowMeta.java b/src/main/java/net/minestom/server/entity/metadata/arrow/SpectralArrowMeta.java index 4e356f4df..d3e70ed47 100644 --- a/src/main/java/net/minestom/server/entity/metadata/arrow/SpectralArrowMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/arrow/SpectralArrowMeta.java @@ -3,10 +3,11 @@ package net.minestom.server.entity.metadata.arrow; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.ObjectDataProvider; +import net.minestom.server.entity.metadata.ProjectileMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class SpectralArrowMeta extends AbstractArrowMeta implements ObjectDataProvider { +public class SpectralArrowMeta extends AbstractArrowMeta implements ObjectDataProvider, ProjectileMeta { private Entity shooter; @@ -14,11 +15,13 @@ public class SpectralArrowMeta extends AbstractArrowMeta implements ObjectDataPr super(entity, metadata); } + @Override @Nullable public Entity getShooter() { return this.shooter; } + @Override public void setShooter(@Nullable Entity shooter) { this.shooter = shooter; } diff --git a/src/main/java/net/minestom/server/entity/metadata/item/FireballMeta.java b/src/main/java/net/minestom/server/entity/metadata/item/FireballMeta.java index 822de1f39..4a82ad567 100644 --- a/src/main/java/net/minestom/server/entity/metadata/item/FireballMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/item/FireballMeta.java @@ -3,11 +3,12 @@ package net.minestom.server.entity.metadata.item; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.ObjectDataProvider; +import net.minestom.server.entity.metadata.ProjectileMeta; import net.minestom.server.item.Material; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class FireballMeta extends ItemContainingMeta implements ObjectDataProvider { +public class FireballMeta extends ItemContainingMeta implements ObjectDataProvider, ProjectileMeta { private Entity shooter; @@ -15,11 +16,13 @@ public class FireballMeta extends ItemContainingMeta implements ObjectDataProvid super(entity, metadata, Material.AIR); } + @Override @Nullable public Entity getShooter() { return shooter; } + @Override public void setShooter(@Nullable Entity shooter) { this.shooter = shooter; } diff --git a/src/main/java/net/minestom/server/entity/metadata/item/SmallFireballMeta.java b/src/main/java/net/minestom/server/entity/metadata/item/SmallFireballMeta.java index 5953445cb..9bc510f2e 100644 --- a/src/main/java/net/minestom/server/entity/metadata/item/SmallFireballMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/item/SmallFireballMeta.java @@ -3,11 +3,12 @@ package net.minestom.server.entity.metadata.item; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.ObjectDataProvider; +import net.minestom.server.entity.metadata.ProjectileMeta; import net.minestom.server.item.Material; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class SmallFireballMeta extends ItemContainingMeta implements ObjectDataProvider { +public class SmallFireballMeta extends ItemContainingMeta implements ObjectDataProvider, ProjectileMeta { private Entity shooter; @@ -15,11 +16,13 @@ public class SmallFireballMeta extends ItemContainingMeta implements ObjectDataP super(entity, metadata, Material.FIRE_CHARGE); } + @Override @Nullable public Entity getShooter() { return shooter; } + @Override public void setShooter(@Nullable Entity shooter) { this.shooter = shooter; } diff --git a/src/main/java/net/minestom/server/entity/metadata/other/DragonFireballMeta.java b/src/main/java/net/minestom/server/entity/metadata/other/DragonFireballMeta.java index 27abf9d32..e653345da 100644 --- a/src/main/java/net/minestom/server/entity/metadata/other/DragonFireballMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/other/DragonFireballMeta.java @@ -4,10 +4,11 @@ import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.EntityMeta; import net.minestom.server.entity.metadata.ObjectDataProvider; +import net.minestom.server.entity.metadata.ProjectileMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class DragonFireballMeta extends EntityMeta implements ObjectDataProvider { +public class DragonFireballMeta extends EntityMeta implements ObjectDataProvider, ProjectileMeta { private Entity shooter; @@ -15,11 +16,13 @@ public class DragonFireballMeta extends EntityMeta implements ObjectDataProvider super(entity, metadata); } + @Override @Nullable public Entity getShooter() { return shooter; } + @Override public void setShooter(@Nullable Entity shooter) { this.shooter = shooter; } diff --git a/src/main/java/net/minestom/server/entity/metadata/other/FireworkRocketMeta.java b/src/main/java/net/minestom/server/entity/metadata/other/FireworkRocketMeta.java index 4dd141292..c3155617d 100644 --- a/src/main/java/net/minestom/server/entity/metadata/other/FireworkRocketMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/other/FireworkRocketMeta.java @@ -3,11 +3,12 @@ package net.minestom.server.entity.metadata.other; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.EntityMeta; +import net.minestom.server.entity.metadata.ProjectileMeta; import net.minestom.server.item.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class FireworkRocketMeta extends EntityMeta { +public class FireworkRocketMeta extends EntityMeta implements ProjectileMeta { private Entity shooter; @@ -24,11 +25,13 @@ public class FireworkRocketMeta extends EntityMeta { super.metadata.setIndex((byte) 7, Metadata.Slot(value)); } + @Override @Nullable public Entity getShooter() { return this.shooter; } + @Override public void setShooter(@Nullable Entity value) { this.shooter = value; Integer entityID = value == null ? null : value.getEntityId(); diff --git a/src/main/java/net/minestom/server/entity/metadata/other/WitherSkullMeta.java b/src/main/java/net/minestom/server/entity/metadata/other/WitherSkullMeta.java index 7f751ab12..854f1c26d 100644 --- a/src/main/java/net/minestom/server/entity/metadata/other/WitherSkullMeta.java +++ b/src/main/java/net/minestom/server/entity/metadata/other/WitherSkullMeta.java @@ -4,10 +4,11 @@ import net.minestom.server.entity.Entity; import net.minestom.server.entity.Metadata; import net.minestom.server.entity.metadata.EntityMeta; import net.minestom.server.entity.metadata.ObjectDataProvider; +import net.minestom.server.entity.metadata.ProjectileMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class WitherSkullMeta extends EntityMeta implements ObjectDataProvider { +public class WitherSkullMeta extends EntityMeta implements ObjectDataProvider, ProjectileMeta { private Entity shooter; @@ -23,11 +24,13 @@ public class WitherSkullMeta extends EntityMeta implements ObjectDataProvider { super.metadata.setIndex((byte) 7, Metadata.Boolean(value)); } + @Override @Nullable public Entity getShooter() { return shooter; } + @Override public void setShooter(@Nullable Entity shooter) { this.shooter = shooter; } diff --git a/src/main/java/net/minestom/server/entity/type/Projectile.java b/src/main/java/net/minestom/server/entity/type/Projectile.java deleted file mode 100644 index 0992f9443..000000000 --- a/src/main/java/net/minestom/server/entity/type/Projectile.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.minestom.server.entity.type; - -import net.minestom.server.entity.Entity; -import net.minestom.server.event.entity.EntityShootEvent; -import net.minestom.server.utils.Position; -import net.minestom.server.utils.Vector; -import net.minestom.server.utils.validate.Check; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -public interface Projectile { - - static void shoot(@NotNull Projectile projectile, @NotNull Entity shooter, Position to, double power, double spread) { - Check.argCondition(!(projectile instanceof Entity), "Projectile must be an instance of Entity!"); - EntityShootEvent event = new EntityShootEvent(shooter, projectile, to, power, spread); - shooter.callEvent(EntityShootEvent.class, event); - if (event.isCancelled()) { - Entity proj = (Entity) projectile; - proj.remove(); - return; - } - Position from = shooter.getPosition().clone().add(0D, shooter.getEyeHeight(), 0D); - shoot(projectile, from, to, event.getPower(), event.getSpread()); - } - - @SuppressWarnings("ConstantConditions") - static void shoot(@NotNull Projectile projectile, @NotNull Position from, @NotNull Position to, double power, double spread) { - Check.argCondition(!(projectile instanceof Entity), "Projectile must be an instance of Entity!"); - Entity proj = (Entity) projectile; - double dx = to.getX() - from.getX(); - double dy = to.getY() - from.getY(); - double dz = to.getZ() - from.getZ(); - double xzLength = Math.sqrt(dx * dx + dz * dz); - dy += xzLength * 0.20000000298023224D; - - double length = Math.sqrt(dx * dx + dy * dy + dz * dz); - dx /= length; - dy /= length; - dz /= length; - Random random = ThreadLocalRandom.current(); - spread *= 0.007499999832361937D; - dx += random.nextGaussian() * spread; - dy += random.nextGaussian() * spread; - dz += random.nextGaussian() * spread; - Vector velocity = proj.getVelocity(); - velocity.setX(dx); - velocity.setY(dy); - velocity.setZ(dz); - velocity.multiply(20 * power); - proj.setView( - (float) Math.toDegrees(Math.atan2(dx, dz)), - (float) Math.toDegrees(Math.atan2(dy, Math.sqrt(dx * dx + dz * dz))) - ); - } - - /** - * Gets the shooter of this projectile. - * - * @return the shooter of this projectile. - */ - @Nullable - Entity getShooter(); - -} diff --git a/src/main/java/net/minestom/server/entity/type/projectile/AbstractProjectile.java b/src/main/java/net/minestom/server/entity/type/projectile/AbstractProjectile.java deleted file mode 100644 index c4ad5c8eb..000000000 --- a/src/main/java/net/minestom/server/entity/type/projectile/AbstractProjectile.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.minestom.server.entity.type.projectile; - -import net.minestom.server.entity.Entity; -import net.minestom.server.entity.EntityType; -import net.minestom.server.entity.ObjectEntity; -import net.minestom.server.entity.type.Projectile; -import net.minestom.server.utils.Position; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class AbstractProjectile extends Entity implements Projectile { - - private final Entity shooter; - - public AbstractProjectile(@Nullable Entity shooter, @NotNull EntityType entityType, @NotNull Position spawnPosition) { - super(entityType, spawnPosition); - setGravity(0.02f, 0.04f, 1.96f); - this.shooter = shooter; - } - - @Override - public Entity getShooter() { - return this.shooter; - } - -} diff --git a/src/main/java/net/minestom/server/entity/type/projectile/EntityArrow.java b/src/main/java/net/minestom/server/entity/type/projectile/EntityArrow.java deleted file mode 100644 index a5a3efc21..000000000 --- a/src/main/java/net/minestom/server/entity/type/projectile/EntityArrow.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.minestom.server.entity.type.projectile; - -import net.minestom.server.entity.Entity; -import net.minestom.server.entity.EntityType; -import net.minestom.server.entity.Metadata; -import net.minestom.server.entity.metadata.arrow.ArrowMeta; -import net.minestom.server.utils.Position; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class EntityArrow extends EntityAbstractArrow { - - public EntityArrow(@Nullable Entity shooter, @NotNull Position spawnPosition) { - super(shooter, EntityType.ARROW, spawnPosition); - ((ArrowMeta) getEntityMeta()).setShooter(shooter); - } - -} diff --git a/src/main/java/net/minestom/server/entity/type/projectile/EntityEyeOfEnder.java b/src/main/java/net/minestom/server/entity/type/projectile/EntityEyeOfEnder.java index 609a87377..ae9f28c5c 100644 --- a/src/main/java/net/minestom/server/entity/type/projectile/EntityEyeOfEnder.java +++ b/src/main/java/net/minestom/server/entity/type/projectile/EntityEyeOfEnder.java @@ -13,10 +13,10 @@ import org.jetbrains.annotations.Nullable; * @deprecated Use {@link net.minestom.server.entity.metadata.item.EyeOfEnderMeta} instead. */ @Deprecated -public class EntityEyeOfEnder extends AbstractProjectile { +public class EntityEyeOfEnder extends Entity { public EntityEyeOfEnder(@Nullable Entity shooter, @NotNull Position spawnPosition) { - super(shooter, EntityType.EYE_OF_ENDER, spawnPosition); + super(EntityType.EYE_OF_ENDER, spawnPosition); } diff --git a/src/main/java/net/minestom/server/entity/type/projectile/EntityPotion.java b/src/main/java/net/minestom/server/entity/type/projectile/EntityPotion.java index f7b9f17de..c42ec9b97 100644 --- a/src/main/java/net/minestom/server/entity/type/projectile/EntityPotion.java +++ b/src/main/java/net/minestom/server/entity/type/projectile/EntityPotion.java @@ -12,10 +12,10 @@ import org.jetbrains.annotations.Nullable; * @deprecated Use {@link net.minestom.server.entity.metadata.item.ThrownPotionMeta} instead. */ @Deprecated -public class EntityPotion extends AbstractProjectile { +public class EntityPotion extends Entity { public EntityPotion(@Nullable Entity shooter, @NotNull Position spawnPosition, @NotNull ItemStack potion) { - super(shooter, EntityType.POTION, spawnPosition); + super(EntityType.POTION, spawnPosition); setBoundingBox(0.25f, 0.25f, 0.25f); setPotion(potion); } diff --git a/src/main/java/net/minestom/server/entity/type/projectile/EntityAbstractArrow.java b/src/main/java/net/minestom/server/entity/type/projectile/EntityProjectile.java similarity index 59% rename from src/main/java/net/minestom/server/entity/type/projectile/EntityAbstractArrow.java rename to src/main/java/net/minestom/server/entity/type/projectile/EntityProjectile.java index bab55e201..4235f73dc 100644 --- a/src/main/java/net/minestom/server/entity/type/projectile/EntityAbstractArrow.java +++ b/src/main/java/net/minestom/server/entity/type/projectile/EntityProjectile.java @@ -3,8 +3,9 @@ package net.minestom.server.entity.type.projectile; import net.minestom.server.entity.Entity; import net.minestom.server.entity.EntityType; import net.minestom.server.entity.LivingEntity; -import net.minestom.server.entity.Metadata; +import net.minestom.server.entity.metadata.ProjectileMeta; import net.minestom.server.event.entity.EntityAttackEvent; +import net.minestom.server.event.entity.EntityShootEvent; import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; @@ -16,17 +17,94 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Optional; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; -public class EntityAbstractArrow extends AbstractProjectile { +/** + * Class that allows to instantiate entities with projectile-like physics handling. + */ +public class EntityProjectile extends Entity { - EntityAbstractArrow(@Nullable Entity shooter, @NotNull EntityType entityType, @NotNull Position spawnPosition) { - super(shooter, entityType, spawnPosition); + private final Entity shooter; + + public EntityProjectile(@Nullable Entity shooter, @NotNull EntityType entityType) { + super(entityType); + this.shooter = shooter; + } + + @Deprecated + public EntityProjectile(@Nullable Entity shooter, @NotNull EntityType entityType, @NotNull Position spawnPosition) { + super(entityType, spawnPosition); + this.shooter = shooter; + } + + private void setup() { super.hasPhysics = false; - + if (getEntityMeta() instanceof ProjectileMeta) { + ((ProjectileMeta) getEntityMeta()).setShooter(this.shooter); + } setBoundingBox(.5F, .5F, .5F); } + @Nullable + public Entity getShooter() { + return this.shooter; + } + + /** + * Called when this projectile is stuck in blocks. + * Probably you want to do nothing with arrows in such case and to remove other types of projectiles. + */ + public void onStuck() { + + } + + /** + * Called when this projectile unstucks. + * Probably you want to add some random velocity to arrows in such case. + */ + public void onUnstuck() { + + } + + public void shoot(Position to, double power, double spread) { + EntityShootEvent event = new EntityShootEvent(this.shooter, this, to, power, spread); + this.shooter.callEvent(EntityShootEvent.class, event); + if (event.isCancelled()) { + remove(); + return; + } + Position from = this.shooter.getPosition().clone().add(0D, this.shooter.getEyeHeight(), 0D); + shoot(from, to, event.getPower(), event.getSpread()); + } + + private void shoot(@NotNull Position from, @NotNull Position to, double power, double spread) { + double dx = to.getX() - from.getX(); + double dy = to.getY() - from.getY(); + double dz = to.getZ() - from.getZ(); + double xzLength = Math.sqrt(dx * dx + dz * dz); + dy += xzLength * 0.20000000298023224D; + + double length = Math.sqrt(dx * dx + dy * dy + dz * dz); + dx /= length; + dy /= length; + dz /= length; + Random random = ThreadLocalRandom.current(); + spread *= 0.007499999832361937D; + dx += random.nextGaussian() * spread; + dy += random.nextGaussian() * spread; + dz += random.nextGaussian() * spread; + super.velocity.setX(dx); + super.velocity.setY(dy); + super.velocity.setZ(dz); + super.velocity.multiply(20 * power); + setView( + (float) Math.toDegrees(Math.atan2(dx, dz)), + (float) Math.toDegrees(Math.atan2(dy, Math.sqrt(dx * dx + dz * dz))) + ); + } + @Override public void tick(long time) { Position posBefore = getPosition().clone(); @@ -40,12 +118,14 @@ public class EntityAbstractArrow extends AbstractProjectile { getVelocity().zero(); sendPacketToViewersAndSelf(getVelocityPacket()); setNoGravity(true); + onStuck(); } else { if (!super.onGround) { return; } super.onGround = false; setNoGravity(false); + onUnstuck(); } } diff --git a/src/main/java/net/minestom/server/entity/type/projectile/EntitySpectralArrow.java b/src/main/java/net/minestom/server/entity/type/projectile/EntitySpectralArrow.java deleted file mode 100644 index 21b958d41..000000000 --- a/src/main/java/net/minestom/server/entity/type/projectile/EntitySpectralArrow.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.minestom.server.entity.type.projectile; - -import net.minestom.server.entity.Entity; -import net.minestom.server.entity.EntityType; -import net.minestom.server.entity.metadata.arrow.SpectralArrowMeta; -import net.minestom.server.utils.Position; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class EntitySpectralArrow extends EntityAbstractArrow { - - public EntitySpectralArrow(@Nullable Entity shooter, @NotNull Position spawnPosition) { - super(shooter, EntityType.SPECTRAL_ARROW, spawnPosition); - ((SpectralArrowMeta) getEntityMeta()).setShooter(shooter); - } - -} diff --git a/src/main/java/net/minestom/server/event/entity/EntityShootEvent.java b/src/main/java/net/minestom/server/event/entity/EntityShootEvent.java index b3110a28b..7ca2df360 100644 --- a/src/main/java/net/minestom/server/event/entity/EntityShootEvent.java +++ b/src/main/java/net/minestom/server/event/entity/EntityShootEvent.java @@ -1,25 +1,24 @@ package net.minestom.server.event.entity; import net.minestom.server.entity.Entity; -import net.minestom.server.entity.type.Projectile; import net.minestom.server.event.CancellableEvent; import net.minestom.server.event.EntityEvent; import net.minestom.server.utils.Position; import org.jetbrains.annotations.NotNull; /** - * Called with {@link Projectile#shoot(Projectile, Entity, Position, double, double)}. + * Called with {@link net.minestom.server.entity.type.projectile.EntityProjectile#shoot(Position, double, double)} */ public class EntityShootEvent extends EntityEvent implements CancellableEvent { - private final Projectile projectile; + private final Entity projectile; private final Position to; private double power; private double spread; private boolean cancelled; - public EntityShootEvent(@NotNull Entity entity, @NotNull Projectile projectile, @NotNull Position to, double power, double spread) { + public EntityShootEvent(@NotNull Entity entity, @NotNull Entity projectile, @NotNull Position to, double power, double spread) { super(entity); this.projectile = projectile; this.to = to; @@ -32,7 +31,7 @@ public class EntityShootEvent extends EntityEvent implements CancellableEvent { * * @return the projectile. */ - public Projectile getProjectile() { + public Entity getProjectile() { return this.projectile; } diff --git a/src/test/java/demo/commands/ShootCommand.java b/src/test/java/demo/commands/ShootCommand.java index 60950889b..071295f49 100644 --- a/src/test/java/demo/commands/ShootCommand.java +++ b/src/test/java/demo/commands/ShootCommand.java @@ -5,12 +5,10 @@ import net.minestom.server.command.builder.Arguments; import net.minestom.server.command.builder.Command; import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.exception.ArgumentSyntaxException; -import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; import net.minestom.server.entity.Player; import net.minestom.server.entity.metadata.arrow.ArrowMeta; -import net.minestom.server.entity.type.Projectile; -import net.minestom.server.entity.type.projectile.EntityArrow; -import net.minestom.server.entity.type.projectile.EntitySpectralArrow; +import net.minestom.server.entity.type.projectile.EntityProjectile; import java.util.concurrent.ThreadLocalRandom; @@ -42,28 +40,28 @@ public class ShootCommand extends Command { } private void onShootCommand(CommandSender sender, Arguments args) { - Player player = (Player) sender; - String mode = args.getWord("type"); - Projectile projectile; - var pos = player.getPosition().clone().add(0D, player.getEyeHeight(), 0D); + Player player = (Player) sender; + String mode = args.getWord("type"); + EntityProjectile projectile; switch (mode) { case "default": - projectile = new EntityArrow(player, pos); + projectile = new EntityProjectile(player, EntityType.ARROW); break; case "spectral": - projectile = new EntitySpectralArrow(player, pos); + projectile = new EntityProjectile(player, EntityType.SPECTRAL_ARROW); break; case "colored": - projectile = new EntityArrow(player, pos); - var meta = (ArrowMeta) ((Entity) projectile).getEntityMeta(); + projectile = new EntityProjectile(player, EntityType.ARROW); + var meta = (ArrowMeta) projectile.getEntityMeta(); meta.setColor(ThreadLocalRandom.current().nextInt()); break; default: return; } - ((Entity) projectile).setInstance(player.getInstance()); + var pos = player.getPosition().clone().add(0D, player.getEyeHeight(), 0D); + projectile.setInstance(player.getInstance(), pos); var dir = pos.getDirection().multiply(30D); pos = pos.clone().add(dir.getX(), dir.getY(), dir.getZ()); - Projectile.shoot(projectile, player, pos, 1D, 0D); + projectile.shoot(pos, 1D, 0D); } }