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}