001    package net.minecraft.block;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    import net.minecraft.world.ChunkPosition;
006    import net.minecraft.world.World;
007    
008    public 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    }