Terraria 1.4.0.5 Source Code
This commit is contained in:
commit
05205f009e
1059 changed files with 563450 additions and 0 deletions
125
Utilities/CrashDump.cs
Normal file
125
Utilities/CrashDump.cs
Normal 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
58
Utilities/CrashWatcher.cs
Normal 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
68
Utilities/FastRandom.cs
Normal 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);
|
||||
}
|
||||
}
|
95
Utilities/FileOperationAPIWrapper.cs
Normal file
95
Utilities/FileOperationAPIWrapper.cs
Normal 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
163
Utilities/FileUtilities.cs
Normal 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
32
Utilities/IntRange.cs
Normal 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
278
Utilities/NPCUtils.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
17
Utilities/PlatformUtilities.cs
Normal file
17
Utilities/PlatformUtilities.cs
Normal 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;
|
||||
}
|
||||
}
|
32
Utilities/Terraria/Utilities/FloatRange.cs
Normal file
32
Utilities/Terraria/Utilities/FloatRange.cs
Normal 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
112
Utilities/UnifiedRandom.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
76
Utilities/WeightedRandom`1.cs
Normal file
76
Utilities/WeightedRandom`1.cs
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue