    001package net.minecraft.block;
    002
    003import java.util.ArrayList;
    004import java.util.List;
    005import net.minecraft.world.ChunkPosition;
    006import net.minecraft.world.World;
    007
    008public class RailLogic
    009{
    010    /** Reference to the World object. */
    011    private World worldObj;
    012    private int trackX;
    013    private int trackY;
    014    private int trackZ;
    015
    016    /**
    017     * A boolean value that is true if the rail is powered, and false if its not.
    018     */
    019    private final boolean isPoweredRail;
    020    private List connectedTracks;
    021
    022    final BlockRail rail;
    023    private final boolean canMakeSlopes;
    024
    025    public RailLogic(BlockRail par1BlockRail, World par2World, int par3, int par4, int par5)
    026    {
    027        this.rail = par1BlockRail;
    028        this.connectedTracks = new ArrayList();
    029        this.worldObj = par2World;
    030        this.trackX = par3;
    031        this.trackY = par4;
    032        this.trackZ = par5;
    033        int var6 = par2World.getBlockId(par3, par4, par5);
    034
    035        BlockRail target = (BlockRail)Block.blocksList[var6];
    036        int var7 = target.getBasicRailMetadata(par2World, null, par3, par4, par5);
    037        isPoweredRail = !target.isFlexibleRail(par2World, par3, par4, par5);
    038        canMakeSlopes = target.canMakeSlopes(par2World, par3, par4, par5);
    039        this.setConnections(var7);
    040    }
    041
    042    private void setConnections(int par1)
    043    {
    044        this.connectedTracks.clear();
    045
    046        if (par1 == 0)
    047        {
    048            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ - 1));
    049            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ + 1));
    050        }
    051        else if (par1 == 1)
    052        {
    053            this.connectedTracks.add(new ChunkPosition(this.trackX - 1, this.trackY, this.trackZ));
    054            this.connectedTracks.add(new ChunkPosition(this.trackX + 1, this.trackY, this.trackZ));
    055        }
    056        else if (par1 == 2)
    057        {
    058            this.connectedTracks.add(new ChunkPosition(this.trackX - 1, this.trackY, this.trackZ));
    059            this.connectedTracks.add(new ChunkPosition(this.trackX + 1, this.trackY + 1, this.trackZ));
    060        }
    061        else if (par1 == 3)
    062        {
    063            this.connectedTracks.add(new ChunkPosition(this.trackX - 1, this.trackY + 1, this.trackZ));
    064            this.connectedTracks.add(new ChunkPosition(this.trackX + 1, this.trackY, this.trackZ));
    065        }
    066        else if (par1 == 4)
    067        {
    068            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY + 1, this.trackZ - 1));
    069            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ + 1));
    070        }
    071        else if (par1 == 5)
    072        {
    073            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ - 1));
    074            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY + 1, this.trackZ + 1));
    075        }
    076        else if (par1 == 6)
    077        {
    078            this.connectedTracks.add(new ChunkPosition(this.trackX + 1, this.trackY, this.trackZ));
    079            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ + 1));
    080        }
    081        else if (par1 == 7)
    082        {
    083            this.connectedTracks.add(new ChunkPosition(this.trackX - 1, this.trackY, this.trackZ));
    084            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ + 1));
    085        }
    086        else if (par1 == 8)
    087        {
    088            this.connectedTracks.add(new ChunkPosition(this.trackX - 1, this.trackY, this.trackZ));
    089            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ - 1));
    090        }
    091        else if (par1 == 9)
    092        {
    093            this.connectedTracks.add(new ChunkPosition(this.trackX + 1, this.trackY, this.trackZ));
    094            this.connectedTracks.add(new ChunkPosition(this.trackX, this.trackY, this.trackZ - 1));
    095        }
    096    }
    097
    098    /**
    099     * Neighboring tracks have potentially been broken, so prune the connected track list
    100     */
    101    private void refreshConnectedTracks()
    102    {
    103        for (int var1 = 0; var1 < this.connectedTracks.size(); ++var1)
    104        {
    105            RailLogic var2 = this.getMinecartTrackLogic((ChunkPosition)this.connectedTracks.get(var1));
    106
    107            if (var2 != null && var2.isConnectedTo(this))
    108            {
    109                this.connectedTracks.set(var1, new ChunkPosition(var2.trackX, var2.trackY, var2.trackZ));
    110            }
    111            else
    112            {
    113                this.connectedTracks.remove(var1--);
    114            }
    115        }
    116    }
    117
    118    private boolean isMinecartTrack(int par1, int par2, int par3)
    119    {
    120        return BlockRail.isRailBlockAt(this.worldObj, par1, par2, par3) ? true : (BlockRail.isRailBlockAt(this.worldObj, par1, par2 + 1, par3) ? true : BlockRail.isRailBlockAt(this.worldObj, par1, par2 - 1, par3));
    121    }
    122
    123    private RailLogic getMinecartTrackLogic(ChunkPosition par1ChunkPosition)
    124    {
    125        return BlockRail.isRailBlockAt(this.worldObj, par1ChunkPosition.x, par1ChunkPosition.y, par1ChunkPosition.z) ? new RailLogic(this.rail, this.worldObj, par1ChunkPosition.x, par1ChunkPosition.y, par1ChunkPosition.z) : (BlockRail.isRailBlockAt(this.worldObj, par1ChunkPosition.x, par1ChunkPosition.y + 1, par1ChunkPosition.z) ? new RailLogic(this.rail, this.worldObj, par1ChunkPosition.x, par1ChunkPosition.y + 1, par1ChunkPosition.z) : (BlockRail.isRailBlockAt(this.worldObj, par1ChunkPosition.x, par1ChunkPosition.y - 1, par1ChunkPosition.z) ? new RailLogic(this.rail, this.worldObj, par1ChunkPosition.x, par1ChunkPosition.y - 1, par1ChunkPosition.z) : null));
    126    }
    127
    128    private boolean isConnectedTo(RailLogic par1RailLogic)
    129    {
    130        for (int var2 = 0; var2 < this.connectedTracks.size(); ++var2)
    131        {
    132            ChunkPosition var3 = (ChunkPosition)this.connectedTracks.get(var2);
    133
    134            if (var3.x == par1RailLogic.trackX && var3.z == par1RailLogic.trackZ)
    135            {
    136                return true;
    137            }
    138        }
    139
    140        return false;
    141    }
    142
    143    /**
    144     * Returns true if the specified block is in the same railway.
    145     */
    146    private boolean isInTrack(int par1, int par2, int par3)
    147    {
    148        for (int var4 = 0; var4 < this.connectedTracks.size(); ++var4)
    149        {
    150            ChunkPosition var5 = (ChunkPosition)this.connectedTracks.get(var4);
    151
    152            if (var5.x == par1 && var5.z == par3)
    153            {
    154                return true;
    155            }
    156        }
    157
    158        return false;
    159    }
    160
    161    private int getAdjacentTracks()
    162    {
    163        int var1 = 0;
    164
    165        if (this.isMinecartTrack(this.trackX, this.trackY, this.trackZ - 1))
    166        {
    167            ++var1;
    168        }
    169
    170        if (this.isMinecartTrack(this.trackX, this.trackY, this.trackZ + 1))
    171        {
    172            ++var1;
    173        }
    174
    175        if (this.isMinecartTrack(this.trackX - 1, this.trackY, this.trackZ))
    176        {
    177            ++var1;
    178        }
    179
    180        if (this.isMinecartTrack(this.trackX + 1, this.trackY, this.trackZ))
    181        {
    182            ++var1;
    183        }
    184
    185        return var1;
    186    }
    187
    188    /**
    189     * Determines whether or not the track can bend to meet the specified rail
    190     */
    191    private boolean canConnectTo(RailLogic par1RailLogic)
    192    {
    193        if (this.isConnectedTo(par1RailLogic))
    194        {
    195            return true;
    196        }
    197        else if (this.connectedTracks.size() == 2)
    198        {
    199            return false;
    200        }
    201        else if (this.connectedTracks.isEmpty())
    202        {
    203            return true;
    204        }
    205        else
    206        {
    207            ChunkPosition var2 = (ChunkPosition)this.connectedTracks.get(0);
    208            return true;
    209        }
    210    }
    211
    212    /**
    213     * The specified neighbor has just formed a new connection, so update accordingly
    214     */
    215    private void connectToNeighbor(RailLogic par1RailLogic)
    216    {
    217        this.connectedTracks.add(new ChunkPosition(par1RailLogic.trackX, par1RailLogic.trackY, par1RailLogic.trackZ));
    218        boolean var2 = this.isInTrack(this.trackX, this.trackY, this.trackZ - 1);
    219        boolean var3 = this.isInTrack(this.trackX, this.trackY, this.trackZ + 1);
    220        boolean var4 = this.isInTrack(this.trackX - 1, this.trackY, this.trackZ);
    221        boolean var5 = this.isInTrack(this.trackX + 1, this.trackY, this.trackZ);
    222        byte var6 = -1;
    223
    224        if (var2 || var3)
    225        {
    226            var6 = 0;
    227        }
    228
    229        if (var4 || var5)
    230        {
    231            var6 = 1;
    232        }
    233
    234        if (!this.isPoweredRail)
    235        {
    236            if (var3 && var5 && !var2 && !var4)
    237            {
    238                var6 = 6;
    239            }
    240
    241            if (var3 && var4 && !var2 && !var5)
    242            {
    243                var6 = 7;
    244            }
    245
    246            if (var2 && var4 && !var3 && !var5)
    247            {
    248                var6 = 8;
    249            }
    250
    251            if (var2 && var5 && !var3 && !var4)
    252            {
    253                var6 = 9;
    254            }
    255        }
    256
    257        if (var6 == 0 && canMakeSlopes)
    258        {
    259            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX, this.trackY + 1, this.trackZ - 1))
    260            {
    261                var6 = 4;
    262            }
    263
    264            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX, this.trackY + 1, this.trackZ + 1))
    265            {
    266                var6 = 5;
    267            }
    268        }
    269
    270        if (var6 == 1 && canMakeSlopes)
    271        {
    272            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX + 1, this.trackY + 1, this.trackZ))
    273            {
    274                var6 = 2;
    275            }
    276
    277            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX - 1, this.trackY + 1, this.trackZ))
    278            {
    279                var6 = 3;
    280            }
    281        }
    282
    283        if (var6 < 0)
    284        {
    285            var6 = 0;
    286        }
    287
    288        int var7 = var6;
    289
    290        if (this.isPoweredRail)
    291        {
    292            var7 = this.worldObj.getBlockMetadata(this.trackX, this.trackY, this.trackZ) & 8 | var6;
    293        }
    294
    295        this.worldObj.setBlockMetadataWithNotify(this.trackX, this.trackY, this.trackZ, var7);
    296    }
    297
    298    /**
    299     * Determines whether or not the target rail can connect to this rail
    300     */
    301    private boolean canConnectFrom(int par1, int par2, int par3)
    302    {
    303        RailLogic var4 = this.getMinecartTrackLogic(new ChunkPosition(par1, par2, par3));
    304
    305        if (var4 == null)
    306        {
    307            return false;
    308        }
    309        else
    310        {
    311            var4.refreshConnectedTracks();
    312            return var4.canConnectTo(this);
    313        }
    314    }
    315
    316    /**
    317     * Completely recalculates the track shape based on neighboring tracks and power state
    318     */
    319    public void refreshTrackShape(boolean par1, boolean par2)
    320    {
    321        boolean var3 = this.canConnectFrom(this.trackX, this.trackY, this.trackZ - 1);
    322        boolean var4 = this.canConnectFrom(this.trackX, this.trackY, this.trackZ + 1);
    323        boolean var5 = this.canConnectFrom(this.trackX - 1, this.trackY, this.trackZ);
    324        boolean var6 = this.canConnectFrom(this.trackX + 1, this.trackY, this.trackZ);
    325        byte var7 = -1;
    326
    327        if ((var3 || var4) && !var5 && !var6)
    328        {
    329            var7 = 0;
    330        }
    331
    332        if ((var5 || var6) && !var3 && !var4)
    333        {
    334            var7 = 1;
    335        }
    336
    337        if (!this.isPoweredRail)
    338        {
    339            if (var4 && var6 && !var3 && !var5)
    340            {
    341                var7 = 6;
    342            }
    343
    344            if (var4 && var5 && !var3 && !var6)
    345            {
    346                var7 = 7;
    347            }
    348
    349            if (var3 && var5 && !var4 && !var6)
    350            {
    351                var7 = 8;
    352            }
    353
    354            if (var3 && var6 && !var4 && !var5)
    355            {
    356                var7 = 9;
    357            }
    358        }
    359
    360        if (var7 == -1)
    361        {
    362            if (var3 || var4)
    363            {
    364                var7 = 0;
    365            }
    366
    367            if (var5 || var6)
    368            {
    369                var7 = 1;
    370            }
    371
    372            if (!this.isPoweredRail)
    373            {
    374                if (par1)
    375                {
    376                    if (var4 && var6)
    377                    {
    378                        var7 = 6;
    379                    }
    380
    381                    if (var5 && var4)
    382                    {
    383                        var7 = 7;
    384                    }
    385
    386                    if (var6 && var3)
    387                    {
    388                        var7 = 9;
    389                    }
    390
    391                    if (var3 && var5)
    392                    {
    393                        var7 = 8;
    394                    }
    395                }
    396                else
    397                {
    398                    if (var3 && var5)
    399                    {
    400                        var7 = 8;
    401                    }
    402
    403                    if (var6 && var3)
    404                    {
    405                        var7 = 9;
    406                    }
    407
    408                    if (var5 && var4)
    409                    {
    410                        var7 = 7;
    411                    }
    412
    413                    if (var4 && var6)
    414                    {
    415                        var7 = 6;
    416                    }
    417                }
    418            }
    419        }
    420
    421        if (var7 == 0 && canMakeSlopes)
    422        {
    423            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX, this.trackY + 1, this.trackZ - 1))
    424            {
    425                var7 = 4;
    426            }
    427
    428            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX, this.trackY + 1, this.trackZ + 1))
    429            {
    430                var7 = 5;
    431            }
    432        }
    433
    434        if (var7 == 1 && canMakeSlopes)
    435        {
    436            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX + 1, this.trackY + 1, this.trackZ))
    437            {
    438                var7 = 2;
    439            }
    440
    441            if (BlockRail.isRailBlockAt(this.worldObj, this.trackX - 1, this.trackY + 1, this.trackZ))
    442            {
    443                var7 = 3;
    444            }
    445        }
    446
    447        if (var7 < 0)
    448        {
    449            var7 = 0;
    450        }
    451
    452        this.setConnections(var7);
    453        int var8 = var7;
    454
    455        if (this.isPoweredRail)
    456        {
    457            var8 = this.worldObj.getBlockMetadata(this.trackX, this.trackY, this.trackZ) & 8 | var7;
    458        }
    459
    460        if (par2 || this.worldObj.getBlockMetadata(this.trackX, this.trackY, this.trackZ) != var8)
    461        {
    462            this.worldObj.setBlockMetadataWithNotify(this.trackX, this.trackY, this.trackZ, var8);
    463
    464            for (int var9 = 0; var9 < this.connectedTracks.size(); ++var9)
    465            {
    466                RailLogic var10 = this.getMinecartTrackLogic((ChunkPosition)this.connectedTracks.get(var9));
    467
    468                if (var10 != null)
    469                {
    470                    var10.refreshConnectedTracks();
    471
    472                    if (var10.canConnectTo(this))
    473                    {
    474                        var10.connectToNeighbor(this);
    475                    }
    476                }
    477            }
    478        }
    479    }
    480
    481    /**
    482     * Get the number of adjacent tracks.
    483     */
    484    public static int getAdjacentTrackCount(RailLogic par0RailLogic)
    485    {
    486        return par0RailLogic.getAdjacentTracks();
    487    }
    488}