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 BlockBaseRailLogic
009{
010    private World logicWorld;
011    private int railX;
012    private int railY;
013    private int railZ;
014    private final boolean isStraightRail;
015
016    /** The chunk position the rail is at. */
017    private List railChunkPosition;
018
019    private final boolean canMakeSlopes;
020
021    final BlockRailBase theRail;
022
023    public BlockBaseRailLogic(BlockRailBase par1, World par2, int par3, int par4, int par5)
024    {
025        this.theRail = par1;
026        this.railChunkPosition = new ArrayList();
027        this.logicWorld = par2;
028        this.railX = par3;
029        this.railY = par4;
030        this.railZ = par5;
031        int l = par2.getBlockId(par3, par4, par5);
032
033        BlockRailBase target = (BlockRailBase)Block.blocksList[l];
034        int i1 = target.getBasicRailMetadata(par2, null, par3, par4, par5);
035        isStraightRail = !target.isFlexibleRail(par2, par3, par4, par5);
036        canMakeSlopes = target.canMakeSlopes(par2, par3, par4, par5);
037
038        this.setBasicRail(i1);
039    }
040
041    private void setBasicRail(int par1)
042    {
043        this.railChunkPosition.clear();
044
045        if (par1 == 0)
046        {
047            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
048            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
049        }
050        else if (par1 == 1)
051        {
052            this.railChunkPosition.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
053            this.railChunkPosition.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
054        }
055        else if (par1 == 2)
056        {
057            this.railChunkPosition.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
058            this.railChunkPosition.add(new ChunkPosition(this.railX + 1, this.railY + 1, this.railZ));
059        }
060        else if (par1 == 3)
061        {
062            this.railChunkPosition.add(new ChunkPosition(this.railX - 1, this.railY + 1, this.railZ));
063            this.railChunkPosition.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
064        }
065        else if (par1 == 4)
066        {
067            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY + 1, this.railZ - 1));
068            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
069        }
070        else if (par1 == 5)
071        {
072            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
073            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY + 1, this.railZ + 1));
074        }
075        else if (par1 == 6)
076        {
077            this.railChunkPosition.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
078            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
079        }
080        else if (par1 == 7)
081        {
082            this.railChunkPosition.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
083            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
084        }
085        else if (par1 == 8)
086        {
087            this.railChunkPosition.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
088            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
089        }
090        else if (par1 == 9)
091        {
092            this.railChunkPosition.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
093            this.railChunkPosition.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
094        }
095    }
096
097    private void refreshConnectedTracks()
098    {
099        for (int i = 0; i < this.railChunkPosition.size(); ++i)
100        {
101            BlockBaseRailLogic blockbaseraillogic = this.getRailLogic((ChunkPosition)this.railChunkPosition.get(i));
102
103            if (blockbaseraillogic != null && blockbaseraillogic.isRailChunkPositionCorrect(this))
104            {
105                this.railChunkPosition.set(i, new ChunkPosition(blockbaseraillogic.railX, blockbaseraillogic.railY, blockbaseraillogic.railZ));
106            }
107            else
108            {
109                this.railChunkPosition.remove(i--);
110            }
111        }
112    }
113
114    private boolean isMinecartTrack(int par1, int par2, int par3)
115    {
116        return BlockRailBase.isRailBlockAt(this.logicWorld, par1, par2, par3) ? true : (BlockRailBase.isRailBlockAt(this.logicWorld, par1, par2 + 1, par3) ? true : BlockRailBase.isRailBlockAt(this.logicWorld, par1, par2 - 1, par3));
117    }
118
119    private BlockBaseRailLogic getRailLogic(ChunkPosition par1ChunkPosition)
120    {
121        return BlockRailBase.isRailBlockAt(this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y, par1ChunkPosition.z) ? new BlockBaseRailLogic(this.theRail, this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y, par1ChunkPosition.z) : (BlockRailBase.isRailBlockAt(this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y + 1, par1ChunkPosition.z) ? new BlockBaseRailLogic(this.theRail, this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y + 1, par1ChunkPosition.z) : (BlockRailBase.isRailBlockAt(this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y - 1, par1ChunkPosition.z) ? new BlockBaseRailLogic(this.theRail, this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y - 1, par1ChunkPosition.z) : null));
122    }
123
124    /**
125     * Checks if the rail is at the chunk position it is expected to be.
126     */
127    private boolean isRailChunkPositionCorrect(BlockBaseRailLogic par1BlockBaseRailLogic)
128    {
129        for (int i = 0; i < this.railChunkPosition.size(); ++i)
130        {
131            ChunkPosition chunkposition = (ChunkPosition)this.railChunkPosition.get(i);
132
133            if (chunkposition.x == par1BlockBaseRailLogic.railX && chunkposition.z == par1BlockBaseRailLogic.railZ)
134            {
135                return true;
136            }
137        }
138
139        return false;
140    }
141
142    private boolean isPartOfTrack(int par1, int par2, int par3)
143    {
144        for (int l = 0; l < this.railChunkPosition.size(); ++l)
145        {
146            ChunkPosition chunkposition = (ChunkPosition)this.railChunkPosition.get(l);
147
148            if (chunkposition.x == par1 && chunkposition.z == par3)
149            {
150                return true;
151            }
152        }
153
154        return false;
155    }
156
157    public int getNumberOfAdjacentTracks()
158    {
159        int i = 0;
160
161        if (this.isMinecartTrack(this.railX, this.railY, this.railZ - 1))
162        {
163            ++i;
164        }
165
166        if (this.isMinecartTrack(this.railX, this.railY, this.railZ + 1))
167        {
168            ++i;
169        }
170
171        if (this.isMinecartTrack(this.railX - 1, this.railY, this.railZ))
172        {
173            ++i;
174        }
175
176        if (this.isMinecartTrack(this.railX + 1, this.railY, this.railZ))
177        {
178            ++i;
179        }
180
181        return i;
182    }
183
184    private boolean canConnectTo(BlockBaseRailLogic par1BlockBaseRailLogic)
185    {
186        return this.isRailChunkPositionCorrect(par1BlockBaseRailLogic) ? true : (this.railChunkPosition.size() == 2 ? false : (this.railChunkPosition.isEmpty() ? true : true));
187    }
188
189    private void connectToNeighbor(BlockBaseRailLogic par1BlockBaseRailLogic)
190    {
191        this.railChunkPosition.add(new ChunkPosition(par1BlockBaseRailLogic.railX, par1BlockBaseRailLogic.railY, par1BlockBaseRailLogic.railZ));
192        boolean flag = this.isPartOfTrack(this.railX, this.railY, this.railZ - 1);
193        boolean flag1 = this.isPartOfTrack(this.railX, this.railY, this.railZ + 1);
194        boolean flag2 = this.isPartOfTrack(this.railX - 1, this.railY, this.railZ);
195        boolean flag3 = this.isPartOfTrack(this.railX + 1, this.railY, this.railZ);
196        byte b0 = -1;
197
198        if (flag || flag1)
199        {
200            b0 = 0;
201        }
202
203        if (flag2 || flag3)
204        {
205            b0 = 1;
206        }
207
208        if (!this.isStraightRail)
209        {
210            if (flag1 && flag3 && !flag && !flag2)
211            {
212                b0 = 6;
213            }
214
215            if (flag1 && flag2 && !flag && !flag3)
216            {
217                b0 = 7;
218            }
219
220            if (flag && flag2 && !flag1 && !flag3)
221            {
222                b0 = 8;
223            }
224
225            if (flag && flag3 && !flag1 && !flag2)
226            {
227                b0 = 9;
228            }
229        }
230
231        if (b0 == 0 && canMakeSlopes)
232        {
233            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ - 1))
234            {
235                b0 = 4;
236            }
237
238            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ + 1))
239            {
240                b0 = 5;
241            }
242        }
243
244        if (b0 == 1 && canMakeSlopes)
245        {
246            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX + 1, this.railY + 1, this.railZ))
247            {
248                b0 = 2;
249            }
250
251            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX - 1, this.railY + 1, this.railZ))
252            {
253                b0 = 3;
254            }
255        }
256
257        if (b0 < 0)
258        {
259            b0 = 0;
260        }
261
262        int i = b0;
263
264        if (this.isStraightRail)
265        {
266            i = this.logicWorld.getBlockMetadata(this.railX, this.railY, this.railZ) & 8 | b0;
267        }
268
269        this.logicWorld.setBlockMetadataWithNotify(this.railX, this.railY, this.railZ, i, 3);
270    }
271
272    private boolean canConnectFrom(int par1, int par2, int par3)
273    {
274        BlockBaseRailLogic blockbaseraillogic = this.getRailLogic(new ChunkPosition(par1, par2, par3));
275
276        if (blockbaseraillogic == null)
277        {
278            return false;
279        }
280        else
281        {
282            blockbaseraillogic.refreshConnectedTracks();
283            return blockbaseraillogic.canConnectTo(this);
284        }
285    }
286
287    public void func_94511_a(boolean par1, boolean par2)
288    {
289        boolean flag2 = this.canConnectFrom(this.railX, this.railY, this.railZ - 1);
290        boolean flag3 = this.canConnectFrom(this.railX, this.railY, this.railZ + 1);
291        boolean flag4 = this.canConnectFrom(this.railX - 1, this.railY, this.railZ);
292        boolean flag5 = this.canConnectFrom(this.railX + 1, this.railY, this.railZ);
293        byte b0 = -1;
294
295        if ((flag2 || flag3) && !flag4 && !flag5)
296        {
297            b0 = 0;
298        }
299
300        if ((flag4 || flag5) && !flag2 && !flag3)
301        {
302            b0 = 1;
303        }
304
305        if (!this.isStraightRail)
306        {
307            if (flag3 && flag5 && !flag2 && !flag4)
308            {
309                b0 = 6;
310            }
311
312            if (flag3 && flag4 && !flag2 && !flag5)
313            {
314                b0 = 7;
315            }
316
317            if (flag2 && flag4 && !flag3 && !flag5)
318            {
319                b0 = 8;
320            }
321
322            if (flag2 && flag5 && !flag3 && !flag4)
323            {
324                b0 = 9;
325            }
326        }
327
328        if (b0 == -1)
329        {
330            if (flag2 || flag3)
331            {
332                b0 = 0;
333            }
334
335            if (flag4 || flag5)
336            {
337                b0 = 1;
338            }
339
340            if (!this.isStraightRail)
341            {
342                if (par1)
343                {
344                    if (flag3 && flag5)
345                    {
346                        b0 = 6;
347                    }
348
349                    if (flag4 && flag3)
350                    {
351                        b0 = 7;
352                    }
353
354                    if (flag5 && flag2)
355                    {
356                        b0 = 9;
357                    }
358
359                    if (flag2 && flag4)
360                    {
361                        b0 = 8;
362                    }
363                }
364                else
365                {
366                    if (flag2 && flag4)
367                    {
368                        b0 = 8;
369                    }
370
371                    if (flag5 && flag2)
372                    {
373                        b0 = 9;
374                    }
375
376                    if (flag4 && flag3)
377                    {
378                        b0 = 7;
379                    }
380
381                    if (flag3 && flag5)
382                    {
383                        b0 = 6;
384                    }
385                }
386            }
387        }
388
389        if (b0 == 0 && canMakeSlopes)
390        {
391            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ - 1))
392            {
393                b0 = 4;
394            }
395
396            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ + 1))
397            {
398                b0 = 5;
399            }
400        }
401
402        if (b0 == 1 && canMakeSlopes)
403        {
404            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX + 1, this.railY + 1, this.railZ))
405            {
406                b0 = 2;
407            }
408
409            if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX - 1, this.railY + 1, this.railZ))
410            {
411                b0 = 3;
412            }
413        }
414
415        if (b0 < 0)
416        {
417            b0 = 0;
418        }
419
420        this.setBasicRail(b0);
421        int i = b0;
422
423        if (this.isStraightRail)
424        {
425            i = this.logicWorld.getBlockMetadata(this.railX, this.railY, this.railZ) & 8 | b0;
426        }
427
428        if (par2 || this.logicWorld.getBlockMetadata(this.railX, this.railY, this.railZ) != i)
429        {
430            this.logicWorld.setBlockMetadataWithNotify(this.railX, this.railY, this.railZ, i, 3);
431
432            for (int j = 0; j < this.railChunkPosition.size(); ++j)
433            {
434                BlockBaseRailLogic blockbaseraillogic = this.getRailLogic((ChunkPosition)this.railChunkPosition.get(j));
435
436                if (blockbaseraillogic != null)
437                {
438                    blockbaseraillogic.refreshConnectedTracks();
439
440                    if (blockbaseraillogic.canConnectTo(this))
441                    {
442                        blockbaseraillogic.connectToNeighbor(this);
443                    }
444                }
445            }
446        }
447    }
448}