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