Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
1package net.minecraft.server;
2
3import org.bukkit.craftbukkit.entity.CraftLivingEntity;
4import org.bukkit.entity.Projectile;
5import org.bukkit.event.entity.EntityDamageByEntityEvent;
6import org.bukkit.event.entity.EntityDamageEvent;
7import org.bukkit.event.entity.ProjectileHitEvent;
8import org.bukkit.event.player.PlayerPickupItemEvent;
9
10import uk.betacraft.uberbukkit.UberbukkitConfig;
11
12import java.util.List;
13
14// CraftBukkit start
15// CraftBukkit end
16
17public class EntityArrow extends Entity {
18
19 private int d = -1;
20 private int e = -1;
21 private int f = -1;
22 private int g = 0;
23 private int h = 0;
24 private boolean inGround = false;
25 public boolean fromPlayer = false;
26 public int shake = 0;
27 public EntityLiving shooter;
28 private int j;
29 private int k = 0;
30
31 public EntityArrow(World world) {
32 super(world);
33 this.b(0.5F, 0.5F);
34 }
35
36 public EntityArrow(World world, double d0, double d1, double d2) {
37 super(world);
38 this.b(0.5F, 0.5F);
39 this.setPosition(d0, d1, d2);
40 this.height = 0.0F;
41 }
42
43 public EntityArrow(World world, EntityLiving entityliving) {
44 super(world);
45 this.shooter = entityliving;
46 this.fromPlayer = entityliving instanceof EntityHuman;
47 this.b(0.5F, 0.5F);
48 this.setPositionRotation(entityliving.locX, entityliving.locY + (double) entityliving.t(), entityliving.locZ, entityliving.yaw, entityliving.pitch);
49 this.locX -= (double) (MathHelper.cos(this.yaw / 180.0F * 3.1415927F) * 0.16F);
50 this.locY -= 0.10000000149011612D;
51 this.locZ -= (double) (MathHelper.sin(this.yaw / 180.0F * 3.1415927F) * 0.16F);
52 this.setPosition(this.locX, this.locY, this.locZ);
53 this.height = 0.0F;
54 this.motX = (double) (-MathHelper.sin(this.yaw / 180.0F * 3.1415927F) * MathHelper.cos(this.pitch / 180.0F * 3.1415927F));
55 this.motZ = (double) (MathHelper.cos(this.yaw / 180.0F * 3.1415927F) * MathHelper.cos(this.pitch / 180.0F * 3.1415927F));
56 this.motY = (double) (-MathHelper.sin(this.pitch / 180.0F * 3.1415927F));
57 this.a(this.motX, this.motY, this.motZ, 1.5F, 1.0F);
58 }
59
60 protected void b() {
61 }
62
63 public void a(double d0, double d1, double d2, float f, float f1) {
64 float f2 = MathHelper.a(d0 * d0 + d1 * d1 + d2 * d2);
65
66 d0 /= (double) f2;
67 d1 /= (double) f2;
68 d2 /= (double) f2;
69 d0 += this.random.nextGaussian() * 0.007499999832361937D * (double) f1;
70 d1 += this.random.nextGaussian() * 0.007499999832361937D * (double) f1;
71 d2 += this.random.nextGaussian() * 0.007499999832361937D * (double) f1;
72 d0 *= (double) f;
73 d1 *= (double) f;
74 d2 *= (double) f;
75 this.motX = d0;
76 this.motY = d1;
77 this.motZ = d2;
78 float f3 = MathHelper.a(d0 * d0 + d2 * d2);
79
80 this.lastYaw = this.yaw = (float) (Math.atan2(d0, d2) * 180.0D / 3.1415927410125732D);
81 this.lastPitch = this.pitch = (float) (Math.atan2(d1, (double) f3) * 180.0D / 3.1415927410125732D);
82 this.j = 0;
83 }
84
85 public void m_() {
86 super.m_();
87 if (this.lastPitch == 0.0F && this.lastYaw == 0.0F) {
88 float f = MathHelper.a(this.motX * this.motX + this.motZ * this.motZ);
89
90 this.lastYaw = this.yaw = (float) (Math.atan2(this.motX, this.motZ) * 180.0D / 3.1415927410125732D);
91 this.lastPitch = this.pitch = (float) (Math.atan2(this.motY, (double) f) * 180.0D / 3.1415927410125732D);
92 }
93
94 int i = this.world.getTypeId(this.d, this.e, this.f);
95
96 if (i > 0) {
97 Block.byId[i].a(this.world, this.d, this.e, this.f);
98 AxisAlignedBB axisalignedbb = Block.byId[i].e(this.world, this.d, this.e, this.f);
99
100 if (axisalignedbb != null && axisalignedbb.a(Vec3D.create(this.locX, this.locY, this.locZ))) {
101 this.inGround = true;
102 }
103 }
104
105 if (this.shake > 0) {
106 --this.shake;
107 }
108
109 if (this.inGround) {
110 i = this.world.getTypeId(this.d, this.e, this.f);
111 int j = this.world.getData(this.d, this.e, this.f);
112
113 if (i == this.g && j == this.h) {
114 ++this.j;
115 if (this.j == 1200) {
116 this.die();
117 }
118 } else {
119 this.inGround = false;
120 this.motX *= (double) (this.random.nextFloat() * 0.2F);
121 this.motY *= (double) (this.random.nextFloat() * 0.2F);
122 this.motZ *= (double) (this.random.nextFloat() * 0.2F);
123 this.j = 0;
124 this.k = 0;
125 }
126 } else {
127 ++this.k;
128 Vec3D vec3d = Vec3D.create(this.locX, this.locY, this.locZ);
129 Vec3D vec3d1 = Vec3D.create(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
130 MovingObjectPosition movingobjectposition = this.world.rayTrace(vec3d, vec3d1, false, true);
131
132 vec3d = Vec3D.create(this.locX, this.locY, this.locZ);
133 vec3d1 = Vec3D.create(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
134 if (movingobjectposition != null) {
135 vec3d1 = Vec3D.create(movingobjectposition.f.a, movingobjectposition.f.b, movingobjectposition.f.c);
136 }
137
138 Entity entity = null;
139 List list = this.world.b((Entity) this, this.boundingBox.a(this.motX, this.motY, this.motZ).b(1.0D, 1.0D, 1.0D));
140 double d0 = 0.0D;
141
142 float f1;
143
144 for (int k = 0; k < list.size(); ++k) {
145 Entity entity1 = (Entity) list.get(k);
146
147 if (entity1.l_() && (entity1 != this.shooter || this.k >= 5)) {
148 f1 = 0.3F;
149 AxisAlignedBB axisalignedbb1 = entity1.boundingBox.b((double) f1, (double) f1, (double) f1);
150 MovingObjectPosition movingobjectposition1 = axisalignedbb1.a(vec3d, vec3d1);
151
152 if (movingobjectposition1 != null) {
153 double d1 = vec3d.a(movingobjectposition1.f);
154
155 if (d1 < d0 || d0 == 0.0D) {
156 entity = entity1;
157 d0 = d1;
158 }
159 }
160 }
161 }
162
163 if (entity != null) {
164 movingobjectposition = new MovingObjectPosition(entity);
165 }
166
167 float f2;
168
169 if (movingobjectposition != null) {
170 // CraftBukkit start
171 ProjectileHitEvent phe = new ProjectileHitEvent((Projectile) this.getBukkitEntity());
172 this.world.getServer().getPluginManager().callEvent(phe);
173 // CraftBukkit end
174 if (movingobjectposition.entity != null) {
175 // CraftBukkit start
176 boolean stick;
177 if (entity instanceof EntityLiving) {
178 org.bukkit.Server server = this.world.getServer();
179
180 // TODO decide if we should create DamageCause.ARROW, DamageCause.PROJECTILE
181 // or leave as DamageCause.ENTITY_ATTACK
182 org.bukkit.entity.Entity damagee = movingobjectposition.entity.getBukkitEntity();
183 Projectile projectile = (Projectile) this.getBukkitEntity();
184 // TODO deal with arrows being fired from a non-entity
185
186 EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(projectile, damagee, EntityDamageEvent.DamageCause.PROJECTILE, 4);
187 server.getPluginManager().callEvent(event);
188 this.shooter = (projectile.getShooter() == null) ? null : ((CraftLivingEntity) projectile.getShooter()).getHandle();
189
190 if (event.isCancelled()) {
191 stick = !projectile.doesBounce();
192 } else {
193 // this function returns if the arrow should stick in or not, i.e. !bounce
194 stick = movingobjectposition.entity.damageEntity(this, event.getDamage());
195 }
196 } else {
197 stick = movingobjectposition.entity.damageEntity(this.shooter, 4);
198 }
199 if (stick) {
200 // CraftBukkit end
201 this.world.makeSound(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
202 this.die();
203 } else {
204 this.motX *= -0.10000000149011612D;
205 this.motY *= -0.10000000149011612D;
206 this.motZ *= -0.10000000149011612D;
207 this.yaw += 180.0F;
208 this.lastYaw += 180.0F;
209 this.k = 0;
210 }
211 } else {
212 this.d = movingobjectposition.b;
213 this.e = movingobjectposition.c;
214 this.f = movingobjectposition.d;
215 this.g = this.world.getTypeId(this.d, this.e, this.f);
216 this.h = this.world.getData(this.d, this.e, this.f);
217 this.motX = (double) ((float) (movingobjectposition.f.a - this.locX));
218 this.motY = (double) ((float) (movingobjectposition.f.b - this.locY));
219 this.motZ = (double) ((float) (movingobjectposition.f.c - this.locZ));
220 f2 = MathHelper.a(this.motX * this.motX + this.motY * this.motY + this.motZ * this.motZ);
221 this.locX -= this.motX / (double) f2 * 0.05000000074505806D;
222 this.locY -= this.motY / (double) f2 * 0.05000000074505806D;
223 this.locZ -= this.motZ / (double) f2 * 0.05000000074505806D;
224 this.world.makeSound(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
225 this.inGround = true;
226 this.shake = 7;
227 }
228 }
229
230 this.locX += this.motX;
231 this.locY += this.motY;
232 this.locZ += this.motZ;
233 f2 = MathHelper.a(this.motX * this.motX + this.motZ * this.motZ);
234 this.yaw = (float) (Math.atan2(this.motX, this.motZ) * 180.0D / 3.1415927410125732D);
235
236 for (this.pitch = (float) (Math.atan2(this.motY, (double) f2) * 180.0D / 3.1415927410125732D); this.pitch - this.lastPitch < -180.0F; this.lastPitch -= 360.0F) {
237 ;
238 }
239
240 while (this.pitch - this.lastPitch >= 180.0F) {
241 this.lastPitch += 360.0F;
242 }
243
244 while (this.yaw - this.lastYaw < -180.0F) {
245 this.lastYaw -= 360.0F;
246 }
247
248 while (this.yaw - this.lastYaw >= 180.0F) {
249 this.lastYaw += 360.0F;
250 }
251
252 this.pitch = this.lastPitch + (this.pitch - this.lastPitch) * 0.2F;
253 this.yaw = this.lastYaw + (this.yaw - this.lastYaw) * 0.2F;
254 float f3 = 0.99F;
255
256 f1 = 0.03F;
257 if (this.ad()) {
258 for (int l = 0; l < 4; ++l) {
259 float f4 = 0.25F;
260
261 this.world.a("bubble", this.locX - this.motX * (double) f4, this.locY - this.motY * (double) f4, this.locZ - this.motZ * (double) f4, this.motX, this.motY, this.motZ);
262 }
263
264 f3 = 0.8F;
265 }
266
267 this.motX *= (double) f3;
268 this.motY *= (double) f3;
269 this.motZ *= (double) f3;
270 this.motY -= (double) f1;
271 this.setPosition(this.locX, this.locY, this.locZ);
272 }
273 }
274
275 public void b(NBTTagCompound nbttagcompound) {
276 nbttagcompound.a("xTile", (short) this.d);
277 nbttagcompound.a("yTile", (short) this.e);
278 nbttagcompound.a("zTile", (short) this.f);
279 nbttagcompound.a("inTile", (byte) this.g);
280 nbttagcompound.a("inData", (byte) this.h);
281 nbttagcompound.a("shake", (byte) this.shake);
282 nbttagcompound.a("inGround", (byte) (this.inGround ? 1 : 0));
283 nbttagcompound.a("player", this.fromPlayer);
284 }
285
286 public void a(NBTTagCompound nbttagcompound) {
287 this.d = nbttagcompound.d("xTile");
288 this.e = nbttagcompound.d("yTile");
289 this.f = nbttagcompound.d("zTile");
290 this.g = nbttagcompound.c("inTile") & 255;
291 this.h = nbttagcompound.c("inData") & 255;
292 this.shake = nbttagcompound.c("shake") & 255;
293 this.inGround = nbttagcompound.c("inGround") == 1;
294 this.fromPlayer = nbttagcompound.m("player");
295 }
296
297 public void b(EntityHuman entityhuman) {
298 if (!this.world.isStatic) {
299
300 // uberbukkit
301 if (!UberbukkitConfig.getInstance().getBoolean("mechanics.arrows_pickup_by_others", true)) {
302 if (this.shooter != entityhuman) {
303 return;
304 }
305 }
306
307 // CraftBukkit start
308 ItemStack itemstack = new ItemStack(Item.ARROW, 1);
309 if (this.inGround && this.fromPlayer && this.shake <= 0 && entityhuman.inventory.canHold(itemstack) > 0) {
310 net.minecraft.server.EntityItem item = new net.minecraft.server.EntityItem(this.world, this.locX, this.locY, this.locZ, itemstack);
311
312 PlayerPickupItemEvent event = new PlayerPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), new org.bukkit.craftbukkit.entity.CraftItem(this.world.getServer(), item), 0);
313 this.world.getServer().getPluginManager().callEvent(event);
314
315 if (event.isCancelled()) {
316 return;
317 }
318 }
319 // CraftBukkit end
320
321 if (this.inGround && this.fromPlayer && this.shake <= 0 && entityhuman.inventory.pickup(new ItemStack(Item.ARROW, 1))) {
322 this.world.makeSound(this, "random.pop", 0.2F, ((this.random.nextFloat() - this.random.nextFloat()) * 0.7F + 1.0F) * 2.0F);
323 entityhuman.receive(this, 1);
324 this.die();
325 }
326 }
327 }
328}