More Projectile API
== AT == public net.minecraft.world.entity.projectile.FishingHook timeUntilLured public net.minecraft.world.entity.projectile.FishingHook fishAngle public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaX public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaY public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaZ public net.minecraft.world.entity.projectile.ShulkerBullet currentMoveDirection public net.minecraft.world.entity.projectile.ShulkerBullet flightSteps public net.minecraft.world.entity.projectile.AbstractArrow soundEvent public net.minecraft.world.entity.projectile.AbstractArrow setPickupItemStack(Lnet/minecraft/world/item/ItemStack;)V public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage public net.minecraft.world.entity.projectile.Arrow NO_EFFECT_COLOR public net.minecraft.world.entity.projectile.Projectile hasBeenShot public net.minecraft.world.entity.projectile.Projectile leftOwner public net.minecraft.world.entity.projectile.Projectile ownerUUID public net.minecraft.world.entity.projectile.Projectile preOnHit(Lnet/minecraft/world/phys/HitResult;)V public net.minecraft.world.entity.projectile.Projectile canHitEntity(Lnet/minecraft/world/entity/Entity;)Z public net.minecraft.world.entity.projectile.FireworkRocketEntity getDefaultItem()Lnet/minecraft/world/item/ItemStack; public net.minecraft.world.item.CrossbowItem FIREWORK_POWER Co-authored-by: Nassim Jahnke <nassim@njahnke.dev> Co-authored-by: SoSeDiK <mrsosedik@gmail.com> Co-authored-by: MelnCat <melncatuwu@gmail.com> Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
This commit is contained in:
@@ -22,11 +22,10 @@
|
|||||||
public class FishingHook extends Projectile {
|
public class FishingHook extends Projectile {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogUtils.getLogger();
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
@@ -67,6 +73,18 @@
|
@@ -68,6 +74,18 @@
|
||||||
public FishingHook.FishHookState currentState;
|
|
||||||
private final int luck;
|
private final int luck;
|
||||||
private final int lureSpeed;
|
private final int lureSpeed;
|
||||||
+
|
|
||||||
+ // CraftBukkit start - Extra variables to enable modification of fishing wait time, values are minecraft defaults
|
+ // CraftBukkit start - Extra variables to enable modification of fishing wait time, values are minecraft defaults
|
||||||
+ public int minWaitTime = 100;
|
+ public int minWaitTime = 100;
|
||||||
+ public int maxWaitTime = 600;
|
+ public int maxWaitTime = 600;
|
||||||
@@ -38,9 +37,10 @@
|
|||||||
+ public boolean rainInfluenced = true;
|
+ public boolean rainInfluenced = true;
|
||||||
+ public boolean skyInfluenced = true;
|
+ public boolean skyInfluenced = true;
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
|
+
|
||||||
private FishingHook(EntityType<? extends FishingHook> type, Level world, int luckBonus, int waitTimeReductionTicks) {
|
private FishingHook(EntityType<? extends FishingHook> type, Level world, int luckBonus, int waitTimeReductionTicks) {
|
||||||
super(type, world);
|
super(type, world);
|
||||||
|
this.syncronizedRandom = RandomSource.create();
|
||||||
@@ -75,13 +93,17 @@
|
@@ -75,13 +93,17 @@
|
||||||
this.currentState = FishingHook.FishHookState.FLYING;
|
this.currentState = FishingHook.FishHookState.FLYING;
|
||||||
this.luck = Math.max(0, luckBonus);
|
this.luck = Math.max(0, luckBonus);
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
this.playSound(SoundEvents.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F);
|
this.playSound(SoundEvents.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F);
|
||||||
double d3 = this.getY() + 0.5D;
|
double d3 = this.getY() + 0.5D;
|
||||||
|
|
||||||
@@ -379,12 +412,16 @@
|
@@ -379,16 +412,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.timeUntilLured <= 0) {
|
if (this.timeUntilLured <= 0) {
|
||||||
@@ -160,13 +160,22 @@
|
|||||||
- this.timeUntilLured = Mth.nextInt(this.random, 100, 600);
|
- this.timeUntilLured = Mth.nextInt(this.random, 100, 600);
|
||||||
- this.timeUntilLured -= this.lureSpeed;
|
- this.timeUntilLured -= this.lureSpeed;
|
||||||
+ // CraftBukkit start - logic to modify fishing wait time
|
+ // CraftBukkit start - logic to modify fishing wait time
|
||||||
+ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
|
+ this.resetTimeUntilLured(); // Paper - more projectile api - extract time until lured reset logic
|
||||||
+ this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed ) : 0; // Paper - Fix Lure infinite loop
|
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,12 +483,20 @@
|
}
|
||||||
|
+ // Paper start - more projectile api - extract time until lured reset logic
|
||||||
|
+ public void resetTimeUntilLured() {
|
||||||
|
+ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime);
|
||||||
|
+ this.timeUntilLured -= (this.applyLure) ? (this.lureSpeed >= this.maxWaitTime ? this.timeUntilLured - 1 : this.lureSpeed ) : 0; // Paper - Fix Lure infinite loop
|
||||||
|
+ }
|
||||||
|
+ // Paper end - more projectile api - extract time until lured reset logic
|
||||||
|
|
||||||
|
public boolean calculateOpenWater(BlockPos pos) {
|
||||||
|
FishingHook.OpenWaterType entityfishinghook_waterposition = FishingHook.OpenWaterType.INVALID;
|
||||||
|
@@ -446,12 +488,20 @@
|
||||||
public void readAdditionalSaveData(CompoundTag nbt) {}
|
public void readAdditionalSaveData(CompoundTag nbt) {}
|
||||||
|
|
||||||
public int retrieve(ItemStack usedItem) {
|
public int retrieve(ItemStack usedItem) {
|
||||||
@@ -188,7 +197,7 @@
|
|||||||
this.pullEntity(this.hookedIn);
|
this.pullEntity(this.hookedIn);
|
||||||
CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, usedItem, this, Collections.emptyList());
|
CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, usedItem, this, Collections.emptyList());
|
||||||
this.level().broadcastEntityEvent(this, (byte) 31);
|
this.level().broadcastEntityEvent(this, (byte) 31);
|
||||||
@@ -466,15 +511,38 @@
|
@@ -466,15 +516,38 @@
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
ItemStack itemstack1 = (ItemStack) iterator.next();
|
ItemStack itemstack1 = (ItemStack) iterator.next();
|
||||||
@@ -231,7 +240,7 @@
|
|||||||
if (itemstack1.is(ItemTags.FISHES)) {
|
if (itemstack1.is(ItemTags.FISHES)) {
|
||||||
entityhuman.awardStat(Stats.FISH_CAUGHT, 1);
|
entityhuman.awardStat(Stats.FISH_CAUGHT, 1);
|
||||||
}
|
}
|
||||||
@@ -484,10 +552,27 @@
|
@@ -484,10 +557,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.onGround()) {
|
if (this.onGround()) {
|
||||||
@@ -260,7 +269,7 @@
|
|||||||
return i;
|
return i;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -496,7 +581,7 @@
|
@@ -496,7 +586,7 @@
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleEntityEvent(byte status) {
|
public void handleEntityEvent(byte status) {
|
||||||
@@ -269,7 +278,7 @@
|
|||||||
this.pullEntity(this.hookedIn);
|
this.pullEntity(this.hookedIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,8 +605,15 @@
|
@@ -520,8 +610,15 @@
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(Entity.RemovalReason reason) {
|
public void remove(Entity.RemovalReason reason) {
|
||||||
@@ -286,7 +295,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -536,7 +628,7 @@
|
@@ -536,7 +633,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOwnerInfo(@Nullable FishingHook fishingBobber) {
|
private void updateOwnerInfo(@Nullable FishingHook fishingBobber) {
|
||||||
@@ -295,7 +304,7 @@
|
|||||||
|
|
||||||
if (entityhuman != null) {
|
if (entityhuman != null) {
|
||||||
entityhuman.fishing = fishingBobber;
|
entityhuman.fishing = fishingBobber;
|
||||||
@@ -545,10 +637,10 @@
|
@@ -545,10 +642,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -308,7 +317,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -575,7 +667,7 @@
|
@@ -575,7 +672,7 @@
|
||||||
int i = packet.getData();
|
int i = packet.getData();
|
||||||
|
|
||||||
FishingHook.LOGGER.error("Failed to recreate fishing hook on client. {} (id: {}) is not a valid owner.", this.level().getEntity(i), i);
|
FishingHook.LOGGER.error("Failed to recreate fishing hook on client. {} (id: {}) is not a valid owner.", this.level().getEntity(i), i);
|
||||||
|
|||||||
@@ -122,7 +122,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ // CraftBukkit start - call projectile hit event
|
+ // CraftBukkit start - call projectile hit event
|
||||||
+ protected ProjectileDeflection preHitTargetOrDeflectSelf(HitResult movingobjectposition) {
|
+ public ProjectileDeflection preHitTargetOrDeflectSelf(HitResult movingobjectposition) { // Paper - protected -> public
|
||||||
+ org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition);
|
+ org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition);
|
||||||
+ this.hitCancelled = event != null && event.isCancelled();
|
+ this.hitCancelled = event != null && event.isCancelled();
|
||||||
+ if (movingobjectposition.getType() == HitResult.Type.BLOCK || !this.hitCancelled) {
|
+ if (movingobjectposition.getType() == HitResult.Type.BLOCK || !this.hitCancelled) {
|
||||||
|
|||||||
@@ -55,7 +55,18 @@
|
|||||||
super(EntityType.POTION, owner, world, stack);
|
super(EntityType.POTION, owner, world, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,64 +109,86 @@
|
@@ -93,70 +103,96 @@
|
||||||
|
@Override
|
||||||
|
protected void onHit(HitResult hitResult) {
|
||||||
|
super.onHit(hitResult);
|
||||||
|
+ // Paper start - More projectile API
|
||||||
|
+ this.splash(hitResult);
|
||||||
|
+ }
|
||||||
|
+ public void splash(@Nullable HitResult hitResult) {
|
||||||
|
+ // Paper end - More projectile API
|
||||||
|
Level world = this.level();
|
||||||
|
-
|
||||||
|
if (world instanceof ServerLevel worldserver) {
|
||||||
ItemStack itemstack = this.getItem();
|
ItemStack itemstack = this.getItem();
|
||||||
PotionContents potioncontents = (PotionContents) itemstack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
|
PotionContents potioncontents = (PotionContents) itemstack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
|
||||||
|
|
||||||
@@ -70,7 +81,7 @@
|
|||||||
+ showParticles = this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
|
+ showParticles = this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
|
||||||
} else {
|
} else {
|
||||||
- this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null);
|
- this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null);
|
||||||
+ showParticles = this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
|
+ showParticles = this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult != null && hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +157,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- private void applySplash(ServerLevel world, Iterable<MobEffectInstance> effects, @Nullable Entity entity) {
|
- private void applySplash(ServerLevel world, Iterable<MobEffectInstance> effects, @Nullable Entity entity) {
|
||||||
+ private boolean applySplash(ServerLevel worldserver, Iterable<MobEffectInstance> iterable, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events
|
+ private boolean applySplash(ServerLevel worldserver, Iterable<MobEffectInstance> iterable, @Nullable Entity entity, @Nullable HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events & More projectile API
|
||||||
AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
|
AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
|
||||||
- List<LivingEntity> list = world.getEntitiesOfClass(LivingEntity.class, axisalignedbb);
|
- List<LivingEntity> list = world.getEntitiesOfClass(LivingEntity.class, axisalignedbb);
|
||||||
+ List<net.minecraft.world.entity.LivingEntity> list = worldserver.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb);
|
+ List<net.minecraft.world.entity.LivingEntity> list = worldserver.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb);
|
||||||
@@ -162,7 +173,7 @@
|
|||||||
|
|
||||||
if (entityliving.isAffectedByPotions()) {
|
if (entityliving.isAffectedByPotions()) {
|
||||||
double d0 = this.distanceToSqr((Entity) entityliving);
|
double d0 = this.distanceToSqr((Entity) entityliving);
|
||||||
@@ -164,43 +196,71 @@
|
@@ -164,43 +200,71 @@
|
||||||
if (d0 < 16.0D) {
|
if (d0 < 16.0D) {
|
||||||
double d1;
|
double d1;
|
||||||
|
|
||||||
@@ -242,7 +253,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- private void makeAreaOfEffectCloud(PotionContents potion) {
|
- private void makeAreaOfEffectCloud(PotionContents potion) {
|
||||||
+ private boolean makeAreaOfEffectCloud(PotionContents potioncontents, HitResult position) { // CraftBukkit - Pass MovingObjectPosition
|
+ private boolean makeAreaOfEffectCloud(PotionContents potioncontents, @Nullable HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - More projectile API
|
||||||
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
|
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
|
||||||
Entity entity = this.getOwner();
|
Entity entity = this.getOwner();
|
||||||
|
|
||||||
@@ -251,7 +262,7 @@
|
|||||||
entityareaeffectcloud.setOwner(entityliving);
|
entityareaeffectcloud.setOwner(entityliving);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,8 +268,17 @@
|
@@ -208,8 +272,17 @@
|
||||||
entityareaeffectcloud.setRadiusOnUse(-0.5F);
|
entityareaeffectcloud.setRadiusOnUse(-0.5F);
|
||||||
entityareaeffectcloud.setWaitTime(10);
|
entityareaeffectcloud.setWaitTime(10);
|
||||||
entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration());
|
entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration());
|
||||||
@@ -271,7 +282,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLingering() {
|
public boolean isLingering() {
|
||||||
@@ -220,19 +289,31 @@
|
@@ -220,19 +293,31 @@
|
||||||
BlockState iblockdata = this.level().getBlockState(pos);
|
BlockState iblockdata = this.level().getBlockState(pos);
|
||||||
|
|
||||||
if (iblockdata.is(BlockTags.FIRE)) {
|
if (iblockdata.is(BlockTags.FIRE)) {
|
||||||
|
|||||||
@@ -17,4 +17,65 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti
|
|||||||
@Override
|
@Override
|
||||||
public void setBounce(boolean doesBounce) {}
|
public void setBounce(boolean doesBounce) {}
|
||||||
|
|
||||||
|
// Paper start - More projectile API
|
||||||
|
@Override
|
||||||
|
public boolean hasLeftShooter() {
|
||||||
|
return this.getHandle().leftOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHasLeftShooter(boolean leftShooter) {
|
||||||
|
this.getHandle().leftOwner = leftShooter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasBeenShot() {
|
||||||
|
return this.getHandle().hasBeenShot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHasBeenShot(boolean beenShot) {
|
||||||
|
this.getHandle().hasBeenShot = beenShot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHitEntity(org.bukkit.entity.Entity entity) {
|
||||||
|
return this.getHandle().canHitEntity(((CraftEntity) entity).getHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hitEntity(org.bukkit.entity.Entity entity) {
|
||||||
|
this.getHandle().preHitTargetOrDeflectSelf(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hitEntity(org.bukkit.entity.Entity entity, org.bukkit.util.Vector vector) {
|
||||||
|
this.getHandle().preHitTargetOrDeflectSelf(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle(), new net.minecraft.world.phys.Vec3(vector.getX(), vector.getY(), vector.getZ())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public net.minecraft.world.entity.projectile.Projectile getHandle() {
|
||||||
|
return (net.minecraft.world.entity.projectile.Projectile) entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final org.bukkit.projectiles.ProjectileSource getShooter() {
|
||||||
|
return this.getHandle().projectileSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void setShooter(org.bukkit.projectiles.ProjectileSource shooter) {
|
||||||
|
if (shooter instanceof CraftEntity craftEntity) {
|
||||||
|
this.getHandle().setOwner(craftEntity.getHandle());
|
||||||
|
} else {
|
||||||
|
this.getHandle().setOwner(null);
|
||||||
|
}
|
||||||
|
this.getHandle().projectileSource = shooter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.util.UUID getOwnerUniqueId() {
|
||||||
|
return this.getHandle().ownerUUID;
|
||||||
|
}
|
||||||
|
// Paper end - More projectile API
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,20 +59,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
|
|||||||
this.getHandle().setCritArrow(critical);
|
this.getHandle().setCritArrow(critical);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Paper - moved to AbstractProjectile
|
||||||
public ProjectileSource getShooter() {
|
|
||||||
return this.getHandle().projectileSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setShooter(ProjectileSource shooter) {
|
|
||||||
if (shooter instanceof Entity) {
|
|
||||||
this.getHandle().setOwner(((CraftEntity) shooter).getHandle());
|
|
||||||
} else {
|
|
||||||
this.getHandle().setOwner(null);
|
|
||||||
}
|
|
||||||
this.getHandle().projectileSource = shooter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInBlock() {
|
public boolean isInBlock() {
|
||||||
@@ -133,6 +120,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getWeapon() {
|
public ItemStack getWeapon() {
|
||||||
|
if (this.getHandle().getWeaponItem() == null) return null; // Paper - fix NPE
|
||||||
return CraftItemStack.asBukkitCopy(this.getHandle().getWeaponItem());
|
return CraftItemStack.asBukkitCopy(this.getHandle().getWeaponItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,4 +140,37 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "CraftArrow";
|
return "CraftArrow";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paper start
|
||||||
|
@Override
|
||||||
|
public CraftItemStack getItemStack() {
|
||||||
|
return CraftItemStack.asCraftMirror(this.getHandle().getPickupItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItemStack(final ItemStack stack) {
|
||||||
|
Preconditions.checkArgument(stack != null, "ItemStack cannot be null");
|
||||||
|
this.getHandle().setPickupItemStack(CraftItemStack.asNMSCopy(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLifetimeTicks(int ticks) {
|
||||||
|
this.getHandle().life = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLifetimeTicks() {
|
||||||
|
return this.getHandle().life;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.bukkit.Sound getHitSound() {
|
||||||
|
return org.bukkit.craftbukkit.CraftSound.minecraftToBukkit(this.getHandle().soundEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHitSound(org.bukkit.Sound sound) {
|
||||||
|
this.getHandle().setSoundEvent(org.bukkit.craftbukkit.CraftSound.bukkitToMinecraft(sound));
|
||||||
|
}
|
||||||
|
// Paper end
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Color getColor() {
|
public Color getColor() {
|
||||||
return Color.fromRGB(this.getHandle().potionContents.getColor());
|
return Color.fromRGB(this.getHandle().potionContents.getColor() & 0x00FFFFFF); // Paper - skip alpha channel
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -143,7 +143,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
|
|||||||
this.removeCustomEffect(effect.getType());
|
this.removeCustomEffect(effect.getType());
|
||||||
}
|
}
|
||||||
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
|
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
|
||||||
this.getHandle().updateColor();
|
// this.getHandle().updateColor(); // Paper - already done above
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud
|
|||||||
public void clearCustomEffects() {
|
public void clearCustomEffects() {
|
||||||
PotionContents old = this.getHandle().potionContents;
|
PotionContents old = this.getHandle().potionContents;
|
||||||
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of(), old.customName()));
|
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of(), old.customName()));
|
||||||
this.getHandle().updateColor();
|
// this.getHandle().updateColor(); // Paper - already done above
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
|
|||||||
this.removeCustomEffect(effect.getType());
|
this.removeCustomEffect(effect.getType());
|
||||||
}
|
}
|
||||||
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
|
this.getHandle().addEffect(CraftPotionUtil.fromBukkit(effect));
|
||||||
this.getHandle().updateColor();
|
// this.getHandle().updateColor(); // Paper - already done above
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
|
|||||||
public void clearCustomEffects() {
|
public void clearCustomEffects() {
|
||||||
PotionContents old = this.getHandle().getPotionContents();
|
PotionContents old = this.getHandle().getPotionContents();
|
||||||
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of(), old.customName()));
|
this.getHandle().setPotionContents(new PotionContents(old.potion(), old.customColor(), List.of(), old.customName()));
|
||||||
this.getHandle().updateColor();
|
// this.getHandle().updateColor(); // Paper - already done above
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -117,16 +117,17 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setColor(Color color) {
|
public void setColor(Color color) {
|
||||||
int colorRGB = (color == null) ? -1 : color.asRGB();
|
int colorRGB = (color == null) ? net.minecraft.world.entity.projectile.Arrow.NO_EFFECT_COLOR : color.asARGB(); // Paper
|
||||||
PotionContents old = this.getHandle().getPotionContents();
|
PotionContents old = this.getHandle().getPotionContents();
|
||||||
this.getHandle().setPotionContents(new PotionContents(old.potion(), Optional.of(colorRGB), old.customEffects(), old.customName()));
|
this.getHandle().setPotionContents(new PotionContents(old.potion(), Optional.of(colorRGB), old.customEffects(), old.customName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Color getColor() {
|
public Color getColor() {
|
||||||
if (this.getHandle().getColor() <= -1) {
|
int color = this.getHandle().getColor(); // Paper
|
||||||
|
if (color == net.minecraft.world.entity.projectile.Arrow.NO_EFFECT_COLOR) { // Paper
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Color.fromRGB(this.getHandle().getColor());
|
return Color.fromARGB(color); // Paper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ public final class CraftEntityTypes {
|
|||||||
BlockPos pos = BlockPos.containing(spawnData.x(), spawnData.y(), spawnData.z());
|
BlockPos pos = BlockPos.containing(spawnData.x(), spawnData.y(), spawnData.z());
|
||||||
return new FallingBlockEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), spawnData.world().getBlockState(pos)); // Paper - create falling block entities correctly
|
return new FallingBlockEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), spawnData.world().getBlockState(pos)); // Paper - create falling block entities correctly
|
||||||
}));
|
}));
|
||||||
register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), net.minecraft.world.item.ItemStack.EMPTY)));
|
register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), FireworkRocketEntity.getDefaultItem()))); // Paper - pass correct default to rocket for data storage
|
||||||
register(new EntityTypeData<>(EntityType.EVOKER_FANGS, EvokerFangs.class, CraftEvokerFangs::new, spawnData -> new net.minecraft.world.entity.projectile.EvokerFangs(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), (float) Math.toRadians(spawnData.yaw()), 0, null)));
|
register(new EntityTypeData<>(EntityType.EVOKER_FANGS, EvokerFangs.class, CraftEvokerFangs::new, spawnData -> new net.minecraft.world.entity.projectile.EvokerFangs(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), (float) Math.toRadians(spawnData.yaw()), 0, null)));
|
||||||
register(new EntityTypeData<>(EntityType.COMMAND_BLOCK_MINECART, CommandMinecart.class, CraftMinecartCommand::new, createMinecart(net.minecraft.world.entity.EntityType.COMMAND_BLOCK_MINECART)));
|
register(new EntityTypeData<>(EntityType.COMMAND_BLOCK_MINECART, CommandMinecart.class, CraftMinecartCommand::new, createMinecart(net.minecraft.world.entity.EntityType.COMMAND_BLOCK_MINECART)));
|
||||||
register(new EntityTypeData<>(EntityType.MINECART, RideableMinecart.class, CraftMinecartRideable::new, createMinecart(net.minecraft.world.entity.EntityType.MINECART)));
|
register(new EntityTypeData<>(EntityType.MINECART, RideableMinecart.class, CraftMinecartRideable::new, createMinecart(net.minecraft.world.entity.EntityType.MINECART)));
|
||||||
|
|||||||
@@ -34,20 +34,7 @@ public class CraftFireball extends AbstractProjectile implements Fireball {
|
|||||||
this.getHandle().bukkitYield = yield;
|
this.getHandle().bukkitYield = yield;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Paper - moved to AbstractProjectile
|
||||||
public ProjectileSource getShooter() {
|
|
||||||
return this.getHandle().projectileSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setShooter(ProjectileSource shooter) {
|
|
||||||
if (shooter instanceof CraftLivingEntity) {
|
|
||||||
this.getHandle().setOwner(((CraftLivingEntity) shooter).getHandle());
|
|
||||||
} else {
|
|
||||||
this.getHandle().setOwner(null);
|
|
||||||
}
|
|
||||||
this.getHandle().projectileSource = shooter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector getDirection() {
|
public Vector getDirection() {
|
||||||
|
|||||||
@@ -15,24 +15,26 @@ import org.bukkit.inventory.meta.FireworkMeta;
|
|||||||
public class CraftFirework extends CraftProjectile implements Firework {
|
public class CraftFirework extends CraftProjectile implements Firework {
|
||||||
|
|
||||||
private final Random random = new Random();
|
private final Random random = new Random();
|
||||||
private final CraftItemStack item;
|
//private CraftItemStack item; // Paper - Remove usage, not accurate representation of current item.
|
||||||
|
|
||||||
public CraftFirework(CraftServer server, FireworkRocketEntity entity) {
|
public CraftFirework(CraftServer server, FireworkRocketEntity entity) {
|
||||||
super(server, entity);
|
super(server, entity);
|
||||||
|
|
||||||
ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
|
// Paper start - Expose firework item directly
|
||||||
|
// ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
|
||||||
if (item.isEmpty()) {
|
//
|
||||||
item = new ItemStack(Items.FIREWORK_ROCKET);
|
// if (item.isEmpty()) {
|
||||||
this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
// item = new ItemStack(Items.FIREWORK_ROCKET);
|
||||||
}
|
// this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
||||||
|
// }
|
||||||
this.item = CraftItemStack.asCraftMirror(item);
|
//
|
||||||
|
// this.item = CraftItemStack.asCraftMirror(item);
|
||||||
// Ensure the item is a firework...
|
//
|
||||||
if (this.item.getType() != Material.FIREWORK_ROCKET) {
|
// // Ensure the item is a firework...
|
||||||
this.item.setType(Material.FIREWORK_ROCKET);
|
// if (this.item.getType() != Material.FIREWORK_ROCKET) {
|
||||||
}
|
// this.item.setType(Material.FIREWORK_ROCKET);
|
||||||
|
// }
|
||||||
|
// Paper end - Expose firework item directly
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -47,12 +49,12 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FireworkMeta getFireworkMeta() {
|
public FireworkMeta getFireworkMeta() {
|
||||||
return (FireworkMeta) this.item.getItemMeta();
|
return (FireworkMeta) CraftItemStack.getItemMeta(this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM), org.bukkit.inventory.ItemType.FIREWORK_ROCKET); // Paper - Expose firework item directly
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFireworkMeta(FireworkMeta meta) {
|
public void setFireworkMeta(FireworkMeta meta) {
|
||||||
this.item.setItemMeta(meta);
|
applyFireworkEffect(meta); // Paper - Expose firework item directly
|
||||||
|
|
||||||
// Copied from EntityFireworks constructor, update firework lifetime/power
|
// Copied from EntityFireworks constructor, update firework lifetime/power
|
||||||
this.getHandle().lifetime = 10 * (1 + meta.getPower()) + this.random.nextInt(6) + this.random.nextInt(7);
|
this.getHandle().lifetime = 10 * (1 + meta.getPower()) + this.random.nextInt(6) + this.random.nextInt(7);
|
||||||
@@ -136,4 +138,46 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
|||||||
return getHandle().spawningEntity;
|
return getHandle().spawningEntity;
|
||||||
}
|
}
|
||||||
// Paper end
|
// Paper end
|
||||||
|
// Paper start - Expose firework item directly + manually setting flight
|
||||||
|
@Override
|
||||||
|
public org.bukkit.inventory.ItemStack getItem() {
|
||||||
|
return CraftItemStack.asBukkitCopy(this.getHandle().getItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setItem(org.bukkit.inventory.ItemStack itemStack) {
|
||||||
|
FireworkMeta meta = getFireworkMeta();
|
||||||
|
ItemStack nmsItem = itemStack == null ? FireworkRocketEntity.getDefaultItem() : CraftItemStack.asNMSCopy(itemStack);
|
||||||
|
this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, nmsItem);
|
||||||
|
|
||||||
|
applyFireworkEffect(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTicksFlown() {
|
||||||
|
return this.getHandle().life;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTicksFlown(int ticks) {
|
||||||
|
this.getHandle().life = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTicksToDetonate() {
|
||||||
|
return this.getHandle().lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTicksToDetonate(int ticks) {
|
||||||
|
this.getHandle().lifetime = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyFireworkEffect(FireworkMeta meta) {
|
||||||
|
ItemStack item = this.getHandle().getItem();
|
||||||
|
CraftItemStack.applyMetaToItem(item, meta);
|
||||||
|
|
||||||
|
this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
||||||
|
}
|
||||||
|
// Paper end - Expose firework item directly + manually setting flight
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,4 +196,42 @@ public class CraftFishHook extends CraftProjectile implements FishHook {
|
|||||||
public HookState getState() {
|
public HookState getState() {
|
||||||
return HookState.values()[this.getHandle().currentState.ordinal()];
|
return HookState.values()[this.getHandle().currentState.ordinal()];
|
||||||
}
|
}
|
||||||
|
// Paper start - More FishHook API
|
||||||
|
@Override
|
||||||
|
public int getWaitTime() {
|
||||||
|
return this.getHandle().timeUntilLured;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWaitTime(int ticks) {
|
||||||
|
this.getHandle().timeUntilLured = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTimeUntilBite() {
|
||||||
|
return this.getHandle().timeUntilHooked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTimeUntilBite(final int ticks) {
|
||||||
|
com.google.common.base.Preconditions.checkArgument(ticks >= 1, "Cannot set time until bite to less than 1 (%s<1)", ticks);
|
||||||
|
final FishingHook hook = this.getHandle();
|
||||||
|
|
||||||
|
// Reset the fish angle hook only when this call "enters" the fish into the lure stage.
|
||||||
|
final boolean alreadyInLuringPhase = hook.timeUntilHooked > 0 && hook.timeUntilLured <= 0;
|
||||||
|
if (!alreadyInLuringPhase) {
|
||||||
|
hook.fishAngle = net.minecraft.util.Mth.nextFloat(hook.random, hook.minLureAngle, hook.maxLureAngle);
|
||||||
|
hook.timeUntilLured = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hook.timeUntilHooked = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetFishingState() {
|
||||||
|
final FishingHook hook = this.getHandle();
|
||||||
|
hook.resetTimeUntilLured();
|
||||||
|
hook.timeUntilHooked = 0; // Reset time until hooked, will be repopulated once lured time is ticked down.
|
||||||
|
}
|
||||||
|
// Paper end
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -579,8 +579,15 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
|
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
|
||||||
|
// Paper start - launchProjectile consumer
|
||||||
|
return this.launchProjectile(projectile, velocity, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity, java.util.function.Consumer<? super T> function) {
|
||||||
|
// Paper end - launchProjectile consumer
|
||||||
Preconditions.checkState(!this.getHandle().generation, "Cannot launch projectile during world generation");
|
Preconditions.checkState(!this.getHandle().generation, "Cannot launch projectile during world generation");
|
||||||
|
|
||||||
net.minecraft.world.level.Level world = ((CraftWorld) this.getWorld()).getHandle();
|
net.minecraft.world.level.Level world = ((CraftWorld) this.getWorld()).getHandle();
|
||||||
@@ -606,7 +613,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
|||||||
} else {
|
} else {
|
||||||
launch = new net.minecraft.world.entity.projectile.Arrow(world, this.getHandle(), new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ARROW), null);
|
launch = new net.minecraft.world.entity.projectile.Arrow(world, this.getHandle(), new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ARROW), null);
|
||||||
}
|
}
|
||||||
((net.minecraft.world.entity.projectile.AbstractArrow) launch).shootFromRotation(this.getHandle(), this.getHandle().getXRot(), this.getHandle().getYRot(), 0.0F, 3.0F, 1.0F); // ItemBow
|
((net.minecraft.world.entity.projectile.AbstractArrow) launch).shootFromRotation(this.getHandle(), this.getHandle().getXRot(), this.getHandle().getYRot(), 0.0F, Trident.class.isAssignableFrom(projectile) ? net.minecraft.world.item.TridentItem.PROJECTILE_SHOOT_POWER : 3.0F, 1.0F); // ItemBow // Paper - see TridentItem
|
||||||
} else if (ThrownPotion.class.isAssignableFrom(projectile)) {
|
} else if (ThrownPotion.class.isAssignableFrom(projectile)) {
|
||||||
if (LingeringPotion.class.isAssignableFrom(projectile)) {
|
if (LingeringPotion.class.isAssignableFrom(projectile)) {
|
||||||
launch = new net.minecraft.world.entity.projectile.ThrownPotion(world, this.getHandle(), new net.minecraft.world.item.ItemStack(Items.LINGERING_POTION));
|
launch = new net.minecraft.world.entity.projectile.ThrownPotion(world, this.getHandle(), new net.minecraft.world.item.ItemStack(Items.LINGERING_POTION));
|
||||||
@@ -663,8 +670,26 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
|||||||
} else if (Firework.class.isAssignableFrom(projectile)) {
|
} else if (Firework.class.isAssignableFrom(projectile)) {
|
||||||
Location location = this.getEyeLocation();
|
Location location = this.getEyeLocation();
|
||||||
|
|
||||||
launch = new FireworkRocketEntity(world, net.minecraft.world.item.ItemStack.EMPTY, this.getHandle());
|
// Paper start - see CrossbowItem
|
||||||
launch.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
launch = new FireworkRocketEntity(world, FireworkRocketEntity.getDefaultItem(), this.getHandle(), location.getX(), location.getY() - 0.15F, location.getZ(), true); // Paper - pass correct default to rocket for data storage & see CrossbowItem for regular launch without elytra boost
|
||||||
|
|
||||||
|
// Lifted from net.minecraft.world.item.ProjectileWeaponItem.shoot
|
||||||
|
float f2 = /* net.minecraft.world.item.enchantment.EnchantmentHelper.processProjectileSpread((ServerLevel) world, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.CROSSBOW), this.getHandle(), 0.0F); */ 0; // Just shortcut this to 0, no need to do any calculations on a non existing stack
|
||||||
|
int projectileSize = 1;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
float f3 = projectileSize == 1 ? 0.0F : 2.0F * f2 / (float) (projectileSize - 1);
|
||||||
|
float f4 = (float) ((projectileSize - 1) % 2) * f3 / 2.0F;
|
||||||
|
float f5 = 1.0F;
|
||||||
|
float yaw = f4 + f5 * (float) ((i + 1) / 2) * f3;
|
||||||
|
|
||||||
|
// Lifted from net.minecraft.world.item.CrossbowItem.shootProjectile
|
||||||
|
Vec3 vec3 = this.getHandle().getUpVector(1.0F);
|
||||||
|
org.joml.Quaternionf quaternionf = new org.joml.Quaternionf().setAngleAxis((double)(yaw * (float) (Math.PI / 180.0)), vec3.x, vec3.y, vec3.z);
|
||||||
|
Vec3 vec32 = this.getHandle().getViewVector(1.0F);
|
||||||
|
org.joml.Vector3f vector3f = vec32.toVector3f().rotate(quaternionf);
|
||||||
|
((FireworkRocketEntity) launch).shoot((double)vector3f.x(), (double)vector3f.y(), (double)vector3f.z(), net.minecraft.world.item.CrossbowItem.FIREWORK_POWER, 1.0F);
|
||||||
|
// Paper end
|
||||||
}
|
}
|
||||||
|
|
||||||
Preconditions.checkArgument(launch != null, "Projectile (%s) not supported", projectile.getName());
|
Preconditions.checkArgument(launch != null, "Projectile (%s) not supported", projectile.getName());
|
||||||
@@ -672,6 +697,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
|||||||
if (velocity != null) {
|
if (velocity != null) {
|
||||||
((T) launch.getBukkitEntity()).setVelocity(velocity);
|
((T) launch.getBukkitEntity()).setVelocity(velocity);
|
||||||
}
|
}
|
||||||
|
// Paper start - launchProjectile consumer
|
||||||
|
if (function != null) {
|
||||||
|
function.accept((T) launch.getBukkitEntity());
|
||||||
|
}
|
||||||
|
// Paper end - launchProjectile consumer
|
||||||
|
|
||||||
world.addFreshEntity(launch);
|
world.addFreshEntity(launch);
|
||||||
return (T) launch.getBukkitEntity();
|
return (T) launch.getBukkitEntity();
|
||||||
|
|||||||
@@ -20,13 +20,5 @@ public class CraftLlamaSpit extends AbstractProjectile implements LlamaSpit {
|
|||||||
return "CraftLlamaSpit";
|
return "CraftLlamaSpit";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Paper - moved to AbstractProjectile
|
||||||
public ProjectileSource getShooter() {
|
|
||||||
return (this.getHandle().getOwner() != null) ? (ProjectileSource) this.getHandle().getOwner().getBukkitEntity() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setShooter(ProjectileSource source) {
|
|
||||||
this.getHandle().setOwner((source != null) ? ((CraftLivingEntity) source).getHandle() : null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,20 +10,7 @@ public abstract class CraftProjectile extends AbstractProjectile implements Proj
|
|||||||
super(server, entity);
|
super(server, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Paper - moved to AbstractProjectile
|
||||||
public ProjectileSource getShooter() {
|
|
||||||
return this.getHandle().projectileSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setShooter(ProjectileSource shooter) {
|
|
||||||
if (shooter instanceof CraftLivingEntity) {
|
|
||||||
this.getHandle().setOwner((LivingEntity) ((CraftLivingEntity) shooter).entity);
|
|
||||||
} else {
|
|
||||||
this.getHandle().setOwner(null);
|
|
||||||
}
|
|
||||||
this.getHandle().projectileSource = shooter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public net.minecraft.world.entity.projectile.Projectile getHandle() {
|
public net.minecraft.world.entity.projectile.Projectile getHandle() {
|
||||||
|
|||||||
@@ -12,20 +12,7 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul
|
|||||||
super(server, entity);
|
super(server, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Paper - moved to AbstractProjectile
|
||||||
public ProjectileSource getShooter() {
|
|
||||||
return this.getHandle().projectileSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setShooter(ProjectileSource shooter) {
|
|
||||||
if (shooter instanceof Entity) {
|
|
||||||
this.getHandle().setOwner(((CraftEntity) shooter).getHandle());
|
|
||||||
} else {
|
|
||||||
this.getHandle().setOwner(null);
|
|
||||||
}
|
|
||||||
this.getHandle().projectileSource = shooter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.bukkit.entity.Entity getTarget() {
|
public org.bukkit.entity.Entity getTarget() {
|
||||||
@@ -39,6 +26,44 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul
|
|||||||
this.getHandle().setTarget(target == null ? null : ((CraftEntity) target).getHandle());
|
this.getHandle().setTarget(target == null ? null : ((CraftEntity) target).getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.bukkit.util.Vector getTargetDelta() {
|
||||||
|
net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
|
||||||
|
return new org.bukkit.util.Vector(bullet.targetDeltaX, bullet.targetDeltaY, bullet.targetDeltaZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTargetDelta(org.bukkit.util.Vector vector) {
|
||||||
|
net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
|
||||||
|
bullet.targetDeltaX = vector.getX();
|
||||||
|
bullet.targetDeltaY = vector.getY();
|
||||||
|
bullet.targetDeltaZ = vector.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.bukkit.block.BlockFace getCurrentMovementDirection() {
|
||||||
|
net.minecraft.core.Direction dir = this.getHandle().currentMoveDirection;
|
||||||
|
if (dir == null) {
|
||||||
|
return null; // random dir
|
||||||
|
}
|
||||||
|
return org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCurrentMovementDirection(org.bukkit.block.BlockFace movementDirection) {
|
||||||
|
this.getHandle().currentMoveDirection = org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(movementDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFlightSteps() {
|
||||||
|
return this.getHandle().flightSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFlightSteps(int steps) {
|
||||||
|
this.getHandle().flightSteps = steps;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "CraftShulkerBullet";
|
return "CraftShulkerBullet";
|
||||||
|
|||||||
@@ -36,11 +36,31 @@ public class CraftThrownPotion extends CraftThrowableProjectile implements Throw
|
|||||||
@Override
|
@Override
|
||||||
public void setItem(ItemStack item) {
|
public void setItem(ItemStack item) {
|
||||||
Preconditions.checkArgument(item != null, "ItemStack cannot be null");
|
Preconditions.checkArgument(item != null, "ItemStack cannot be null");
|
||||||
Preconditions.checkArgument(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack material must be Material.LINGERING_POTION or Material.SPLASH_POTION but was Material.%s", item.getType());
|
// Preconditions.checkArgument(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack material must be Material.LINGERING_POTION or Material.SPLASH_POTION but was Material.%s", item.getType()); // Paper - Projectile API
|
||||||
|
org.bukkit.inventory.meta.PotionMeta meta = (item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION) ? null : this.getPotionMeta(); // Paper - Projectile API
|
||||||
|
|
||||||
this.getHandle().setItem(CraftItemStack.asNMSCopy(item));
|
this.getHandle().setItem(CraftItemStack.asNMSCopy(item));
|
||||||
|
if (meta != null) this.setPotionMeta(meta); // Paper - Projectile API
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paper start - Projectile API
|
||||||
|
@Override
|
||||||
|
public org.bukkit.inventory.meta.PotionMeta getPotionMeta() {
|
||||||
|
return (org.bukkit.inventory.meta.PotionMeta) CraftItemStack.getItemMeta(this.getHandle().getItem(), org.bukkit.inventory.ItemType.SPLASH_POTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPotionMeta(org.bukkit.inventory.meta.PotionMeta meta) {
|
||||||
|
net.minecraft.world.item.ItemStack item = this.getHandle().getItem();
|
||||||
|
CraftItemStack.applyMetaToItem(item, meta);
|
||||||
|
this.getHandle().setItem(item); // Reset item
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void splash() {
|
||||||
|
this.getHandle().splash(null);
|
||||||
|
}
|
||||||
|
// Paper end
|
||||||
@Override
|
@Override
|
||||||
public net.minecraft.world.entity.projectile.ThrownPotion getHandle() {
|
public net.minecraft.world.entity.projectile.ThrownPotion getHandle() {
|
||||||
return (net.minecraft.world.entity.projectile.ThrownPotion) this.entity;
|
return (net.minecraft.world.entity.projectile.ThrownPotion) this.entity;
|
||||||
|
|||||||
@@ -53,5 +53,15 @@ public class CraftTrident extends CraftAbstractArrow implements Trident {
|
|||||||
com.google.common.base.Preconditions.checkArgument(loyaltyLevel >= 0 && loyaltyLevel <= 127, "The loyalty level has to be between 0 and 127");
|
com.google.common.base.Preconditions.checkArgument(loyaltyLevel >= 0 && loyaltyLevel <= 127, "The loyalty level has to be between 0 and 127");
|
||||||
this.getHandle().setLoyalty((byte) loyaltyLevel);
|
this.getHandle().setLoyalty((byte) loyaltyLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDealtDamage() {
|
||||||
|
return this.getHandle().dealtDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHasDealtDamage(boolean hasDealtDamage) {
|
||||||
|
this.getHandle().dealtDamage = hasDealtDamage;
|
||||||
|
}
|
||||||
// Paper end
|
// Paper end
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -841,19 +841,19 @@ public class CraftEventFactory {
|
|||||||
/**
|
/**
|
||||||
* PotionSplashEvent
|
* PotionSplashEvent
|
||||||
*/
|
*/
|
||||||
public static PotionSplashEvent callPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, HitResult position, Map<LivingEntity, Double> affectedEntities) {
|
public static PotionSplashEvent callPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, @Nullable HitResult position, Map<LivingEntity, Double> affectedEntities) { // Paper - nullable hitResult
|
||||||
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
|
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
|
||||||
|
|
||||||
Block hitBlock = null;
|
Block hitBlock = null;
|
||||||
BlockFace hitFace = null;
|
BlockFace hitFace = null;
|
||||||
if (position.getType() == HitResult.Type.BLOCK) {
|
if (position != null && position.getType() == HitResult.Type.BLOCK) { // Paper - nullable hitResult
|
||||||
BlockHitResult positionBlock = (BlockHitResult) position;
|
BlockHitResult positionBlock = (BlockHitResult) position;
|
||||||
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
|
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
|
||||||
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
|
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
org.bukkit.entity.Entity hitEntity = null;
|
org.bukkit.entity.Entity hitEntity = null;
|
||||||
if (position.getType() == HitResult.Type.ENTITY) {
|
if (position != null && position.getType() == HitResult.Type.ENTITY) { // Paper - nullable hitResult
|
||||||
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
|
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -862,20 +862,20 @@ public class CraftEventFactory {
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LingeringPotionSplashEvent callLingeringPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, HitResult position, net.minecraft.world.entity.AreaEffectCloud cloud) {
|
public static LingeringPotionSplashEvent callLingeringPotionSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, @Nullable HitResult position, net.minecraft.world.entity.AreaEffectCloud cloud) { // Paper - nullable hitResult
|
||||||
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
|
ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity();
|
||||||
AreaEffectCloud effectCloud = (AreaEffectCloud) cloud.getBukkitEntity();
|
AreaEffectCloud effectCloud = (AreaEffectCloud) cloud.getBukkitEntity();
|
||||||
|
|
||||||
Block hitBlock = null;
|
Block hitBlock = null;
|
||||||
BlockFace hitFace = null;
|
BlockFace hitFace = null;
|
||||||
if (position.getType() == HitResult.Type.BLOCK) {
|
if (position != null && position.getType() == HitResult.Type.BLOCK) { // Paper
|
||||||
BlockHitResult positionBlock = (BlockHitResult) position;
|
BlockHitResult positionBlock = (BlockHitResult) position;
|
||||||
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
|
hitBlock = CraftBlock.at(potion.level(), positionBlock.getBlockPos());
|
||||||
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
|
hitFace = CraftBlock.notchToBlockFace(positionBlock.getDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
org.bukkit.entity.Entity hitEntity = null;
|
org.bukkit.entity.Entity hitEntity = null;
|
||||||
if (position.getType() == HitResult.Type.ENTITY) {
|
if (position != null && position.getType() == HitResult.Type.ENTITY) { // Paper
|
||||||
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
|
hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -341,12 +341,23 @@ public final class CraftItemStack extends ItemStack {
|
|||||||
public ItemMeta getItemMeta() {
|
public ItemMeta getItemMeta() {
|
||||||
return CraftItemStack.getItemMeta(this.handle);
|
return CraftItemStack.getItemMeta(this.handle);
|
||||||
}
|
}
|
||||||
|
// Paper start
|
||||||
|
public static void applyMetaToItem(net.minecraft.world.item.ItemStack itemStack, ItemMeta itemMeta) {
|
||||||
|
final CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator();
|
||||||
|
((CraftMetaItem) itemMeta).applyToItem(tag);
|
||||||
|
itemStack.applyComponents(tag.build());
|
||||||
|
}
|
||||||
|
|
||||||
public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item) {
|
public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item) {
|
||||||
|
return getItemMeta(item, null);
|
||||||
|
}
|
||||||
|
public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item, org.bukkit.inventory.ItemType metaForType) {
|
||||||
|
// Paper end
|
||||||
if (!CraftItemStack.hasItemMeta(item)) {
|
if (!CraftItemStack.hasItemMeta(item)) {
|
||||||
return CraftItemFactory.instance().getItemMeta(CraftItemStack.getType(item));
|
return CraftItemFactory.instance().getItemMeta(CraftItemStack.getType(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (metaForType != null) { return ((CraftItemType<?>) metaForType).getItemMeta(item); } // Paper
|
||||||
return ((CraftItemType<?>) CraftItemType.minecraftToBukkitNew(item.getItem())).getItemMeta(item);
|
return ((CraftItemType<?>) CraftItemType.minecraftToBukkitNew(item.getItem())).getItemMeta(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,15 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
|
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
|
||||||
|
// Paper start - launchProjectile consumer
|
||||||
|
return this.launchProjectile(projectile, velocity, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity, java.util.function.Consumer<? super T> function) {
|
||||||
|
// Paper end - launchProjectile consumer
|
||||||
Preconditions.checkArgument(this.getBlock().getType() == Material.DISPENSER, "Block is no longer dispenser");
|
Preconditions.checkArgument(this.getBlock().getType() == Material.DISPENSER, "Block is no longer dispenser");
|
||||||
|
|
||||||
// Copied from BlockDispenser.dispense()
|
// Copied from BlockDispenser.dispense()
|
||||||
BlockSource sourceblock = new BlockSource((ServerLevel) this.dispenserBlock.getLevel(), this.dispenserBlock.getBlockPos(), this.dispenserBlock.getBlockState(), this.dispenserBlock);
|
BlockSource sourceblock = new BlockSource((ServerLevel) this.dispenserBlock.getLevel(), this.dispenserBlock.getBlockPos(), this.dispenserBlock.getBlockState(), this.dispenserBlock);
|
||||||
// Copied from DispenseBehaviorProjectile
|
// Copied from DispenseBehaviorProjectile
|
||||||
@@ -68,7 +76,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
|||||||
item = Items.SNOWBALL;
|
item = Items.SNOWBALL;
|
||||||
} else if (Egg.class.isAssignableFrom(projectile)) {
|
} else if (Egg.class.isAssignableFrom(projectile)) {
|
||||||
item = Items.EGG;
|
item = Items.EGG;
|
||||||
} else if (EnderPearl.class.isAssignableFrom(projectile)) {
|
} else if (false && EnderPearl.class.isAssignableFrom(projectile)) { // Paper - more projectile API - disallow enderpearl, it is not a projectile item
|
||||||
item = Items.ENDER_PEARL;
|
item = Items.ENDER_PEARL;
|
||||||
} else if (ThrownExpBottle.class.isAssignableFrom(projectile)) {
|
} else if (ThrownExpBottle.class.isAssignableFrom(projectile)) {
|
||||||
item = Items.EXPERIENCE_BOTTLE;
|
item = Items.EXPERIENCE_BOTTLE;
|
||||||
@@ -83,20 +91,20 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
|||||||
item = Items.TIPPED_ARROW;
|
item = Items.TIPPED_ARROW;
|
||||||
} else if (SpectralArrow.class.isAssignableFrom(projectile)) {
|
} else if (SpectralArrow.class.isAssignableFrom(projectile)) {
|
||||||
item = Items.SPECTRAL_ARROW;
|
item = Items.SPECTRAL_ARROW;
|
||||||
} else {
|
} else if (org.bukkit.entity.Arrow.class.isAssignableFrom(projectile)) { // Paper - more projectile API - disallow trident
|
||||||
item = Items.ARROW;
|
item = Items.ARROW;
|
||||||
}
|
}
|
||||||
} else if (Fireball.class.isAssignableFrom(projectile)) {
|
} else if (Fireball.class.isAssignableFrom(projectile)) {
|
||||||
if (AbstractWindCharge.class.isAssignableFrom(projectile)) {
|
if (org.bukkit.entity.WindCharge.class.isAssignableFrom(projectile)) { // Paper - more projectile API - only allow wind charge not breeze wind charge
|
||||||
item = Items.WIND_CHARGE;
|
item = Items.WIND_CHARGE;
|
||||||
} else {
|
} else if (org.bukkit.entity.SmallFireball.class.isAssignableFrom(projectile)) { // Paper - more projectile API - only allow firing fire charges.
|
||||||
item = Items.FIRE_CHARGE;
|
item = Items.FIRE_CHARGE;
|
||||||
}
|
}
|
||||||
} else if (Firework.class.isAssignableFrom(projectile)) {
|
} else if (Firework.class.isAssignableFrom(projectile)) {
|
||||||
item = Items.FIREWORK_ROCKET;
|
item = Items.FIREWORK_ROCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
Preconditions.checkArgument(item instanceof ProjectileItem, "Projectile not supported");
|
Preconditions.checkArgument(item instanceof ProjectileItem, "Projectile '%s' not supported", projectile.getSimpleName()); // Paper - more projectile API - include simple name in exception
|
||||||
|
|
||||||
ItemStack itemstack = new ItemStack(item);
|
ItemStack itemstack = new ItemStack(item);
|
||||||
ProjectileItem projectileItem = (ProjectileItem) item;
|
ProjectileItem projectileItem = (ProjectileItem) item;
|
||||||
@@ -105,7 +113,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
|||||||
Position iposition = dispenseConfig.positionFunction().getDispensePosition(sourceblock, enumdirection);
|
Position iposition = dispenseConfig.positionFunction().getDispensePosition(sourceblock, enumdirection);
|
||||||
net.minecraft.world.entity.projectile.Projectile launch = projectileItem.asProjectile(world, iposition, itemstack, enumdirection);
|
net.minecraft.world.entity.projectile.Projectile launch = projectileItem.asProjectile(world, iposition, itemstack, enumdirection);
|
||||||
|
|
||||||
if (Fireball.class.isAssignableFrom(projectile)) {
|
if (false && Fireball.class.isAssignableFrom(projectile)) { // Paper - more project API - dispensers cannot launch anything but fire charges.
|
||||||
AbstractHurtingProjectile customFireball = null;
|
AbstractHurtingProjectile customFireball = null;
|
||||||
if (WitherSkull.class.isAssignableFrom(projectile)) {
|
if (WitherSkull.class.isAssignableFrom(projectile)) {
|
||||||
launch = customFireball = EntityType.WITHER_SKULL.create(world, EntitySpawnReason.TRIGGERED);
|
launch = customFireball = EntityType.WITHER_SKULL.create(world, EntitySpawnReason.TRIGGERED);
|
||||||
@@ -130,7 +138,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (launch instanceof net.minecraft.world.entity.projectile.AbstractArrow arrow) {
|
if (false && launch instanceof net.minecraft.world.entity.projectile.AbstractArrow arrow) { // Paper - more projectile API - this is set by the respective ArrowItem when constructing the projectile
|
||||||
arrow.pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.ALLOWED;
|
arrow.pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.ALLOWED;
|
||||||
}
|
}
|
||||||
launch.projectileSource = this;
|
launch.projectileSource = this;
|
||||||
@@ -139,6 +147,11 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
|
|||||||
if (velocity != null) {
|
if (velocity != null) {
|
||||||
((T) launch.getBukkitEntity()).setVelocity(velocity);
|
((T) launch.getBukkitEntity()).setVelocity(velocity);
|
||||||
}
|
}
|
||||||
|
// Paper start
|
||||||
|
if (function != null) {
|
||||||
|
function.accept((T) launch.getBukkitEntity());
|
||||||
|
}
|
||||||
|
// Paper end
|
||||||
|
|
||||||
world.addFreshEntity(launch);
|
world.addFreshEntity(launch);
|
||||||
return (T) launch.getBukkitEntity();
|
return (T) launch.getBukkitEntity();
|
||||||
|
|||||||
Reference in New Issue
Block a user