SPIGOT-7910: Fix launching breeze wind charge from API and improve dispenser launch API

By: md_5 <git@md-5.net>
This commit is contained in:
CraftBukkit/Spigot 2024-09-29 10:29:39 +10:00
parent 08fdfd6434
commit 8fc133212d
2 changed files with 69 additions and 70 deletions

View File

@ -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);
}

View File

@ -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);
}