--- ../src_base/common/net/minecraft/src/EntityMinecart.java +++ ../src_work/common/net/minecraft/src/EntityMinecart.java @@ -2,7 +2,15 @@ import cpw.mods.fml.common.Side; import cpw.mods.fml.common.asm.SideOnly; + +import java.util.ArrayList; import java.util.List; +import net.minecraftforge.common.IMinecartCollisionHandler; +import net.minecraftforge.common.MinecartRegistry; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.minecart.MinecartCollisionEvent; +import net.minecraftforge.event.entity.minecart.MinecartInteractEvent; +import net.minecraftforge.event.entity.minecart.MinecartUpdateEvent; public class EntityMinecart extends Entity implements IInventory { @@ -31,6 +39,25 @@ @SideOnly(Side.CLIENT) protected double velocityZ; + /* Forge: Minecart Compatibility Layer Integration. */ + public static float defaultMaxSpeedRail = 0.4f; + public static float defaultMaxSpeedGround = 0.4f; + public static float defaultMaxSpeedAirLateral = 0.4f; + public static float defaultMaxSpeedAirVertical = -1f; + public static double defaultDragRidden = 0.996999979019165D; + public static double defaultDragEmpty = 0.9599999785423279D; + public static double defaultDragAir = 0.94999998807907104D; + protected boolean canUseRail = true; + protected boolean canBePushed = true; + private static IMinecartCollisionHandler collisionHandler = null; + + /* Instance versions of the above physics properties */ + protected float maxSpeedRail; + protected float maxSpeedGround; + protected float maxSpeedAirLateral; + protected float maxSpeedAirVertical; + protected double dragAir; + public EntityMinecart(World par1World) { super(par1World); @@ -40,6 +65,18 @@ this.preventEntitySpawning = true; this.setSize(0.98F, 0.7F); this.yOffset = this.height / 2.0F; + + maxSpeedRail = defaultMaxSpeedRail; + maxSpeedGround = defaultMaxSpeedGround; + maxSpeedAirLateral = defaultMaxSpeedAirLateral; + maxSpeedAirVertical = defaultMaxSpeedAirVertical; + dragAir = defaultDragAir; + } + + public EntityMinecart(World world, int type) + { + this(world); + minecartType = type; } /** @@ -65,6 +102,10 @@ */ public AxisAlignedBB getCollisionBox(Entity par1Entity) { + if (getCollisionHandler() != null) + { + return getCollisionHandler().getCollisionBox(this, par1Entity); + } return par1Entity.boundingBox; } @@ -73,6 +114,10 @@ */ public AxisAlignedBB getBoundingBox() { + if (getCollisionHandler() != null) + { + return getCollisionHandler().getBoundingBox(this); + } return null; } @@ -81,7 +126,7 @@ */ public boolean canBePushed() { - return true; + return canBePushed; } public EntityMinecart(World par1World, double par2, double par4, double par6, int par8) @@ -130,48 +175,7 @@ } this.setDead(); - this.dropItemWithOffset(Item.minecartEmpty.shiftedIndex, 1, 0.0F); - - if (this.minecartType == 1) - { - EntityMinecart var3 = this; - - for (int var4 = 0; var4 < var3.getSizeInventory(); ++var4) - { - ItemStack var5 = var3.getStackInSlot(var4); - - if (var5 != null) - { - float var6 = this.rand.nextFloat() * 0.8F + 0.1F; - float var7 = this.rand.nextFloat() * 0.8F + 0.1F; - float var8 = this.rand.nextFloat() * 0.8F + 0.1F; - - while (var5.stackSize > 0) - { - int var9 = this.rand.nextInt(21) + 10; - - if (var9 > var5.stackSize) - { - var9 = var5.stackSize; - } - - var5.stackSize -= var9; - EntityItem var10 = new EntityItem(this.worldObj, this.posX + (double)var6, this.posY + (double)var7, this.posZ + (double)var8, new ItemStack(var5.itemID, var9, var5.getItemDamage())); - float var11 = 0.05F; - var10.motionX = (double)((float)this.rand.nextGaussian() * var11); - var10.motionY = (double)((float)this.rand.nextGaussian() * var11 + 0.2F); - var10.motionZ = (double)((float)this.rand.nextGaussian() * var11); - this.worldObj.spawnEntityInWorld(var10); - } - } - } - - this.dropItemWithOffset(Block.chest.blockID, 1, 0.0F); - } - else if (this.minecartType == 2) - { - this.dropItemWithOffset(Block.stoneOvenIdle.blockID, 1, 0.0F); - } + dropCartAsItem(); } return true; @@ -266,7 +270,7 @@ this.kill(); } - if (this.isMinecartPowered() && this.rand.nextInt(4) == 0) + if (this.isMinecartPowered() && this.rand.nextInt(4) == 0 && minecartType == 2 && getClass() == EntityMinecart.class) { this.worldObj.spawnParticle("largesmoke", this.posX, this.posY + 0.8D, this.posZ, 0.0D, 0.0D, 0.0D); } @@ -310,17 +314,17 @@ double var6 = 0.0078125D; int var8 = this.worldObj.getBlockId(var1, var2, var3); - if (BlockRail.isRailBlock(var8)) + if (canUseRail() && BlockRail.isRailBlock(var8)) { Vec3 var9 = this.func_70489_a(this.posX, this.posY, this.posZ); - int var10 = this.worldObj.getBlockMetadata(var1, var2, var3); + int var10 = ((BlockRail)Block.blocksList[var8]).getBasicRailMetadata(worldObj, this, var1, var2, var3); this.posY = (double)var2; boolean var11 = false; boolean var12 = false; if (var8 == Block.railPowered.blockID) { - var11 = (var10 & 8) != 0; + var11 = (worldObj.getBlockMetadata(var1, var2, var3) & 8) != 0; var12 = !var11; } @@ -334,25 +338,7 @@ this.posY = (double)(var2 + 1); } - if (var10 == 2) - { - this.motionX -= var6; - } - - if (var10 == 3) - { - this.motionX += var6; - } - - if (var10 == 4) - { - this.motionZ += var6; - } - - if (var10 == 5) - { - this.motionZ -= var6; - } + adjustSlopeVelocities(var10); int[][] var13 = field_70500_g[var10]; double var14 = (double)(var13[1][0] - var13[0][0]); @@ -385,7 +371,7 @@ } } - if (var12) + if (var12 && shouldDoRailFunctions()) { var24 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ); @@ -433,36 +419,8 @@ this.posX = var26 + var14 * var24; this.posZ = var28 + var16 * var24; this.setPosition(this.posX, this.posY + (double)this.yOffset, this.posZ); - var34 = this.motionX; - var36 = this.motionZ; - - if (this.riddenByEntity != null) - { - var34 *= 0.75D; - var36 *= 0.75D; - } - - if (var34 < -var4) - { - var34 = -var4; - } - - if (var34 > var4) - { - var34 = var4; - } - - if (var36 < -var4) - { - var36 = -var4; - } - - if (var36 > var4) - { - var36 = var4; - } - - this.moveEntity(var34, 0.0D, var36); + + moveMinecartOnRail(var1, var2, var3); if (var13[0][1] != 0 && MathHelper.floor_double(this.posX) - var1 == var13[0][0] && MathHelper.floor_double(this.posZ) - var3 == var13[0][2]) { @@ -473,42 +431,7 @@ this.setPosition(this.posX, this.posY + (double)var13[1][1], this.posZ); } - if (this.riddenByEntity != null) - { - this.motionX *= 0.996999979019165D; - this.motionY *= 0.0D; - this.motionZ *= 0.996999979019165D; - } - else - { - if (this.minecartType == 2) - { - double var38 = this.pushX * this.pushX + this.pushZ * this.pushZ; - - if (var38 > 1.0E-4D) - { - var38 = (double)MathHelper.sqrt_double(var38); - this.pushX /= var38; - this.pushZ /= var38; - double var40 = 0.04D; - this.motionX *= 0.800000011920929D; - this.motionY *= 0.0D; - this.motionZ *= 0.800000011920929D; - this.motionX += this.pushX * var40; - this.motionZ += this.pushZ * var40; - } - else - { - this.motionX *= 0.8999999761581421D; - this.motionY *= 0.0D; - this.motionZ *= 0.8999999761581421D; - } - } - - this.motionX *= 0.9599999785423279D; - this.motionY *= 0.0D; - this.motionZ *= 0.9599999785423279D; - } + applyDragAndPushForces(); Vec3 var52 = this.func_70489_a(this.posX, this.posY, this.posZ); @@ -538,30 +461,14 @@ double var41; - if (this.minecartType == 2) - { - var41 = this.pushX * this.pushX + this.pushZ * this.pushZ; - - if (var41 > 1.0E-4D && this.motionX * this.motionX + this.motionZ * this.motionZ > 0.001D) - { - var41 = (double)MathHelper.sqrt_double(var41); - this.pushX /= var41; - this.pushZ /= var41; - - if (this.pushX * this.motionX + this.pushZ * this.motionZ < 0.0D) - { - this.pushX = 0.0D; - this.pushZ = 0.0D; - } - else - { - this.pushX = this.motionX; - this.pushZ = this.motionZ; - } - } - } - - if (var11) + updatePushForces(); + + if(shouldDoRailFunctions()) + { + ((BlockRail)Block.blocksList[var8]).onMinecartPass(worldObj, this, var1, var2, var3); + } + + if (var11 && shouldDoRailFunctions()) { var41 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ); @@ -599,41 +506,7 @@ } else { - if (this.motionX < -var4) - { - this.motionX = -var4; - } - - if (this.motionX > var4) - { - this.motionX = var4; - } - - if (this.motionZ < -var4) - { - this.motionZ = -var4; - } - - if (this.motionZ > var4) - { - this.motionZ = var4; - } - - if (this.onGround) - { - this.motionX *= 0.5D; - this.motionY *= 0.5D; - this.motionZ *= 0.5D; - } - - this.moveEntity(this.motionX, this.motionY, this.motionZ); - - if (!this.onGround) - { - this.motionX *= 0.949999988079071D; - this.motionY *= 0.949999988079071D; - this.motionZ *= 0.949999988079071D; - } + moveMinecartOffRail(var1, var2, var3); } this.rotationPitch = 0.0F; @@ -659,7 +532,18 @@ } this.setRotation(this.rotationYaw, this.rotationPitch); - List var15 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D)); + + AxisAlignedBB box = null; + if (getCollisionHandler() != null) + { + box = getCollisionHandler().getMinecartCollisionBox(this); + } + else + { + box = boundingBox.expand(0.2D, 0.0D, 0.2D); + } + + List var15 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, box); if (var15 != null && !var15.isEmpty()) { @@ -684,17 +568,8 @@ this.riddenByEntity = null; } - if (this.fuel > 0) - { - --this.fuel; - } - - if (this.fuel <= 0) - { - this.pushX = this.pushZ = 0.0D; - } - - this.setMinecartPowered(this.fuel > 0); + updateFuel(); + MinecraftForge.EVENT_BUS.post(new MinecartUpdateEvent(this, var1, var2, var3)); } } @@ -718,12 +593,7 @@ } else { - int var13 = this.worldObj.getBlockMetadata(var9, var10, var11); - - if (((BlockRail)Block.blocksList[var12]).isPowered()) - { - var13 &= 7; - } + int var13 = ((BlockRail)Block.blocksList[var12]).getBasicRailMetadata(worldObj, this, var9, var10, var11); par3 = (double)var10; @@ -769,13 +639,8 @@ if (BlockRail.isRailBlock(var10)) { - int var11 = this.worldObj.getBlockMetadata(var7, var8, var9); + int var11 = ((BlockRail)Block.blocksList[var10]).getBasicRailMetadata(worldObj, this, var7, var8, var9); par3 = (double)var8; - - if (((BlockRail)Block.blocksList[var10]).isPowered()) - { - var11 &= 7; - } if (var11 >= 2 && var11 <= 5) { @@ -840,13 +705,14 @@ { par1NBTTagCompound.setInteger("Type", this.minecartType); - if (this.minecartType == 2) + if (isPoweredCart()) { par1NBTTagCompound.setDouble("PushX", this.pushX); par1NBTTagCompound.setDouble("PushZ", this.pushZ); - par1NBTTagCompound.setShort("Fuel", (short)this.fuel); - } - else if (this.minecartType == 1) + par1NBTTagCompound.setInteger("Fuel", this.fuel); + } + + if (getSizeInventory() > 0) { NBTTagList var2 = new NBTTagList(); @@ -872,13 +738,21 @@ { this.minecartType = par1NBTTagCompound.getInteger("Type"); - if (this.minecartType == 2) + if (isPoweredCart()) { this.pushX = par1NBTTagCompound.getDouble("PushX"); this.pushZ = par1NBTTagCompound.getDouble("PushZ"); - this.fuel = par1NBTTagCompound.getShort("Fuel"); - } - else if (this.minecartType == 1) + try + { + this.fuel = par1NBTTagCompound.getInteger("Fuel"); + } + catch (ClassCastException e) + { + this.fuel = par1NBTTagCompound.getShort("Fuel"); + } + } + + if (getSizeInventory() > 0) { NBTTagList var2 = par1NBTTagCompound.getTagList("Items"); this.cargoItems = new ItemStack[this.getSizeInventory()]; @@ -907,11 +781,17 @@ */ public void applyEntityCollision(Entity par1Entity) { + MinecraftForge.EVENT_BUS.post(new MinecartCollisionEvent(this, par1Entity)); + if (getCollisionHandler() != null) + { + getCollisionHandler().onEntityCollision(this, par1Entity); + return; + } if (!this.worldObj.isRemote) { if (par1Entity != this.riddenByEntity) { - if (par1Entity instanceof EntityLiving && !(par1Entity instanceof EntityPlayer) && !(par1Entity instanceof EntityIronGolem) && this.minecartType == 0 && this.motionX * this.motionX + this.motionZ * this.motionZ > 0.01D && this.riddenByEntity == null && par1Entity.ridingEntity == null) + 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) { par1Entity.mountEntity(this); } @@ -957,7 +837,7 @@ double var18 = par1Entity.motionX + this.motionX; double var20 = par1Entity.motionZ + this.motionZ; - if (((EntityMinecart)par1Entity).minecartType == 2 && this.minecartType != 2) + if (((EntityMinecart)par1Entity).isPoweredCart() && !isPoweredCart()) { this.motionX *= 0.20000000298023224D; this.motionZ *= 0.20000000298023224D; @@ -965,7 +845,7 @@ par1Entity.motionX *= 0.949999988079071D; par1Entity.motionZ *= 0.949999988079071D; } - else if (((EntityMinecart)par1Entity).minecartType != 2 && this.minecartType == 2) + else if (!((EntityMinecart)par1Entity).isPoweredCart() && isPoweredCart()) { par1Entity.motionX *= 0.20000000298023224D; par1Entity.motionZ *= 0.20000000298023224D; @@ -1000,7 +880,7 @@ */ public int getSizeInventory() { - return 27; + return (minecartType == 1 && getClass() == EntityMinecart.class ? 27 : 0); } /** @@ -1103,7 +983,12 @@ */ public boolean interact(EntityPlayer par1EntityPlayer) { - if (this.minecartType == 0) + if (MinecraftForge.EVENT_BUS.post(new MinecartInteractEvent(this, par1EntityPlayer))) + { + return true; + } + + if (canBeRidden()) { if (this.riddenByEntity != null && this.riddenByEntity instanceof EntityPlayer && this.riddenByEntity != par1EntityPlayer) { @@ -1115,14 +1000,14 @@ par1EntityPlayer.mountEntity(this); } } - else if (this.minecartType == 1) + else if (getSizeInventory() > 0) { if (!this.worldObj.isRemote) { par1EntityPlayer.displayGUIChest(this); } } - else if (this.minecartType == 2) + else if (this.minecartType == 2 && getClass() == EntityMinecart.class) { ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem(); @@ -1246,4 +1131,375 @@ { return this.dataWatcher.getWatchableObjectInt(18); } + + /** + * Drops the cart as a item. The exact item dropped is defined by getItemDropped(). + */ + public void dropCartAsItem() + { + for(ItemStack item : getItemsDropped()) + { + entityDropItem(item, 0); + } + } + + /** + * Override this to define which items your cart drops when broken. + * This does not include items contained in the inventory, + * that is handled elsewhere. + * @return A list of items dropped. + */ + public List getItemsDropped() + { + List items = new ArrayList(); + items.add(new ItemStack(Item.minecartEmpty)); + + switch(minecartType) + { + case 1: + items.add(new ItemStack(Block.chest)); + break; + case 2: + items.add(new ItemStack(Block.stoneOvenIdle)); + break; + } + return items; + } + + /** + * This function returns an ItemStack that represents this cart. + * This should be an ItemStack that can be used by the player to place the cart. + * This is the item that was registered with the cart via the registerMinecart function, + * but is not necessary the item the cart drops when destroyed. + * @return An ItemStack that can be used to place the cart. + */ + public ItemStack getCartItem() + { + return MinecartRegistry.getItemForCart(this); + } + + /** + * Returns true if this cart is self propelled. + * @return True if powered. + */ + public boolean isPoweredCart() + { + return minecartType == 2 && getClass() == EntityMinecart.class; + } + + /** + * Returns true if this cart is a storage cart + * Some carts may have inventories but not be storage carts + * and some carts without inventories may be storage carts. + * @return True if this cart should be classified as a storage cart. + */ + public boolean isStorageCart() + { + return minecartType == 1 && getClass() == EntityMinecart.class; + } + + /** + * Returns true if this cart can be ridden by an Entity. + * @return True if this cart can be ridden. + */ + public boolean canBeRidden() + { + if(minecartType == 0 && getClass() == EntityMinecart.class) + { + return true; + } + return false; + } + + /** + * Returns true if this cart can currently use rails. + * This function is mainly used to gracefully detach a minecart from a rail. + * @return True if the minecart can use rails. + */ + public boolean canUseRail() + { + return canUseRail; + } + + /** + * Set whether the minecart can use rails. + * This function is mainly used to gracefully detach a minecart from a rail. + * @param use Whether the minecart can currently use rails. + */ + public void setCanUseRail(boolean use) + { + canUseRail = use; + } + + /** + * Return false if this cart should not call IRail.onMinecartPass() and should ignore Powered Rails. + * @return True if this cart should call IRail.onMinecartPass(). + */ + public boolean shouldDoRailFunctions() + { + return true; + } + + /** + * Simply returns the minecartType variable. + * @return minecartType + */ + public int getMinecartType() + { + return minecartType; + } + + /** + * Gets the current global Minecart Collision handler if none + * is registered, returns null + * @return The collision handler or null + */ + public static IMinecartCollisionHandler getCollisionHandler() + { + return collisionHandler; + } + + /** + * Sets the global Minecart Collision handler, overwrites any + * that is currently set. + * @param handler The new handler + */ + public static void setCollisionHandler(IMinecartCollisionHandler handler) + { + collisionHandler = handler; + } + + /** + * Carts should return their drag factor here + * @return The drag rate. + */ + protected double getDrag() + { + return riddenByEntity != null ? defaultDragRidden : defaultDragEmpty; + } + + /** + * Moved to allow overrides. + * This code applies drag and updates push forces. + */ + protected void applyDragAndPushForces() + { + if(isPoweredCart()) + { + double d27 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); + if(d27 > 0.01D) + { + pushX /= d27; + pushZ /= d27; + double d29 = 0.04; + motionX *= 0.8D; + motionY *= 0.0D; + motionZ *= 0.8D; + motionX += pushX * d29; + motionZ += pushZ * d29; + } + else + { + motionX *= 0.9D; + motionY *= 0.0D; + motionZ *= 0.9D; + } + } + motionX *= getDrag(); + motionY *= 0.0D; + motionZ *= getDrag(); + } + + /** + * Moved to allow overrides. + * This code updates push forces. + */ + protected void updatePushForces() + { + if(isPoweredCart()) + { + double push = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); + if(push > 0.01D && motionX * motionX + motionZ * motionZ > 0.001D) + { + pushX /= push; + pushZ /= push; + if(pushX * motionX + pushZ * motionZ < 0.0D) + { + pushX = 0.0D; + pushZ = 0.0D; + } + else + { + pushX = motionX; + pushZ = motionZ; + } + } + } + } + + /** + * Moved to allow overrides. + * This code handles minecart movement and speed capping when on a rail. + */ + protected void moveMinecartOnRail(int i, int j, int k) + { + int id = worldObj.getBlockId(i, j, k); + if (!BlockRail.isRailBlock(id)) + { + return; + } + float railMaxSpeed = ((BlockRail)Block.blocksList[id]).getRailMaxSpeed(worldObj, this, i, j, k); + + double maxSpeed = Math.min(railMaxSpeed, getMaxSpeedRail()); + double mX = motionX; + double mZ = motionZ; + if(riddenByEntity != null) + { + mX *= 0.75D; + mZ *= 0.75D; + } + if(mX < -maxSpeed) mX = -maxSpeed; + if(mX > maxSpeed) mX = maxSpeed; + if(mZ < -maxSpeed) mZ = -maxSpeed; + if(mZ > maxSpeed) mZ = maxSpeed; + moveEntity(mX, 0.0D, mZ); + } + + /** + * Moved to allow overrides. + * This code handles minecart movement and speed capping when not on a rail. + */ + protected void moveMinecartOffRail(int i, int j, int k) + { + double d2 = getMaxSpeedGround(); + if(!onGround) + { + d2 = getMaxSpeedAirLateral(); + } + if(motionX < -d2) motionX = -d2; + if(motionX > d2) motionX = d2; + if(motionZ < -d2) motionZ = -d2; + if(motionZ > d2) motionZ = d2; + double moveY = motionY; + if(getMaxSpeedAirVertical() > 0 && motionY > getMaxSpeedAirVertical()) + { + moveY = getMaxSpeedAirVertical(); + if(Math.abs(motionX) < 0.3f && Math.abs(motionZ) < 0.3f) + { + moveY = 0.15f; + motionY = moveY; + } + } + if(onGround) + { + motionX *= 0.5D; + motionY *= 0.5D; + motionZ *= 0.5D; + } + moveEntity(motionX, moveY, motionZ); + if(!onGround) + { + motionX *= getDragAir(); + motionY *= getDragAir(); + motionZ *= getDragAir(); + } + } + + /** + * Moved to allow overrides. + * This code applies fuel consumption. + */ + protected void updateFuel() + { + if (fuel > 0) fuel--; + if (fuel <= 0) pushX = pushZ = 0.0D; + setMinecartPowered(fuel > 0); + } + + /** + * Moved to allow overrides, This code handle slopes affecting velocity. + * @param metadata The blocks position metadata + */ + protected void adjustSlopeVelocities(int metadata) + { + double acceleration = 0.0078125D; + if (metadata == 2) + { + motionX -= acceleration; + } + else if (metadata == 3) + { + motionX += acceleration; + } + else if (metadata == 4) + { + motionZ += acceleration; + } + else if (metadata == 5) + { + motionZ -= acceleration; + } + } + + /** + * Getters/setters for physics variables + */ + + /** + * Returns the carts max speed. + * Carts going faster than 1.1 cause issues with chunk loading. + * Carts cant traverse slopes or corners at greater than 0.5 - 0.6. + * This value is compared with the rails max speed to determine + * the carts current max speed. A normal rails max speed is 0.4. + * @return Carts max speed. + */ + public float getMaxSpeedRail() + { + return maxSpeedRail; + } + + public void setMaxSpeedRail(float value) + { + maxSpeedRail = value; + } + + public float getMaxSpeedGround() + { + return maxSpeedGround; + } + + public void setMaxSpeedGround(float value) + { + maxSpeedGround = value; + } + + public float getMaxSpeedAirLateral() + { + return maxSpeedAirLateral; + } + + public void setMaxSpeedAirLateral(float value) + { + maxSpeedAirLateral = value; + } + + public float getMaxSpeedAirVertical() + { + return maxSpeedAirVertical; + } + + public void setMaxSpeedAirVertical(float value) + { + maxSpeedAirVertical = value; + } + + public double getDragAir() + { + return dragAir; + } + + public void setDragAir(double value) + { + dragAir = value; + } }