From 8fc133212d7b5cdc4bb2d1b495b7d44c589bed5b Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Sun, 29 Sep 2024 10:29:39 +1000 Subject: [PATCH] SPIGOT-7910: Fix launching breeze wind charge from API and improve dispenser launch API By: md_5 --- .../craftbukkit/entity/CraftLivingEntity.java | 16 ++- .../CraftBlockProjectileSource.java | 123 +++++++++--------- 2 files changed, 69 insertions(+), 70 deletions(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index 586d0a6d27..5f48235b40 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -58,7 +58,9 @@ import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.potion.CraftPotionEffectType; import org.bukkit.entity.AbstractArrow; +import org.bukkit.entity.AbstractWindCharge; import org.bukkit.entity.Arrow; +import org.bukkit.entity.BreezeWindCharge; import org.bukkit.entity.DragonFireball; import org.bukkit.entity.Egg; import org.bukkit.entity.EnderPearl; @@ -81,7 +83,6 @@ import org.bukkit.entity.ThrownExpBottle; import org.bukkit.entity.ThrownPotion; import org.bukkit.entity.TippedArrow; import org.bukkit.entity.Trident; -import org.bukkit.entity.WindCharge; import org.bukkit.entity.WitherSkull; import org.bukkit.entity.memory.MemoryKey; import org.bukkit.event.entity.EntityPotionEffectEvent; @@ -498,10 +499,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { launch = new EntityWitherSkull(world, getHandle(), vec); } else if (DragonFireball.class.isAssignableFrom(projectile)) { launch = new EntityDragonFireball(world, getHandle(), vec); - } else if (WindCharge.class.isAssignableFrom(projectile)) { - launch = EntityTypes.WIND_CHARGE.create(world); - ((net.minecraft.world.entity.projectile.windcharge.WindCharge) launch).setOwner(getHandle()); - ((net.minecraft.world.entity.projectile.windcharge.WindCharge) launch).assignDirectionalMovement(vec, 0.1D); + } else if (AbstractWindCharge.class.isAssignableFrom(projectile)) { + if (BreezeWindCharge.class.isAssignableFrom(projectile)) { + launch = EntityTypes.BREEZE_WIND_CHARGE.create(world); + } else { + launch = EntityTypes.WIND_CHARGE.create(world); + } + + ((net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge) launch).setOwner(getHandle()); + ((net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge) launch).shootFromRotation(getHandle(), getHandle().getXRot(), getHandle().getYRot(), 0.0F, 1.5F, 1.0F); // WindChargeItem } else { launch = new EntityLargeFireball(world, getHandle(), vec, 1); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java b/paper-server/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java index f7d387d899..3c35b3f8fb 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java @@ -8,39 +8,33 @@ import net.minecraft.server.level.WorldServer; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.entity.projectile.EntityArrow; -import net.minecraft.world.entity.projectile.EntityEgg; -import net.minecraft.world.entity.projectile.EntityEnderPearl; import net.minecraft.world.entity.projectile.EntityFireball; -import net.minecraft.world.entity.projectile.EntityPotion; -import net.minecraft.world.entity.projectile.EntityProjectile; -import net.minecraft.world.entity.projectile.EntitySmallFireball; -import net.minecraft.world.entity.projectile.EntitySnowball; -import net.minecraft.world.entity.projectile.EntitySpectralArrow; -import net.minecraft.world.entity.projectile.EntityThrownExpBottle; -import net.minecraft.world.entity.projectile.EntityTippedArrow; import net.minecraft.world.entity.projectile.IProjectile; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.ProjectileItem; import net.minecraft.world.level.block.BlockDispenser; import net.minecraft.world.level.block.entity.TileEntityDispenser; import net.minecraft.world.phys.Vec3D; import org.bukkit.Material; import org.bukkit.block.Block; -import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.AbstractArrow; -import org.bukkit.entity.Arrow; +import org.bukkit.entity.AbstractWindCharge; +import org.bukkit.entity.BreezeWindCharge; +import org.bukkit.entity.DragonFireball; import org.bukkit.entity.Egg; import org.bukkit.entity.EnderPearl; import org.bukkit.entity.Fireball; +import org.bukkit.entity.Firework; +import org.bukkit.entity.LargeFireball; import org.bukkit.entity.LingeringPotion; import org.bukkit.entity.Projectile; -import org.bukkit.entity.SmallFireball; import org.bukkit.entity.Snowball; import org.bukkit.entity.SpectralArrow; import org.bukkit.entity.ThrownExpBottle; import org.bukkit.entity.ThrownPotion; import org.bukkit.entity.TippedArrow; import org.bukkit.entity.WitherSkull; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionType; import org.bukkit.projectiles.BlockProjectileSource; import org.bukkit.util.Vector; @@ -67,83 +61,82 @@ public class CraftBlockProjectileSource implements BlockProjectileSource { // Copied from BlockDispenser.dispense() SourceBlock sourceblock = new SourceBlock((WorldServer) dispenserBlock.getLevel(), dispenserBlock.getBlockPos(), dispenserBlock.getBlockState(), dispenserBlock); // Copied from DispenseBehaviorProjectile - IPosition iposition = BlockDispenser.getDispensePosition(sourceblock); EnumDirection enumdirection = (EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING); net.minecraft.world.level.World world = dispenserBlock.getLevel(); - net.minecraft.world.entity.Entity launch = null; + net.minecraft.world.item.Item item = null; if (Snowball.class.isAssignableFrom(projectile)) { - launch = new EntitySnowball(world, iposition.x(), iposition.y(), iposition.z()); + item = Items.SNOWBALL; } else if (Egg.class.isAssignableFrom(projectile)) { - launch = new EntityEgg(world, iposition.x(), iposition.y(), iposition.z()); + item = Items.EGG; } else if (EnderPearl.class.isAssignableFrom(projectile)) { - launch = new EntityEnderPearl(world, null); - launch.setPos(iposition.x(), iposition.y(), iposition.z()); + item = Items.ENDER_PEARL; } else if (ThrownExpBottle.class.isAssignableFrom(projectile)) { - launch = new EntityThrownExpBottle(world, iposition.x(), iposition.y(), iposition.z()); + item = Items.EXPERIENCE_BOTTLE; } else if (ThrownPotion.class.isAssignableFrom(projectile)) { if (LingeringPotion.class.isAssignableFrom(projectile)) { - launch = new EntityPotion(world, iposition.x(), iposition.y(), iposition.z()); - ((EntityPotion) launch).setItem(CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.LINGERING_POTION, 1))); + item = Items.LINGERING_POTION; } else { - launch = new EntityPotion(world, iposition.x(), iposition.y(), iposition.z()); - ((EntityPotion) launch).setItem(CraftItemStack.asNMSCopy(new ItemStack(org.bukkit.Material.SPLASH_POTION, 1))); + item = Items.SPLASH_POTION; } } else if (AbstractArrow.class.isAssignableFrom(projectile)) { if (TippedArrow.class.isAssignableFrom(projectile)) { - launch = new EntityTippedArrow(world, iposition.x(), iposition.y(), iposition.z(), new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ARROW), null); - ((Arrow) launch.getBukkitEntity()).setBasePotionType(PotionType.WATER); + item = Items.TIPPED_ARROW; } else if (SpectralArrow.class.isAssignableFrom(projectile)) { - launch = new EntitySpectralArrow(world, iposition.x(), iposition.y(), iposition.z(), new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.SPECTRAL_ARROW), null); + item = Items.SPECTRAL_ARROW; } else { - launch = new EntityTippedArrow(world, iposition.x(), iposition.y(), iposition.z(), new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ARROW), null); + item = Items.ARROW; } - ((EntityArrow) launch).pickup = EntityArrow.PickupStatus.ALLOWED; - ((EntityArrow) launch).projectileSource = this; } else if (Fireball.class.isAssignableFrom(projectile)) { - double d0 = iposition.x() + (double) ((float) enumdirection.getStepX() * 0.3F); - double d1 = iposition.y() + (double) ((float) enumdirection.getStepY() * 0.3F); - double d2 = iposition.z() + (double) ((float) enumdirection.getStepZ() * 0.3F); - RandomSource random = world.random; - double d3 = random.nextGaussian() * 0.05D + (double) enumdirection.getStepX(); - double d4 = random.nextGaussian() * 0.05D + (double) enumdirection.getStepY(); - double d5 = random.nextGaussian() * 0.05D + (double) enumdirection.getStepZ(); - - if (SmallFireball.class.isAssignableFrom(projectile)) { - launch = new EntitySmallFireball(world, null, new Vec3D(d0, d1, d2)); - } else if (WitherSkull.class.isAssignableFrom(projectile)) { - launch = EntityTypes.WITHER_SKULL.create(world); - launch.setPos(d0, d1, d2); - - ((EntityFireball) launch).assignDirectionalMovement(new Vec3D(d3, d4, d5), 0.1D); + if (AbstractWindCharge.class.isAssignableFrom(projectile)) { + item = Items.WIND_CHARGE; } else { - launch = EntityTypes.FIREBALL.create(world); - launch.setPos(d0, d1, d2); - - ((EntityFireball) launch).assignDirectionalMovement(new Vec3D(d3, d4, d5), 0.1D); + item = Items.FIRE_CHARGE; } - - ((EntityFireball) launch).projectileSource = this; + } else if (Firework.class.isAssignableFrom(projectile)) { + item = Items.FIREWORK_ROCKET; } - Preconditions.checkArgument(launch != null, "Projectile not supported"); + Preconditions.checkArgument(item instanceof ProjectileItem, "Projectile not supported"); - if (launch instanceof IProjectile) { - if (launch instanceof EntityProjectile) { - ((EntityProjectile) launch).projectileSource = this; + ItemStack itemstack = new ItemStack(item); + ProjectileItem projectileItem = (ProjectileItem) item; + ProjectileItem.a dispenseConfig = projectileItem.createDispenseConfig(); + + IPosition iposition = dispenseConfig.positionFunction().getDispensePosition(sourceblock, enumdirection); + IProjectile launch = projectileItem.asProjectile(world, iposition, itemstack, enumdirection); + + if (Fireball.class.isAssignableFrom(projectile)) { + EntityFireball customFireball = null; + if (WitherSkull.class.isAssignableFrom(projectile)) { + launch = customFireball = EntityTypes.WITHER_SKULL.create(world); + } else if (DragonFireball.class.isAssignableFrom(projectile)) { + launch = EntityTypes.DRAGON_FIREBALL.create(world); + } else if (BreezeWindCharge.class.isAssignableFrom(projectile)) { + launch = customFireball = EntityTypes.BREEZE_WIND_CHARGE.create(world); + } else if (LargeFireball.class.isAssignableFrom(projectile)) { + launch = customFireball = EntityTypes.FIREBALL.create(world); } - // Values from DispenseBehaviorProjectile - float a = 6.0F; - float b = 1.1F; - if (launch instanceof EntityPotion || launch instanceof ThrownExpBottle) { - // Values from respective DispenseBehavior classes - a *= 0.5F; - b *= 1.25F; + + if (customFireball != null) { + customFireball.setPos(iposition.x(), iposition.y(), iposition.z()); + + // Values from ItemFireball + RandomSource randomsource = world.getRandom(); + double d0 = randomsource.triangle((double) enumdirection.getStepX(), 0.11485000000000001D); + double d1 = randomsource.triangle((double) enumdirection.getStepY(), 0.11485000000000001D); + double d2 = randomsource.triangle((double) enumdirection.getStepZ(), 0.11485000000000001D); + Vec3D vec3d = new Vec3D(d0, d1, d2); + customFireball.assignDirectionalMovement(vec3d, 0.1D); } - // Copied from DispenseBehaviorProjectile - ((IProjectile) launch).shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), b, a); } + if (launch instanceof EntityArrow arrow) { + arrow.pickup = EntityArrow.PickupStatus.ALLOWED; + } + launch.projectileSource = this; + projectileItem.shoot(launch, (double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), dispenseConfig.power(), dispenseConfig.uncertainty()); + if (velocity != null) { ((T) launch.getBukkitEntity()).setVelocity(velocity); }