terraria-source-code/GameContent/Generation/TrackGenerator.cs
2021-10-27 18:03:19 -04:00

279 lines
8.8 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Terraria.GameContent.Generation.TrackGenerator
// Assembly: Terraria, Version=1.3.5.3, Culture=neutral, PublicKeyToken=null
// MVID: 68659D26-2BE6-448F-8663-74FA559E6F08
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using Microsoft.Xna.Framework;
using System;
using Terraria.ID;
using Terraria.World.Generation;
namespace Terraria.GameContent.Generation
{
public class TrackGenerator
{
private static readonly byte[] INVALID_WALLS = new byte[13]
{
(byte) 7,
(byte) 94,
(byte) 95,
(byte) 8,
(byte) 98,
(byte) 99,
(byte) 9,
(byte) 96,
(byte) 97,
(byte) 3,
(byte) 83,
(byte) 87,
(byte) 86
};
private const int TOTAL_TILE_IGNORES = 150;
private const int PLAYER_HEIGHT = 6;
private const int MAX_RETRIES = 400;
private const int MAX_SMOOTH_DISTANCE = 15;
private const int MAX_ITERATIONS = 1000000;
private TrackGenerator.TrackHistory[] _historyCache = new TrackGenerator.TrackHistory[2048];
public void Generate(int trackCount, int minimumLength)
{
int num = trackCount;
while (num > 0)
{
int x = WorldGen.genRand.Next(150, Main.maxTilesX - 150);
int y = WorldGen.genRand.Next((int) Main.worldSurface + 25, Main.maxTilesY - 200);
if (this.IsLocationEmpty(x, y))
{
while (this.IsLocationEmpty(x, y + 1))
++y;
if (this.FindPath(x, y, minimumLength))
--num;
}
}
}
private bool IsLocationEmpty(int x, int y)
{
if (y > Main.maxTilesY - 200 || x < 0 || y < (int) Main.worldSurface || x > Main.maxTilesX - 5)
return false;
for (int index = 0; index < 6; ++index)
{
if (WorldGen.SolidTile(x, y - index))
return false;
}
return true;
}
private bool CanTrackBePlaced(int x, int y)
{
if (y > Main.maxTilesY - 200 || x < 0 || y < (int) Main.worldSurface || x > Main.maxTilesX - 5)
return false;
byte wall = Main.tile[x, y].wall;
for (int index = 0; index < TrackGenerator.INVALID_WALLS.Length; ++index)
{
if ((int) wall == (int) TrackGenerator.INVALID_WALLS[index])
return false;
}
for (int index = -1; index <= 1; ++index)
{
if (Main.tile[x + index, y].active() && (Main.tile[x + index, y].type == (ushort) 314 || !TileID.Sets.GeneralPlacementTiles[(int) Main.tile[x + index, y].type]))
return false;
}
return true;
}
private void SmoothTrack(TrackGenerator.TrackHistory[] history, int length)
{
int val2 = length - 1;
bool flag = false;
for (int index1 = length - 1; index1 >= 0; --index1)
{
if (flag)
{
val2 = Math.Min(index1 + 15, val2);
if ((int) history[index1].Y >= (int) history[val2].Y)
{
for (int index2 = index1 + 1; (int) history[index2].Y > (int) history[index1].Y; ++index2)
history[index2].Y = history[index1].Y;
if ((int) history[index1].Y == (int) history[val2].Y)
flag = false;
}
}
else if ((int) history[index1].Y > (int) history[val2].Y)
flag = true;
else
val2 = index1;
}
}
public bool FindPath(int x, int y, int minimumLength, bool debugMode = false)
{
TrackGenerator.TrackHistory[] historyCache = this._historyCache;
int index1 = 0;
Tile[,] tile = Main.tile;
bool flag1 = true;
int num1 = WorldGen.genRand.Next(2) == 0 ? 1 : -1;
if (debugMode)
num1 = Main.player[Main.myPlayer].direction;
int yDirection = 1;
int length = 0;
int num2 = 400;
bool flag2 = false;
int num3 = 150;
int num4 = 0;
for (int index2 = 1000000; index2 > 0 & flag1 && index1 < historyCache.Length - 1; ++index1)
{
--index2;
historyCache[index1] = new TrackGenerator.TrackHistory(x, y, yDirection);
bool flag3 = false;
int num5 = 1;
if (index1 > minimumLength >> 1)
num5 = -1;
else if (index1 > (minimumLength >> 1) - 5)
num5 = 0;
if (flag2)
{
int num6 = 0;
int num7 = num3;
bool flag4 = false;
for (int index3 = Math.Min(1, yDirection + 1); index3 >= Math.Max(-1, yDirection - 1); --index3)
{
int num8;
for (num8 = 0; num8 <= num3; ++num8)
{
if (this.IsLocationEmpty(x + (num8 + 1) * num1, y + (num8 + 1) * index3 * num5))
{
flag4 = true;
break;
}
}
if (num8 < num7)
{
num7 = num8;
num6 = index3;
}
}
if (flag4)
{
yDirection = num6;
for (int index4 = 0; index4 < num7 - 1; ++index4)
{
++index1;
x += num1;
y += yDirection * num5;
historyCache[index1] = new TrackGenerator.TrackHistory(x, y, yDirection);
num4 = index1;
}
x += num1;
y += yDirection * num5;
length = index1 + 1;
flag2 = false;
}
num3 -= num7;
if (num3 < 0)
flag1 = false;
}
else
{
for (int index5 = Math.Min(1, yDirection + 1); index5 >= Math.Max(-1, yDirection - 1); --index5)
{
if (this.IsLocationEmpty(x + num1, y + index5 * num5))
{
yDirection = index5;
flag3 = true;
x += num1;
y += yDirection * num5;
length = index1 + 1;
break;
}
}
if (!flag3)
{
while (index1 > num4 && y == (int) historyCache[index1].Y)
--index1;
x = (int) historyCache[index1].X;
y = (int) historyCache[index1].Y;
yDirection = (int) historyCache[index1].YDirection - 1;
--num2;
if (num2 <= 0)
{
index1 = length;
x = (int) historyCache[index1].X;
y = (int) historyCache[index1].Y;
yDirection = (int) historyCache[index1].YDirection;
flag2 = true;
num2 = 200;
}
--index1;
}
}
}
if (!(length > minimumLength | debugMode))
return false;
this.SmoothTrack(historyCache, length);
if (!debugMode)
{
for (int index6 = 0; index6 < length; ++index6)
{
for (int index7 = -1; index7 < 7; ++index7)
{
if (!this.CanTrackBePlaced((int) historyCache[index6].X, (int) historyCache[index6].Y - index7))
return false;
}
}
}
for (int index8 = 0; index8 < length; ++index8)
{
TrackGenerator.TrackHistory trackHistory = historyCache[index8];
for (int index9 = 0; index9 < 6; ++index9)
Main.tile[(int) trackHistory.X, (int) trackHistory.Y - index9].active(false);
}
for (int index10 = 0; index10 < length; ++index10)
{
TrackGenerator.TrackHistory trackHistory = historyCache[index10];
Tile.SmoothSlope((int) trackHistory.X, (int) trackHistory.Y + 1);
Tile.SmoothSlope((int) trackHistory.X, (int) trackHistory.Y - 6);
bool wire = Main.tile[(int) trackHistory.X, (int) trackHistory.Y].wire();
Main.tile[(int) trackHistory.X, (int) trackHistory.Y].ResetToType((ushort) 314);
Main.tile[(int) trackHistory.X, (int) trackHistory.Y].wire(wire);
if (index10 != 0)
{
for (int index11 = 0; index11 < 6; ++index11)
WorldUtils.TileFrame((int) historyCache[index10 - 1].X, (int) historyCache[index10 - 1].Y - index11, true);
if (index10 == length - 1)
{
for (int index12 = 0; index12 < 6; ++index12)
WorldUtils.TileFrame((int) trackHistory.X, (int) trackHistory.Y - index12, true);
}
}
}
return true;
}
public static void Run(int trackCount = 30, int minimumLength = 250) => new TrackGenerator().Generate(trackCount, minimumLength);
public static void Run(Point start) => new TrackGenerator().FindPath(start.X, start.Y, 250, true);
private struct TrackHistory
{
public short X;
public short Y;
public byte YDirection;
public TrackHistory(int x, int y, int yDirection)
{
this.X = (short) x;
this.Y = (short) y;
this.YDirection = (byte) yDirection;
}
public TrackHistory(short x, short y, byte yDirection)
{
this.X = x;
this.Y = y;
this.YDirection = yDirection;
}
}
}
}