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