[Bleeding] Implement ProjectileSource API. Addresses BUKKIT-1038, BUKKIT-1156

This commit is contained in:
t00thpick1 2014-01-20 00:03:21 -05:00 committed by Nate Mortensen
parent ac53442e7e
commit 8a5ad89a68
14 changed files with 277 additions and 33 deletions

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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