summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authort00thpick1 <t00thpick1dirko@gmail.com>2014-01-20 00:03:21 -0500
committerNate Mortensen <nate.richard.mortensen@gmail.com>2014-01-30 21:47:44 -0700
commit8a5ad89a680ca5442f486f56553077cdfee921fa (patch)
tree31cac0af3166e3bbda1d30f2e4a07a1cd9fb8868
parentac53442e7e07f86117dfa0862ed1dc2f4c26126b (diff)
downloadcraftbukkit-8a5ad89a680ca5442f486f56553077cdfee921fa.tar
craftbukkit-8a5ad89a680ca5442f486f56553077cdfee921fa.tar.gz
craftbukkit-8a5ad89a680ca5442f486f56553077cdfee921fa.tar.lz
craftbukkit-8a5ad89a680ca5442f486f56553077cdfee921fa.tar.xz
craftbukkit-8a5ad89a680ca5442f486f56553077cdfee921fa.zip
[Bleeding] Implement ProjectileSource API. Addresses BUKKIT-1038, BUKKIT-1156
-rw-r--r--maps.yml10
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorFireball.java5
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java1
-rw-r--r--src/main/java/net/minecraft/server/Entity.java1
-rw-r--r--src/main/java/net/minecraft/server/EntityArrow.java3
-rw-r--r--src/main/java/net/minecraft/server/EntityFireball.java1
-rw-r--r--src/main/java/net/minecraft/server/EntityProjectile.java1
-rw-r--r--src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java13
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java41
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java29
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java15
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java12
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java36
-rw-r--r--src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java142
14 files changed, 277 insertions, 33 deletions
diff --git a/maps.yml b/maps.yml
index 2c560f7c..57eda7fd 100644
--- a/maps.yml
+++ b/maps.yml
@@ -15,6 +15,8 @@ members:
"org/bukkit/event/entity/EntityRegainHealthEvent _INVALID_setAmount (I)V": setAmount
"org/bukkit/entity/Minecart _INVALID_getDamage ()I": getDamage
"org/bukkit/entity/Minecart _INVALID_setDamage (I)V": setDamage
+ "org/bukkit/entity/Projectile _INVALID_getShooter ()Lorg/bukkit/entity/LivingEntity;": getShooter
+ "org/bukkit/entity/Projectile _INVALID_setShooter (Lorg/bukkit/entity/LivingEntity;)V": setShooter
flags:
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity getHealth ()I": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart getHealth ()I": 0x1001
@@ -32,3 +34,11 @@ flags:
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity setLastDamage (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftMinecart setDamage (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftMinecart getDamage ()I": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftProjectile getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftProjectile setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftArrow getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftArrow setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFireball getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFireball setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFish getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
+ "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFish setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java b/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java
index 56ff6122..0fd9487b 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java
@@ -49,7 +49,10 @@ final class DispenseBehaviorFireball extends DispenseBehaviorItem {
}
}
- world.addEntity(new EntitySmallFireball(world, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()));
+ EntitySmallFireball entitysmallfireball = new EntitySmallFireball(world, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ());
+ entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource((TileEntityDispenser) isourceblock.getTileEntity());
+
+ world.addEntity(entitysmallfireball);
// itemstack.a(1); // Handled during event processing
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java b/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java
index 0a51bafd..49de3f41 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java
@@ -42,6 +42,7 @@ public abstract class DispenseBehaviorProjectile extends DispenseBehaviorItem {
}
iprojectile.shoot(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.b(), this.a());
+ ((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource((TileEntityDispenser) isourceblock.getTileEntity());
// CraftBukkit end
world.addEntity((Entity) iprojectile);
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index dc0abc59..f74d937e 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -109,6 +109,7 @@ public abstract class Entity {
public UUID uniqueID; // CraftBukkit - protected -> public
public EnumEntitySize at;
public boolean valid; // CraftBukkit
+ public org.bukkit.projectiles.ProjectileSource projectileSource; // CraftBukkit - For projectiles only
public int getId() {
return this.id;
diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java
index efa05ba2..51c3173f 100644
--- a/src/main/java/net/minecraft/server/EntityArrow.java
+++ b/src/main/java/net/minecraft/server/EntityArrow.java
@@ -3,6 +3,7 @@ package net.minecraft.server;
import java.util.List;
// CraftBukkit start
+import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
// CraftBukkit end
@@ -41,6 +42,7 @@ public class EntityArrow extends Entity implements IProjectile {
super(world);
this.k = 10.0D;
this.shooter = entityliving;
+ this.projectileSource = (LivingEntity) entityliving.getBukkitEntity(); // CraftBukkit
if (entityliving instanceof EntityHuman) {
this.fromPlayer = 1;
}
@@ -69,6 +71,7 @@ public class EntityArrow extends Entity implements IProjectile {
super(world);
this.k = 10.0D;
this.shooter = entityliving;
+ this.projectileSource = (LivingEntity) entityliving.getBukkitEntity(); // CraftBukkit
if (entityliving instanceof EntityHuman) {
this.fromPlayer = 1;
}
diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/java/net/minecraft/server/EntityFireball.java
index 82da554b..939de5dd 100644
--- a/src/main/java/net/minecraft/server/EntityFireball.java
+++ b/src/main/java/net/minecraft/server/EntityFireball.java
@@ -42,6 +42,7 @@ public abstract class EntityFireball extends Entity {
public EntityFireball(World world, EntityLiving entityliving, double d0, double d1, double d2) {
super(world);
this.shooter = entityliving;
+ this.projectileSource = (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity(); // CraftBukkit
this.a(1.0F, 1.0F);
this.setPositionRotation(entityliving.locX, entityliving.locY, entityliving.locZ, entityliving.yaw, entityliving.pitch);
this.setPosition(this.locX, this.locY, this.locZ);
diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java
index 10c242c1..329aecd8 100644
--- a/src/main/java/net/minecraft/server/EntityProjectile.java
+++ b/src/main/java/net/minecraft/server/EntityProjectile.java
@@ -25,6 +25,7 @@ public abstract class EntityProjectile extends Entity implements IProjectile {
public EntityProjectile(World world, EntityLiving entityliving) {
super(world);
this.shooter = entityliving;
+ this.projectileSource = (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity(); // CraftBukkit
this.a(0.25F, 0.25F);
this.setPositionRotation(entityliving.locX, entityliving.locY + (double) entityliving.getHeadHeight(), entityliving.locZ, entityliving.yaw, entityliving.pitch);
this.locX -= (double) (MathHelper.cos(this.yaw / 180.0F * 3.1415927F) * 0.16F);
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
index 1e39bd3a..762a8e6d 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
@@ -3,12 +3,15 @@ package org.bukkit.craftbukkit.block;
import net.minecraft.server.BlockDispenser;
import net.minecraft.server.Blocks;
import net.minecraft.server.TileEntityDispenser;
+
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Dispenser;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventory;
+import org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource;
import org.bukkit.inventory.Inventory;
+import org.bukkit.projectiles.BlockProjectileSource;
public class CraftDispenser extends CraftBlockState implements Dispenser {
private final CraftWorld world;
@@ -25,6 +28,16 @@ public class CraftDispenser extends CraftBlockState implements Dispenser {
return new CraftInventory(dispenser);
}
+ public BlockProjectileSource getBlockProjectileSource() {
+ Block block = getBlock();
+
+ if (block.getType() != Material.DISPENSER) {
+ return null;
+ }
+
+ return new CraftBlockProjectileSource(dispenser);
+ }
+
public boolean dispense() {
Block block = getBlock();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
index 3f1bcd25..4c319a7f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
@@ -7,6 +7,7 @@ import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
+import org.bukkit.projectiles.ProjectileSource;
public class CraftArrow extends AbstractProjectile implements Arrow {
@@ -14,20 +15,6 @@ public class CraftArrow extends AbstractProjectile implements Arrow {
super(server, entity);
}
- public LivingEntity getShooter() {
- if (getHandle().shooter != null) {
- return (LivingEntity) getHandle().shooter.getBukkitEntity();
- }
-
- return null;
- }
-
- public void setShooter(LivingEntity shooter) {
- if (shooter instanceof CraftLivingEntity) {
- getHandle().shooter = ((CraftLivingEntity) shooter).getHandle();
- }
- }
-
public void setKnockbackStrength(int knockbackStrength) {
Validate.isTrue(knockbackStrength >= 0, "Knockback cannot be negative");
getHandle().a(knockbackStrength);
@@ -45,6 +32,19 @@ public class CraftArrow extends AbstractProjectile implements Arrow {
getHandle().a(critical);
}
+ public ProjectileSource getShooter() {
+ return getHandle().projectileSource;
+ }
+
+ public void setShooter(ProjectileSource shooter) {
+ if (shooter instanceof LivingEntity) {
+ getHandle().shooter = ((CraftLivingEntity) shooter).getHandle();
+ } else {
+ getHandle().shooter = null;
+ }
+ getHandle().projectileSource = shooter;
+ }
+
@Override
public EntityArrow getHandle() {
return (EntityArrow) entity;
@@ -58,4 +58,17 @@ public class CraftArrow extends AbstractProjectile implements Arrow {
public EntityType getType() {
return EntityType.ARROW;
}
+
+ @Deprecated
+ public LivingEntity _INVALID_getShooter() {
+ if (getHandle().shooter == null) {
+ return null;
+ }
+ return (LivingEntity) getHandle().shooter.getBukkitEntity();
+ }
+
+ @Deprecated
+ public void _INVALID_setShooter(LivingEntity shooter) {
+ getHandle().shooter = ((CraftLivingEntity) shooter).getHandle();
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
index 6ebe28d3..3a987176 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java
@@ -7,6 +7,7 @@ import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.LivingEntity;
+import org.bukkit.projectiles.ProjectileSource;
import org.bukkit.util.Vector;
public class CraftFireball extends AbstractProjectile implements Fireball {
@@ -30,18 +31,17 @@ public class CraftFireball extends AbstractProjectile implements Fireball {
getHandle().bukkitYield = yield;
}
- public LivingEntity getShooter() {
- if (getHandle().shooter != null) {
- return (LivingEntity) getHandle().shooter.getBukkitEntity();
- }
-
- return null;
+ public ProjectileSource getShooter() {
+ return getHandle().projectileSource;
}
- public void setShooter(LivingEntity shooter) {
+ public void setShooter(ProjectileSource shooter) {
if (shooter instanceof CraftLivingEntity) {
- getHandle().shooter = (EntityLiving) ((CraftLivingEntity) shooter).entity;
+ getHandle().shooter = ((CraftLivingEntity) shooter).getHandle();
+ } else {
+ getHandle().shooter = null;
}
+ getHandle().projectileSource = shooter;
}
public Vector getDirection() {
@@ -65,4 +65,17 @@ public class CraftFireball extends AbstractProjectile implements Fireball {
public EntityType getType() {
return EntityType.UNKNOWN;
}
+
+ @Deprecated
+ public void _INVALID_setShooter(LivingEntity shooter) {
+ setShooter(shooter);
+ }
+
+ @Deprecated
+ public LivingEntity _INVALID_getShooter() {
+ if (getHandle().shooter != null) {
+ return (LivingEntity) getHandle().shooter.getBukkitEntity();
+ }
+ return null;
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java
index b6575e96..edb30e7c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java
@@ -9,6 +9,7 @@ import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fish;
import org.bukkit.entity.LivingEntity;
+import org.bukkit.projectiles.ProjectileSource;
public class CraftFish extends AbstractProjectile implements Fish {
private double biteChance = -1;
@@ -17,7 +18,7 @@ public class CraftFish extends AbstractProjectile implements Fish {
super(server, entity);
}
- public LivingEntity getShooter() {
+ public ProjectileSource getShooter() {
if (getHandle().owner != null) {
return getHandle().owner.getBukkitEntity();
}
@@ -25,7 +26,7 @@ public class CraftFish extends AbstractProjectile implements Fish {
return null;
}
- public void setShooter(LivingEntity shooter) {
+ public void setShooter(ProjectileSource shooter) {
if (shooter instanceof CraftHumanEntity) {
getHandle().owner = (EntityHuman) ((CraftHumanEntity) shooter).entity;
}
@@ -61,4 +62,14 @@ public class CraftFish extends AbstractProjectile implements Fish {
Validate.isTrue(chance >= 0 && chance <= 1, "The bite chance must be between 0 and 1.");
this.biteChance = chance;
}
+
+ @Deprecated
+ public LivingEntity _INVALID_getShooter() {
+ return (LivingEntity) getShooter();
+ }
+
+ @Deprecated
+ public void _INVALID_setShooter(LivingEntity shooter) {
+ setShooter(shooter);
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 3f45837c..9cdb0c18 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -13,6 +13,7 @@ import net.minecraft.server.EntityEnderDragon;
import net.minecraft.server.EntityEnderPearl;
import net.minecraft.server.EntityFishingHook;
import net.minecraft.server.EntityHuman;
+import net.minecraft.server.EntityFireball;
import net.minecraft.server.EntityInsentient;
import net.minecraft.server.EntityLargeFireball;
import net.minecraft.server.EntityLiving;
@@ -293,8 +294,12 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
return effects;
}
- @SuppressWarnings("unchecked")
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile) {
+ return launchProjectile(projectile, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
net.minecraft.server.World world = ((CraftWorld) getWorld()).getHandle();
net.minecraft.server.Entity launch = null;
@@ -324,11 +329,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
launch = new EntityLargeFireball(world, getHandle(), direction.getX(), direction.getY(), direction.getZ());
}
+ ((EntityFireball) launch).projectileSource = this;
launch.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
Validate.notNull(launch, "Projectile not supported");
+ if (velocity != null) {
+ ((T) launch.getBukkitEntity()).setVelocity(velocity);
+ }
+
world.addEntity(launch);
return (T) launch.getBukkitEntity();
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
index b60d97b1..2f29f2fc 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java
@@ -2,30 +2,32 @@ package org.bukkit.craftbukkit.entity;
import net.minecraft.server.EntityLiving;
import net.minecraft.server.EntityProjectile;
+
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Projectile;
+import org.bukkit.projectiles.ProjectileSource;
public abstract class CraftProjectile extends AbstractProjectile implements Projectile {
public CraftProjectile(CraftServer server, net.minecraft.server.Entity entity) {
super(server, entity);
}
- public LivingEntity getShooter() {
- if (getHandle().getShooter() != null) {
- return (LivingEntity) getHandle().getShooter().getBukkitEntity();
- }
-
- return null;
+ public ProjectileSource getShooter() {
+ return getHandle().projectileSource;
}
- public void setShooter(LivingEntity shooter) {
+ public void setShooter(ProjectileSource shooter) {
if (shooter instanceof CraftLivingEntity) {
getHandle().shooter = (EntityLiving) ((CraftLivingEntity) shooter).entity;
if (shooter instanceof CraftHumanEntity) {
getHandle().shooterName = ((CraftHumanEntity) shooter).getName();
}
+ } else {
+ getHandle().shooter = null;
+ getHandle().shooterName = null;
}
+ getHandle().projectileSource = shooter;
}
@Override
@@ -37,4 +39,24 @@ public abstract class CraftProjectile extends AbstractProjectile implements Proj
public String toString() {
return "CraftProjectile";
}
+
+
+ @Deprecated
+ public LivingEntity _INVALID_getShooter() {
+ if (getHandle().shooter == null) {
+ return null;
+ }
+ return (LivingEntity) getHandle().shooter.getBukkitEntity();
+ }
+
+ @Deprecated
+ public void _INVALID_setShooter(LivingEntity shooter) {
+ if (shooter == null) {
+ return;
+ }
+ getHandle().shooter = ((CraftLivingEntity) shooter).getHandle();
+ if (shooter instanceof CraftHumanEntity) {
+ getHandle().shooterName = ((CraftHumanEntity) shooter).getName();
+ }
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
new file mode 100644
index 00000000..f3550458
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
@@ -0,0 +1,142 @@
+package org.bukkit.craftbukkit.projectiles;
+
+import java.util.Random;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.entity.Arrow;
+import org.bukkit.entity.Egg;
+import org.bukkit.entity.EnderPearl;
+import org.bukkit.entity.Fireball;
+import org.bukkit.entity.Projectile;
+import org.bukkit.entity.SmallFireball;
+import org.bukkit.entity.Snowball;
+import org.bukkit.entity.ThrownExpBottle;
+import org.bukkit.entity.ThrownPotion;
+import org.bukkit.entity.WitherSkull;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.projectiles.BlockProjectileSource;
+import org.bukkit.util.Vector;
+
+import net.minecraft.server.BlockDispenser;
+import net.minecraft.server.EntityArrow;
+import net.minecraft.server.EntityEgg;
+import net.minecraft.server.EntityEnderPearl;
+import net.minecraft.server.EntityFireball;
+import net.minecraft.server.EntityLargeFireball;
+import net.minecraft.server.EntityPotion;
+import net.minecraft.server.EntityProjectile;
+import net.minecraft.server.EntitySmallFireball;
+import net.minecraft.server.EntitySnowball;
+import net.minecraft.server.EntityThrownExpBottle;
+import net.minecraft.server.EntityWitherSkull;
+import net.minecraft.server.EnumFacing;
+import net.minecraft.server.IPosition;
+import net.minecraft.server.IProjectile;
+import net.minecraft.server.MathHelper;
+import net.minecraft.server.SourceBlock;
+import net.minecraft.server.TileEntityDispenser;
+
+public class CraftBlockProjectileSource implements BlockProjectileSource {
+ private final TileEntityDispenser dispenserBlock;
+
+ public CraftBlockProjectileSource(TileEntityDispenser dispenserBlock) {
+ this.dispenserBlock = dispenserBlock;
+ }
+
+ @Override
+ public Block getBlock() {
+ return dispenserBlock.getWorld().getWorld().getBlockAt(dispenserBlock.x, dispenserBlock.y, dispenserBlock.z);
+ }
+
+ @Override
+ public <T extends Projectile> T launchProjectile(Class<? extends T> projectile) {
+ return launchProjectile(projectile, null);
+ }
+
+ @Override
+ public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
+ Validate.isTrue(getBlock().getType() == Material.DISPENSER, "Block is no longer dispenser");
+ // Copied from BlockDispenser.dispense()
+ SourceBlock isourceblock = new SourceBlock(dispenserBlock.getWorld(), dispenserBlock.x, dispenserBlock.y, dispenserBlock.z);
+ // Copied from DispenseBehaviorProjectile
+ IPosition iposition = BlockDispenser.a(isourceblock);
+ EnumFacing enumfacing = BlockDispenser.b(isourceblock.h());
+ net.minecraft.server.World world = dispenserBlock.getWorld();
+ net.minecraft.server.Entity launch = null;
+
+ if (Snowball.class.isAssignableFrom(projectile)) {
+ launch = new EntitySnowball(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ } else if (Egg.class.isAssignableFrom(projectile)) {
+ launch = new EntityEgg(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ } else if (EnderPearl.class.isAssignableFrom(projectile)) {
+ launch = new EntityEnderPearl(world);
+ launch.setPosition(iposition.getX(), iposition.getY(), iposition.getZ());
+ } else if (ThrownExpBottle.class.isAssignableFrom(projectile)) {
+ launch = new EntityThrownExpBottle(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ } else if (ThrownPotion.class.isAssignableFrom(projectile)) {
+ launch = new EntityPotion(world, iposition.getX(), iposition.getY(), iposition.getZ(), CraftItemStack.asNMSCopy(new ItemStack(Material.POTION, 1)));
+ } else if (Arrow.class.isAssignableFrom(projectile)) {
+ launch = new EntityArrow(world, iposition.getX(), iposition.getY(), iposition.getZ());
+ ((EntityArrow) launch).fromPlayer = 1;
+ ((EntityArrow) launch).projectileSource = this;
+ } else if (Fireball.class.isAssignableFrom(projectile)) {
+ double d0 = iposition.getX() + (double) ((float) enumfacing.c() * 0.3F);
+ double d1 = iposition.getY() + (double) ((float) enumfacing.c() * 0.3F);
+ double d2 = iposition.getZ() + (double) ((float) enumfacing.e() * 0.3F);
+ Random random = world.random;
+ double d3 = random.nextGaussian() * 0.05D + (double) enumfacing.c();
+ double d4 = random.nextGaussian() * 0.05D + (double) enumfacing.d();
+ double d5 = random.nextGaussian() * 0.05D + (double) enumfacing.e();
+
+ if (SmallFireball.class.isAssignableFrom(projectile)) {
+ launch = new EntitySmallFireball(world, d0, d1, d2, d3, d4, d5);
+ } else if (WitherSkull.class.isAssignableFrom(projectile)) {
+ launch = new EntityWitherSkull(world);
+ launch.setPosition(d0, d1, d2);
+ double d6 = (double) MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
+
+ ((EntityFireball) launch).dirX = d3 / d6 * 0.1D;
+ ((EntityFireball) launch).dirY = d4 / d6 * 0.1D;
+ ((EntityFireball) launch).dirZ = d5 / d6 * 0.1D;
+ } else {
+ launch = new EntityLargeFireball(world);
+ launch.setPosition(d0, d1, d2);
+ double d6 = (double) MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
+
+ ((EntityFireball) launch).dirX = d3 / d6 * 0.1D;
+ ((EntityFireball) launch).dirY = d4 / d6 * 0.1D;
+ ((EntityFireball) launch).dirZ = d5 / d6 * 0.1D;
+ }
+
+ ((EntityFireball) launch).projectileSource = this;
+ }
+
+ Validate.notNull(launch, "Projectile not supported");
+
+ if (launch instanceof IProjectile) {
+ if (launch instanceof EntityProjectile) {
+ ((EntityProjectile) launch).projectileSource = this;
+ }
+ // 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;
+ }
+ // Copied from DispenseBehaviorProjectile
+ ((IProjectile) launch).shoot((double) enumfacing.c(), (double) ((float) enumfacing.d() + 0.1F), (double) enumfacing.e(), b, a);
+ }
+
+ if (velocity != null) {
+ ((T) launch.getBukkitEntity()).setVelocity(velocity);
+ }
+
+ world.addEntity(launch);
+ return (T) launch.getBukkitEntity();
+ }
+}