001 package net.minecraft.entity.item;
002
003 import cpw.mods.fml.common.Side;
004 import cpw.mods.fml.common.asm.SideOnly;
005
006 import java.util.ArrayList;
007 import java.util.List;
008 import net.minecraft.block.Block;
009 import net.minecraft.block.BlockRail;
010 import net.minecraft.entity.Entity;
011 import net.minecraft.entity.EntityLiving;
012 import net.minecraft.entity.monster.EntityIronGolem;
013 import net.minecraft.entity.player.EntityPlayer;
014 import net.minecraft.inventory.IInventory;
015 import net.minecraft.item.Item;
016 import net.minecraft.item.ItemStack;
017 import net.minecraft.nbt.NBTTagCompound;
018 import net.minecraft.nbt.NBTTagList;
019 import net.minecraft.server.gui.IUpdatePlayerListBox;
020 import net.minecraft.util.AxisAlignedBB;
021 import net.minecraft.util.DamageSource;
022 import net.minecraft.util.MathHelper;
023 import net.minecraft.util.Vec3;
024 import net.minecraft.world.World;
025
026 import net.minecraftforge.common.IMinecartCollisionHandler;
027 import net.minecraftforge.common.MinecartRegistry;
028 import net.minecraftforge.common.MinecraftForge;
029 import net.minecraftforge.event.entity.minecart.*;
030
031 public class EntityMinecart extends Entity implements IInventory
032 {
033 /** Array of item stacks stored in minecart (for storage minecarts). */
034 protected ItemStack[] cargoItems;
035 protected int fuel;
036 protected boolean field_70499_f;
037
038 /** The type of minecart, 2 for powered, 1 for storage. */
039 public int minecartType;
040 public double pushX;
041 public double pushZ;
042 protected final IUpdatePlayerListBox field_82344_g;
043 protected boolean field_82345_h;
044 protected static final int[][][] field_70500_g = new int[][][] {{{0, 0, -1}, {0, 0, 1}}, {{ -1, 0, 0}, {1, 0, 0}}, {{ -1, -1, 0}, {1, 0, 0}}, {{ -1, 0, 0}, {1, -1, 0}}, {{0, 0, -1}, {0, -1, 1}}, {{0, -1, -1}, {0, 0, 1}}, {{0, 0, 1}, {1, 0, 0}}, {{0, 0, 1}, { -1, 0, 0}}, {{0, 0, -1}, { -1, 0, 0}}, {{0, 0, -1}, {1, 0, 0}}};
045
046 /** appears to be the progress of the turn */
047 protected int turnProgress;
048 protected double minecartX;
049 protected double minecartY;
050 protected double minecartZ;
051 protected double minecartYaw;
052 protected double minecartPitch;
053 @SideOnly(Side.CLIENT)
054 protected double velocityX;
055 @SideOnly(Side.CLIENT)
056 protected double velocityY;
057 @SideOnly(Side.CLIENT)
058 protected double velocityZ;
059
060 /* Forge: Minecart Compatibility Layer Integration. */
061 public static float defaultMaxSpeedRail = 0.4f;
062 public static float defaultMaxSpeedGround = 0.4f;
063 public static float defaultMaxSpeedAirLateral = 0.4f;
064 public static float defaultMaxSpeedAirVertical = -1f;
065 public static double defaultDragRidden = 0.996999979019165D;
066 public static double defaultDragEmpty = 0.9599999785423279D;
067 public static double defaultDragAir = 0.94999998807907104D;
068 protected boolean canUseRail = true;
069 protected boolean canBePushed = true;
070 private static IMinecartCollisionHandler collisionHandler = null;
071
072 /* Instance versions of the above physics properties */
073 protected float maxSpeedRail;
074 protected float maxSpeedGround;
075 protected float maxSpeedAirLateral;
076 protected float maxSpeedAirVertical;
077 protected double dragAir;
078
079 public EntityMinecart(World par1World)
080 {
081 super(par1World);
082 this.cargoItems = new ItemStack[36];
083 this.fuel = 0;
084 this.field_70499_f = false;
085 this.field_82345_h = true;
086 this.preventEntitySpawning = true;
087 this.setSize(0.98F, 0.7F);
088 this.yOffset = this.height / 2.0F;
089 this.field_82344_g = par1World != null ? par1World.func_82735_a(this) : null;
090
091 maxSpeedRail = defaultMaxSpeedRail;
092 maxSpeedGround = defaultMaxSpeedGround;
093 maxSpeedAirLateral = defaultMaxSpeedAirLateral;
094 maxSpeedAirVertical = defaultMaxSpeedAirVertical;
095 dragAir = defaultDragAir;
096 }
097
098 public EntityMinecart(World world, int type)
099 {
100 this(world);
101 minecartType = type;
102 }
103
104 /**
105 * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
106 * prevent them from trampling crops
107 */
108 protected boolean canTriggerWalking()
109 {
110 return false;
111 }
112
113 protected void entityInit()
114 {
115 this.dataWatcher.addObject(16, new Byte((byte)0));
116 this.dataWatcher.addObject(17, new Integer(0));
117 this.dataWatcher.addObject(18, new Integer(1));
118 this.dataWatcher.addObject(19, new Integer(0));
119 }
120
121 /**
122 * Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be
123 * pushable on contact, like boats or minecarts.
124 */
125 public AxisAlignedBB getCollisionBox(Entity par1Entity)
126 {
127 if (getCollisionHandler() != null)
128 {
129 return getCollisionHandler().getCollisionBox(this, par1Entity);
130 }
131 return par1Entity.canBePushed() ? par1Entity.boundingBox : null;
132 }
133
134 /**
135 * returns the bounding box for this entity
136 */
137 public AxisAlignedBB getBoundingBox()
138 {
139 if (getCollisionHandler() != null)
140 {
141 return getCollisionHandler().getBoundingBox(this);
142 }
143 return null;
144 }
145
146 /**
147 * Returns true if this entity should push and be pushed by other entities when colliding.
148 */
149 public boolean canBePushed()
150 {
151 return canBePushed;
152 }
153
154 public EntityMinecart(World par1World, double par2, double par4, double par6, int par8)
155 {
156 this(par1World);
157 this.setPosition(par2, par4 + (double)this.yOffset, par6);
158 this.motionX = 0.0D;
159 this.motionY = 0.0D;
160 this.motionZ = 0.0D;
161 this.prevPosX = par2;
162 this.prevPosY = par4;
163 this.prevPosZ = par6;
164 this.minecartType = par8;
165 }
166
167 /**
168 * Returns the Y offset from the entity's position for any entity riding this one.
169 */
170 public double getMountedYOffset()
171 {
172 return (double)this.height * 0.0D - 0.30000001192092896D;
173 }
174
175 /**
176 * Called when the entity is attacked.
177 */
178 public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
179 {
180 if (!this.worldObj.isRemote && !this.isDead)
181 {
182 if (this.func_85032_ar())
183 {
184 return false;
185 }
186 else
187 {
188 this.func_70494_i(-this.func_70493_k());
189 this.func_70497_h(10);
190 this.setBeenAttacked();
191 this.setDamage(this.getDamage() + par2 * 10);
192
193 if (par1DamageSource.getEntity() instanceof EntityPlayer && ((EntityPlayer)par1DamageSource.getEntity()).capabilities.isCreativeMode)
194 {
195 this.setDamage(100);
196 }
197
198 if (this.getDamage() > 40)
199 {
200 if (this.riddenByEntity != null)
201 {
202 this.riddenByEntity.mountEntity(this);
203 }
204
205 this.setDead();
206 dropCartAsItem();
207 }
208
209 return true;
210 }
211 }
212 else
213 {
214 return true;
215 }
216 }
217
218 @SideOnly(Side.CLIENT)
219
220 /**
221 * Setups the entity to do the hurt animation. Only used by packets in multiplayer.
222 */
223 public void performHurtAnimation()
224 {
225 this.func_70494_i(-this.func_70493_k());
226 this.func_70497_h(10);
227 this.setDamage(this.getDamage() + this.getDamage() * 10);
228 }
229
230 /**
231 * Returns true if other Entities should be prevented from moving through this Entity.
232 */
233 public boolean canBeCollidedWith()
234 {
235 return !this.isDead;
236 }
237
238 /**
239 * Will get destroyed next tick.
240 */
241 public void setDead()
242 {
243 if (this.field_82345_h)
244 {
245 for (int var1 = 0; var1 < this.getSizeInventory(); ++var1)
246 {
247 ItemStack var2 = this.getStackInSlot(var1);
248
249 if (var2 != null)
250 {
251 float var3 = this.rand.nextFloat() * 0.8F + 0.1F;
252 float var4 = this.rand.nextFloat() * 0.8F + 0.1F;
253 float var5 = this.rand.nextFloat() * 0.8F + 0.1F;
254
255 while (var2.stackSize > 0)
256 {
257 int var6 = this.rand.nextInt(21) + 10;
258
259 if (var6 > var2.stackSize)
260 {
261 var6 = var2.stackSize;
262 }
263
264 var2.stackSize -= var6;
265 EntityItem var7 = new EntityItem(this.worldObj, this.posX + (double)var3, this.posY + (double)var4, this.posZ + (double)var5, new ItemStack(var2.itemID, var6, var2.getItemDamage()));
266
267 if (var2.hasTagCompound())
268 {
269 var7.item.setTagCompound((NBTTagCompound)var2.getTagCompound().copy());
270 }
271
272 float var8 = 0.05F;
273 var7.motionX = (double)((float)this.rand.nextGaussian() * var8);
274 var7.motionY = (double)((float)this.rand.nextGaussian() * var8 + 0.2F);
275 var7.motionZ = (double)((float)this.rand.nextGaussian() * var8);
276 this.worldObj.spawnEntityInWorld(var7);
277 }
278 }
279 }
280 }
281
282 super.setDead();
283
284 if (this.field_82344_g != null)
285 {
286 this.field_82344_g.update();
287 }
288 }
289
290 /**
291 * Teleports the entity to another dimension. Params: Dimension number to teleport to
292 */
293 public void travelToDimension(int par1)
294 {
295 this.field_82345_h = false;
296 super.travelToDimension(par1);
297 }
298
299 /**
300 * Called to update the entity's position/logic.
301 */
302 public void onUpdate()
303 {
304 if (this.field_82344_g != null)
305 {
306 this.field_82344_g.update();
307 }
308
309 if (this.func_70496_j() > 0)
310 {
311 this.func_70497_h(this.func_70496_j() - 1);
312 }
313
314 if (this.getDamage() > 0)
315 {
316 this.setDamage(this.getDamage() - 1);
317 }
318
319 if (this.posY < -64.0D)
320 {
321 this.kill();
322 }
323
324 if (this.isMinecartPowered() && this.rand.nextInt(4) == 0 && minecartType == 2 && getClass() == EntityMinecart.class)
325 {
326 this.worldObj.spawnParticle("largesmoke", this.posX, this.posY + 0.8D, this.posZ, 0.0D, 0.0D, 0.0D);
327 }
328
329 if (this.worldObj.isRemote)
330 {
331 if (this.turnProgress > 0)
332 {
333 double var45 = this.posX + (this.minecartX - this.posX) / (double)this.turnProgress;
334 double var46 = this.posY + (this.minecartY - this.posY) / (double)this.turnProgress;
335 double var5 = this.posZ + (this.minecartZ - this.posZ) / (double)this.turnProgress;
336 double var7 = MathHelper.wrapAngleTo180_double(this.minecartYaw - (double)this.rotationYaw);
337 this.rotationYaw = (float)((double)this.rotationYaw + var7 / (double)this.turnProgress);
338 this.rotationPitch = (float)((double)this.rotationPitch + (this.minecartPitch - (double)this.rotationPitch) / (double)this.turnProgress);
339 --this.turnProgress;
340 this.setPosition(var45, var46, var5);
341 this.setRotation(this.rotationYaw, this.rotationPitch);
342 }
343 else
344 {
345 this.setPosition(this.posX, this.posY, this.posZ);
346 this.setRotation(this.rotationYaw, this.rotationPitch);
347 }
348 }
349 else
350 {
351 this.prevPosX = this.posX;
352 this.prevPosY = this.posY;
353 this.prevPosZ = this.posZ;
354 this.motionY -= 0.03999999910593033D;
355 int var1 = MathHelper.floor_double(this.posX);
356 int var2 = MathHelper.floor_double(this.posY);
357 int var3 = MathHelper.floor_double(this.posZ);
358
359 if (BlockRail.isRailBlockAt(this.worldObj, var1, var2 - 1, var3))
360 {
361 --var2;
362 }
363
364 double var4 = 0.4D;
365 double var6 = 0.0078125D;
366 int var8 = this.worldObj.getBlockId(var1, var2, var3);
367
368 if (canUseRail() && BlockRail.isRailBlock(var8))
369 {
370 this.fallDistance = 0.0F;
371 Vec3 var9 = this.func_70489_a(this.posX, this.posY, this.posZ);
372 int var10 = ((BlockRail)Block.blocksList[var8]).getBasicRailMetadata(worldObj, this, var1, var2, var3);
373 this.posY = (double)var2;
374 boolean var11 = false;
375 boolean var12 = false;
376
377 if (var8 == Block.railPowered.blockID)
378 {
379 var11 = (worldObj.getBlockMetadata(var1, var2, var3) & 8) != 0;
380 var12 = !var11;
381 }
382
383 if (((BlockRail)Block.blocksList[var8]).isPowered())
384 {
385 var10 &= 7;
386 }
387
388 if (var10 >= 2 && var10 <= 5)
389 {
390 this.posY = (double)(var2 + 1);
391 }
392
393 adjustSlopeVelocities(var10);
394
395 int[][] var13 = field_70500_g[var10];
396 double var14 = (double)(var13[1][0] - var13[0][0]);
397 double var16 = (double)(var13[1][2] - var13[0][2]);
398 double var18 = Math.sqrt(var14 * var14 + var16 * var16);
399 double var20 = this.motionX * var14 + this.motionZ * var16;
400
401 if (var20 < 0.0D)
402 {
403 var14 = -var14;
404 var16 = -var16;
405 }
406
407 double var22 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
408 this.motionX = var22 * var14 / var18;
409 this.motionZ = var22 * var16 / var18;
410 double var24;
411 double var26;
412
413 if (this.riddenByEntity != null)
414 {
415 var24 = this.riddenByEntity.motionX * this.riddenByEntity.motionX + this.riddenByEntity.motionZ * this.riddenByEntity.motionZ;
416 var26 = this.motionX * this.motionX + this.motionZ * this.motionZ;
417
418 if (var24 > 1.0E-4D && var26 < 0.01D)
419 {
420 this.motionX += this.riddenByEntity.motionX * 0.1D;
421 this.motionZ += this.riddenByEntity.motionZ * 0.1D;
422 var12 = false;
423 }
424 }
425
426 if (var12 && shouldDoRailFunctions())
427 {
428 var24 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
429
430 if (var24 < 0.03D)
431 {
432 this.motionX *= 0.0D;
433 this.motionY *= 0.0D;
434 this.motionZ *= 0.0D;
435 }
436 else
437 {
438 this.motionX *= 0.5D;
439 this.motionY *= 0.0D;
440 this.motionZ *= 0.5D;
441 }
442 }
443
444 var24 = 0.0D;
445 var26 = (double)var1 + 0.5D + (double)var13[0][0] * 0.5D;
446 double var28 = (double)var3 + 0.5D + (double)var13[0][2] * 0.5D;
447 double var30 = (double)var1 + 0.5D + (double)var13[1][0] * 0.5D;
448 double var32 = (double)var3 + 0.5D + (double)var13[1][2] * 0.5D;
449 var14 = var30 - var26;
450 var16 = var32 - var28;
451 double var34;
452 double var36;
453
454 if (var14 == 0.0D)
455 {
456 this.posX = (double)var1 + 0.5D;
457 var24 = this.posZ - (double)var3;
458 }
459 else if (var16 == 0.0D)
460 {
461 this.posZ = (double)var3 + 0.5D;
462 var24 = this.posX - (double)var1;
463 }
464 else
465 {
466 var34 = this.posX - var26;
467 var36 = this.posZ - var28;
468 var24 = (var34 * var14 + var36 * var16) * 2.0D;
469 }
470
471 this.posX = var26 + var14 * var24;
472 this.posZ = var28 + var16 * var24;
473 this.setPosition(this.posX, this.posY + (double)this.yOffset, this.posZ);
474
475 moveMinecartOnRail(var1, var2, var3);
476
477 if (var13[0][1] != 0 && MathHelper.floor_double(this.posX) - var1 == var13[0][0] && MathHelper.floor_double(this.posZ) - var3 == var13[0][2])
478 {
479 this.setPosition(this.posX, this.posY + (double)var13[0][1], this.posZ);
480 }
481 else if (var13[1][1] != 0 && MathHelper.floor_double(this.posX) - var1 == var13[1][0] && MathHelper.floor_double(this.posZ) - var3 == var13[1][2])
482 {
483 this.setPosition(this.posX, this.posY + (double)var13[1][1], this.posZ);
484 }
485
486 applyDragAndPushForces();
487
488 Vec3 var52 = this.func_70489_a(this.posX, this.posY, this.posZ);
489
490 if (var52 != null && var9 != null)
491 {
492 double var39 = (var9.yCoord - var52.yCoord) * 0.05D;
493 var22 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
494
495 if (var22 > 0.0D)
496 {
497 this.motionX = this.motionX / var22 * (var22 + var39);
498 this.motionZ = this.motionZ / var22 * (var22 + var39);
499 }
500
501 this.setPosition(this.posX, var52.yCoord, this.posZ);
502 }
503
504 int var51 = MathHelper.floor_double(this.posX);
505 int var53 = MathHelper.floor_double(this.posZ);
506
507 if (var51 != var1 || var53 != var3)
508 {
509 var22 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
510 this.motionX = var22 * (double)(var51 - var1);
511 this.motionZ = var22 * (double)(var53 - var3);
512 }
513
514 double var41;
515
516 updatePushForces();
517
518 if(shouldDoRailFunctions())
519 {
520 ((BlockRail)Block.blocksList[var8]).onMinecartPass(worldObj, this, var1, var2, var3);
521 }
522
523 if (var11 && shouldDoRailFunctions())
524 {
525 var41 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
526
527 if (var41 > 0.01D)
528 {
529 double var43 = 0.06D;
530 this.motionX += this.motionX / var41 * var43;
531 this.motionZ += this.motionZ / var41 * var43;
532 }
533 else if (var10 == 1)
534 {
535 if (this.worldObj.isBlockNormalCube(var1 - 1, var2, var3))
536 {
537 this.motionX = 0.02D;
538 }
539 else if (this.worldObj.isBlockNormalCube(var1 + 1, var2, var3))
540 {
541 this.motionX = -0.02D;
542 }
543 }
544 else if (var10 == 0)
545 {
546 if (this.worldObj.isBlockNormalCube(var1, var2, var3 - 1))
547 {
548 this.motionZ = 0.02D;
549 }
550 else if (this.worldObj.isBlockNormalCube(var1, var2, var3 + 1))
551 {
552 this.motionZ = -0.02D;
553 }
554 }
555 }
556 }
557 else
558 {
559 moveMinecartOffRail(var1, var2, var3);
560 }
561
562 this.doBlockCollisions();
563 this.rotationPitch = 0.0F;
564 double var47 = this.prevPosX - this.posX;
565 double var48 = this.prevPosZ - this.posZ;
566
567 if (var47 * var47 + var48 * var48 > 0.001D)
568 {
569 this.rotationYaw = (float)(Math.atan2(var48, var47) * 180.0D / Math.PI);
570
571 if (this.field_70499_f)
572 {
573 this.rotationYaw += 180.0F;
574 }
575 }
576
577 double var49 = (double)MathHelper.wrapAngleTo180_float(this.rotationYaw - this.prevRotationYaw);
578
579 if (var49 < -170.0D || var49 >= 170.0D)
580 {
581 this.rotationYaw += 180.0F;
582 this.field_70499_f = !this.field_70499_f;
583 }
584
585 this.setRotation(this.rotationYaw, this.rotationPitch);
586
587 AxisAlignedBB box = null;
588 if (getCollisionHandler() != null)
589 {
590 box = getCollisionHandler().getMinecartCollisionBox(this);
591 }
592 else
593 {
594 box = boundingBox.expand(0.2D, 0.0D, 0.2D);
595 }
596
597 List var15 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, box);
598
599 if (var15 != null && !var15.isEmpty())
600 {
601 for (int var50 = 0; var50 < var15.size(); ++var50)
602 {
603 Entity var17 = (Entity)var15.get(var50);
604
605 if (var17 != this.riddenByEntity && var17.canBePushed() && var17 instanceof EntityMinecart)
606 {
607 var17.applyEntityCollision(this);
608 }
609 }
610 }
611
612 if (this.riddenByEntity != null && this.riddenByEntity.isDead)
613 {
614 if (this.riddenByEntity.ridingEntity == this)
615 {
616 this.riddenByEntity.ridingEntity = null;
617 }
618
619 this.riddenByEntity = null;
620 }
621
622 updateFuel();
623 MinecraftForge.EVENT_BUS.post(new MinecartUpdateEvent(this, var1, var2, var3));
624 }
625 }
626
627 @SideOnly(Side.CLIENT)
628 public Vec3 func_70495_a(double par1, double par3, double par5, double par7)
629 {
630 int var9 = MathHelper.floor_double(par1);
631 int var10 = MathHelper.floor_double(par3);
632 int var11 = MathHelper.floor_double(par5);
633
634 if (BlockRail.isRailBlockAt(this.worldObj, var9, var10 - 1, var11))
635 {
636 --var10;
637 }
638
639 int var12 = this.worldObj.getBlockId(var9, var10, var11);
640
641 if (!BlockRail.isRailBlock(var12))
642 {
643 return null;
644 }
645 else
646 {
647 int var13 = ((BlockRail)Block.blocksList[var12]).getBasicRailMetadata(worldObj, this, var9, var10, var11);
648
649 par3 = (double)var10;
650
651 if (var13 >= 2 && var13 <= 5)
652 {
653 par3 = (double)(var10 + 1);
654 }
655
656 int[][] var14 = field_70500_g[var13];
657 double var15 = (double)(var14[1][0] - var14[0][0]);
658 double var17 = (double)(var14[1][2] - var14[0][2]);
659 double var19 = Math.sqrt(var15 * var15 + var17 * var17);
660 var15 /= var19;
661 var17 /= var19;
662 par1 += var15 * par7;
663 par5 += var17 * par7;
664
665 if (var14[0][1] != 0 && MathHelper.floor_double(par1) - var9 == var14[0][0] && MathHelper.floor_double(par5) - var11 == var14[0][2])
666 {
667 par3 += (double)var14[0][1];
668 }
669 else if (var14[1][1] != 0 && MathHelper.floor_double(par1) - var9 == var14[1][0] && MathHelper.floor_double(par5) - var11 == var14[1][2])
670 {
671 par3 += (double)var14[1][1];
672 }
673
674 return this.func_70489_a(par1, par3, par5);
675 }
676 }
677
678 public Vec3 func_70489_a(double par1, double par3, double par5)
679 {
680 int var7 = MathHelper.floor_double(par1);
681 int var8 = MathHelper.floor_double(par3);
682 int var9 = MathHelper.floor_double(par5);
683
684 if (BlockRail.isRailBlockAt(this.worldObj, var7, var8 - 1, var9))
685 {
686 --var8;
687 }
688
689 int var10 = this.worldObj.getBlockId(var7, var8, var9);
690
691 if (BlockRail.isRailBlock(var10))
692 {
693 int var11 = ((BlockRail)Block.blocksList[var10]).getBasicRailMetadata(worldObj, this, var7, var8, var9);
694 par3 = (double)var8;
695
696 if (var11 >= 2 && var11 <= 5)
697 {
698 par3 = (double)(var8 + 1);
699 }
700
701 int[][] var12 = field_70500_g[var11];
702 double var13 = 0.0D;
703 double var15 = (double)var7 + 0.5D + (double)var12[0][0] * 0.5D;
704 double var17 = (double)var8 + 0.5D + (double)var12[0][1] * 0.5D;
705 double var19 = (double)var9 + 0.5D + (double)var12[0][2] * 0.5D;
706 double var21 = (double)var7 + 0.5D + (double)var12[1][0] * 0.5D;
707 double var23 = (double)var8 + 0.5D + (double)var12[1][1] * 0.5D;
708 double var25 = (double)var9 + 0.5D + (double)var12[1][2] * 0.5D;
709 double var27 = var21 - var15;
710 double var29 = (var23 - var17) * 2.0D;
711 double var31 = var25 - var19;
712
713 if (var27 == 0.0D)
714 {
715 par1 = (double)var7 + 0.5D;
716 var13 = par5 - (double)var9;
717 }
718 else if (var31 == 0.0D)
719 {
720 par5 = (double)var9 + 0.5D;
721 var13 = par1 - (double)var7;
722 }
723 else
724 {
725 double var33 = par1 - var15;
726 double var35 = par5 - var19;
727 var13 = (var33 * var27 + var35 * var31) * 2.0D;
728 }
729
730 par1 = var15 + var27 * var13;
731 par3 = var17 + var29 * var13;
732 par5 = var19 + var31 * var13;
733
734 if (var29 < 0.0D)
735 {
736 ++par3;
737 }
738
739 if (var29 > 0.0D)
740 {
741 par3 += 0.5D;
742 }
743
744 return this.worldObj.getWorldVec3Pool().getVecFromPool(par1, par3, par5);
745 }
746 else
747 {
748 return null;
749 }
750 }
751
752 /**
753 * (abstract) Protected helper method to write subclass entity data to NBT.
754 */
755 protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
756 {
757 par1NBTTagCompound.setInteger("Type", this.minecartType);
758
759 if (isPoweredCart())
760 {
761 par1NBTTagCompound.setDouble("PushX", this.pushX);
762 par1NBTTagCompound.setDouble("PushZ", this.pushZ);
763 par1NBTTagCompound.setInteger("Fuel", this.fuel);
764 }
765
766 if (getSizeInventory() > 0)
767 {
768 NBTTagList var2 = new NBTTagList();
769
770 for (int var3 = 0; var3 < this.cargoItems.length; ++var3)
771 {
772 if (this.cargoItems[var3] != null)
773 {
774 NBTTagCompound var4 = new NBTTagCompound();
775 var4.setByte("Slot", (byte)var3);
776 this.cargoItems[var3].writeToNBT(var4);
777 var2.appendTag(var4);
778 }
779 }
780
781 par1NBTTagCompound.setTag("Items", var2);
782 }
783 }
784
785 /**
786 * (abstract) Protected helper method to read subclass entity data from NBT.
787 */
788 protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
789 {
790 this.minecartType = par1NBTTagCompound.getInteger("Type");
791
792 if (isPoweredCart())
793 {
794 this.pushX = par1NBTTagCompound.getDouble("PushX");
795 this.pushZ = par1NBTTagCompound.getDouble("PushZ");
796 try
797 {
798 this.fuel = par1NBTTagCompound.getInteger("Fuel");
799 }
800 catch (ClassCastException e)
801 {
802 this.fuel = par1NBTTagCompound.getShort("Fuel");
803 }
804 }
805
806 if (getSizeInventory() > 0)
807 {
808 NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
809 this.cargoItems = new ItemStack[this.getSizeInventory()];
810
811 for (int var3 = 0; var3 < var2.tagCount(); ++var3)
812 {
813 NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
814 int var5 = var4.getByte("Slot") & 255;
815
816 if (var5 >= 0 && var5 < this.cargoItems.length)
817 {
818 this.cargoItems[var5] = ItemStack.loadItemStackFromNBT(var4);
819 }
820 }
821 }
822 }
823
824 @SideOnly(Side.CLIENT)
825 public float getShadowSize()
826 {
827 return 0.0F;
828 }
829
830 /**
831 * Applies a velocity to each of the entities pushing them away from each other. Args: entity
832 */
833 public void applyEntityCollision(Entity par1Entity)
834 {
835 MinecraftForge.EVENT_BUS.post(new MinecartCollisionEvent(this, par1Entity));
836 if (getCollisionHandler() != null)
837 {
838 getCollisionHandler().onEntityCollision(this, par1Entity);
839 return;
840 }
841 if (!this.worldObj.isRemote)
842 {
843 if (par1Entity != this.riddenByEntity)
844 {
845 if (par1Entity instanceof EntityLiving && !(par1Entity instanceof EntityPlayer) && !(par1Entity instanceof EntityIronGolem) && canBeRidden() && this.motionX * this.motionX + this.motionZ * this.motionZ > 0.01D && this.riddenByEntity == null && par1Entity.ridingEntity == null)
846 {
847 par1Entity.mountEntity(this);
848 }
849
850 double var2 = par1Entity.posX - this.posX;
851 double var4 = par1Entity.posZ - this.posZ;
852 double var6 = var2 * var2 + var4 * var4;
853
854 if (var6 >= 9.999999747378752E-5D)
855 {
856 var6 = (double)MathHelper.sqrt_double(var6);
857 var2 /= var6;
858 var4 /= var6;
859 double var8 = 1.0D / var6;
860
861 if (var8 > 1.0D)
862 {
863 var8 = 1.0D;
864 }
865
866 var2 *= var8;
867 var4 *= var8;
868 var2 *= 0.10000000149011612D;
869 var4 *= 0.10000000149011612D;
870 var2 *= (double)(1.0F - this.entityCollisionReduction);
871 var4 *= (double)(1.0F - this.entityCollisionReduction);
872 var2 *= 0.5D;
873 var4 *= 0.5D;
874
875 if (par1Entity instanceof EntityMinecart)
876 {
877 double var10 = par1Entity.posX - this.posX;
878 double var12 = par1Entity.posZ - this.posZ;
879 Vec3 var14 = this.worldObj.getWorldVec3Pool().getVecFromPool(var10, 0.0D, var12).normalize();
880 Vec3 var15 = this.worldObj.getWorldVec3Pool().getVecFromPool((double)MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F), 0.0D, (double)MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F)).normalize();
881 double var16 = Math.abs(var14.dotProduct(var15));
882
883 if (var16 < 0.800000011920929D)
884 {
885 return;
886 }
887
888 double var18 = par1Entity.motionX + this.motionX;
889 double var20 = par1Entity.motionZ + this.motionZ;
890
891 if (((EntityMinecart)par1Entity).isPoweredCart() && !isPoweredCart())
892 {
893 this.motionX *= 0.20000000298023224D;
894 this.motionZ *= 0.20000000298023224D;
895 this.addVelocity(par1Entity.motionX - var2, 0.0D, par1Entity.motionZ - var4);
896 par1Entity.motionX *= 0.949999988079071D;
897 par1Entity.motionZ *= 0.949999988079071D;
898 }
899 else if (!((EntityMinecart)par1Entity).isPoweredCart() && isPoweredCart())
900 {
901 par1Entity.motionX *= 0.20000000298023224D;
902 par1Entity.motionZ *= 0.20000000298023224D;
903 par1Entity.addVelocity(this.motionX + var2, 0.0D, this.motionZ + var4);
904 this.motionX *= 0.949999988079071D;
905 this.motionZ *= 0.949999988079071D;
906 }
907 else
908 {
909 var18 /= 2.0D;
910 var20 /= 2.0D;
911 this.motionX *= 0.20000000298023224D;
912 this.motionZ *= 0.20000000298023224D;
913 this.addVelocity(var18 - var2, 0.0D, var20 - var4);
914 par1Entity.motionX *= 0.20000000298023224D;
915 par1Entity.motionZ *= 0.20000000298023224D;
916 par1Entity.addVelocity(var18 + var2, 0.0D, var20 + var4);
917 }
918 }
919 else
920 {
921 this.addVelocity(-var2, 0.0D, -var4);
922 par1Entity.addVelocity(var2 / 4.0D, 0.0D, var4 / 4.0D);
923 }
924 }
925 }
926 }
927 }
928
929 /**
930 * Returns the number of slots in the inventory.
931 */
932 public int getSizeInventory()
933 {
934 return (minecartType == 1 && getClass() == EntityMinecart.class ? 27 : 0);
935 }
936
937 /**
938 * Returns the stack in slot i
939 */
940 public ItemStack getStackInSlot(int par1)
941 {
942 return this.cargoItems[par1];
943 }
944
945 /**
946 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
947 * new stack.
948 */
949 public ItemStack decrStackSize(int par1, int par2)
950 {
951 if (this.cargoItems[par1] != null)
952 {
953 ItemStack var3;
954
955 if (this.cargoItems[par1].stackSize <= par2)
956 {
957 var3 = this.cargoItems[par1];
958 this.cargoItems[par1] = null;
959 return var3;
960 }
961 else
962 {
963 var3 = this.cargoItems[par1].splitStack(par2);
964
965 if (this.cargoItems[par1].stackSize == 0)
966 {
967 this.cargoItems[par1] = null;
968 }
969
970 return var3;
971 }
972 }
973 else
974 {
975 return null;
976 }
977 }
978
979 /**
980 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
981 * like when you close a workbench GUI.
982 */
983 public ItemStack getStackInSlotOnClosing(int par1)
984 {
985 if (this.cargoItems[par1] != null)
986 {
987 ItemStack var2 = this.cargoItems[par1];
988 this.cargoItems[par1] = null;
989 return var2;
990 }
991 else
992 {
993 return null;
994 }
995 }
996
997 /**
998 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
999 */
1000 public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
1001 {
1002 this.cargoItems[par1] = par2ItemStack;
1003
1004 if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
1005 {
1006 par2ItemStack.stackSize = this.getInventoryStackLimit();
1007 }
1008 }
1009
1010 /**
1011 * Returns the name of the inventory.
1012 */
1013 public String getInvName()
1014 {
1015 return "container.minecart";
1016 }
1017
1018 /**
1019 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
1020 * this more of a set than a get?*
1021 */
1022 public int getInventoryStackLimit()
1023 {
1024 return 64;
1025 }
1026
1027 /**
1028 * Called when an the contents of an Inventory change, usually
1029 */
1030 public void onInventoryChanged() {}
1031
1032 /**
1033 * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
1034 */
1035 public boolean interact(EntityPlayer par1EntityPlayer)
1036 {
1037 if (MinecraftForge.EVENT_BUS.post(new MinecartInteractEvent(this, par1EntityPlayer)))
1038 {
1039 return true;
1040 }
1041
1042 if (canBeRidden())
1043 {
1044 if (this.riddenByEntity != null && this.riddenByEntity instanceof EntityPlayer && this.riddenByEntity != par1EntityPlayer)
1045 {
1046 return true;
1047 }
1048
1049 if (!this.worldObj.isRemote)
1050 {
1051 par1EntityPlayer.mountEntity(this);
1052 }
1053 }
1054 else if (getSizeInventory() > 0)
1055 {
1056 if (!this.worldObj.isRemote)
1057 {
1058 par1EntityPlayer.displayGUIChest(this);
1059 }
1060 }
1061 else if (this.minecartType == 2 && getClass() == EntityMinecart.class)
1062 {
1063 ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
1064
1065 if (var2 != null && var2.itemID == Item.coal.shiftedIndex)
1066 {
1067 if (--var2.stackSize == 0)
1068 {
1069 par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack)null);
1070 }
1071
1072 this.fuel += 3600;
1073 }
1074
1075 this.pushX = this.posX - par1EntityPlayer.posX;
1076 this.pushZ = this.posZ - par1EntityPlayer.posZ;
1077 }
1078
1079 return true;
1080 }
1081
1082 @SideOnly(Side.CLIENT)
1083
1084 /**
1085 * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
1086 * posY, posZ, yaw, pitch
1087 */
1088 public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
1089 {
1090 this.minecartX = par1;
1091 this.minecartY = par3;
1092 this.minecartZ = par5;
1093 this.minecartYaw = (double)par7;
1094 this.minecartPitch = (double)par8;
1095 this.turnProgress = par9 + 2;
1096 this.motionX = this.velocityX;
1097 this.motionY = this.velocityY;
1098 this.motionZ = this.velocityZ;
1099 }
1100
1101 @SideOnly(Side.CLIENT)
1102
1103 /**
1104 * Sets the velocity to the args. Args: x, y, z
1105 */
1106 public void setVelocity(double par1, double par3, double par5)
1107 {
1108 this.velocityX = this.motionX = par1;
1109 this.velocityY = this.motionY = par3;
1110 this.velocityZ = this.motionZ = par5;
1111 }
1112
1113 /**
1114 * Do not make give this method the name canInteractWith because it clashes with Container
1115 */
1116 public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
1117 {
1118 return this.isDead ? false : par1EntityPlayer.getDistanceSqToEntity(this) <= 64.0D;
1119 }
1120
1121 /**
1122 * Is this minecart powered (Fuel > 0)
1123 */
1124 public boolean isMinecartPowered()
1125 {
1126 return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
1127 }
1128
1129 /**
1130 * Set if this minecart is powered (Fuel > 0)
1131 */
1132 protected void setMinecartPowered(boolean par1)
1133 {
1134 if (par1)
1135 {
1136 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(this.dataWatcher.getWatchableObjectByte(16) | 1)));
1137 }
1138 else
1139 {
1140 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(this.dataWatcher.getWatchableObjectByte(16) & -2)));
1141 }
1142 }
1143
1144 public void openChest() {}
1145
1146 public void closeChest() {}
1147
1148 /**
1149 * Sets the current amount of damage the minecart has taken. Decreases over time. The cart breaks when this is over
1150 * 40.
1151 */
1152 public void setDamage(int par1)
1153 {
1154 this.dataWatcher.updateObject(19, Integer.valueOf(par1));
1155 }
1156
1157 /**
1158 * Gets the current amount of damage the minecart has taken. Decreases over time. The cart breaks when this is over
1159 * 40.
1160 */
1161 public int getDamage()
1162 {
1163 return this.dataWatcher.getWatchableObjectInt(19);
1164 }
1165
1166 public void func_70497_h(int par1)
1167 {
1168 this.dataWatcher.updateObject(17, Integer.valueOf(par1));
1169 }
1170
1171 public int func_70496_j()
1172 {
1173 return this.dataWatcher.getWatchableObjectInt(17);
1174 }
1175
1176 public void func_70494_i(int par1)
1177 {
1178 this.dataWatcher.updateObject(18, Integer.valueOf(par1));
1179 }
1180
1181 public int func_70493_k()
1182 {
1183 return this.dataWatcher.getWatchableObjectInt(18);
1184 }
1185
1186 /**
1187 * Drops the cart as a item. The exact item dropped is defined by getItemDropped().
1188 */
1189 public void dropCartAsItem()
1190 {
1191 for(ItemStack item : getItemsDropped())
1192 {
1193 entityDropItem(item, 0);
1194 }
1195 }
1196
1197 /**
1198 * Override this to define which items your cart drops when broken.
1199 * This does not include items contained in the inventory,
1200 * that is handled elsewhere.
1201 * @return A list of items dropped.
1202 */
1203 public List<ItemStack> getItemsDropped()
1204 {
1205 List<ItemStack> items = new ArrayList<ItemStack>();
1206 items.add(new ItemStack(Item.minecartEmpty));
1207
1208 switch(minecartType)
1209 {
1210 case 1:
1211 items.add(new ItemStack(Block.chest));
1212 break;
1213 case 2:
1214 items.add(new ItemStack(Block.stoneOvenIdle));
1215 break;
1216 }
1217 return items;
1218 }
1219
1220 /**
1221 * This function returns an ItemStack that represents this cart.
1222 * This should be an ItemStack that can be used by the player to place the cart.
1223 * This is the item that was registered with the cart via the registerMinecart function,
1224 * but is not necessary the item the cart drops when destroyed.
1225 * @return An ItemStack that can be used to place the cart.
1226 */
1227 public ItemStack getCartItem()
1228 {
1229 return MinecartRegistry.getItemForCart(this);
1230 }
1231
1232 /**
1233 * Returns true if this cart is self propelled.
1234 * @return True if powered.
1235 */
1236 public boolean isPoweredCart()
1237 {
1238 return minecartType == 2 && getClass() == EntityMinecart.class;
1239 }
1240
1241 /**
1242 * Returns true if this cart is a storage cart
1243 * Some carts may have inventories but not be storage carts
1244 * and some carts without inventories may be storage carts.
1245 * @return True if this cart should be classified as a storage cart.
1246 */
1247 public boolean isStorageCart()
1248 {
1249 return minecartType == 1 && getClass() == EntityMinecart.class;
1250 }
1251
1252 /**
1253 * Returns true if this cart can be ridden by an Entity.
1254 * @return True if this cart can be ridden.
1255 */
1256 public boolean canBeRidden()
1257 {
1258 if(minecartType == 0 && getClass() == EntityMinecart.class)
1259 {
1260 return true;
1261 }
1262 return false;
1263 }
1264
1265 /**
1266 * Returns true if this cart can currently use rails.
1267 * This function is mainly used to gracefully detach a minecart from a rail.
1268 * @return True if the minecart can use rails.
1269 */
1270 public boolean canUseRail()
1271 {
1272 return canUseRail;
1273 }
1274
1275 /**
1276 * Set whether the minecart can use rails.
1277 * This function is mainly used to gracefully detach a minecart from a rail.
1278 * @param use Whether the minecart can currently use rails.
1279 */
1280 public void setCanUseRail(boolean use)
1281 {
1282 canUseRail = use;
1283 }
1284
1285 /**
1286 * Return false if this cart should not call IRail.onMinecartPass() and should ignore Powered Rails.
1287 * @return True if this cart should call IRail.onMinecartPass().
1288 */
1289 public boolean shouldDoRailFunctions()
1290 {
1291 return true;
1292 }
1293
1294 /**
1295 * Simply returns the minecartType variable.
1296 * @return minecartType
1297 */
1298 public int getMinecartType()
1299 {
1300 return minecartType;
1301 }
1302
1303 /**
1304 * Gets the current global Minecart Collision handler if none
1305 * is registered, returns null
1306 * @return The collision handler or null
1307 */
1308 public static IMinecartCollisionHandler getCollisionHandler()
1309 {
1310 return collisionHandler;
1311 }
1312
1313 /**
1314 * Sets the global Minecart Collision handler, overwrites any
1315 * that is currently set.
1316 * @param handler The new handler
1317 */
1318 public static void setCollisionHandler(IMinecartCollisionHandler handler)
1319 {
1320 collisionHandler = handler;
1321 }
1322
1323 /**
1324 * Carts should return their drag factor here
1325 * @return The drag rate.
1326 */
1327 protected double getDrag()
1328 {
1329 return riddenByEntity != null ? defaultDragRidden : defaultDragEmpty;
1330 }
1331
1332 /**
1333 * Moved to allow overrides.
1334 * This code applies drag and updates push forces.
1335 */
1336 protected void applyDragAndPushForces()
1337 {
1338 if(isPoweredCart())
1339 {
1340 double d27 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ);
1341 if(d27 > 0.01D)
1342 {
1343 pushX /= d27;
1344 pushZ /= d27;
1345 double d29 = 0.04;
1346 motionX *= 0.8D;
1347 motionY *= 0.0D;
1348 motionZ *= 0.8D;
1349 motionX += pushX * d29;
1350 motionZ += pushZ * d29;
1351 }
1352 else
1353 {
1354 motionX *= 0.9D;
1355 motionY *= 0.0D;
1356 motionZ *= 0.9D;
1357 }
1358 }
1359 motionX *= getDrag();
1360 motionY *= 0.0D;
1361 motionZ *= getDrag();
1362 }
1363
1364 /**
1365 * Moved to allow overrides.
1366 * This code updates push forces.
1367 */
1368 protected void updatePushForces()
1369 {
1370 if(isPoweredCart())
1371 {
1372 double push = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ);
1373 if(push > 0.01D && motionX * motionX + motionZ * motionZ > 0.001D)
1374 {
1375 pushX /= push;
1376 pushZ /= push;
1377 if(pushX * motionX + pushZ * motionZ < 0.0D)
1378 {
1379 pushX = 0.0D;
1380 pushZ = 0.0D;
1381 }
1382 else
1383 {
1384 pushX = motionX;
1385 pushZ = motionZ;
1386 }
1387 }
1388 }
1389 }
1390
1391 /**
1392 * Moved to allow overrides.
1393 * This code handles minecart movement and speed capping when on a rail.
1394 */
1395 protected void moveMinecartOnRail(int i, int j, int k)
1396 {
1397 int id = worldObj.getBlockId(i, j, k);
1398 if (!BlockRail.isRailBlock(id))
1399 {
1400 return;
1401 }
1402 float railMaxSpeed = ((BlockRail)Block.blocksList[id]).getRailMaxSpeed(worldObj, this, i, j, k);
1403
1404 double maxSpeed = Math.min(railMaxSpeed, getMaxSpeedRail());
1405 double mX = motionX;
1406 double mZ = motionZ;
1407 if(riddenByEntity != null)
1408 {
1409 mX *= 0.75D;
1410 mZ *= 0.75D;
1411 }
1412 if(mX < -maxSpeed) mX = -maxSpeed;
1413 if(mX > maxSpeed) mX = maxSpeed;
1414 if(mZ < -maxSpeed) mZ = -maxSpeed;
1415 if(mZ > maxSpeed) mZ = maxSpeed;
1416 moveEntity(mX, 0.0D, mZ);
1417 }
1418
1419 /**
1420 * Moved to allow overrides.
1421 * This code handles minecart movement and speed capping when not on a rail.
1422 */
1423 protected void moveMinecartOffRail(int i, int j, int k)
1424 {
1425 double d2 = getMaxSpeedGround();
1426 if(!onGround)
1427 {
1428 d2 = getMaxSpeedAirLateral();
1429 }
1430 if(motionX < -d2) motionX = -d2;
1431 if(motionX > d2) motionX = d2;
1432 if(motionZ < -d2) motionZ = -d2;
1433 if(motionZ > d2) motionZ = d2;
1434 double moveY = motionY;
1435 if(getMaxSpeedAirVertical() > 0 && motionY > getMaxSpeedAirVertical())
1436 {
1437 moveY = getMaxSpeedAirVertical();
1438 if(Math.abs(motionX) < 0.3f && Math.abs(motionZ) < 0.3f)
1439 {
1440 moveY = 0.15f;
1441 motionY = moveY;
1442 }
1443 }
1444 if(onGround)
1445 {
1446 motionX *= 0.5D;
1447 motionY *= 0.5D;
1448 motionZ *= 0.5D;
1449 }
1450 moveEntity(motionX, moveY, motionZ);
1451 if(!onGround)
1452 {
1453 motionX *= getDragAir();
1454 motionY *= getDragAir();
1455 motionZ *= getDragAir();
1456 }
1457 }
1458
1459 /**
1460 * Moved to allow overrides.
1461 * This code applies fuel consumption.
1462 */
1463 protected void updateFuel()
1464 {
1465 if (fuel > 0) fuel--;
1466 if (fuel <= 0) pushX = pushZ = 0.0D;
1467 setMinecartPowered(fuel > 0);
1468 }
1469
1470 /**
1471 * Moved to allow overrides, This code handle slopes affecting velocity.
1472 * @param metadata The blocks position metadata
1473 */
1474 protected void adjustSlopeVelocities(int metadata)
1475 {
1476 double acceleration = 0.0078125D;
1477 if (metadata == 2)
1478 {
1479 motionX -= acceleration;
1480 }
1481 else if (metadata == 3)
1482 {
1483 motionX += acceleration;
1484 }
1485 else if (metadata == 4)
1486 {
1487 motionZ += acceleration;
1488 }
1489 else if (metadata == 5)
1490 {
1491 motionZ -= acceleration;
1492 }
1493 }
1494
1495 /**
1496 * Getters/setters for physics variables
1497 */
1498
1499 /**
1500 * Returns the carts max speed.
1501 * Carts going faster than 1.1 cause issues with chunk loading.
1502 * Carts cant traverse slopes or corners at greater than 0.5 - 0.6.
1503 * This value is compared with the rails max speed to determine
1504 * the carts current max speed. A normal rails max speed is 0.4.
1505 * @return Carts max speed.
1506 */
1507 public float getMaxSpeedRail()
1508 {
1509 return maxSpeedRail;
1510 }
1511
1512 public void setMaxSpeedRail(float value)
1513 {
1514 maxSpeedRail = value;
1515 }
1516
1517 public float getMaxSpeedGround()
1518 {
1519 return maxSpeedGround;
1520 }
1521
1522 public void setMaxSpeedGround(float value)
1523 {
1524 maxSpeedGround = value;
1525 }
1526
1527 public float getMaxSpeedAirLateral()
1528 {
1529 return maxSpeedAirLateral;
1530 }
1531
1532 public void setMaxSpeedAirLateral(float value)
1533 {
1534 maxSpeedAirLateral = value;
1535 }
1536
1537 public float getMaxSpeedAirVertical()
1538 {
1539 return maxSpeedAirVertical;
1540 }
1541
1542 public void setMaxSpeedAirVertical(float value)
1543 {
1544 maxSpeedAirVertical = value;
1545 }
1546
1547 public double getDragAir()
1548 {
1549 return dragAir;
1550 }
1551
1552 public void setDragAir(double value)
1553 {
1554 dragAir = value;
1555 }
1556 }