Terraria 1.4.0.5 Source Code

This commit is contained in:
MikeyIsBaeYT 2021-10-26 12:45:26 -04:00
commit 05205f009e
1059 changed files with 563450 additions and 0 deletions

125
Utilities/CrashDump.cs Normal file
View file

@ -0,0 +1,125 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.CrashDump
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using ReLogic.OS;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
namespace Terraria.Utilities
{
public static class CrashDump
{
public static bool WriteException(CrashDump.Options options, string outputDirectory = ".") => CrashDump.Write(options, CrashDump.ExceptionInfo.Present, outputDirectory);
public static bool Write(CrashDump.Options options, string outputDirectory = ".") => CrashDump.Write(options, CrashDump.ExceptionInfo.None, outputDirectory);
private static string CreateDumpName()
{
DateTime localTime = DateTime.Now.ToLocalTime();
return string.Format("{0}_{1}_{2}_{3}.dmp", (object) "Terraria", (object) Main.versionNumber, (object) localTime.ToString("MM-dd-yy_HH-mm-ss-ffff", (IFormatProvider) CultureInfo.InvariantCulture), (object) Thread.CurrentThread.ManagedThreadId);
}
private static bool Write(
CrashDump.Options options,
CrashDump.ExceptionInfo exceptionInfo,
string outputDirectory)
{
if (!Platform.IsWindows)
return false;
string path = Path.Combine(outputDirectory, CrashDump.CreateDumpName());
if (!Utils.TryCreatingDirectory(outputDirectory))
return false;
using (FileStream fileStream = File.Create(path))
return CrashDump.Write((SafeHandle) fileStream.SafeFileHandle, options, exceptionInfo);
}
private static bool Write(
SafeHandle fileHandle,
CrashDump.Options options,
CrashDump.ExceptionInfo exceptionInfo)
{
if (!Platform.IsWindows)
return false;
Process currentProcess = Process.GetCurrentProcess();
IntPtr handle = currentProcess.Handle;
uint id = (uint) currentProcess.Id;
CrashDump.MiniDumpExceptionInformation expParam;
expParam.ThreadId = CrashDump.GetCurrentThreadId();
expParam.ClientPointers = false;
expParam.ExceptionPointers = IntPtr.Zero;
if (exceptionInfo == CrashDump.ExceptionInfo.Present)
expParam.ExceptionPointers = Marshal.GetExceptionPointers();
return !(expParam.ExceptionPointers == IntPtr.Zero) ? CrashDump.MiniDumpWriteDump(handle, id, fileHandle, (uint) options, ref expParam, IntPtr.Zero, IntPtr.Zero) : CrashDump.MiniDumpWriteDump(handle, id, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
}
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
SafeHandle hFile,
uint dumpType,
ref CrashDump.MiniDumpExceptionInformation expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
SafeHandle hFile,
uint dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
[DllImport("kernel32.dll")]
private static extern uint GetCurrentThreadId();
[System.Flags]
public enum Options : uint
{
Normal = 0,
WithDataSegs = 1,
WithFullMemory = 2,
WithHandleData = 4,
FilterMemory = 8,
ScanMemory = 16, // 0x00000010
WithUnloadedModules = 32, // 0x00000020
WithIndirectlyReferencedMemory = 64, // 0x00000040
FilterModulePaths = 128, // 0x00000080
WithProcessThreadData = 256, // 0x00000100
WithPrivateReadWriteMemory = 512, // 0x00000200
WithoutOptionalData = 1024, // 0x00000400
WithFullMemoryInfo = 2048, // 0x00000800
WithThreadInfo = 4096, // 0x00001000
WithCodeSegs = 8192, // 0x00002000
WithoutAuxiliaryState = 16384, // 0x00004000
WithFullAuxiliaryState = 32768, // 0x00008000
WithPrivateWriteCopyMemory = 65536, // 0x00010000
IgnoreInaccessibleMemory = 131072, // 0x00020000
ValidTypeFlags = IgnoreInaccessibleMemory | WithPrivateWriteCopyMemory | WithFullAuxiliaryState | WithoutAuxiliaryState | WithCodeSegs | WithThreadInfo | WithFullMemoryInfo | WithoutOptionalData | WithPrivateReadWriteMemory | WithProcessThreadData | FilterModulePaths | WithIndirectlyReferencedMemory | WithUnloadedModules | ScanMemory | FilterMemory | WithHandleData | WithFullMemory | WithDataSegs, // 0x0003FFFF
}
private enum ExceptionInfo
{
None,
Present,
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct MiniDumpExceptionInformation
{
public uint ThreadId;
public IntPtr ExceptionPointers;
[MarshalAs(UnmanagedType.Bool)]
public bool ClientPointers;
}
}
}

58
Utilities/CrashWatcher.cs Normal file
View file

@ -0,0 +1,58 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.CrashWatcher
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.ExceptionServices;
using System.Threading;
namespace Terraria.Utilities
{
public static class CrashWatcher
{
public static bool LogAllExceptions { get; set; }
public static bool DumpOnException { get; set; }
public static bool DumpOnCrash { get; private set; }
public static CrashDump.Options CrashDumpOptions { get; private set; }
private static string DumpPath => Path.Combine(Main.SavePath, "Dumps");
public static void Inititialize()
{
Console.WriteLine("Error Logging Enabled.");
AppDomain.CurrentDomain.FirstChanceException += (EventHandler<FirstChanceExceptionEventArgs>) ((sender, exceptionArgs) =>
{
if (!CrashWatcher.LogAllExceptions)
return;
Console.Write("================\r\n" + string.Format("{0}: First-Chance Exception\r\nThread: {1} [{2}]\r\nCulture: {3}\r\nException: {4}\r\n", (object) DateTime.Now, (object) Thread.CurrentThread.ManagedThreadId, (object) Thread.CurrentThread.Name, (object) Thread.CurrentThread.CurrentCulture.Name, (object) exceptionArgs.Exception.ToString()) + "================\r\n\r\n");
});
AppDomain.CurrentDomain.UnhandledException += (UnhandledExceptionEventHandler) ((sender, exceptionArgs) =>
{
Console.Write("================\r\n" + string.Format("{0}: Unhandled Exception\r\nThread: {1} [{2}]\r\nCulture: {3}\r\nException: {4}\r\n", (object) DateTime.Now, (object) Thread.CurrentThread.ManagedThreadId, (object) Thread.CurrentThread.Name, (object) Thread.CurrentThread.CurrentCulture.Name, (object) exceptionArgs.ExceptionObject.ToString()) + "================\r\n");
if (!CrashWatcher.DumpOnCrash)
return;
CrashDump.WriteException(CrashWatcher.CrashDumpOptions, CrashWatcher.DumpPath);
});
}
public static void EnableCrashDumps(CrashDump.Options options)
{
CrashWatcher.DumpOnCrash = true;
CrashWatcher.CrashDumpOptions = options;
}
public static void DisableCrashDumps() => CrashWatcher.DumpOnCrash = false;
[Conditional("DEBUG")]
private static void HookDebugExceptionDialog()
{
}
}
}

68
Utilities/FastRandom.cs Normal file
View file

@ -0,0 +1,68 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.FastRandom
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using System;
namespace Terraria.Utilities
{
public struct FastRandom
{
private const ulong RANDOM_MULTIPLIER = 25214903917;
private const ulong RANDOM_ADD = 11;
private const ulong RANDOM_MASK = 281474976710655;
public ulong Seed { get; private set; }
public FastRandom(ulong seed)
: this()
{
this.Seed = seed;
}
public FastRandom(int seed)
: this()
{
this.Seed = (ulong) seed;
}
public FastRandom WithModifier(ulong modifier) => new FastRandom(FastRandom.NextSeed(modifier) ^ this.Seed);
public FastRandom WithModifier(int x, int y) => this.WithModifier((ulong) ((long) x + 2654435769L + ((long) y << 6)) + ((ulong) y >> 2));
public static FastRandom CreateWithRandomSeed() => new FastRandom((ulong) Guid.NewGuid().GetHashCode());
public void NextSeed() => this.Seed = FastRandom.NextSeed(this.Seed);
private int NextBits(int bits)
{
this.Seed = FastRandom.NextSeed(this.Seed);
return (int) (this.Seed >> 48 - bits);
}
public float NextFloat() => (float) this.NextBits(24) * 5.960464E-08f;
public double NextDouble() => (double) this.NextBits(32) * 4.65661287307739E-10;
public int Next(int max)
{
if ((max & -max) == max)
return (int) ((long) max * (long) this.NextBits(31) >> 31);
int num1;
int num2;
do
{
num1 = this.NextBits(31);
num2 = num1 % max;
}
while (num1 - num2 + (max - 1) < 0);
return num2;
}
public int Next(int min, int max) => this.Next(max - min) + min;
private static ulong NextSeed(ulong seed) => (ulong) ((long) seed * 25214903917L + 11L & 281474976710655L);
}
}

View file

@ -0,0 +1,95 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.FileOperationAPIWrapper
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using System;
using System.Runtime.InteropServices;
namespace Terraria.Utilities
{
public static class FileOperationAPIWrapper
{
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int SHFileOperation(ref FileOperationAPIWrapper.SHFILEOPSTRUCT FileOp);
private static bool Send(string path, FileOperationAPIWrapper.FileOperationFlags flags)
{
try
{
FileOperationAPIWrapper.SHFILEOPSTRUCT FileOp = new FileOperationAPIWrapper.SHFILEOPSTRUCT()
{
wFunc = FileOperationAPIWrapper.FileOperationType.FO_DELETE,
pFrom = path + "\0\0",
fFlags = FileOperationAPIWrapper.FileOperationFlags.FOF_ALLOWUNDO | flags
};
FileOperationAPIWrapper.SHFileOperation(ref FileOp);
return true;
}
catch (Exception ex)
{
return false;
}
}
private static bool Send(string path) => FileOperationAPIWrapper.Send(path, FileOperationAPIWrapper.FileOperationFlags.FOF_NOCONFIRMATION | FileOperationAPIWrapper.FileOperationFlags.FOF_WANTNUKEWARNING);
public static bool MoveToRecycleBin(string path) => FileOperationAPIWrapper.Send(path, FileOperationAPIWrapper.FileOperationFlags.FOF_SILENT | FileOperationAPIWrapper.FileOperationFlags.FOF_NOCONFIRMATION | FileOperationAPIWrapper.FileOperationFlags.FOF_NOERRORUI);
private static bool DeleteFile(string path, FileOperationAPIWrapper.FileOperationFlags flags)
{
try
{
FileOperationAPIWrapper.SHFILEOPSTRUCT FileOp = new FileOperationAPIWrapper.SHFILEOPSTRUCT()
{
wFunc = FileOperationAPIWrapper.FileOperationType.FO_DELETE,
pFrom = path + "\0\0",
fFlags = flags
};
FileOperationAPIWrapper.SHFileOperation(ref FileOp);
return true;
}
catch (Exception ex)
{
return false;
}
}
private static bool DeleteCompletelySilent(string path) => FileOperationAPIWrapper.DeleteFile(path, FileOperationAPIWrapper.FileOperationFlags.FOF_SILENT | FileOperationAPIWrapper.FileOperationFlags.FOF_NOCONFIRMATION | FileOperationAPIWrapper.FileOperationFlags.FOF_NOERRORUI);
[Flags]
private enum FileOperationFlags : ushort
{
FOF_SILENT = 4,
FOF_NOCONFIRMATION = 16, // 0x0010
FOF_ALLOWUNDO = 64, // 0x0040
FOF_SIMPLEPROGRESS = 256, // 0x0100
FOF_NOERRORUI = 1024, // 0x0400
FOF_WANTNUKEWARNING = 16384, // 0x4000
}
private enum FileOperationType : uint
{
FO_MOVE = 1,
FO_COPY = 2,
FO_DELETE = 3,
FO_RENAME = 4,
}
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Auto)]
private struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
[MarshalAs(UnmanagedType.U4)]
public FileOperationAPIWrapper.FileOperationType wFunc;
public string pFrom;
public string pTo;
public FileOperationAPIWrapper.FileOperationFlags fFlags;
[MarshalAs(UnmanagedType.Bool)]
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
public string lpszProgressTitle;
}
}
}

