    001package net.minecraft.entity.item;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.List;
    006import net.minecraft.block.Block;
    007import net.minecraft.block.BlockRailBase;
    008import net.minecraft.entity.Entity;
    009import net.minecraft.entity.EntityLiving;
    010import net.minecraft.entity.ai.EntityMinecartMobSpawner;
    011import net.minecraft.entity.monster.EntityIronGolem;
    012import net.minecraft.entity.player.EntityPlayer;
    013import net.minecraft.item.Item;
    014import net.minecraft.item.ItemStack;
    015import net.minecraft.nbt.NBTTagCompound;
    016import net.minecraft.server.MinecraftServer;
    017import net.minecraft.server.gui.IUpdatePlayerListBox;
    018import net.minecraft.util.AxisAlignedBB;
    019import net.minecraft.util.DamageSource;
    020import net.minecraft.util.MathHelper;
    021import net.minecraft.util.Vec3;
    022import net.minecraft.world.World;
    023import net.minecraft.world.WorldServer;
    024import net.minecraftforge.common.IMinecartCollisionHandler;
    025import net.minecraftforge.common.MinecraftForge;
    026import net.minecraftforge.event.entity.minecart.MinecartCollisionEvent;
    027import net.minecraftforge.event.entity.minecart.MinecartUpdateEvent;
    028
    029public abstract class EntityMinecart extends Entity
    030{
    031    protected boolean isInReverse;
    032    protected final IUpdatePlayerListBox field_82344_g;
    033    protected String entityName;
    034
    035    /** Minecart rotational logic matrix */
    036    protected static final int[][][] matrix = 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}}};
    037
    038    /** appears to be the progress of the turn */
    039    protected int turnProgress;
    040    protected double minecartX;
    041    protected double minecartY;
    042    protected double minecartZ;
    043    protected double minecartYaw;
    044    protected double minecartPitch;
    045    @SideOnly(Side.CLIENT)
    046    protected double velocityX;
    047    @SideOnly(Side.CLIENT)
    048    protected double velocityY;
    049    @SideOnly(Side.CLIENT)
    050    protected double velocityZ;
    051
    052    /* Forge: Minecart Compatibility Layer Integration. */
    053    public static float defaultMaxSpeedAirLateral = 0.4f;
    054    public static float defaultMaxSpeedAirVertical = -1f;
    055    public static double defaultDragAir = 0.94999998807907104D;
    056    protected boolean canUseRail = true;
    057    protected boolean canBePushed = true;
    058    private static IMinecartCollisionHandler collisionHandler = null;
    059
    060    /* Instance versions of the above physics properties */
    061    private float currentSpeedRail = getMaxCartSpeedOnRail();
    062    protected float maxSpeedAirLateral = defaultMaxSpeedAirLateral;
    063    protected float maxSpeedAirVertical = defaultMaxSpeedAirVertical;
    064    protected double dragAir = defaultDragAir;
    065
    066    public EntityMinecart(World par1World)
    067    {
    068        super(par1World);
    069        this.isInReverse = false;
    070        this.preventEntitySpawning = true;
    071        this.setSize(0.98F, 0.7F);
    072        this.yOffset = this.height / 2.0F;
    073        this.field_82344_g = par1World != null ? par1World.func_82735_a(this) : null;
    074    }
    075
    076    /**
    077     * Creates a new minecart of the specified type in the specified location in the given world. par0World - world to
    078     * create the minecart in, double par1,par3,par5 represent x,y,z respectively. int par7 specifies the type: 1 for
    079     * MinecartChest, 2 for MinecartFurnace, 3 for MinecartTNT, 4 for MinecartMobSpawner, 5 for MinecartHopper and 0 for
    080     * a standard empty minecart
    081     */
    082    public static EntityMinecart createMinecart(World par0World, double par1, double par3, double par5, int par7)
    083    {
    084        switch (par7)
    085        {
    086            case 1:
    087                return new EntityMinecartChest(par0World, par1, par3, par5);
    088            case 2:
    089                return new EntityMinecartFurnace(par0World, par1, par3, par5);
    090            case 3:
    091                return new EntityMinecartTNT(par0World, par1, par3, par5);
    092            case 4:
    093                return new EntityMinecartMobSpawner(par0World, par1, par3, par5);
    094            case 5:
    095                return new EntityMinecartHopper(par0World, par1, par3, par5);
    096            default:
    097                return new EntityMinecartEmpty(par0World, par1, par3, par5);
    098        }
    099    }
    100
    101    /**
    102     * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
    103     * prevent them from trampling crops
    104     */
    105    protected boolean canTriggerWalking()
    106    {
    107        return false;
    108    }
    109
    110    protected void entityInit()
    111    {
    112        this.dataWatcher.addObject(17, new Integer(0));
    113        this.dataWatcher.addObject(18, new Integer(1));
    114        this.dataWatcher.addObject(19, new Integer(0));
    115        this.dataWatcher.addObject(20, new Integer(0));
    116        this.dataWatcher.addObject(21, new Integer(6));
    117        this.dataWatcher.addObject(22, Byte.valueOf((byte)0));
    118    }
    119
    120    /**
    121     * Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be
    122     * pushable on contact, like boats or minecarts.
    123     */
    124    public AxisAlignedBB getCollisionBox(Entity par1Entity)
    125    {
    126        if (getCollisionHandler() != null)
    127        {
    128            return getCollisionHandler().getCollisionBox(this, par1Entity);
    129        }
    130        return par1Entity.canBePushed() ? par1Entity.boundingBox : null;
    131    }
    132
    133    /**
    134     * returns the bounding box for this entity
    135     */
    136    public AxisAlignedBB getBoundingBox()
    137    {
    138        if (getCollisionHandler() != null)
    139        {
    140            return getCollisionHandler().getBoundingBox(this);
    141        }
    142        return null;
    143    }
    144
    145    /**
    146     * Returns true if this entity should push and be pushed by other entities when colliding.
    147     */
    148    public boolean canBePushed()
    149    {
    150        return canBePushed;
    151    }
    152
    153    public EntityMinecart(World par1World, double par2, double par4, double par6)
    154    {
    155        this(par1World);
    156        this.setPosition(par2, par4 + (double)this.yOffset, par6);
    157        this.motionX = 0.0D;
    158        this.motionY = 0.0D;
    159        this.motionZ = 0.0D;
    160        this.prevPosX = par2;
    161        this.prevPosY = par4;
    162        this.prevPosZ = par6;
    163    }
    164
    165    /**
    166     * Returns the Y offset from the entity's position for any entity riding this one.
    167     */
    168    public double getMountedYOffset()
    169    {
    170        return (double)this.height * 0.0D - 0.30000001192092896D;
    171    }
    172
    173    /**
    174     * Called when the entity is attacked.
    175     */
    176    public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    177    {
    178        if (!this.worldObj.isRemote && !this.isDead)
    179        {
    180            if (this.isEntityInvulnerable())
    181            {
    182                return false;
    183            }
    184            else
    185            {
    186                this.setRollingDirection(-this.getRollingDirection());
    187                this.setRollingAmplitude(10);
    188                this.setBeenAttacked();
    189                this.setDamage(this.getDamage() + par2 * 10);
    190                boolean flag = par1DamageSource.getEntity() instanceof EntityPlayer && ((EntityPlayer)par1DamageSource.getEntity()).capabilities.isCreativeMode;
    191
    192                if (flag || this.getDamage() > 40)
    193                {
    194                    if (this.riddenByEntity != null)
    195                    {
    196                        this.riddenByEntity.mountEntity(this);
    197                    }
    198
    199                    if (flag && !this.isInvNameLocalized())
    200                    {
    201                        this.setDead();
    202                    }
    203                    else
    204                    {
    205                        this.killMinecart(par1DamageSource);
    206                    }
    207                }
    208
    209                return true;
    210            }
    211        }
    212        else
    213        {
    214            return true;
    215        }
    216    }
    217
    218    public void killMinecart(DamageSource par1DamageSource)
    219    {
    220        this.setDead();
    221        ItemStack itemstack = new ItemStack(Item.minecartEmpty, 1);
    222
    223        if (this.entityName != null)
    224        {
    225            itemstack.setItemName(this.entityName);
    226        }
    227
    228        this.entityDropItem(itemstack, 0.0F);
    229    }
    230
    231    @SideOnly(Side.CLIENT)
    232
    233    /**
    234     * Setups the entity to do the hurt animation. Only used by packets in multiplayer.
    235     */
    236    public void performHurtAnimation()
    237    {
    238        this.setRollingDirection(-this.getRollingDirection());
    239        this.setRollingAmplitude(10);
    240        this.setDamage(this.getDamage() + this.getDamage() * 10);
    241    }
    242
    243    /**
    244     * Returns true if other Entities should be prevented from moving through this Entity.
    245     */
    246    public boolean canBeCollidedWith()
    247    {
    248        return !this.isDead;
    249    }
    250
    251    /**
    252     * Will get destroyed next tick.
    253     */
    254    public void setDead()
    255    {
    256        super.setDead();
    257
    258        if (this.field_82344_g != null)
    259        {
    260            this.field_82344_g.update();
    261        }
    262    }
    263
    264    /**
    265     * Called to update the entity's position/logic.
    266     */
    267    public void onUpdate()
    268    {
    269        if (this.field_82344_g != null)
    270        {
    271            this.field_82344_g.update();
    272        }
    273
    274        if (this.getRollingAmplitude() > 0)
    275        {
    276            this.setRollingAmplitude(this.getRollingAmplitude() - 1);
    277        }
    278
    279        if (this.getDamage() > 0)
    280        {
    281            this.setDamage(this.getDamage() - 1);
    282        }
    283
    284        if (this.posY < -64.0D)
    285        {
    286            this.kill();
    287        }
    288
    289        int i;
    290
    291        if (!this.worldObj.isRemote && this.worldObj instanceof WorldServer)
    292        {
    293            this.worldObj.theProfiler.startSection("portal");
    294            MinecraftServer minecraftserver = ((WorldServer)this.worldObj).getMinecraftServer();
    295            i = this.getMaxInPortalTime();
    296
    297            if (this.inPortal)
    298            {
    299                if (minecraftserver.getAllowNether())
    300                {
    301                    if (this.ridingEntity == null && this.timeInPortal++ >= i)
    302                    {
    303                        this.timeInPortal = i;
    304                        this.timeUntilPortal = this.getPortalCooldown();
    305                        byte b0;
    306
    307                        if (this.worldObj.provider.dimensionId == -1)
    308                        {
    309                            b0 = 0;
    310                        }
    311                        else
    312                        {
    313                            b0 = -1;
    314                        }
    315
    316                        this.travelToDimension(b0);
    317                    }
    318
    319                    this.inPortal = false;
    320                }
    321            }
    322            else
    323            {
    324                if (this.timeInPortal > 0)
    325                {
    326                    this.timeInPortal -= 4;
    327                }
    328
    329                if (this.timeInPortal < 0)
    330                {
    331                    this.timeInPortal = 0;
    332                }
    333            }
    334
    335            if (this.timeUntilPortal > 0)
    336            {
    337                --this.timeUntilPortal;
    338            }
    339
    340            this.worldObj.theProfiler.endSection();
    341        }
    342
    343        if (this.worldObj.isRemote)
    344        {
    345            if (this.turnProgress > 0)
    346            {
    347                double d0 = this.posX + (this.minecartX - this.posX) / (double)this.turnProgress;
    348                double d1 = this.posY + (this.minecartY - this.posY) / (double)this.turnProgress;
    349                double d2 = this.posZ + (this.minecartZ - this.posZ) / (double)this.turnProgress;
    350                double d3 = MathHelper.wrapAngleTo180_double(this.minecartYaw - (double)this.rotationYaw);
    351                this.rotationYaw = (float)((double)this.rotationYaw + d3 / (double)this.turnProgress);
    352                this.rotationPitch = (float)((double)this.rotationPitch + (this.minecartPitch - (double)this.rotationPitch) / (double)this.turnProgress);
    353                --this.turnProgress;
    354                this.setPosition(d0, d1, d2);
    355                this.setRotation(this.rotationYaw, this.rotationPitch);
    356            }
    357            else
    358            {
    359                this.setPosition(this.posX, this.posY, this.posZ);
    360                this.setRotation(this.rotationYaw, this.rotationPitch);
    361            }
    362        }
    363        else
    364        {
    365            this.prevPosX = this.posX;
    366            this.prevPosY = this.posY;
    367            this.prevPosZ = this.posZ;
    368            this.motionY -= 0.03999999910593033D;
    369            int j = MathHelper.floor_double(this.posX);
    370            i = MathHelper.floor_double(this.posY);
    371            int k = MathHelper.floor_double(this.posZ);
    372
    373            if (BlockRailBase.isRailBlockAt(this.worldObj, j, i - 1, k))
    374            {
    375                --i;
    376            }
    377
    378            double d4 = 0.4D;
    379            double d5 = 0.0078125D;
    380            int l = this.worldObj.getBlockId(j, i, k);
    381
    382            if (canUseRail() && BlockRailBase.isRailBlock(l))
    383            {
    384                BlockRailBase rail = (BlockRailBase)Block.blocksList[l];
    385                float railMaxSpeed = rail.getRailMaxSpeed(worldObj, this, j, i, k);
    386                double maxSpeed = Math.min(railMaxSpeed, getCurrentCartSpeedCapOnRail());
    387                int i1 = rail.getBasicRailMetadata(worldObj, this, j, i, k);
    388                this.updateOnTrack(j, i, k, maxSpeed, getSlopeAdjustment(), l, i1);
    389                if (l == Block.railActivator.blockID)
    390                {
    391                    this.onActivatorRailPass(j, i, k, (worldObj.getBlockMetadata(j, i, k) & 8) != 0);
    392                }
    393            }
    394            else
    395            {
    396                this.func_94088_b(onGround ? d4 : getMaxSpeedAirLateral());
    397            }
    398
    399            this.doBlockCollisions();
    400            this.rotationPitch = 0.0F;
    401            double d6 = this.prevPosX - this.posX;
    402            double d7 = this.prevPosZ - this.posZ;
    403
    404            if (d6 * d6 + d7 * d7 > 0.001D)
    405            {
    406                this.rotationYaw = (float)(Math.atan2(d7, d6) * 180.0D / Math.PI);
    407
    408                if (this.isInReverse)
    409                {
    410                    this.rotationYaw += 180.0F;
    411                }
    412            }
    413
    414            double d8 = (double)MathHelper.wrapAngleTo180_float(this.rotationYaw - this.prevRotationYaw);
    415
    416            if (d8 < -170.0D || d8 >= 170.0D)
    417            {
    418                this.rotationYaw += 180.0F;
    419                this.isInReverse = !this.isInReverse;
    420            }
    421
    422            this.setRotation(this.rotationYaw, this.rotationPitch);
    423
    424            AxisAlignedBB box;
    425            if (getCollisionHandler() != null)
    426            {
    427                box = getCollisionHandler().getMinecartCollisionBox(this);
    428            }
    429            else
    430            {
    431                box = boundingBox.expand(0.2D, 0.0D, 0.2D);
    432            }
    433
    434            List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, box);
    435
    436            if (list != null && !list.isEmpty())
    437            {
    438                for (int j1 = 0; j1 < list.size(); ++j1)
    439                {
    440                    Entity entity = (Entity)list.get(j1);
    441
    442                    if (entity != this.riddenByEntity && entity.canBePushed() && entity instanceof EntityMinecart)
    443                    {
    444                        entity.applyEntityCollision(this);
    445                    }
    446                }
    447            }
    448
    449            if (this.riddenByEntity != null && this.riddenByEntity.isDead)
    450            {
    451                if (this.riddenByEntity.ridingEntity == this)
    452                {
    453                    this.riddenByEntity.ridingEntity = null;
    454                }
    455
    456                this.riddenByEntity = null;
    457            }
    458
    459            MinecraftForge.EVENT_BUS.post(new MinecartUpdateEvent(this, j, i, k));
    460        }
    461    }
    462
    463    /**
    464     * Called every tick the minecart is on an activator rail.
    465     */
    466    public void onActivatorRailPass(int par1, int par2, int par3, boolean par4) {}
    467
    468    protected void func_94088_b(double par1)
    469    {
    470        if (this.motionX < -par1)
    471        {
    472            this.motionX = -par1;
    473        }
    474
    475        if (this.motionX > par1)
    476        {
    477            this.motionX = par1;
    478        }
    479
    480        if (this.motionZ < -par1)
    481        {
    482            this.motionZ = -par1;
    483        }
    484
    485        if (this.motionZ > par1)
    486        {
    487            this.motionZ = par1;
    488        }
    489
    490        double moveY = motionY;
    491        if(getMaxSpeedAirVertical() > 0 && motionY > getMaxSpeedAirVertical())
    492        {
    493            moveY = getMaxSpeedAirVertical();
    494            if(Math.abs(motionX) < 0.3f && Math.abs(motionZ) < 0.3f)
    495            {
    496                moveY = 0.15f;
    497                motionY = moveY;
    498            }
    499        }
    500
    501        if (this.onGround)
    502        {
    503            this.motionX *= 0.5D;
    504            this.motionY *= 0.5D;
    505            this.motionZ *= 0.5D;
    506        }
    507
    508        this.moveEntity(this.motionX, moveY, this.motionZ);
    509
    510        if (!this.onGround)
    511        {
    512            this.motionX *= getDragAir();
    513            this.motionY *= getDragAir();
    514            this.motionZ *= getDragAir();
    515        }
    516    }
    517
    518    protected void updateOnTrack(int par1, int par2, int par3, double par4, double par6, int par8, int par9)
    519    {
    520        this.fallDistance = 0.0F;
    521        Vec3 vec3 = this.func_70489_a(this.posX, this.posY, this.posZ);
    522        this.posY = (double)par2;
    523        boolean flag = false;
    524        boolean flag1 = false;
    525
    526        if (par8 == Block.railPowered.blockID)
    527        {
    528            flag = (worldObj.getBlockMetadata(par1, par2, par3) & 8) != 0;
    529            flag1 = !flag;
    530        }
    531
    532        if (((BlockRailBase)Block.blocksList[par8]).isPowered())
    533        {
    534            par9 &= 7;
    535        }
    536
    537        if (par9 >= 2 && par9 <= 5)
    538        {
    539            this.posY = (double)(par2 + 1);
    540        }
    541
    542        if (par9 == 2)
    543        {
    544            this.motionX -= par6;
    545        }
    546
    547        if (par9 == 3)
    548        {
    549            this.motionX += par6;
    550        }
    551
    552        if (par9 == 4)
    553        {
    554            this.motionZ += par6;
    555        }
    556
    557        if (par9 == 5)
    558        {
    559            this.motionZ -= par6;
    560        }
    561
    562        int[][] aint = matrix[par9];
    563        double d2 = (double)(aint[1][0] - aint[0][0]);
    564        double d3 = (double)(aint[1][2] - aint[0][2]);
    565        double d4 = Math.sqrt(d2 * d2 + d3 * d3);
    566        double d5 = this.motionX * d2 + this.motionZ * d3;
    567
    568        if (d5 < 0.0D)
    569        {
    570            d2 = -d2;
    571            d3 = -d3;
    572        }
    573
    574        double d6 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
    575
    576        if (d6 > 2.0D)
    577        {
    578            d6 = 2.0D;
    579        }
    580
    581        this.motionX = d6 * d2 / d4;
    582        this.motionZ = d6 * d3 / d4;
    583        double d7;
    584        double d8;
    585
    586        if (this.riddenByEntity != null)
    587        {
    588            d7 = this.riddenByEntity.motionX * this.riddenByEntity.motionX + this.riddenByEntity.motionZ * this.riddenByEntity.motionZ;
    589            d8 = this.motionX * this.motionX + this.motionZ * this.motionZ;
    590
    591            if (d7 > 1.0E-4D && d8 < 0.01D)
    592            {
    593                this.motionX += this.riddenByEntity.motionX * 0.1D;
    594                this.motionZ += this.riddenByEntity.motionZ * 0.1D;
    595                flag1 = false;
    596            }
    597        }
    598
    599        if (flag1 && shouldDoRailFunctions())
    600        {
    601            d7 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
    602
    603            if (d7 < 0.03D)
    604            {
    605                this.motionX *= 0.0D;
    606                this.motionY *= 0.0D;
    607                this.motionZ *= 0.0D;
    608            }
    609            else
    610            {
    611                this.motionX *= 0.5D;
    612                this.motionY *= 0.0D;
    613                this.motionZ *= 0.5D;
    614            }
    615        }
    616
    617        d7 = 0.0D;
    618        d8 = (double)par1 + 0.5D + (double)aint[0][0] * 0.5D;
    619        double d9 = (double)par3 + 0.5D + (double)aint[0][2] * 0.5D;
    620        double d10 = (double)par1 + 0.5D + (double)aint[1][0] * 0.5D;
    621        double d11 = (double)par3 + 0.5D + (double)aint[1][2] * 0.5D;
    622        d2 = d10 - d8;
    623        d3 = d11 - d9;
    624        double d12;
    625        double d13;
    626
    627        if (d2 == 0.0D)
    628        {
    629            this.posX = (double)par1 + 0.5D;
    630            d7 = this.posZ - (double)par3;
    631        }
    632        else if (d3 == 0.0D)
    633        {
    634            this.posZ = (double)par3 + 0.5D;
    635            d7 = this.posX - (double)par1;
    636        }
    637        else
    638        {
    639            d12 = this.posX - d8;
    640            d13 = this.posZ - d9;
    641            d7 = (d12 * d2 + d13 * d3) * 2.0D;
    642        }
    643
    644        this.posX = d8 + d2 * d7;
    645        this.posZ = d9 + d3 * d7;
    646        this.setPosition(this.posX, this.posY + (double)this.yOffset, this.posZ);
    647
    648        moveMinecartOnRail(par1, par2, par3, par4);
    649
    650        if (aint[0][1] != 0 && MathHelper.floor_double(this.posX) - par1 == aint[0][0] && MathHelper.floor_double(this.posZ) - par3 == aint[0][2])
    651        {
    652            this.setPosition(this.posX, this.posY + (double)aint[0][1], this.posZ);
    653        }
    654        else if (aint[1][1] != 0 && MathHelper.floor_double(this.posX) - par1 == aint[1][0] && MathHelper.floor_double(this.posZ) - par3 == aint[1][2])
    655        {
    656            this.setPosition(this.posX, this.posY + (double)aint[1][1], this.posZ);
    657        }
    658
    659        this.applyDrag();
    660        Vec3 vec31 = this.func_70489_a(this.posX, this.posY, this.posZ);
    661
    662        if (vec31 != null && vec3 != null)
    663        {
    664            double d14 = (vec3.yCoord - vec31.yCoord) * 0.05D;
    665            d6 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
    666
    667            if (d6 > 0.0D)
    668            {
    669                this.motionX = this.motionX / d6 * (d6 + d14);
    670                this.motionZ = this.motionZ / d6 * (d6 + d14);
    671            }
    672
    673            this.setPosition(this.posX, vec31.yCoord, this.posZ);
    674        }
    675
    676        int j1 = MathHelper.floor_double(this.posX);
    677        int k1 = MathHelper.floor_double(this.posZ);
    678
    679        if (j1 != par1 || k1 != par3)
    680        {
    681            d6 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
    682            this.motionX = d6 * (double)(j1 - par1);
    683            this.motionZ = d6 * (double)(k1 - par3);
    684        }
    685
    686        if(shouldDoRailFunctions())
    687        {
    688            ((BlockRailBase)Block.blocksList[par8]).onMinecartPass(worldObj, this, par1, par2, par3);
    689        }
    690
    691        if (flag && shouldDoRailFunctions())
    692        {
    693            double d15 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
    694
    695            if (d15 > 0.01D)
    696            {
    697                double d16 = 0.06D;
    698                this.motionX += this.motionX / d15 * d16;
    699                this.motionZ += this.motionZ / d15 * d16;
    700            }
    701            else if (par9 == 1)
    702            {
    703                if (this.worldObj.isBlockNormalCube(par1 - 1, par2, par3))
    704                {
    705                    this.motionX = 0.02D;
    706                }
    707                else if (this.worldObj.isBlockNormalCube(par1 + 1, par2, par3))
    708                {
    709                    this.motionX = -0.02D;
    710                }
    711            }
    712            else if (par9 == 0)
    713            {
    714                if (this.worldObj.isBlockNormalCube(par1, par2, par3 - 1))
    715                {
    716                    this.motionZ = 0.02D;
    717                }
    718                else if (this.worldObj.isBlockNormalCube(par1, par2, par3 + 1))
    719                {
    720                    this.motionZ = -0.02D;
    721                }
    722            }
    723        }
    724    }
    725
    726    protected void applyDrag()
    727    {
    728        if (this.riddenByEntity != null)
    729        {
    730            this.motionX *= 0.996999979019165D;
    731            this.motionY *= 0.0D;
    732            this.motionZ *= 0.996999979019165D;
    733        }
    734        else
    735        {
    736            this.motionX *= 0.9599999785423279D;
    737            this.motionY *= 0.0D;
    738            this.motionZ *= 0.9599999785423279D;
    739        }
    740    }
    741
    742    @SideOnly(Side.CLIENT)
    743    public Vec3 func_70495_a(double par1, double par3, double par5, double par7)
    744    {
    745        int i = MathHelper.floor_double(par1);
    746        int j = MathHelper.floor_double(par3);
    747        int k = MathHelper.floor_double(par5);
    748
    749        if (BlockRailBase.isRailBlockAt(this.worldObj, i, j - 1, k))
    750        {
    751            --j;
    752        }
    753
    754        int l = this.worldObj.getBlockId(i, j, k);
    755
    756        if (!BlockRailBase.isRailBlock(l))
    757        {
    758            return null;
    759        }
    760        else
    761        {
    762            int i1 = ((BlockRailBase)Block.blocksList[l]).getBasicRailMetadata(worldObj, this, i, j, k);
    763
    764            par3 = (double)j;
    765
    766            if (i1 >= 2 && i1 <= 5)
    767            {
    768                par3 = (double)(j + 1);
    769            }
    770
    771            int[][] aint = matrix[i1];
    772            double d4 = (double)(aint[1][0] - aint[0][0]);
    773            double d5 = (double)(aint[1][2] - aint[0][2]);
    774            double d6 = Math.sqrt(d4 * d4 + d5 * d5);
    775            d4 /= d6;
    776            d5 /= d6;
    777            par1 += d4 * par7;
    778            par5 += d5 * par7;
    779
    780            if (aint[0][1] != 0 && MathHelper.floor_double(par1) - i == aint[0][0] && MathHelper.floor_double(par5) - k == aint[0][2])
    781            {
    782                par3 += (double)aint[0][1];
    783            }
    784            else if (aint[1][1] != 0 && MathHelper.floor_double(par1) - i == aint[1][0] && MathHelper.floor_double(par5) - k == aint[1][2])
    785            {
    786                par3 += (double)aint[1][1];
    787            }
    788
    789            return this.func_70489_a(par1, par3, par5);
    790        }
    791    }
    792
    793    public Vec3 func_70489_a(double par1, double par3, double par5)
    794    {
    795        int i = MathHelper.floor_double(par1);
    796        int j = MathHelper.floor_double(par3);
    797        int k = MathHelper.floor_double(par5);
    798
    799        if (BlockRailBase.isRailBlockAt(this.worldObj, i, j - 1, k))
    800        {
    801            --j;
    802        }
    803
    804        int l = this.worldObj.getBlockId(i, j, k);
    805
    806        if (BlockRailBase.isRailBlock(l))
    807        {
    808            int i1 = ((BlockRailBase)Block.blocksList[l]).getBasicRailMetadata(worldObj, this, i, j, k);
    809            par3 = (double)j;
    810
    811            if (i1 >= 2 && i1 <= 5)
    812            {
    813                par3 = (double)(j + 1);
    814            }
    815
    816            int[][] aint = matrix[i1];
    817            double d3 = 0.0D;
    818            double d4 = (double)i + 0.5D + (double)aint[0][0] * 0.5D;
    819            double d5 = (double)j + 0.5D + (double)aint[0][1] * 0.5D;
    820            double d6 = (double)k + 0.5D + (double)aint[0][2] * 0.5D;
    821            double d7 = (double)i + 0.5D + (double)aint[1][0] * 0.5D;
    822            double d8 = (double)j + 0.5D + (double)aint[1][1] * 0.5D;
    823            double d9 = (double)k + 0.5D + (double)aint[1][2] * 0.5D;
    824            double d10 = d7 - d4;
    825            double d11 = (d8 - d5) * 2.0D;
    826            double d12 = d9 - d6;
    827
    828            if (d10 == 0.0D)
    829            {
    830                par1 = (double)i + 0.5D;
    831                d3 = par5 - (double)k;
    832            }
    833            else if (d12 == 0.0D)
    834            {
    835                par5 = (double)k + 0.5D;
    836                d3 = par1 - (double)i;
    837            }
    838            else
    839            {
    840                double d13 = par1 - d4;
    841                double d14 = par5 - d6;
    842                d3 = (d13 * d10 + d14 * d12) * 2.0D;
    843            }
    844
    845            par1 = d4 + d10 * d3;
    846            par3 = d5 + d11 * d3;
    847            par5 = d6 + d12 * d3;
    848
    849            if (d11 < 0.0D)
    850            {
    851                ++par3;
    852            }
    853
    854            if (d11 > 0.0D)
    855            {
    856                par3 += 0.5D;
    857            }
    858
    859            return this.worldObj.getWorldVec3Pool().getVecFromPool(par1, par3, par5);
    860        }
    861        else
    862        {
    863            return null;
    864        }
    865    }
    866
    867    /**
    868     * (abstract) Protected helper method to read subclass entity data from NBT.
    869     */
    870    protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    871    {
    872        if (par1NBTTagCompound.getBoolean("CustomDisplayTile"))
    873        {
    874            this.setDisplayTile(par1NBTTagCompound.getInteger("DisplayTile"));
    875            this.setDisplayTileData(par1NBTTagCompound.getInteger("DisplayData"));
    876            this.setDisplayTileOffset(par1NBTTagCompound.getInteger("DisplayOffset"));
    877        }
    878
    879        if (par1NBTTagCompound.hasKey("CustomName") && par1NBTTagCompound.getString("CustomName").length() > 0)
    880        {
    881            this.entityName = par1NBTTagCompound.getString("CustomName");
    882        }
    883    }
    884
    885    /**
    886     * (abstract) Protected helper method to write subclass entity data to NBT.
    887     */
    888    protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    889    {
    890        if (this.hasDisplayTile())
    891        {
    892            par1NBTTagCompound.setBoolean("CustomDisplayTile", true);
    893            par1NBTTagCompound.setInteger("DisplayTile", this.getDisplayTile() == null ? 0 : this.getDisplayTile().blockID);
    894            par1NBTTagCompound.setInteger("DisplayData", this.getDisplayTileData());
    895            par1NBTTagCompound.setInteger("DisplayOffset", this.getDisplayTileOffset());
    896        }
    897
    898        if (this.entityName != null && this.entityName.length() > 0)
    899        {
    900            par1NBTTagCompound.setString("CustomName", this.entityName);
    901        }
    902    }
    903
    904    @SideOnly(Side.CLIENT)
    905    public float getShadowSize()
    906    {
    907        return 0.0F;
    908    }
    909
    910    /**
    911     * Applies a velocity to each of the entities pushing them away from each other. Args: entity
    912     */
    913    public void applyEntityCollision(Entity par1Entity)
    914    {
    915        MinecraftForge.EVENT_BUS.post(new MinecartCollisionEvent(this, par1Entity));
    916        if (getCollisionHandler() != null)
    917        {
    918            getCollisionHandler().onEntityCollision(this, par1Entity);
    919            return;
    920        }
    921        if (!this.worldObj.isRemote)
    922        {
    923            if (par1Entity != this.riddenByEntity)
    924            {
    925                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)
    926                {
    927                    par1Entity.mountEntity(this);
    928                }
    929
    930                double d0 = par1Entity.posX - this.posX;
    931                double d1 = par1Entity.posZ - this.posZ;
    932                double d2 = d0 * d0 + d1 * d1;
    933
    934                if (d2 >= 9.999999747378752E-5D)
    935                {
    936                    d2 = (double)MathHelper.sqrt_double(d2);
    937                    d0 /= d2;
    938                    d1 /= d2;
    939                    double d3 = 1.0D / d2;
    940
    941                    if (d3 > 1.0D)
    942                    {
    943                        d3 = 1.0D;
    944                    }
    945
    946                    d0 *= d3;
    947                    d1 *= d3;
    948                    d0 *= 0.10000000149011612D;
    949                    d1 *= 0.10000000149011612D;
    950                    d0 *= (double)(1.0F - this.entityCollisionReduction);
    951                    d1 *= (double)(1.0F - this.entityCollisionReduction);
    952                    d0 *= 0.5D;
    953                    d1 *= 0.5D;
    954
    955                    if (par1Entity instanceof EntityMinecart)
    956                    {
    957                        double d4 = par1Entity.posX - this.posX;
    958                        double d5 = par1Entity.posZ - this.posZ;
    959                        Vec3 vec3 = this.worldObj.getWorldVec3Pool().getVecFromPool(d4, 0.0D, d5).normalize();
    960                        Vec3 vec31 = 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();
    961                        double d6 = Math.abs(vec3.dotProduct(vec31));
    962
    963                        if (d6 < 0.800000011920929D)
    964                        {
    965                            return;
    966                        }
    967
    968                        double d7 = par1Entity.motionX + this.motionX;
    969                        double d8 = par1Entity.motionZ + this.motionZ;
    970
    971                        if (((EntityMinecart)par1Entity).isPoweredCart() && !isPoweredCart())
    972                        {
    973                            this.motionX *= 0.20000000298023224D;
    974                            this.motionZ *= 0.20000000298023224D;
    975                            this.addVelocity(par1Entity.motionX - d0, 0.0D, par1Entity.motionZ - d1);
    976                            par1Entity.motionX *= 0.949999988079071D;
    977                            par1Entity.motionZ *= 0.949999988079071D;
    978                        }
    979                        else if (!((EntityMinecart)par1Entity).isPoweredCart() && isPoweredCart())
    980                        {
    981                            par1Entity.motionX *= 0.20000000298023224D;
    982                            par1Entity.motionZ *= 0.20000000298023224D;
    983                            par1Entity.addVelocity(this.motionX + d0, 0.0D, this.motionZ + d1);
    984                            this.motionX *= 0.949999988079071D;
    985                            this.motionZ *= 0.949999988079071D;
    986                        }
    987                        else
    988                        {
    989                            d7 /= 2.0D;
    990                            d8 /= 2.0D;
    991                            this.motionX *= 0.20000000298023224D;
    992                            this.motionZ *= 0.20000000298023224D;
    993                            this.addVelocity(d7 - d0, 0.0D, d8 - d1);
    994                            par1Entity.motionX *= 0.20000000298023224D;
    995                            par1Entity.motionZ *= 0.20000000298023224D;
    996                            par1Entity.addVelocity(d7 + d0, 0.0D, d8 + d1);
    997                        }
    998                    }
    999                    else
    1000                    {
    1001                        this.addVelocity(-d0, 0.0D, -d1);
    1002                        par1Entity.addVelocity(d0 / 4.0D, 0.0D, d1 / 4.0D);
    1003                    }
    1004                }
    1005            }
    1006        }
    1007    }
    1008
    1009    @SideOnly(Side.CLIENT)
    1010
    1011    /**
    1012     * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
    1013     * posY, posZ, yaw, pitch
    1014     */
    1015    public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
    1016    {
    1017        this.minecartX = par1;
    1018        this.minecartY = par3;
    1019        this.minecartZ = par5;
    1020        this.minecartYaw = (double)par7;
    1021        this.minecartPitch = (double)par8;
    1022        this.turnProgress = par9 + 2;
    1023        this.motionX = this.velocityX;
    1024        this.motionY = this.velocityY;
    1025        this.motionZ = this.velocityZ;
    1026    }
    1027
    1028    @SideOnly(Side.CLIENT)
    1029
    1030    /**
    1031     * Sets the velocity to the args. Args: x, y, z
    1032     */
    1033    public void setVelocity(double par1, double par3, double par5)
    1034    {
    1035        this.velocityX = this.motionX = par1;
    1036        this.velocityY = this.motionY = par3;
    1037        this.velocityZ = this.motionZ = par5;
    1038    }
    1039
    1040    /**
    1041     * Sets the current amount of damage the minecart has taken. Decreases over time. The cart breaks when this is over
    1042     * 40.
    1043     */
    1044    public void setDamage(int par1)
    1045    {
    1046        this.dataWatcher.updateObject(19, Integer.valueOf(par1));
    1047    }
    1048
    1049    /**
    1050     * Gets the current amount of damage the minecart has taken. Decreases over time. The cart breaks when this is over
    1051     * 40.
    1052     */
    1053    public int getDamage()
    1054    {
    1055        return this.dataWatcher.getWatchableObjectInt(19);
    1056    }
    1057
    1058    /**
    1059     * Sets the rolling amplitude the cart rolls while being attacked.
    1060     */
    1061    public void setRollingAmplitude(int par1)
    1062    {
    1063        this.dataWatcher.updateObject(17, Integer.valueOf(par1));
    1064    }
    1065
    1066    /**
    1067     * Gets the rolling amplitude the cart rolls while being attacked.
    1068     */
    1069    public int getRollingAmplitude()
    1070    {
    1071        return this.dataWatcher.getWatchableObjectInt(17);
    1072    }
    1073
    1074    /**
    1075     * Sets the rolling direction the cart rolls while being attacked. Can be 1 or -1.
    1076     */
    1077    public void setRollingDirection(int par1)
    1078    {
    1079        this.dataWatcher.updateObject(18, Integer.valueOf(par1));
    1080    }
    1081
    1082    /**
    1083     * Gets the rolling direction the cart rolls while being attacked. Can be 1 or -1.
    1084     */
    1085    public int getRollingDirection()
    1086    {
    1087        return this.dataWatcher.getWatchableObjectInt(18);
    1088    }
    1089
    1090    public abstract int getMinecartType();
    1091
    1092    public Block getDisplayTile()
    1093    {
    1094        if (!this.hasDisplayTile())
    1095        {
    1096            return this.getDefaultDisplayTile();
    1097        }
    1098        else
    1099        {
    1100            int i = this.getDataWatcher().getWatchableObjectInt(20) & 65535;
    1101            return i > 0 && i < Block.blocksList.length ? Block.blocksList[i] : null;
    1102        }
    1103    }
    1104
    1105    public Block getDefaultDisplayTile()
    1106    {
    1107        return null;
    1108    }
    1109
    1110    public int getDisplayTileData()
    1111    {
    1112        return !this.hasDisplayTile() ? this.getDefaultDisplayTileData() : this.getDataWatcher().getWatchableObjectInt(20) >> 16;
    1113    }
    1114
    1115    public int getDefaultDisplayTileData()
    1116    {
    1117        return 0;
    1118    }
    1119
    1120    public int getDisplayTileOffset()
    1121    {
    1122        return !this.hasDisplayTile() ? this.getDefaultDisplayTileOffset() : this.getDataWatcher().getWatchableObjectInt(21);
    1123    }
    1124
    1125    public int getDefaultDisplayTileOffset()
    1126    {
    1127        return 6;
    1128    }
    1129
    1130    public void setDisplayTile(int par1)
    1131    {
    1132        this.getDataWatcher().updateObject(20, Integer.valueOf(par1 & 65535 | this.getDisplayTileData() << 16));
    1133        this.setHasDisplayTile(true);
    1134    }
    1135
    1136    public void setDisplayTileData(int par1)
    1137    {
    1138        Block block = this.getDisplayTile();
    1139        int j = block == null ? 0 : block.blockID;
    1140        this.getDataWatcher().updateObject(20, Integer.valueOf(j & 65535 | par1 << 16));
    1141        this.setHasDisplayTile(true);
    1142    }
    1143
    1144    public void setDisplayTileOffset(int par1)
    1145    {
    1146        this.getDataWatcher().updateObject(21, Integer.valueOf(par1));
    1147        this.setHasDisplayTile(true);
    1148    }
    1149
    1150    public boolean hasDisplayTile()
    1151    {
    1152        return this.getDataWatcher().getWatchableObjectByte(22) == 1;
    1153    }
    1154
    1155    public void setHasDisplayTile(boolean par1)
    1156    {
    1157        this.getDataWatcher().updateObject(22, Byte.valueOf((byte)(par1 ? 1 : 0)));
    1158    }
    1159
    1160    public void func_96094_a(String par1Str)
    1161    {
    1162        this.entityName = par1Str;
    1163    }
    1164
    1165    /**
    1166     * Gets the username of the entity.
    1167     */
    1168    public String getEntityName()
    1169    {
    1170        return this.entityName != null ? this.entityName : super.getEntityName();
    1171    }
    1172
    1173    /**
    1174     * If this returns false, the inventory name will be used as an unlocalized name, and translated into the player's
    1175     * language. Otherwise it will be used directly.
    1176     */
    1177    public boolean isInvNameLocalized()
    1178    {
    1179        return this.entityName != null;
    1180    }
    1181
    1182    public String func_95999_t()
    1183    {
    1184        return this.entityName;
    1185    }
    1186
    1187    /**
    1188     * Moved to allow overrides.
    1189     * This code handles minecart movement and speed capping when on a rail.
    1190     */
    1191    public void moveMinecartOnRail(int x, int y, int z, double par4){
    1192        double d12 = this.motionX;
    1193        double d13 = this.motionZ;
    1194
    1195        if (this.riddenByEntity != null)
    1196        {
    1197            d12 *= 0.75D;
    1198            d13 *= 0.75D;
    1199        }
    1200
    1201        if (d12 < -par4)
    1202        {
    1203            d12 = -par4;
    1204        }
    1205
    1206        if (d12 > par4)
    1207        {
    1208            d12 = par4;
    1209        }
    1210
    1211        if (d13 < -par4)
    1212        {
    1213            d13 = -par4;
    1214        }
    1215
    1216        if (d13 > par4)
    1217        {
    1218            d13 = par4;
    1219        }
    1220
    1221        this.moveEntity(d12, 0.0D, d13);
    1222    }
    1223
    1224    /**
    1225     * Gets the current global Minecart Collision handler if none
    1226     * is registered, returns null
    1227     * @return The collision handler or null
    1228     */
    1229    public static IMinecartCollisionHandler getCollisionHandler()
    1230    {
    1231        return collisionHandler;
    1232    }
    1233
    1234    /**
    1235     * Sets the global Minecart Collision handler, overwrites any
    1236     * that is currently set.
    1237     * @param handler The new handler
    1238     */
    1239    public static void setCollisionHandler(IMinecartCollisionHandler handler)
    1240    {
    1241        collisionHandler = handler;
    1242    }
    1243
    1244    /**
    1245     * This function returns an ItemStack that represents this cart.
    1246     * This should be an ItemStack that can be used by the player to place the cart,
    1247     * but is not necessary the item the cart drops when destroyed.
    1248     * @return An ItemStack that can be used to place the cart.
    1249     */
    1250    public ItemStack getCartItem()
    1251    {
    1252        if (this instanceof EntityMinecartChest)
    1253        {
    1254            return new ItemStack(Item.minecartCrate);
    1255        }
    1256        else if (this instanceof EntityMinecartTNT)
    1257        {
    1258            return new ItemStack(Item.tntMinecart);
    1259        }
    1260        else if (this instanceof EntityMinecartFurnace)
    1261        {
    1262            return new ItemStack(Item.minecartPowered);
    1263        }
    1264        else if (this instanceof EntityMinecartHopper)
    1265        {
    1266            return new ItemStack(Item.hopperMinecart);
    1267        }
    1268        return new ItemStack(Item.minecartEmpty);
    1269    }
    1270
    1271    /**
    1272     * Returns true if this cart can currently use rails.
    1273     * This function is mainly used to gracefully detach a minecart from a rail.
    1274     * @return True if the minecart can use rails.
    1275     */
    1276    public boolean canUseRail()
    1277    {
    1278        return canUseRail;
    1279    }
    1280
    1281    /**
    1282     * Set whether the minecart can use rails.
    1283     * This function is mainly used to gracefully detach a minecart from a rail.
    1284     * @param use Whether the minecart can currently use rails.
    1285     */
    1286    public void setCanUseRail(boolean use)
    1287    {
    1288        canUseRail = use;
    1289    }
    1290
    1291    /**
    1292     * Return false if this cart should not call onMinecartPass() and should ignore Powered Rails.
    1293     * @return True if this cart should call onMinecartPass().
    1294     */
    1295    public boolean shouldDoRailFunctions()
    1296    {
    1297        return true;
    1298    }
    1299
    1300    /**
    1301     * Returns true if this cart is self propelled.
    1302     * @return True if powered.
    1303     */
    1304    public boolean isPoweredCart()
    1305    {
    1306        return getMinecartType()== 2;
    1307    }
    1308
    1309    /**
    1310     * Returns true if this cart can be ridden by an Entity.
    1311     * @return True if this cart can be ridden.
    1312     */
    1313    public boolean canBeRidden()
    1314    {
    1315        if(this instanceof EntityMinecartEmpty)
    1316        {
    1317            return true;
    1318        }
    1319        return false;
    1320    }
    1321
    1322    /**
    1323     * Getters/setters for physics variables
    1324     */
    1325
    1326    /**
    1327     * Returns the carts max speed when traveling on rails. Carts going faster
    1328     * than 1.1 cause issues with chunk loading. Carts cant traverse slopes or
    1329     * corners at greater than 0.5 - 0.6. This value is compared with the rails
    1330     * max speed and the carts current speed cap to determine the carts current
    1331     * max speed. A normal rail's max speed is 0.4.
    1332     *
    1333     * @return Carts max speed.
    1334     */
    1335    public float getMaxCartSpeedOnRail()
    1336    {
    1337        return 1.2f;
    1338    }
    1339
    1340    /**
    1341     * Returns the current speed cap for the cart when traveling on rails. This
    1342     * functions differs from getMaxCartSpeedOnRail() in that it controls
    1343     * current movement and cannot be overridden. The value however can never be
    1344     * higher than getMaxCartSpeedOnRail().
    1345     *
    1346     * @return
    1347     */
    1348    public final float getCurrentCartSpeedCapOnRail()
    1349    {
    1350        return currentSpeedRail;
    1351    }
    1352
    1353    public final void setCurrentCartSpeedCapOnRail(float value)
    1354    {
    1355        value = Math.min(value, getMaxCartSpeedOnRail());
    1356        currentSpeedRail = value;
    1357    }
    1358
    1359    public float getMaxSpeedAirLateral()
    1360    {
    1361        return maxSpeedAirLateral;
    1362    }
    1363
    1364    public void setMaxSpeedAirLateral(float value)
    1365    {
    1366        maxSpeedAirLateral = value;
    1367    }
    1368
    1369    public float getMaxSpeedAirVertical()
    1370    {
    1371        return maxSpeedAirVertical;
    1372    }
    1373
    1374    public void setMaxSpeedAirVertical(float value)
    1375    {
    1376        maxSpeedAirVertical = value;
    1377    }
    1378
    1379    public double getDragAir()
    1380    {
    1381        return dragAir;
    1382    }
    1383
    1384    public void setDragAir(double value)
    1385    {
    1386        dragAir = value;
    1387    }
    1388
    1389    public double getSlopeAdjustment()
    1390    {
    1391        return 0.0078125D;
    1392    }
    1393}