163
Utilities/FileUtilities.cs Normal file
View file

@ -0,0 +1,163 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.FileUtilities
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using Terraria.Social;
namespace Terraria.Utilities
{
public static class FileUtilities
{
private static Regex FileNameRegex = new Regex("^(?<path>.*[\\\\\\/])?(?:$|(?<fileName>.+?)(?:(?<extension>\\.[^.]*$)|$))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static bool Exists(string path, bool cloud) => cloud && SocialAPI.Cloud != null ? SocialAPI.Cloud.HasFile(path) : File.Exists(path);
public static void Delete(string path, bool cloud)
{
if (cloud && SocialAPI.Cloud != null)
SocialAPI.Cloud.Delete(path);
else
FileOperationAPIWrapper.MoveToRecycleBin(path);
}
public static string GetFullPath(string path, bool cloud) => !cloud ? Path.GetFullPath(path) : path;
public static void Copy(string source, string destination, bool cloud, bool overwrite = true)
{
if (!cloud)
{
File.Copy(source, destination, overwrite);
}
else
{
if (SocialAPI.Cloud == null || !overwrite && SocialAPI.Cloud.HasFile(destination))
return;
SocialAPI.Cloud.Write(destination, SocialAPI.Cloud.Read(source));
}
}
public static void Move(string source, string destination, bool cloud, bool overwrite = true)
{
FileUtilities.Copy(source, destination, cloud, overwrite);
FileUtilities.Delete(source, cloud);
}
public static int GetFileSize(string path, bool cloud) => cloud && SocialAPI.Cloud != null ? SocialAPI.Cloud.GetFileSize(path) : (int) new FileInfo(path).Length;
public static void Read(string path, byte[] buffer, int length, bool cloud)
{
if (cloud && SocialAPI.Cloud != null)
{
SocialAPI.Cloud.Read(path, buffer, length);
}
else
{
using (FileStream fileStream = File.OpenRead(path))
fileStream.Read(buffer, 0, length);
}
}
public static byte[] ReadAllBytes(string path, bool cloud) => cloud && SocialAPI.Cloud != null ? SocialAPI.Cloud.Read(path) : File.ReadAllBytes(path);
public static void WriteAllBytes(string path, byte[] data, bool cloud) => FileUtilities.Write(path, data, data.Length, cloud);
public static void Write(string path, byte[] data, int length, bool cloud)
{
if (cloud && SocialAPI.Cloud != null)
{
SocialAPI.Cloud.Write(path, data, length);
}
else
{
string parentFolderPath = FileUtilities.GetParentFolderPath(path);
if (parentFolderPath != "")
Utils.TryCreatingDirectory(parentFolderPath);
FileUtilities.RemoveReadOnlyAttribute(path);
using (FileStream fileStream = File.Open(path, FileMode.Create))
{
while (fileStream.Position < (long) length)
fileStream.Write(data, (int) fileStream.Position, Math.Min(length - (int) fileStream.Position, 2048));
}
}
}
public static void RemoveReadOnlyAttribute(string path)
{
if (!File.Exists(path))
return;
try
{
FileAttributes attributes = File.GetAttributes(path);
if ((attributes & FileAttributes.ReadOnly) != FileAttributes.ReadOnly)
return;
FileAttributes fileAttributes = attributes & ~FileAttributes.ReadOnly;
File.SetAttributes(path, fileAttributes);
}
catch (Exception ex)
{
}
}
public static bool MoveToCloud(string localPath, string cloudPath)
{
if (SocialAPI.Cloud == null)
return false;
FileUtilities.WriteAllBytes(cloudPath, FileUtilities.ReadAllBytes(localPath, false), true);
FileUtilities.Delete(localPath, false);
return true;
}
public static bool MoveToLocal(string cloudPath, string localPath)
{
if (SocialAPI.Cloud == null)
return false;
FileUtilities.WriteAllBytes(localPath, FileUtilities.ReadAllBytes(cloudPath, true), false);
FileUtilities.Delete(cloudPath, true);
return true;
}
public static string GetFileName(string path, bool includeExtension = true)
{
Match match = FileUtilities.FileNameRegex.Match(path);
if (match == null || match.Groups["fileName"] == null)
return "";
includeExtension &= match.Groups["extension"] != null;
return match.Groups["fileName"].Value + (includeExtension ? match.Groups["extension"].Value : "");
}
public static string GetParentFolderPath(string path, bool includeExtension = true)
{
Match match = FileUtilities.FileNameRegex.Match(path);
return match == null || match.Groups[nameof (path)] == null ? "" : match.Groups[nameof (path)].Value;
}
public static void CopyFolder(string sourcePath, string destinationPath)
{
Directory.CreateDirectory(destinationPath);
foreach (string directory in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(directory.Replace(sourcePath, destinationPath));
foreach (string file in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
File.Copy(file, file.Replace(sourcePath, destinationPath), true);
}
public static void ProtectedInvoke(Action action)
{
bool isBackground = Thread.CurrentThread.IsBackground;
try
{
Thread.CurrentThread.IsBackground = false;
action();
}
finally
{
Thread.CurrentThread.IsBackground = isBackground;
}
}
}
}

32
Utilities/IntRange.cs Normal file
View file

@ -0,0 +1,32 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.IntRange
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using Newtonsoft.Json;
namespace Terraria.Utilities
{
public struct IntRange
{
[JsonProperty("Min")]
public readonly int Minimum;
[JsonProperty("Max")]
public readonly int Maximum;
public IntRange(int minimum, int maximum)
{
this.Minimum = minimum;
this.Maximum = maximum;
}
public static IntRange operator *(IntRange range, float scale) => new IntRange((int) ((double) range.Minimum * (double) scale), (int) ((double) range.Maximum * (double) scale));
public static IntRange operator *(float scale, IntRange range) => range * scale;
public static IntRange operator /(IntRange range, float scale) => new IntRange((int) ((double) range.Minimum / (double) scale), (int) ((double) range.Maximum / (double) scale));
public static IntRange operator /(float scale, IntRange range) => range / scale;
}
}

278
Utilities/NPCUtils.cs Normal file
View file

@ -0,0 +1,278 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.NPCUtils
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using Microsoft.Xna.Framework;
using System;
namespace Terraria.Utilities
{
public static class NPCUtils
{
public static NPCUtils.TargetSearchResults SearchForTarget(
Vector2 position,
NPCUtils.TargetSearchFlag flags = NPCUtils.TargetSearchFlag.All,
NPCUtils.SearchFilter<Player> playerFilter = null,
NPCUtils.SearchFilter<NPC> npcFilter = null)
{
return NPCUtils.SearchForTarget((NPC) null, position, flags, playerFilter, npcFilter);
}
public static NPCUtils.TargetSearchResults SearchForTarget(
NPC searcher,
NPCUtils.TargetSearchFlag flags = NPCUtils.TargetSearchFlag.All,
NPCUtils.SearchFilter<Player> playerFilter = null,
NPCUtils.SearchFilter<NPC> npcFilter = null)
{
return NPCUtils.SearchForTarget(searcher, searcher.Center, flags, playerFilter, npcFilter);
}
public static NPCUtils.TargetSearchResults SearchForTarget(
NPC searcher,
Vector2 position,
NPCUtils.TargetSearchFlag flags = NPCUtils.TargetSearchFlag.All,
NPCUtils.SearchFilter<Player> playerFilter = null,
NPCUtils.SearchFilter<NPC> npcFilter = null)
{
float num1 = float.MaxValue;
int nearestNPCIndex = -1;
float adjustedTankDistance = float.MaxValue;
float nearestTankDistance = float.MaxValue;
int nearestTankIndex = -1;
NPCUtils.TargetType tankType = NPCUtils.TargetType.Player;
if (flags.HasFlag((Enum) NPCUtils.TargetSearchFlag.NPCs))
{
for (int index = 0; index < 200; ++index)
{
NPC entity = Main.npc[index];
if (entity.active && entity.whoAmI != searcher.whoAmI && (npcFilter == null || npcFilter(entity)))
{
float num2 = Vector2.DistanceSquared(position, entity.Center);
if ((double) num2 < (double) num1)
{
nearestNPCIndex = index;
num1 = num2;
}
}
}
}
if (flags.HasFlag((Enum) NPCUtils.TargetSearchFlag.Players))
{
for (int index = 0; index < (int) byte.MaxValue; ++index)
{
Player entity = Main.player[index];
if (entity.active && !entity.dead && !entity.ghost && (playerFilter == null || playerFilter(entity)))
{
float num3 = Vector2.Distance(position, entity.Center);
float num4 = num3 - (float) entity.aggro;
bool flag = searcher != null && entity.npcTypeNoAggro[searcher.type];
if (searcher != null & flag && searcher.direction == 0)
num4 += 1000f;
if ((double) num4 < (double) adjustedTankDistance)
{
nearestTankIndex = index;
adjustedTankDistance = num4;
nearestTankDistance = num3;
tankType = NPCUtils.TargetType.Player;
}
if (entity.tankPet >= 0 && !flag)
{
Vector2 center = Main.projectile[entity.tankPet].Center;
float num5 = Vector2.Distance(position, center);
float num6 = num5 - 200f;
if ((double) num6 < (double) adjustedTankDistance && (double) num6 < 200.0 && Collision.CanHit(position, 0, 0, center, 0, 0))
{
nearestTankIndex = index;
adjustedTankDistance = num6;
nearestTankDistance = num5;
tankType = NPCUtils.TargetType.TankPet;
}
}
}
}
}
return new NPCUtils.TargetSearchResults(searcher, nearestNPCIndex, (float) Math.Sqrt((double) num1), nearestTankIndex, nearestTankDistance, adjustedTankDistance, tankType);
}
public static void TargetClosestOldOnesInvasion(
NPC searcher,
bool faceTarget = true,
Vector2? checkPosition = null)
{
NPCUtils.TargetSearchResults searchResults = NPCUtils.SearchForTarget(searcher, playerFilter: NPCUtils.SearchFilters.OnlyPlayersInCertainDistance(searcher.Center, 200f), npcFilter: new NPCUtils.SearchFilter<NPC>(NPCUtils.SearchFilters.OnlyCrystal));
if (!searchResults.FoundTarget)
return;
searcher.target = searchResults.NearestTargetIndex;
searcher.targetRect = searchResults.NearestTargetHitbox;
if (!(searcher.ShouldFaceTarget(ref searchResults) & faceTarget))
return;
searcher.FaceTarget();
}
public static void TargetClosestNonBees(NPC searcher, bool faceTarget = true, Vector2? checkPosition = null)
{
NPCUtils.TargetSearchResults searchResults = NPCUtils.SearchForTarget(searcher, npcFilter: new NPCUtils.SearchFilter<NPC>(NPCUtils.SearchFilters.NonBeeNPCs));
if (!searchResults.FoundTarget)
return;
searcher.target = searchResults.NearestTargetIndex;
searcher.targetRect = searchResults.NearestTargetHitbox;
if (!(searcher.ShouldFaceTarget(ref searchResults) & faceTarget))
return;
searcher.FaceTarget();
}
public static void TargetClosestCommon(NPC searcher, bool faceTarget = true, Vector2? checkPosition = null) => searcher.TargetClosest(faceTarget);
public static void TargetClosestBetsy(NPC searcher, bool faceTarget = true, Vector2? checkPosition = null)
{
NPCUtils.TargetSearchResults searchResults = NPCUtils.SearchForTarget(searcher, npcFilter: new NPCUtils.SearchFilter<NPC>(NPCUtils.SearchFilters.OnlyCrystal));
if (!searchResults.FoundTarget)
return;
NPCUtils.TargetType targetType = searchResults.NearestTargetType;
if (searchResults.FoundTank && !searchResults.NearestTankOwner.dead)
targetType = NPCUtils.TargetType.Player;
searcher.target = searchResults.NearestTargetIndex;
searcher.targetRect = searchResults.NearestTargetHitbox;
if (!(searcher.ShouldFaceTarget(ref searchResults, new NPCUtils.TargetType?(targetType)) & faceTarget))
return;
searcher.FaceTarget();
}
public delegate bool SearchFilter<T>(T entity) where T : Entity;
public delegate void NPCTargetingMethod(NPC searcher, bool faceTarget, Vector2? checkPosition);
public static class SearchFilters
{
public static bool OnlyCrystal(NPC npc) => npc.type == 548 && !npc.dontTakeDamageFromHostiles;
public static NPCUtils.SearchFilter<Player> OnlyPlayersInCertainDistance(
Vector2 position,
float maxDistance)
{
return (NPCUtils.SearchFilter<Player>) (player => (double) player.Distance(position) <= (double) maxDistance);
}
public static bool NonBeeNPCs(NPC npc) => npc.type != 211 && npc.type != 210 && npc.type != 222 && npc.CanBeChasedBy();
}
public enum TargetType
{
None,
NPC,
Player,
TankPet,
}
public struct TargetSearchResults
{
private NPCUtils.TargetType _nearestTargetType;
private int _nearestNPCIndex;
private float _nearestNPCDistance;
private int _nearestTankIndex;
private float _nearestTankDistance;
private float _adjustedTankDistance;
private NPCUtils.TargetType _nearestTankType;
public int NearestTargetIndex
{
get
{
switch (this._nearestTargetType)
{
case NPCUtils.TargetType.NPC:
return this.NearestNPC.WhoAmIToTargettingIndex;
case NPCUtils.TargetType.Player:
case NPCUtils.TargetType.TankPet:
return this._nearestTankIndex;
default:
return -1;
}
}
}
public Rectangle NearestTargetHitbox
{
get
{
switch (this._nearestTargetType)
{
case NPCUtils.TargetType.NPC:
return this.NearestNPC.Hitbox;
case NPCUtils.TargetType.Player:
return this.NearestTankOwner.Hitbox;
case NPCUtils.TargetType.TankPet:
return Main.projectile[this.NearestTankOwner.tankPet].Hitbox;
default:
return Rectangle.Empty;
}
}
}
public NPCUtils.TargetType NearestTargetType => this._nearestTargetType;
public bool FoundTarget => (uint) this._nearestTargetType > 0U;
public NPC NearestNPC => this._nearestNPCIndex != -1 ? Main.npc[this._nearestNPCIndex] : (NPC) null;
public bool FoundNPC => this._nearestNPCIndex != -1;
public int NearestNPCIndex => this._nearestNPCIndex;
public float NearestNPCDistance => this._nearestNPCDistance;
public Player NearestTankOwner => this._nearestTankIndex != -1 ? Main.player[this._nearestTankIndex] : (Player) null;
public bool FoundTank => this._nearestTankIndex != -1;
public int NearestTankOwnerIndex => this._nearestTankIndex;
public float NearestTankDistance => this._nearestTankDistance;
public float AdjustedTankDistance => this._adjustedTankDistance;
public NPCUtils.TargetType NearestTankType => this._nearestTankType;
public TargetSearchResults(
NPC searcher,
int nearestNPCIndex,
float nearestNPCDistance,
int nearestTankIndex,
float nearestTankDistance,
float adjustedTankDistance,
NPCUtils.TargetType tankType)
{
this._nearestNPCIndex = nearestNPCIndex;
this._nearestNPCDistance = nearestNPCDistance;
this._nearestTankIndex = nearestTankIndex;
this._adjustedTankDistance = adjustedTankDistance;
this._nearestTankDistance = nearestTankDistance;
this._nearestTankType = tankType;
if (this._nearestNPCIndex != -1 && this._nearestTankIndex != -1)
{
if ((double) this._nearestNPCDistance < (double) this._adjustedTankDistance)
this._nearestTargetType = NPCUtils.TargetType.NPC;
else
this._nearestTargetType = tankType;
}
else if (this._nearestNPCIndex != -1)
this._nearestTargetType = NPCUtils.TargetType.NPC;
else if (this._nearestTankIndex != -1)
this._nearestTargetType = tankType;
else
this._nearestTargetType = NPCUtils.TargetType.None;
}
}
[Flags]
public enum TargetSearchFlag
{
None = 0,
NPCs = 1,
Players = 2,
All = Players | NPCs, // 0x00000003
}
}
}

View file

@ -0,0 +1,17 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.PlatformUtilities
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
namespace Terraria.Utilities
{
public static class PlatformUtilities
{
public const bool IsXNA = true;
public const bool IsFNA = false;
public const bool IsWindows = true;
public const bool IsOSX = false;
public const bool IsLinux = false;
}
}

View file

@ -0,0 +1,32 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.Terraria.Utilities.FloatRange
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using Newtonsoft.Json;
namespace Terraria.Utilities.Terraria.Utilities
{
public struct FloatRange
{
[JsonProperty("Min")]
public readonly float Minimum;
[JsonProperty("Max")]
public readonly float Maximum;
public FloatRange(float minimum, float maximum)
{
this.Minimum = minimum;
this.Maximum = maximum;
}
public static FloatRange operator *(FloatRange range, float scale) => new FloatRange(range.Minimum * scale, range.Maximum * scale);
public static FloatRange operator *(float scale, FloatRange range) => range * scale;
public static FloatRange operator /(FloatRange range, float scale) => new FloatRange(range.Minimum / scale, range.Maximum / scale);
public static FloatRange operator /(float scale, FloatRange range) => range / scale;
}
}

112
Utilities/UnifiedRandom.cs Normal file
View file

@ -0,0 +1,112 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.UnifiedRandom
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using System;
namespace Terraria.Utilities
{
[Serializable]
public class UnifiedRandom
{
private const int MBIG = 2147483647;
private const int MSEED = 161803398;
private const int MZ = 0;
private int inext;
private int inextp;
private int[] SeedArray = new int[56];
public UnifiedRandom()
: this(Environment.TickCount)
{
}
public UnifiedRandom(int Seed)
{
int num1 = 161803398 - (Seed == int.MinValue ? int.MaxValue : Math.Abs(Seed));
this.SeedArray[55] = num1;
int num2 = 1;
for (int index1 = 1; index1 < 55; ++index1)
{
int index2 = 21 * index1 % 55;
this.SeedArray[index2] = num2;
num2 = num1 - num2;
if (num2 < 0)
num2 += int.MaxValue;
num1 = this.SeedArray[index2];
}
for (int index3 = 1; index3 < 5; ++index3)
{
for (int index4 = 1; index4 < 56; ++index4)
{
this.SeedArray[index4] -= this.SeedArray[1 + (index4 + 30) % 55];
if (this.SeedArray[index4] < 0)
this.SeedArray[index4] += int.MaxValue;
}
}
this.inext = 0;
this.inextp = 21;
Seed = 1;
}
protected virtual double Sample() => (double) this.InternalSample() * 4.6566128752458E-10;
private int InternalSample()
{
int inext = this.inext;
int inextp = this.inextp;
int index1;
if ((index1 = inext + 1) >= 56)
index1 = 1;
int index2;
if ((index2 = inextp + 1) >= 56)
index2 = 1;
int num = this.SeedArray[index1] - this.SeedArray[index2];
if (num == int.MaxValue)
--num;
if (num < 0)
num += int.MaxValue;
this.SeedArray[index1] = num;
this.inext = index1;
this.inextp = index2;
return num;
}
public virtual int Next() => this.InternalSample();
private double GetSampleForLargeRange()
{
int num = this.InternalSample();
if ((this.InternalSample() % 2 == 0 ? 1 : 0) != 0)
num = -num;
return ((double) num + 2147483646.0) / 4294967293.0;
}
public virtual int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
throw new ArgumentOutOfRangeException(nameof (minValue), "minValue must be less than maxValue");
long num = (long) maxValue - (long) minValue;
return num <= (long) int.MaxValue ? (int) (this.Sample() * (double) num) + minValue : (int) ((long) (this.GetSampleForLargeRange() * (double) num) + (long) minValue);
}
public virtual int Next(int maxValue)
{
if (maxValue < 0)
throw new ArgumentOutOfRangeException(nameof (maxValue), "maxValue must be positive.");
return (int) (this.Sample() * (double) maxValue);
}
public virtual double NextDouble() => this.Sample();
public virtual void NextBytes(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof (buffer));
for (int index = 0; index < buffer.Length; ++index)
buffer[index] = (byte) (this.InternalSample() % 256);
}
}
}

View file

@ -0,0 +1,76 @@
// Decompiled with JetBrains decompiler
// Type: Terraria.Utilities.WeightedRandom`1
// Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null
// MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83
// Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe
using System;
using System.Collections.Generic;
using System.Linq;
namespace Terraria.Utilities
{
public class WeightedRandom<T>
{
public readonly List<Tuple<T, double>> elements = new List<Tuple<T, double>>();
public readonly UnifiedRandom random;
public bool needsRefresh = true;
private double _totalWeight;
public WeightedRandom() => this.random = new UnifiedRandom();
public WeightedRandom(int seed) => this.random = new UnifiedRandom(seed);
public WeightedRandom(UnifiedRandom random) => this.random = random;
public WeightedRandom(params Tuple<T, double>[] theElements)
{
this.random = new UnifiedRandom();
this.elements = ((IEnumerable<Tuple<T, double>>) theElements).ToList<Tuple<T, double>>();
}
public WeightedRandom(int seed, params Tuple<T, double>[] theElements)
{
this.random = new UnifiedRandom(seed);
this.elements = ((IEnumerable<Tuple<T, double>>) theElements).ToList<Tuple<T, double>>();
}
public WeightedRandom(UnifiedRandom random, params Tuple<T, double>[] theElements)
{
this.random = random;
this.elements = ((IEnumerable<Tuple<T, double>>) theElements).ToList<Tuple<T, double>>();
}
public void Add(T element, double weight = 1.0)
{
this.elements.Add(new Tuple<T, double>(element, weight));
this.needsRefresh = true;
}
public T Get()
{
if (this.needsRefresh)
this.CalculateTotalWeight();
double num = this.random.NextDouble() * this._totalWeight;
foreach (Tuple<T, double> element in this.elements)
{
if (num <= element.Item2)
return element.Item1;
num -= element.Item2;
}
return default (T);
}
public void CalculateTotalWeight()
{
this._totalWeight = 0.0;
foreach (Tuple<T, double> element in this.elements)
this._totalWeight += element.Item2;
this.needsRefresh = false;
}
public void Clear() => this.elements.Clear();
public static implicit operator T(WeightedRandom<T> weightedRandom) => weightedRandom.Get();
}
}