Clean up
This commit is contained in:
@ -1,12 +1,11 @@
|
||||
using GTA.Math;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using GTA.Math;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal class BitReader : BinaryReader
|
||||
{
|
||||
|
||||
public BitReader(byte[] array) : base(new MemoryStream(array))
|
||||
{
|
||||
}
|
||||
@ -21,6 +20,7 @@ namespace RageCoop.Core
|
||||
{
|
||||
return base.ReadBytes(ReadInt32());
|
||||
}
|
||||
|
||||
public override string ReadString()
|
||||
{
|
||||
return Encoding.UTF8.GetString(ReadBytes(ReadInt32()));
|
||||
@ -28,24 +28,26 @@ namespace RageCoop.Core
|
||||
|
||||
public Vector3 ReadVector3()
|
||||
{
|
||||
return new Vector3()
|
||||
return new Vector3
|
||||
{
|
||||
X = ReadSingle(),
|
||||
Y = ReadSingle(),
|
||||
Z = ReadSingle()
|
||||
};
|
||||
}
|
||||
|
||||
public Vector2 ReadVector2()
|
||||
{
|
||||
return new Vector2()
|
||||
return new Vector2
|
||||
{
|
||||
X = ReadSingle(),
|
||||
Y = ReadSingle()
|
||||
};
|
||||
}
|
||||
|
||||
public Quaternion ReadQuaternion()
|
||||
{
|
||||
return new Quaternion()
|
||||
return new Quaternion
|
||||
{
|
||||
X = ReadSingle(),
|
||||
Y = ReadSingle(),
|
||||
@ -54,4 +56,4 @@ namespace RageCoop.Core
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,4 @@
|
||||
using GTA.Math;
|
||||
using Lidgren.Network;
|
||||
using Newtonsoft.Json;
|
||||
using RageCoop.Core.Scripting;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -15,38 +11,26 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using GTA;
|
||||
using GTA.Math;
|
||||
using Lidgren.Network;
|
||||
using Newtonsoft.Json;
|
||||
using RageCoop.Core.Scripting;
|
||||
using Console = System.Console;
|
||||
|
||||
[assembly: InternalsVisibleTo("RageCoop.Server")]
|
||||
[assembly: InternalsVisibleTo("RageCoop.Client")]
|
||||
[assembly: InternalsVisibleTo("RageCoop.Client.Installer")]
|
||||
[assembly: InternalsVisibleTo("RageCoop.Client.DataDumper")]
|
||||
[assembly: InternalsVisibleTo("RageCoop.ResourceBuilder")]
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal static class CoreUtils
|
||||
{
|
||||
private static Random random = new Random();
|
||||
public static string FormatToSharpStyle(string input,int offset=14)
|
||||
{
|
||||
var ss = input.Substring(offset).Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
||||
// Replace first character with upper case
|
||||
for (int i = 0; i < ss.Length; i++)
|
||||
{
|
||||
var sec = ss[i].ToLower();
|
||||
var head = sec[0];
|
||||
ss[i] = head.ToString().ToUpper() + sec.Remove(0, 1);
|
||||
}
|
||||
return string.Join("", ss);
|
||||
}
|
||||
public static string ToHex(this int value)
|
||||
{
|
||||
return String.Format("0x{0:X}", value);
|
||||
}
|
||||
public static string ToHex(this uint value)
|
||||
{
|
||||
return String.Format("0x{0:X}", value);
|
||||
}
|
||||
private static readonly HashSet<string> ToIgnore = new HashSet<string>()
|
||||
private static readonly Random random = new Random();
|
||||
|
||||
private static readonly HashSet<string> ToIgnore = new HashSet<string>
|
||||
{
|
||||
"RageCoop.Client",
|
||||
"RageCoop.Client.Loader",
|
||||
@ -57,10 +41,36 @@ namespace RageCoop.Core
|
||||
"ScriptHookVDotNet3",
|
||||
"ScriptHookVDotNet"
|
||||
};
|
||||
public static int RandInt(int start,int end)
|
||||
|
||||
public static string FormatToSharpStyle(string input, int offset = 14)
|
||||
{
|
||||
var ss = input.Substring(offset).Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
||||
// Replace first character with upper case
|
||||
for (var i = 0; i < ss.Length; i++)
|
||||
{
|
||||
var sec = ss[i].ToLower();
|
||||
var head = sec[0];
|
||||
ss[i] = head.ToString().ToUpper() + sec.Remove(0, 1);
|
||||
}
|
||||
|
||||
return string.Join("", ss);
|
||||
}
|
||||
|
||||
public static string ToHex(this int value)
|
||||
{
|
||||
return string.Format("0x{0:X}", value);
|
||||
}
|
||||
|
||||
public static string ToHex(this uint value)
|
||||
{
|
||||
return string.Format("0x{0:X}", value);
|
||||
}
|
||||
|
||||
public static int RandInt(int start, int end)
|
||||
{
|
||||
return random.Next(start, end);
|
||||
}
|
||||
|
||||
public static string GetTempDirectory(string dir = null)
|
||||
{
|
||||
dir = dir ?? Path.GetTempPath();
|
||||
@ -72,109 +82,151 @@ namespace RageCoop.Core
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static string RandomString(int length)
|
||||
{
|
||||
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
return new string(Enumerable.Repeat(chars, length)
|
||||
.Select(s => s[random.Next(s.Length)]).ToArray());
|
||||
}
|
||||
|
||||
public static void GetDependencies(Assembly assembly, ref HashSet<string> existing)
|
||||
{
|
||||
if (assembly.FullName.StartsWith("System")) { return; }
|
||||
if (assembly.FullName.StartsWith("System")) return;
|
||||
foreach (var name in assembly.GetReferencedAssemblies())
|
||||
{
|
||||
if (name.FullName.StartsWith("System")) { continue; }
|
||||
if (name.FullName.StartsWith("System")) continue;
|
||||
try
|
||||
{
|
||||
var asm = Assembly.Load(name);
|
||||
GetDependencies(asm, ref existing);
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (!existing.Contains(assembly.FullName))
|
||||
{
|
||||
Console.WriteLine(assembly.FullName);
|
||||
existing.Add(assembly.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
public static Version GetLatestVersion(string branch = "dev-nightly")
|
||||
{
|
||||
var url = $"https://raw.githubusercontent.com/RAGECOOP/RAGECOOP-V/{branch}/RageCoop.Server/Properties/AssemblyInfo.cs";
|
||||
var versionLine = HttpHelper.DownloadString(url).Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Where(x => x.Contains("[assembly: AssemblyVersion(")).First();
|
||||
var url =
|
||||
$"https://raw.githubusercontent.com/RAGECOOP/RAGECOOP-V/{branch}/RageCoop.Server/Properties/AssemblyInfo.cs";
|
||||
var versionLine = HttpHelper.DownloadString(url)
|
||||
.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Where(x => x.Contains("[assembly: AssemblyVersion(")).First();
|
||||
var start = versionLine.IndexOf('\"') + 1;
|
||||
var end = versionLine.LastIndexOf('\"');
|
||||
return Version.Parse(versionLine.Substring(start, end - start));
|
||||
}
|
||||
|
||||
public static bool CanBeIgnored(this string name)
|
||||
{
|
||||
return ToIgnore.Contains(Path.GetFileNameWithoutExtension(name));
|
||||
}
|
||||
|
||||
public static string ToFullPath(this string path)
|
||||
{
|
||||
return Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
public static void GetBytesFromObject(object obj, NetOutgoingMessage m)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
case byte value:
|
||||
m.Write((byte)0x01); m.Write(value); break;
|
||||
m.Write((byte)0x01);
|
||||
m.Write(value);
|
||||
break;
|
||||
case short value:
|
||||
m.Write((byte)0x02); m.Write(value); break;
|
||||
m.Write((byte)0x02);
|
||||
m.Write(value);
|
||||
break;
|
||||
case ushort value:
|
||||
m.Write((byte)0x03); m.Write(value); break;
|
||||
m.Write((byte)0x03);
|
||||
m.Write(value);
|
||||
break;
|
||||
case int value:
|
||||
m.Write((byte)0x04); m.Write(value); break;
|
||||
m.Write((byte)0x04);
|
||||
m.Write(value);
|
||||
break;
|
||||
case uint value:
|
||||
m.Write((byte)0x05); m.Write(value); break;
|
||||
m.Write((byte)0x05);
|
||||
m.Write(value);
|
||||
break;
|
||||
case long value:
|
||||
m.Write((byte)0x06); m.Write(value); break;
|
||||
m.Write((byte)0x06);
|
||||
m.Write(value);
|
||||
break;
|
||||
case ulong value:
|
||||
m.Write((byte)0x07); m.Write(value); break;
|
||||
m.Write((byte)0x07);
|
||||
m.Write(value);
|
||||
break;
|
||||
case float value:
|
||||
m.Write((byte)0x08); m.Write(value); break;
|
||||
m.Write((byte)0x08);
|
||||
m.Write(value);
|
||||
break;
|
||||
case bool value:
|
||||
m.Write((byte)0x09); m.Write(value); break;
|
||||
m.Write((byte)0x09);
|
||||
m.Write(value);
|
||||
break;
|
||||
case string value:
|
||||
m.Write((byte)0x10); m.Write(value); break;
|
||||
m.Write((byte)0x10);
|
||||
m.Write(value);
|
||||
break;
|
||||
case Vector3 value:
|
||||
m.Write((byte)0x11); m.Write(value); break;
|
||||
m.Write((byte)0x11);
|
||||
m.Write(value);
|
||||
break;
|
||||
case Quaternion value:
|
||||
m.Write((byte)0x12); m.Write(value); break;
|
||||
case GTA.Model value:
|
||||
m.Write((byte)0x13); m.Write(value); break;
|
||||
m.Write((byte)0x12);
|
||||
m.Write(value);
|
||||
break;
|
||||
case Model value:
|
||||
m.Write((byte)0x13);
|
||||
m.Write(value);
|
||||
break;
|
||||
case Vector2 value:
|
||||
m.Write((byte)0x14); m.Write(value); break;
|
||||
m.Write((byte)0x14);
|
||||
m.Write(value);
|
||||
break;
|
||||
case byte[] value:
|
||||
m.Write((byte)0x15); m.WriteByteArray(value); break;
|
||||
m.Write((byte)0x15);
|
||||
m.WriteByteArray(value);
|
||||
break;
|
||||
case Tuple<byte, byte[]> value:
|
||||
m.Write(value.Item1); m.Write(value.Item2); break;
|
||||
m.Write(value.Item1);
|
||||
m.Write(value.Item2);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unsupported object type: " + obj.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
public static IPEndPoint StringToEndPoint(string endpointstring)
|
||||
{
|
||||
return StringToEndPoint(endpointstring, -1);
|
||||
}
|
||||
|
||||
public static IPEndPoint StringToEndPoint(string endpointstring, int defaultport)
|
||||
{
|
||||
if (string.IsNullOrEmpty(endpointstring)
|
||||
|| endpointstring.Trim().Length == 0)
|
||||
{
|
||||
throw new ArgumentException("Endpoint descriptor may not be empty.");
|
||||
}
|
||||
|
||||
if (defaultport != -1 &&
|
||||
(defaultport < IPEndPoint.MinPort
|
||||
|| defaultport > IPEndPoint.MaxPort))
|
||||
{
|
||||
|| defaultport > IPEndPoint.MaxPort))
|
||||
throw new ArgumentException(string.Format("Invalid default port '{0}'", defaultport));
|
||||
}
|
||||
|
||||
string[] values = endpointstring.Split(new char[] { ':' });
|
||||
var values = endpointstring.Split(':');
|
||||
IPAddress ipaddy;
|
||||
int port = -1;
|
||||
var port = -1;
|
||||
|
||||
//check if we have an IPv6 or ports
|
||||
if (values.Length <= 2) // ipv4 or hostname
|
||||
@ -194,7 +246,7 @@ namespace RageCoop.Core
|
||||
//could [a:b:c]:d
|
||||
if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]"))
|
||||
{
|
||||
string ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray());
|
||||
var ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray());
|
||||
ipaddy = IPAddress.Parse(ipaddressstring);
|
||||
port = getPort(values[values.Length - 1]);
|
||||
}
|
||||
@ -217,25 +269,24 @@ namespace RageCoop.Core
|
||||
|
||||
private static int getPort(string p)
|
||||
{
|
||||
|
||||
if (!int.TryParse(p, out int port)
|
||||
|| port < IPEndPoint.MinPort
|
||||
|| port > IPEndPoint.MaxPort)
|
||||
{
|
||||
if (!int.TryParse(p, out var port)
|
||||
|| port < IPEndPoint.MinPort
|
||||
|| port > IPEndPoint.MaxPort)
|
||||
throw new FormatException(string.Format("Invalid end point port '{0}'", p));
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
public static IPAddress GetLocalAddress(string target = "8.8.8.8")
|
||||
{
|
||||
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
|
||||
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
|
||||
{
|
||||
socket.Connect(target, 65530);
|
||||
IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
|
||||
var endPoint = socket.LocalEndPoint as IPEndPoint;
|
||||
return endPoint.Address;
|
||||
}
|
||||
}
|
||||
|
||||
public static IPAddress GetIPfromHost(string p)
|
||||
{
|
||||
var hosts = Dns.GetHostAddresses(p);
|
||||
@ -245,121 +296,124 @@ namespace RageCoop.Core
|
||||
|
||||
return hosts[0];
|
||||
}
|
||||
|
||||
public static IpInfo GetIPInfo()
|
||||
{
|
||||
// TLS only
|
||||
ServicePointManager.Expect100Continue = true;
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
|
||||
ServicePointManager.SecurityProtocol =
|
||||
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
|
||||
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
|
||||
|
||||
var httpClient = new HttpClient();
|
||||
HttpResponseMessage response = httpClient.GetAsync("https://ipinfo.io/json").GetAwaiter().GetResult();
|
||||
var response = httpClient.GetAsync("https://ipinfo.io/json").GetAwaiter().GetResult();
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new Exception($"IPv4 request failed! [{(int)response.StatusCode}/{response.ReasonPhrase}]");
|
||||
}
|
||||
|
||||
string content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
return JsonConvert.DeserializeObject<IpInfo>(content);
|
||||
}
|
||||
|
||||
public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
|
||||
{
|
||||
foreach (DirectoryInfo dir in source.GetDirectories())
|
||||
foreach (var dir in source.GetDirectories())
|
||||
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
|
||||
foreach (FileInfo file in source.GetFiles())
|
||||
foreach (var file in source.GetFiles())
|
||||
file.CopyTo(Path.Combine(target.FullName, file.Name), true);
|
||||
}
|
||||
|
||||
public static string GetInvariantRID()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return "win-" + RuntimeInformation.OSArchitecture.ToString().ToLower();
|
||||
}
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
return "linux-" + RuntimeInformation.OSArchitecture.ToString().ToLower();
|
||||
}
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
return "osx-" + RuntimeInformation.OSArchitecture.ToString().ToLower();
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get local ip addresses on all network interfaces
|
||||
/// Get local ip addresses on all network interfaces
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<IPAddress> GetLocalAddress()
|
||||
{
|
||||
var addresses = new List<IPAddress>();
|
||||
foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
|
||||
foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
IPInterfaceProperties ipProps = netInterface.GetIPProperties();
|
||||
foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses)
|
||||
{
|
||||
addresses.Add(addr.Address);
|
||||
}
|
||||
var ipProps = netInterface.GetIPProperties();
|
||||
foreach (var addr in ipProps.UnicastAddresses) addresses.Add(addr.Address);
|
||||
}
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public static StreamWriter OpenWriter(string path, FileMode mode = FileMode.Create, FileAccess access = FileAccess.Write, FileShare share = FileShare.ReadWrite)
|
||||
public static StreamWriter OpenWriter(string path, FileMode mode = FileMode.Create,
|
||||
FileAccess access = FileAccess.Write, FileShare share = FileShare.ReadWrite)
|
||||
{
|
||||
return new StreamWriter(File.Open(path, mode, access, share));
|
||||
}
|
||||
}
|
||||
|
||||
internal class IpInfo
|
||||
{
|
||||
[JsonProperty("ip")]
|
||||
public string Address { get; set; }
|
||||
[JsonProperty("ip")] public string Address { get; set; }
|
||||
|
||||
[JsonProperty("country")]
|
||||
public string Country { get; set; }
|
||||
[JsonProperty("country")] public string Country { get; set; }
|
||||
}
|
||||
|
||||
internal static class Extensions
|
||||
{
|
||||
public static byte[] GetBytes(this string s)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(s);
|
||||
}
|
||||
|
||||
public static string GetString(this byte[] data)
|
||||
{
|
||||
return Encoding.UTF8.GetString(data);
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(this Vector3 vec)
|
||||
{
|
||||
// 12 bytes
|
||||
return new List<byte[]>() { BitConverter.GetBytes(vec.X), BitConverter.GetBytes(vec.Y), BitConverter.GetBytes(vec.Z) }.Join(4);
|
||||
return new List<byte[]>
|
||||
{ BitConverter.GetBytes(vec.X), BitConverter.GetBytes(vec.Y), BitConverter.GetBytes(vec.Z) }.Join(4);
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(this Vector2 vec)
|
||||
{
|
||||
// 8 bytes
|
||||
return new List<byte[]>() { BitConverter.GetBytes(vec.X), BitConverter.GetBytes(vec.Y) }.Join(4);
|
||||
return new List<byte[]> { BitConverter.GetBytes(vec.X), BitConverter.GetBytes(vec.Y) }.Join(4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="qua"></param>
|
||||
/// <returns>An array of bytes with length 16</returns>
|
||||
public static byte[] GetBytes(this Quaternion qua)
|
||||
{
|
||||
// 16 bytes
|
||||
return new List<byte[]>() { BitConverter.GetBytes(qua.X), BitConverter.GetBytes(qua.Y), BitConverter.GetBytes(qua.Z), BitConverter.GetBytes(qua.W) }.Join(4);
|
||||
return new List<byte[]>
|
||||
{
|
||||
BitConverter.GetBytes(qua.X), BitConverter.GetBytes(qua.Y), BitConverter.GetBytes(qua.Z),
|
||||
BitConverter.GetBytes(qua.W)
|
||||
}.Join(4);
|
||||
}
|
||||
|
||||
public static T GetPacket<T>(this NetIncomingMessage msg) where T : Packet, new()
|
||||
{
|
||||
var p = new T();
|
||||
p.Deserialize(msg);
|
||||
return p;
|
||||
}
|
||||
|
||||
public static bool HasPedFlag(this PedDataFlags flags, PedDataFlags flag)
|
||||
{
|
||||
return (flags & flag) != 0;
|
||||
}
|
||||
|
||||
public static bool HasProjDataFlag(this ProjectileDataFlags flags, ProjectileDataFlags flag)
|
||||
{
|
||||
return (flags & flag) != 0;
|
||||
@ -369,18 +423,19 @@ namespace RageCoop.Core
|
||||
{
|
||||
return (flags & flag) != 0;
|
||||
}
|
||||
|
||||
public static bool HasConfigFlag(this PlayerConfigFlags flags, PlayerConfigFlags flag)
|
||||
{
|
||||
return (flags & flag) != 0;
|
||||
}
|
||||
|
||||
public static bool HasEventFlag(this CustomEventFlags flags, CustomEventFlags flag)
|
||||
{
|
||||
return (flags & flag) != 0;
|
||||
|
||||
}
|
||||
|
||||
public static Type GetActualType(this TypeCode code)
|
||||
{
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
@ -423,43 +478,41 @@ namespace RageCoop.Core
|
||||
return typeof(sbyte);
|
||||
|
||||
case TypeCode.Single:
|
||||
return typeof(Single);
|
||||
return typeof(float);
|
||||
|
||||
case TypeCode.String:
|
||||
return typeof(string);
|
||||
|
||||
case TypeCode.UInt16:
|
||||
return typeof(UInt16);
|
||||
return typeof(ushort);
|
||||
|
||||
case TypeCode.UInt32:
|
||||
return typeof(UInt32);
|
||||
return typeof(uint);
|
||||
|
||||
case TypeCode.UInt64:
|
||||
return typeof(UInt64);
|
||||
return typeof(ulong);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string DumpWithType(this IEnumerable<object> objects)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
sb.Append(obj.GetType() + ":" + obj.ToString() + "\n");
|
||||
}
|
||||
var sb = new StringBuilder();
|
||||
foreach (var obj in objects) sb.Append(obj.GetType() + ":" + obj + "\n");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string Dump<T>(this IEnumerable<T> objects)
|
||||
{
|
||||
return $"{{{string.Join(",", objects)}}}";
|
||||
}
|
||||
|
||||
public static void ForEach<T>(this IEnumerable<T> objects, Action<T> action)
|
||||
{
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
action(obj);
|
||||
}
|
||||
foreach (var obj in objects) action(obj);
|
||||
}
|
||||
|
||||
public static byte[] ReadToEnd(this Stream stream)
|
||||
{
|
||||
if (stream is MemoryStream)
|
||||
@ -471,22 +524,27 @@ namespace RageCoop.Core
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static MemoryStream ToMemStream(this Stream stream)
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
stream.CopyTo(memoryStream);
|
||||
return memoryStream;
|
||||
}
|
||||
|
||||
public static byte[] Join(this List<byte[]> arrays, int lengthPerArray = -1)
|
||||
{
|
||||
if (arrays.Count == 1) { return arrays[0]; }
|
||||
var output = lengthPerArray == -1 ? new byte[arrays.Sum(arr => arr.Length)] : new byte[arrays.Count * lengthPerArray];
|
||||
int writeIdx = 0;
|
||||
if (arrays.Count == 1) return arrays[0];
|
||||
var output = lengthPerArray == -1
|
||||
? new byte[arrays.Sum(arr => arr.Length)]
|
||||
: new byte[arrays.Count * lengthPerArray];
|
||||
var writeIdx = 0;
|
||||
foreach (var byteArr in arrays)
|
||||
{
|
||||
byteArr.CopyTo(output, writeIdx);
|
||||
writeIdx += byteArr.Length;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -494,37 +552,38 @@ namespace RageCoop.Core
|
||||
{
|
||||
return !type.IsAbstract && type.IsSubclassOf(scriptType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some extension methods provided by RageCoop
|
||||
/// Some extension methods provided by RageCoop
|
||||
/// </summary>
|
||||
public static class PublicExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Get a SHA256 hashed byte array of the input string, internally used to hash password at client side.
|
||||
/// Get a SHA256 hashed byte array of the input string, internally used to hash password at client side.
|
||||
/// </summary>
|
||||
/// <param name="inputString"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] GetSHA256Hash(this string inputString)
|
||||
{
|
||||
using (HashAlgorithm algorithm = SHA256.Create())
|
||||
{
|
||||
return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a byte array to hex-encoded string, internally used to trigger handshake event
|
||||
/// Convert a byte array to hex-encoded string, internally used to trigger handshake event
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToHexString(this byte[] data)
|
||||
{
|
||||
return BitConverter.ToString(data).Replace("-", String.Empty);
|
||||
return BitConverter.ToString(data).Replace("-", string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a string to IP address
|
||||
/// Convert a string to IP address
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
@ -532,6 +591,5 @@ namespace RageCoop.Core
|
||||
{
|
||||
return IPAddress.Parse(ip);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<Costura />
|
||||
<Costura />
|
||||
</Weavers>
|
138
Core/Logger.cs
138
Core/Logger.cs
@ -7,7 +7,6 @@ using System.Threading;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
|
||||
public enum LogLevel
|
||||
{
|
||||
Trace = 0,
|
||||
@ -18,83 +17,92 @@ namespace RageCoop.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Logger : MarshalByRefObject, IDisposable
|
||||
{
|
||||
public class LogLine
|
||||
{
|
||||
internal LogLine() { }
|
||||
public DateTime TimeStamp;
|
||||
public LogLevel LogLevel;
|
||||
public string Message;
|
||||
}
|
||||
/// <summary>
|
||||
/// 0:Trace, 1:Debug, 2:Info, 3:Warning, 4:Error
|
||||
/// </summary>
|
||||
public int LogLevel = 0;
|
||||
/// <summary>
|
||||
/// Name of this logger
|
||||
/// </summary>
|
||||
public string Name = "Logger";
|
||||
public readonly string DateTimeFormat = "HH:mm:ss";
|
||||
|
||||
/// <summary>
|
||||
/// Whether to use UTC time for timestamping the log
|
||||
/// </summary>
|
||||
public readonly bool UseUtc = false;
|
||||
public List<StreamWriter> Writers = new List<StreamWriter> { new StreamWriter(Console.OpenStandardOutput()) };
|
||||
public int FlushInterval = 1000;
|
||||
public event FlushDelegate OnFlush;
|
||||
public bool FlushImmediately = false;
|
||||
public delegate void FlushDelegate(LogLine line, string fomatted);
|
||||
|
||||
private readonly Thread LoggerThread;
|
||||
private bool Stopping = false;
|
||||
private readonly ConcurrentQueue<LogLine> _queuedLines = new ConcurrentQueue<LogLine>();
|
||||
public readonly string DateTimeFormat = "HH:mm:ss";
|
||||
|
||||
private readonly Thread LoggerThread;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to use UTC time for timestamping the log
|
||||
/// </summary>
|
||||
public readonly bool UseUtc = false;
|
||||
|
||||
public bool FlushImmediately = false;
|
||||
public int FlushInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// 0:Trace, 1:Debug, 2:Info, 3:Warning, 4:Error
|
||||
/// </summary>
|
||||
public int LogLevel = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Name of this logger
|
||||
/// </summary>
|
||||
public string Name = "Logger";
|
||||
|
||||
private bool Stopping;
|
||||
public List<StreamWriter> Writers = new List<StreamWriter> { new StreamWriter(Console.OpenStandardOutput()) };
|
||||
|
||||
internal Logger()
|
||||
{
|
||||
Name = Process.GetCurrentProcess().Id.ToString();
|
||||
if (!FlushImmediately)
|
||||
{
|
||||
LoggerThread = new Thread(() =>
|
||||
{
|
||||
while (!Stopping)
|
||||
{
|
||||
Flush();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
Flush();
|
||||
});
|
||||
{
|
||||
while (!Stopping)
|
||||
{
|
||||
Flush();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
Flush();
|
||||
});
|
||||
LoggerThread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop backdround thread and flush all pending messages.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Stopping = true;
|
||||
LoggerThread?.Join();
|
||||
}
|
||||
|
||||
public event FlushDelegate OnFlush;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void Info(string message)
|
||||
{
|
||||
Enqueue(2, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void Warning(string message)
|
||||
{
|
||||
Enqueue(3, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void Error(string message)
|
||||
{
|
||||
Enqueue(4, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="error"></param>
|
||||
@ -102,51 +110,50 @@ namespace RageCoop.Core
|
||||
{
|
||||
Enqueue(4, $"{message}:\n {error}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
public void Error(Exception ex)
|
||||
{
|
||||
Enqueue(4, ex.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void Debug(string message)
|
||||
{
|
||||
Enqueue(1, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void Trace(string message)
|
||||
{
|
||||
Enqueue(0, message);
|
||||
}
|
||||
|
||||
public void Enqueue(int level, string message)
|
||||
{
|
||||
if (level < LogLevel) { return; }
|
||||
_queuedLines.Enqueue(new LogLine()
|
||||
if (level < LogLevel) return;
|
||||
_queuedLines.Enqueue(new LogLine
|
||||
{
|
||||
Message = message,
|
||||
TimeStamp = UseUtc ? DateTime.UtcNow : DateTime.Now,
|
||||
LogLevel = (LogLevel)level
|
||||
});
|
||||
if (FlushImmediately)
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
if (FlushImmediately) Flush();
|
||||
}
|
||||
|
||||
private string Format(LogLine line)
|
||||
{
|
||||
return string.Format("[{0}][{2}] [{3}] {1}", line.TimeStamp.ToString(DateTimeFormat), line.Message, Name, line.LogLevel.ToString());
|
||||
return string.Format("[{0}][{2}] [{3}] {1}", line.TimeStamp.ToString(DateTimeFormat), line.Message, Name,
|
||||
line.LogLevel.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Flush()
|
||||
{
|
||||
@ -157,20 +164,29 @@ namespace RageCoop.Core
|
||||
while (_queuedLines.TryDequeue(out var line))
|
||||
{
|
||||
var formatted = Format(line);
|
||||
Writers.ForEach(x => { x.WriteLine(formatted); x.Flush(); });
|
||||
Writers.ForEach(x =>
|
||||
{
|
||||
x.WriteLine(formatted);
|
||||
x.Flush();
|
||||
});
|
||||
OnFlush?.Invoke(line, formatted);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Stop backdround thread and flush all pending messages.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
|
||||
public class LogLine
|
||||
{
|
||||
Stopping = true;
|
||||
LoggerThread?.Join();
|
||||
public LogLevel LogLevel;
|
||||
public string Message;
|
||||
public DateTime TimeStamp;
|
||||
|
||||
internal LogLine()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
using GTA.Math;
|
||||
using System;
|
||||
using System;
|
||||
using GTA.Math;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
@ -10,9 +10,9 @@ namespace RageCoop.Core
|
||||
|
||||
public static Vector3 ToDirection(this Vector3 rotation)
|
||||
{
|
||||
double z = DegToRad(rotation.Z);
|
||||
double x = DegToRad(rotation.X);
|
||||
double num = Math.Abs(Math.Cos(x));
|
||||
var z = DegToRad(rotation.Z);
|
||||
var x = DegToRad(rotation.X);
|
||||
var num = Math.Abs(Math.Cos(x));
|
||||
|
||||
return new Vector3
|
||||
{
|
||||
@ -23,11 +23,10 @@ namespace RageCoop.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static Vector3 ToVector(this Quaternion vec)
|
||||
{
|
||||
return new Vector3()
|
||||
return new Vector3
|
||||
{
|
||||
X = vec.X,
|
||||
Y = vec.Y,
|
||||
@ -36,11 +35,10 @@ namespace RageCoop.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static Quaternion ToQuaternion(this Vector3 vec, float vW = 0.0f)
|
||||
{
|
||||
return new Quaternion()
|
||||
return new Quaternion
|
||||
{
|
||||
X = vec.X,
|
||||
Y = vec.Y,
|
||||
@ -61,35 +59,35 @@ namespace RageCoop.Core
|
||||
|
||||
public static Vector3 ToRadians(this Vector3 i)
|
||||
{
|
||||
return new Vector3()
|
||||
return new Vector3
|
||||
{
|
||||
X = ToRadians(i.X),
|
||||
Y = ToRadians(i.Y),
|
||||
Z = ToRadians(i.Z),
|
||||
Z = ToRadians(i.Z)
|
||||
};
|
||||
}
|
||||
|
||||
public static Quaternion ToQuaternion(this Vector3 vect)
|
||||
{
|
||||
vect = new Vector3()
|
||||
vect = new Vector3
|
||||
{
|
||||
X = vect.X.Denormalize() * -1,
|
||||
Y = vect.Y.Denormalize() - 180f,
|
||||
Z = vect.Z.Denormalize() - 180f,
|
||||
Z = vect.Z.Denormalize() - 180f
|
||||
};
|
||||
|
||||
vect = vect.ToRadians();
|
||||
|
||||
float rollOver2 = vect.Z * 0.5f;
|
||||
float sinRollOver2 = (float)Math.Sin(rollOver2);
|
||||
float cosRollOver2 = (float)Math.Cos(rollOver2);
|
||||
float pitchOver2 = vect.Y * 0.5f;
|
||||
float sinPitchOver2 = (float)Math.Sin(pitchOver2);
|
||||
float cosPitchOver2 = (float)Math.Cos(pitchOver2);
|
||||
float yawOver2 = vect.X * 0.5f; // pitch
|
||||
float sinYawOver2 = (float)Math.Sin(yawOver2);
|
||||
float cosYawOver2 = (float)Math.Cos(yawOver2);
|
||||
Quaternion result = new Quaternion()
|
||||
var rollOver2 = vect.Z * 0.5f;
|
||||
var sinRollOver2 = (float)Math.Sin(rollOver2);
|
||||
var cosRollOver2 = (float)Math.Cos(rollOver2);
|
||||
var pitchOver2 = vect.Y * 0.5f;
|
||||
var sinPitchOver2 = (float)Math.Sin(pitchOver2);
|
||||
var cosPitchOver2 = (float)Math.Cos(pitchOver2);
|
||||
var yawOver2 = vect.X * 0.5f; // pitch
|
||||
var sinYawOver2 = (float)Math.Sin(yawOver2);
|
||||
var cosYawOver2 = (float)Math.Cos(yawOver2);
|
||||
var result = new Quaternion
|
||||
{
|
||||
X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2,
|
||||
Y = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2,
|
||||
@ -98,27 +96,31 @@ namespace RageCoop.Core
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double DegToRad(double deg)
|
||||
{
|
||||
return deg * Math.PI / 180.0;
|
||||
}
|
||||
|
||||
public static Vector3 ToEulerRotation(this Vector3 dir, Vector3 up)
|
||||
{
|
||||
var rot = Quaternion.LookRotation(dir.Normalized, up).ToEulerAngles().ToDegree();
|
||||
return rot;
|
||||
|
||||
}
|
||||
|
||||
public static Vector3 ToDegree(this Vector3 radian)
|
||||
{
|
||||
return radian * (float)(180 / Math.PI);
|
||||
}
|
||||
|
||||
public static Vector3 ToEulerDegrees(this Quaternion q)
|
||||
{
|
||||
return q.ToEulerAngles().ToDegree();
|
||||
}
|
||||
|
||||
public static Vector3 ToEulerAngles(this Quaternion q)
|
||||
{
|
||||
Vector3 angles = new Vector3();
|
||||
var angles = new Vector3();
|
||||
|
||||
// roll / x
|
||||
double sinr_cosp = 2 * (q.W * q.X + q.Y * q.Z);
|
||||
@ -128,13 +130,9 @@ namespace RageCoop.Core
|
||||
// pitch / y
|
||||
double sinp = 2 * (q.W * q.Y - q.Z * q.X);
|
||||
if (Math.Abs(sinp) >= 1)
|
||||
{
|
||||
angles.Y = CopySign(Math.PI / 2, sinp);
|
||||
}
|
||||
else
|
||||
{
|
||||
angles.Y = (float)Math.Asin(sinp);
|
||||
}
|
||||
|
||||
// yaw / z
|
||||
double siny_cosp = 2 * (q.W * q.Z + q.X * q.Y);
|
||||
@ -143,23 +141,22 @@ namespace RageCoop.Core
|
||||
|
||||
return angles;
|
||||
}
|
||||
|
||||
private static float CopySign(double x, double y)
|
||||
{
|
||||
if (y >= 0)
|
||||
{
|
||||
return x >= 0 ? (float)x : (float)-x;
|
||||
}
|
||||
if (y >= 0) return x >= 0 ? (float)x : (float)-x;
|
||||
|
||||
return x >= 0 ? (float)-x : (float)x;
|
||||
}
|
||||
|
||||
public static double AngelTo(this Vector3 v1, Vector3 v2)
|
||||
{
|
||||
return Math.Acos(v1.GetCosTheta(v2));
|
||||
}
|
||||
|
||||
public static float GetCosTheta(this Vector3 v1, Vector3 v2)
|
||||
{
|
||||
return Vector3.Dot(v1, v2) / (v1.Length() * v2.Length());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +1,33 @@
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal class CoopPeer : NetPeer, IDisposable
|
||||
{
|
||||
public EventHandler<NetIncomingMessage> OnMessageReceived;
|
||||
private readonly Thread ListenerThread;
|
||||
private bool _stopping = false;
|
||||
private bool _stopping;
|
||||
public EventHandler<NetIncomingMessage> OnMessageReceived;
|
||||
|
||||
public CoopPeer(NetPeerConfiguration config) : base(config)
|
||||
{
|
||||
Start();
|
||||
NetIncomingMessage msg;
|
||||
ListenerThread = new Thread(() =>
|
||||
{
|
||||
while (!_stopping)
|
||||
{
|
||||
msg = WaitMessage(200);
|
||||
if (msg != null)
|
||||
{
|
||||
OnMessageReceived?.Invoke(this, msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
{
|
||||
while (!_stopping)
|
||||
{
|
||||
msg = WaitMessage(200);
|
||||
if (msg != null) OnMessageReceived?.Invoke(this, msg);
|
||||
}
|
||||
});
|
||||
ListenerThread.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminate all connections and background thread
|
||||
/// Terminate all connections and background thread
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
@ -37,24 +35,30 @@ namespace RageCoop.Core
|
||||
Shutdown("Bye!");
|
||||
ListenerThread.Join();
|
||||
}
|
||||
public void SendTo(Packet p, NetConnection connection, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
|
||||
|
||||
public void SendTo(Packet p, NetConnection connection, ConnectionChannel channel = ConnectionChannel.Default,
|
||||
NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = CreateMessage();
|
||||
var outgoingMessage = CreateMessage();
|
||||
p.Pack(outgoingMessage);
|
||||
SendMessage(outgoingMessage, connection, method, (int)channel);
|
||||
}
|
||||
public void SendTo(Packet p, IList<NetConnection> connections, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
|
||||
{
|
||||
|
||||
NetOutgoingMessage outgoingMessage = CreateMessage();
|
||||
public void SendTo(Packet p, IList<NetConnection> connections,
|
||||
ConnectionChannel channel = ConnectionChannel.Default,
|
||||
NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
|
||||
{
|
||||
var outgoingMessage = CreateMessage();
|
||||
p.Pack(outgoingMessage);
|
||||
SendMessage(outgoingMessage, connections, method, (int)channel);
|
||||
}
|
||||
public void Send(Packet p, IList<NetConnection> cons, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
|
||||
|
||||
public void Send(Packet p, IList<NetConnection> cons, ConnectionChannel channel = ConnectionChannel.Default,
|
||||
NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = CreateMessage();
|
||||
var outgoingMessage = CreateMessage();
|
||||
p.Pack(outgoingMessage);
|
||||
SendMessage(outgoingMessage, cons, method, (int)channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -9,9 +9,9 @@ namespace RageCoop.Core
|
||||
{
|
||||
public static void DownloadFile(string url, string destination, Action<int> progressCallback = null)
|
||||
{
|
||||
if (File.Exists(destination)) { File.Delete(destination); }
|
||||
AutoResetEvent ae = new AutoResetEvent(false);
|
||||
WebClient client = new WebClient();
|
||||
if (File.Exists(destination)) File.Delete(destination);
|
||||
var ae = new AutoResetEvent(false);
|
||||
var client = new WebClient();
|
||||
|
||||
// TLS only
|
||||
ServicePointManager.Expect100Continue = true;
|
||||
@ -19,13 +19,11 @@ namespace RageCoop.Core
|
||||
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
|
||||
|
||||
client.DownloadProgressChanged += (s, e1) => progressCallback?.Invoke(e1.ProgressPercentage);
|
||||
client.DownloadFileCompleted += (s, e2) =>
|
||||
{
|
||||
ae.Set();
|
||||
};
|
||||
client.DownloadFileCompleted += (s, e2) => { ae.Set(); };
|
||||
client.DownloadFileAsync(new Uri(url), destination);
|
||||
ae.WaitOne();
|
||||
}
|
||||
|
||||
public static string DownloadString(string url)
|
||||
{
|
||||
// TLS only
|
||||
@ -35,8 +33,8 @@ namespace RageCoop.Core
|
||||
SecurityProtocolType.Tls;
|
||||
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
|
||||
|
||||
WebClient client = new WebClient();
|
||||
var client = new WebClient();
|
||||
return client.DownloadString(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,10 +4,9 @@ namespace RageCoop.Core
|
||||
{
|
||||
internal class PublicKey
|
||||
{
|
||||
public PublicKey()
|
||||
{
|
||||
public byte[] Exponent;
|
||||
public byte[] Modulus;
|
||||
|
||||
}
|
||||
public static PublicKey FromServerInfo(ServerInfo info)
|
||||
{
|
||||
return new PublicKey
|
||||
@ -16,7 +15,5 @@ namespace RageCoop.Core
|
||||
Exponent = Convert.FromBase64String(info.publicKeyExponent)
|
||||
};
|
||||
}
|
||||
public byte[] Modulus;
|
||||
public byte[] Exponent;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A json object representing a server's information as annouced to master server.
|
||||
/// A json object representing a server's information as annouced to master server.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ServerInfo
|
||||
@ -30,6 +30,5 @@ namespace RageCoop.Core
|
||||
public string ztAddress { get; set; }
|
||||
public string publicKeyModulus { get; set; }
|
||||
public string publicKeyExponent { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -5,11 +5,20 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal class ZeroTierNetwork
|
||||
{
|
||||
public List<string> Addresses = new List<string>();
|
||||
public string Device;
|
||||
public string ID;
|
||||
public string Mac;
|
||||
public string Name;
|
||||
public string Status;
|
||||
public string Type;
|
||||
|
||||
public ZeroTierNetwork(string line)
|
||||
{
|
||||
// <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips>
|
||||
@ -20,80 +29,34 @@ namespace RageCoop.Core
|
||||
Status = v[3];
|
||||
Type = v[4];
|
||||
Device = v[5];
|
||||
foreach (var i in v[6].Split(','))
|
||||
{
|
||||
Addresses.Add(i.Split('/')[0]);
|
||||
}
|
||||
foreach (var i in v[6].Split(',')) Addresses.Add(i.Split('/')[0]);
|
||||
}
|
||||
public string ID;
|
||||
public string Name;
|
||||
public string Mac;
|
||||
public string Status;
|
||||
public string Type;
|
||||
public string Device;
|
||||
public List<string> Addresses = new List<string>();
|
||||
|
||||
}
|
||||
|
||||
internal static class ZeroTierHelper
|
||||
{
|
||||
private static readonly string _path = "zerotier-cli";
|
||||
private static readonly string _arg = "";
|
||||
|
||||
static ZeroTierHelper()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
var batpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "ZeroTier", "One", "zerotier-cli.bat");
|
||||
var batpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
|
||||
"ZeroTier", "One", "zerotier-cli.bat");
|
||||
_arg = $"/c \"{batpath}\" ";
|
||||
_path = "cmd.exe";
|
||||
}
|
||||
|
||||
var status = RunCommand("status");
|
||||
if (!status.StartsWith("200"))
|
||||
{
|
||||
throw new Exception("ZeroTier not ready: " + status);
|
||||
}
|
||||
}
|
||||
public static ZeroTierNetwork Join(string networkId, int timeout = 10000)
|
||||
{
|
||||
var p = Run("join " + networkId);
|
||||
var o = p.StandardOutput.ReadToEnd();
|
||||
if (!o.StartsWith("200 join OK"))
|
||||
{
|
||||
throw new Exception(o + p.StandardError.ReadToEnd());
|
||||
}
|
||||
if (timeout == 0) { return Networks[networkId]; }
|
||||
int i = 0;
|
||||
while (i <= timeout)
|
||||
{
|
||||
i += 100;
|
||||
if (Networks.TryGetValue(networkId, out var n))
|
||||
{
|
||||
if (n.Addresses.Count != 0 && (!n.Addresses.Where(x => x == "-").Any()))
|
||||
{
|
||||
return n;
|
||||
}
|
||||
System.Threading.Thread.Sleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static void Leave(string networkId)
|
||||
{
|
||||
var p = Run("leave " + networkId);
|
||||
var o = p.StandardOutput.ReadToEnd();
|
||||
if (!o.StartsWith("200 leave OK"))
|
||||
{
|
||||
throw new Exception(o + p.StandardError.ReadToEnd());
|
||||
}
|
||||
if (!status.StartsWith("200")) throw new Exception("ZeroTier not ready: " + status);
|
||||
}
|
||||
|
||||
public static Dictionary<string, ZeroTierNetwork> Networks
|
||||
{
|
||||
get
|
||||
{
|
||||
Dictionary<string, ZeroTierNetwork> networks = new Dictionary<string, ZeroTierNetwork>();
|
||||
var networks = new Dictionary<string, ZeroTierNetwork>();
|
||||
var p = Run("listnetworks");
|
||||
var lines = Regex.Split(p.StandardOutput.ReadToEnd(), "\n").Skip(1);
|
||||
|
||||
@ -106,33 +69,67 @@ namespace RageCoop.Core
|
||||
networks.Add(n.ID, n);
|
||||
}
|
||||
}
|
||||
|
||||
return networks;
|
||||
}
|
||||
}
|
||||
|
||||
public static ZeroTierNetwork Join(string networkId, int timeout = 10000)
|
||||
{
|
||||
var p = Run("join " + networkId);
|
||||
var o = p.StandardOutput.ReadToEnd();
|
||||
if (!o.StartsWith("200 join OK")) throw new Exception(o + p.StandardError.ReadToEnd());
|
||||
if (timeout == 0) return Networks[networkId];
|
||||
var i = 0;
|
||||
while (i <= timeout)
|
||||
{
|
||||
i += 100;
|
||||
if (Networks.TryGetValue(networkId, out var n))
|
||||
{
|
||||
if (n.Addresses.Count != 0 && !n.Addresses.Where(x => x == "-").Any()) return n;
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Leave(string networkId)
|
||||
{
|
||||
var p = Run("leave " + networkId);
|
||||
var o = p.StandardOutput.ReadToEnd();
|
||||
if (!o.StartsWith("200 leave OK")) throw new Exception(o + p.StandardError.ReadToEnd());
|
||||
}
|
||||
|
||||
private static Process Run(string args)
|
||||
{
|
||||
var p = new Process();
|
||||
p.StartInfo = new ProcessStartInfo()
|
||||
p.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = _path,
|
||||
Arguments = _arg + args,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
p.Start();
|
||||
p.WaitForExit();
|
||||
return p;
|
||||
}
|
||||
|
||||
private static string RunCommand(string command)
|
||||
{
|
||||
var p = Run(command);
|
||||
return p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd();
|
||||
}
|
||||
|
||||
public static void Check()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,24 +5,32 @@ namespace RageCoop.Core
|
||||
{
|
||||
internal static class PacketExtensions
|
||||
{
|
||||
internal static bool IsSyncEvent(this PacketType p)
|
||||
{
|
||||
return 30 <= (byte)p && (byte)p <= 40;
|
||||
}
|
||||
|
||||
#region MESSAGE-READ
|
||||
|
||||
public static Vector3 ReadVector3(this NetIncomingMessage m)
|
||||
{
|
||||
return new Vector3
|
||||
{
|
||||
X = m.ReadFloat(),
|
||||
Y = m.ReadFloat(),
|
||||
Z = m.ReadFloat(),
|
||||
Z = m.ReadFloat()
|
||||
};
|
||||
}
|
||||
|
||||
public static Vector2 ReadVector2(this NetIncomingMessage m)
|
||||
{
|
||||
return new Vector2
|
||||
{
|
||||
X = m.ReadFloat(),
|
||||
Y = m.ReadFloat(),
|
||||
Y = m.ReadFloat()
|
||||
};
|
||||
}
|
||||
|
||||
public static Quaternion ReadQuaternion(this NetIncomingMessage m)
|
||||
{
|
||||
return new Quaternion
|
||||
@ -30,22 +38,26 @@ namespace RageCoop.Core
|
||||
X = m.ReadFloat(),
|
||||
Y = m.ReadFloat(),
|
||||
Z = m.ReadFloat(),
|
||||
W = m.ReadFloat(),
|
||||
W = m.ReadFloat()
|
||||
};
|
||||
}
|
||||
|
||||
public static byte[] ReadByteArray(this NetIncomingMessage m)
|
||||
{
|
||||
return m.ReadBytes(m.ReadInt32());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MESSAGE-WRITE
|
||||
|
||||
public static void Write(this NetOutgoingMessage m, Vector3 v)
|
||||
{
|
||||
m.Write(v.X);
|
||||
m.Write(v.Y);
|
||||
m.Write(v.Z);
|
||||
}
|
||||
|
||||
public static void Write(this NetOutgoingMessage m, Quaternion q)
|
||||
{
|
||||
m.Write(q.X);
|
||||
@ -53,16 +65,13 @@ namespace RageCoop.Core
|
||||
m.Write(q.Z);
|
||||
m.Write(q.W);
|
||||
}
|
||||
|
||||
public static void WriteByteArray(this NetOutgoingMessage m, byte[] b)
|
||||
{
|
||||
m.Write(b.Length);
|
||||
m.Write(b);
|
||||
}
|
||||
#endregion
|
||||
|
||||
internal static bool IsSyncEvent(this PacketType p)
|
||||
{
|
||||
return (30 <= (byte)p) && ((byte)p <= 40);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +1,51 @@
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
internal class ChatMessage : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.ChatMessage;
|
||||
private readonly Func<string, byte[]> crypt;
|
||||
private readonly Func<byte[], byte[]> decrypt;
|
||||
|
||||
public ChatMessage(Func<string, byte[]> crypter)
|
||||
{
|
||||
crypt = crypter;
|
||||
}
|
||||
|
||||
public ChatMessage(Func<byte[], byte[]> decrypter)
|
||||
{
|
||||
decrypt = decrypter;
|
||||
}
|
||||
|
||||
public override PacketType Type => PacketType.ChatMessage;
|
||||
public string Username { get; set; }
|
||||
|
||||
public string Message { get; set; }
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Write Username
|
||||
m.Write(Username);
|
||||
|
||||
|
||||
// Write Message
|
||||
m.WriteByteArray(crypt(Message));
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
// Read username
|
||||
Username = m.ReadString();
|
||||
|
||||
Message = decrypt(m.ReadByteArray()).GetString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +1,23 @@
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using GTA;
|
||||
using Lidgren.Network;
|
||||
using RageCoop.Core.Scripting;
|
||||
using System;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
internal class CustomEvent : Packet
|
||||
{
|
||||
public static Func<byte, NetIncomingMessage, object> ResolveHandle = null;
|
||||
public CustomEventFlags Flags;
|
||||
public override PacketType Type => PacketType.CustomEvent;
|
||||
|
||||
public CustomEvent(CustomEventFlags flags = CustomEventFlags.None)
|
||||
{
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
public override PacketType Type => PacketType.CustomEvent;
|
||||
public int Hash { get; set; }
|
||||
public object[] Args { get; set; }
|
||||
|
||||
@ -24,65 +27,75 @@ namespace RageCoop.Core
|
||||
m.Write((byte)Flags);
|
||||
m.Write(Hash);
|
||||
m.Write(Args.Length);
|
||||
foreach (var arg in Args)
|
||||
{
|
||||
CoreUtils.GetBytesFromObject(arg, m);
|
||||
}
|
||||
foreach (var arg in Args) CoreUtils.GetBytesFromObject(arg, m);
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
Flags = (CustomEventFlags)m.ReadByte();
|
||||
Hash = m.ReadInt32();
|
||||
Args = new object[m.ReadInt32()];
|
||||
for (int i = 0; i < Args.Length; i++)
|
||||
for (var i = 0; i < Args.Length; i++)
|
||||
{
|
||||
byte type = m.ReadByte();
|
||||
var type = m.ReadByte();
|
||||
switch (type)
|
||||
{
|
||||
case 0x01:
|
||||
Args[i] = m.ReadByte(); break;
|
||||
Args[i] = m.ReadByte();
|
||||
break;
|
||||
case 0x02:
|
||||
Args[i] = m.ReadInt32(); break;
|
||||
Args[i] = m.ReadInt32();
|
||||
break;
|
||||
case 0x03:
|
||||
Args[i] = m.ReadUInt16(); break;
|
||||
Args[i] = m.ReadUInt16();
|
||||
break;
|
||||
case 0x04:
|
||||
Args[i] = m.ReadInt32(); break;
|
||||
Args[i] = m.ReadInt32();
|
||||
break;
|
||||
case 0x05:
|
||||
Args[i] = m.ReadUInt32(); break;
|
||||
Args[i] = m.ReadUInt32();
|
||||
break;
|
||||
case 0x06:
|
||||
Args[i] = m.ReadInt64(); break;
|
||||
Args[i] = m.ReadInt64();
|
||||
break;
|
||||
case 0x07:
|
||||
Args[i] = m.ReadUInt64(); break;
|
||||
Args[i] = m.ReadUInt64();
|
||||
break;
|
||||
case 0x08:
|
||||
Args[i] = m.ReadFloat(); break;
|
||||
Args[i] = m.ReadFloat();
|
||||
break;
|
||||
case 0x09:
|
||||
Args[i] = m.ReadBoolean(); break;
|
||||
Args[i] = m.ReadBoolean();
|
||||
break;
|
||||
case 0x10:
|
||||
Args[i] = m.ReadString(); break;
|
||||
Args[i] = m.ReadString();
|
||||
break;
|
||||
case 0x11:
|
||||
Args[i] = m.ReadVector3(); break;
|
||||
Args[i] = m.ReadVector3();
|
||||
break;
|
||||
case 0x12:
|
||||
Args[i] = m.ReadQuaternion(); break;
|
||||
Args[i] = m.ReadQuaternion();
|
||||
break;
|
||||
case 0x13:
|
||||
Args[i] = (GTA.Model)m.ReadInt32(); break;
|
||||
Args[i] = (Model)m.ReadInt32();
|
||||
break;
|
||||
case 0x14:
|
||||
Args[i] = m.ReadVector2(); break;
|
||||
Args[i] = m.ReadVector2();
|
||||
break;
|
||||
case 0x15:
|
||||
Args[i] = m.ReadByteArray(); break;
|
||||
Args[i] = m.ReadByteArray();
|
||||
break;
|
||||
default:
|
||||
if (ResolveHandle == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected type: {type}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Args[i] = ResolveHandle(type, m); break;
|
||||
}
|
||||
|
||||
Args[i] = ResolveHandle(type, m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
|
||||
using Lidgren.Network;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
@ -9,8 +8,9 @@ namespace RageCoop.Core
|
||||
AlreadyExists = 1,
|
||||
Completed = 2,
|
||||
Loaded = 3,
|
||||
LoadFailed = 4,
|
||||
LoadFailed = 4
|
||||
}
|
||||
|
||||
internal partial class Packets
|
||||
{
|
||||
internal class FileTransferRequest : Packet
|
||||
@ -24,9 +24,6 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
// The ID from the download
|
||||
m.Write(ID);
|
||||
|
||||
@ -36,13 +33,10 @@ namespace RageCoop.Core
|
||||
|
||||
// The length of the file
|
||||
m.Write(FileLength);
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
|
||||
ID = m.ReadInt32();
|
||||
Name = m.ReadString();
|
||||
FileLength = m.ReadInt64();
|
||||
@ -54,19 +48,17 @@ namespace RageCoop.Core
|
||||
public override PacketType Type => PacketType.FileTransferResponse;
|
||||
public int ID { get; set; }
|
||||
public FileResponse Response { get; set; }
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
// The ID from the download
|
||||
m.Write(ID);
|
||||
|
||||
m.Write((byte)Response);
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
ID = m.ReadInt32();
|
||||
Response = (FileResponse)m.ReadByte();
|
||||
}
|
||||
@ -81,17 +73,13 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
// The ID from the download
|
||||
m.Write(ID);
|
||||
m.WriteByteArray(FileChunk);
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
ID = m.ReadInt32();
|
||||
FileChunk = m.ReadByteArray();
|
||||
}
|
||||
@ -104,24 +92,19 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
// The ID for the download
|
||||
m.Write(ID);
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
|
||||
ID = m.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
internal class AllResourcesSent : Packet
|
||||
{
|
||||
|
||||
public override PacketType Type => PacketType.AllResourcesSent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
internal class HolePunchInit : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.HolePunchInit;
|
||||
@ -12,16 +11,13 @@ namespace RageCoop.Core
|
||||
public string TargetInternal { get; set; }
|
||||
public string TargetExternal { get; set; }
|
||||
public bool Connect { get; set; }
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
m.Write(TargetID);
|
||||
m.Write(TargetInternal);
|
||||
m.Write(TargetExternal);
|
||||
m.Write(Connect);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
@ -32,26 +28,25 @@ namespace RageCoop.Core
|
||||
TargetInternal = m.ReadString();
|
||||
TargetExternal = m.ReadString();
|
||||
Connect = m.ReadBoolean();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
internal class HolePunch : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.HolePunch;
|
||||
public int Puncher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 1:initial, 2:acknowledged, 3:confirmed
|
||||
/// 1:initial, 2:acknowledged, 3:confirmed
|
||||
/// </summary>
|
||||
public byte Status { get; set; }
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
m.Write(Puncher);
|
||||
m.Write(Status);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
@ -60,8 +55,9 @@ namespace RageCoop.Core
|
||||
|
||||
Puncher = m.ReadInt32();
|
||||
Status = m.ReadByte();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +1,49 @@
|
||||
using Lidgren.Network;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
/// <summary>
|
||||
/// Request direct connection to another client
|
||||
/// Request direct connection to another client
|
||||
/// </summary>
|
||||
internal class ConnectionRequest : Packet
|
||||
{
|
||||
public int TargetID { get; set; }
|
||||
public override PacketType Type => PacketType.ConnectionRequest;
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
var data = new List<byte>(10);
|
||||
m.Write(TargetID);
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
TargetID = m.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sent to the host when a direct connection has been established
|
||||
/// Sent to the host when a direct connection has been established
|
||||
/// </summary>
|
||||
internal class P2PConnect : Packet
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public override PacketType Type => PacketType.P2PConnect;
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
var data = new List<byte>(10);
|
||||
m.Write(ID);
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
ID = m.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
@ -33,9 +33,11 @@ namespace RageCoop.Core
|
||||
Voice = 22,
|
||||
|
||||
#region Sync
|
||||
|
||||
PedSync = 23,
|
||||
VehicleSync = 24,
|
||||
ProjectileSync = 25,
|
||||
|
||||
#endregion
|
||||
|
||||
#region EVENT
|
||||
@ -50,6 +52,7 @@ namespace RageCoop.Core
|
||||
|
||||
Unknown = 255
|
||||
}
|
||||
|
||||
internal enum ConnectionChannel
|
||||
{
|
||||
Default = 0,
|
||||
@ -64,7 +67,7 @@ namespace RageCoop.Core
|
||||
VehicleSync = 9,
|
||||
PedSync = 10,
|
||||
ProjectileSync = 11,
|
||||
SyncEvents = 12,
|
||||
SyncEvents = 12
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@ -86,7 +89,7 @@ namespace RageCoop.Core
|
||||
IsInCoverFacingLeft = 1 << 12,
|
||||
IsBlindFiring = 1 << 13,
|
||||
IsInvincible = 1 << 14,
|
||||
IsFullSync = 1 << 15,
|
||||
IsFullSync = 1 << 15
|
||||
}
|
||||
|
||||
internal enum ProjectileDataFlags : byte
|
||||
@ -95,9 +98,11 @@ namespace RageCoop.Core
|
||||
Exploded = 1 << 0,
|
||||
IsAttached = 1 << 1,
|
||||
IsOrgin = 1 << 2,
|
||||
IsShotByVehicle = 1 << 3,
|
||||
IsShotByVehicle = 1 << 3
|
||||
}
|
||||
|
||||
#region ===== VEHICLE DATA =====
|
||||
|
||||
internal enum VehicleDataFlags : ushort
|
||||
{
|
||||
None = 0,
|
||||
@ -116,7 +121,7 @@ namespace RageCoop.Core
|
||||
HasRoof = 1 << 12,
|
||||
IsFullSync = 1 << 13,
|
||||
IsOnFire = 1 << 14,
|
||||
Repaired = 1 << 15,
|
||||
Repaired = 1 << 15
|
||||
}
|
||||
|
||||
internal enum PlayerConfigFlags : byte
|
||||
@ -135,6 +140,7 @@ namespace RageCoop.Core
|
||||
public byte LeftHeadLightBroken { get; set; }
|
||||
public byte RightHeadLightBroken { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal interface IPacket
|
||||
@ -147,12 +153,19 @@ namespace RageCoop.Core
|
||||
internal abstract class Packet : IPacket
|
||||
{
|
||||
public abstract PacketType Type { get; }
|
||||
|
||||
public virtual void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
}
|
||||
|
||||
public void Pack(NetOutgoingMessage m)
|
||||
{
|
||||
m.Write((byte)Type);
|
||||
Serialize(m);
|
||||
}
|
||||
protected virtual void Serialize(NetOutgoingMessage m) { }
|
||||
public virtual void Deserialize(NetIncomingMessage m) { }
|
||||
|
||||
protected virtual void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,12 @@
|
||||
using GTA;
|
||||
using System.Collections.Generic;
|
||||
using GTA;
|
||||
using GTA.Math;
|
||||
using Lidgren.Network;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
|
||||
internal class PedSync : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.PedSync;
|
||||
@ -28,13 +26,6 @@ namespace RageCoop.Core
|
||||
|
||||
public Vector3 Velocity { get; set; }
|
||||
|
||||
#region RAGDOLL
|
||||
public Vector3 HeadPosition { get; set; }
|
||||
public Vector3 RightFootPosition { get; set; }
|
||||
public Vector3 LeftFootPosition { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public byte Speed { get; set; }
|
||||
|
||||
public Vector3 AimCoords { get; set; }
|
||||
@ -42,27 +33,8 @@ namespace RageCoop.Core
|
||||
|
||||
public float Heading { get; set; }
|
||||
|
||||
#region FULL
|
||||
|
||||
public int ModelHash { get; set; }
|
||||
|
||||
public uint CurrentWeaponHash { get; set; }
|
||||
|
||||
public byte[] Clothes { get; set; }
|
||||
|
||||
public Dictionary<uint, bool> WeaponComponents { get; set; }
|
||||
|
||||
public byte WeaponTint { get; set; }
|
||||
public BlipColor BlipColor { get; set; } = (BlipColor)255;
|
||||
|
||||
public BlipSprite BlipSprite { get; set; } = 0;
|
||||
public float BlipScale { get; set; } = 1;
|
||||
#endregion
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
m.Write(ID);
|
||||
m.Write(OwnerID);
|
||||
m.Write((ushort)Flags);
|
||||
@ -73,7 +45,6 @@ namespace RageCoop.Core
|
||||
m.Write(HeadPosition);
|
||||
m.Write(RightFootPosition);
|
||||
m.Write(LeftFootPosition);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -82,16 +53,15 @@ namespace RageCoop.Core
|
||||
m.Write(VehicleID);
|
||||
m.Write((byte)(Seat + 3));
|
||||
}
|
||||
|
||||
m.Write(Position);
|
||||
}
|
||||
|
||||
m.Write(Rotation);
|
||||
m.Write(Velocity);
|
||||
|
||||
|
||||
if (Flags.HasPedFlag(PedDataFlags.IsAiming))
|
||||
{
|
||||
m.Write(AimCoords);
|
||||
}
|
||||
if (Flags.HasPedFlag(PedDataFlags.IsAiming)) m.Write(AimCoords);
|
||||
|
||||
m.Write(Heading);
|
||||
|
||||
@ -104,7 +74,7 @@ namespace RageCoop.Core
|
||||
{
|
||||
m.Write(true);
|
||||
m.Write((ushort)WeaponComponents.Count);
|
||||
foreach (KeyValuePair<uint, bool> component in WeaponComponents)
|
||||
foreach (var component in WeaponComponents)
|
||||
{
|
||||
m.Write(component.Key);
|
||||
m.Write(component.Value);
|
||||
@ -125,15 +95,12 @@ namespace RageCoop.Core
|
||||
m.Write(BlipScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
ID = m.ReadInt32();
|
||||
OwnerID = m.ReadInt32();
|
||||
Flags = (PedDataFlags)m.ReadUInt16();
|
||||
@ -164,10 +131,8 @@ namespace RageCoop.Core
|
||||
Velocity = m.ReadVector3();
|
||||
|
||||
if (Flags.HasPedFlag(PedDataFlags.IsAiming))
|
||||
{
|
||||
// Read player aim coords
|
||||
AimCoords = m.ReadVector3();
|
||||
}
|
||||
|
||||
Heading = m.ReadFloat();
|
||||
|
||||
@ -186,12 +151,10 @@ namespace RageCoop.Core
|
||||
if (m.ReadBoolean())
|
||||
{
|
||||
WeaponComponents = new Dictionary<uint, bool>();
|
||||
ushort comCount = m.ReadUInt16();
|
||||
for (ushort i = 0; i < comCount; i++)
|
||||
{
|
||||
WeaponComponents.Add(m.ReadUInt32(), m.ReadBoolean());
|
||||
}
|
||||
var comCount = m.ReadUInt16();
|
||||
for (ushort i = 0; i < comCount; i++) WeaponComponents.Add(m.ReadUInt32(), m.ReadBoolean());
|
||||
}
|
||||
|
||||
WeaponTint = m.ReadByte();
|
||||
|
||||
BlipColor = (BlipColor)m.ReadByte();
|
||||
@ -202,12 +165,35 @@ namespace RageCoop.Core
|
||||
BlipScale = m.ReadFloat();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region RAGDOLL
|
||||
|
||||
public Vector3 HeadPosition { get; set; }
|
||||
public Vector3 RightFootPosition { get; set; }
|
||||
public Vector3 LeftFootPosition { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region FULL
|
||||
|
||||
public int ModelHash { get; set; }
|
||||
|
||||
public uint CurrentWeaponHash { get; set; }
|
||||
|
||||
public byte[] Clothes { get; set; }
|
||||
|
||||
public Dictionary<uint, bool> WeaponComponents { get; set; }
|
||||
|
||||
public byte WeaponTint { get; set; }
|
||||
public BlipColor BlipColor { get; set; } = (BlipColor)255;
|
||||
|
||||
public BlipSprite BlipSprite { get; set; } = 0;
|
||||
public float BlipScale { get; set; } = 1;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using GTA.Math;
|
||||
using System.Net;
|
||||
using GTA.Math;
|
||||
using Lidgren.Network;
|
||||
using System.Net;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
@ -11,8 +11,19 @@ namespace RageCoop.Core
|
||||
public int ID;
|
||||
public string Username;
|
||||
}
|
||||
|
||||
public class Handshake : Packet
|
||||
{
|
||||
/// <summary>
|
||||
/// The asymetrically crypted Aes IV
|
||||
/// </summary>
|
||||
public byte[] AesIVCrypted;
|
||||
|
||||
/// <summary>
|
||||
/// The asymetrically crypted Aes key
|
||||
/// </summary>
|
||||
public byte[] AesKeyCrypted;
|
||||
|
||||
public override PacketType Type => PacketType.Handshake;
|
||||
public int PedID { get; set; }
|
||||
|
||||
@ -21,24 +32,14 @@ namespace RageCoop.Core
|
||||
public string ModVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The asymetrically crypted Aes key
|
||||
/// </summary>
|
||||
public byte[] AesKeyCrypted;
|
||||
|
||||
/// <summary>
|
||||
/// The asymetrically crypted Aes IV
|
||||
/// </summary>
|
||||
public byte[] AesIVCrypted;
|
||||
|
||||
/// <summary>
|
||||
/// The password hash with client Aes
|
||||
/// The password hash with client Aes
|
||||
/// </summary>
|
||||
public byte[] PasswordEncrypted { get; set; }
|
||||
|
||||
public IPEndPoint InternalEndPoint { get; set; }
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
// Write Player Ped ID
|
||||
m.Write(PedID);
|
||||
|
||||
@ -59,15 +60,12 @@ namespace RageCoop.Core
|
||||
|
||||
// Write PassHash
|
||||
m.WriteByteArray(PasswordEncrypted);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
// Read player netHandle
|
||||
PedID = m.ReadInt32();
|
||||
|
||||
@ -85,13 +83,16 @@ namespace RageCoop.Core
|
||||
|
||||
|
||||
PasswordEncrypted = m.ReadByteArray();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
public class HandshakeSuccess : Packet
|
||||
{
|
||||
public PlayerData[] Players { get; set; }
|
||||
public override PacketType Type => PacketType.HandshakeSuccess;
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
m.Write(Players.Length);
|
||||
@ -101,20 +102,19 @@ namespace RageCoop.Core
|
||||
m.Write(p.Username);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
Players = new PlayerData[m.ReadInt32()];
|
||||
for (int i = 0; i < Players.Length; i++)
|
||||
{
|
||||
Players[i] = new PlayerData()
|
||||
for (var i = 0; i < Players.Length; i++)
|
||||
Players[i] = new PlayerData
|
||||
{
|
||||
ID = m.ReadInt32(),
|
||||
Username = m.ReadString(),
|
||||
Username = m.ReadString()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerConnect : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.PlayerConnect;
|
||||
@ -124,7 +124,6 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
// Write NetHandle
|
||||
m.Write(PedID);
|
||||
|
||||
@ -140,6 +139,7 @@ namespace RageCoop.Core
|
||||
|
||||
// Read Username
|
||||
Username = m.ReadString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -151,9 +151,7 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
m.Write(PedID);
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
@ -161,24 +159,27 @@ namespace RageCoop.Core
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
PedID = m.ReadInt32();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerInfoUpdate : Packet
|
||||
{
|
||||
public bool IsHost;
|
||||
public override PacketType Type => PacketType.PlayerInfoUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Ped ID for this Player
|
||||
/// Ped ID for this Player
|
||||
/// </summary>
|
||||
public int PedID { get; set; }
|
||||
|
||||
public string Username { get; set; }
|
||||
public float Latency { get; set; }
|
||||
public Vector3 Position { get; set; }
|
||||
public bool IsHost;
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
// Write ID
|
||||
m.Write(PedID);
|
||||
|
||||
@ -195,8 +196,6 @@ namespace RageCoop.Core
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
|
||||
// Read player ID
|
||||
PedID = m.ReadInt32();
|
||||
|
||||
@ -213,23 +212,18 @@ namespace RageCoop.Core
|
||||
|
||||
public class PublicKeyResponse : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.PublicKeyResponse;
|
||||
public byte[] Exponent;
|
||||
|
||||
public byte[] Modulus;
|
||||
public byte[] Exponent;
|
||||
public override PacketType Type => PacketType.PublicKeyResponse;
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
m.WriteByteArray(Modulus);
|
||||
|
||||
m.WriteByteArray(Exponent);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
@ -246,4 +240,4 @@ namespace RageCoop.Core
|
||||
public override PacketType Type => PacketType.PublicKeyRequest;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,12 +22,8 @@ namespace RageCoop.Core
|
||||
public ProjectileDataFlags Flags { get; set; }
|
||||
|
||||
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Write id
|
||||
m.Write(ID);
|
||||
|
||||
@ -46,16 +42,12 @@ namespace RageCoop.Core
|
||||
// Write velocity
|
||||
m.Write(Velocity);
|
||||
m.Write((byte)Flags);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
// Read id
|
||||
ID = m.ReadInt32();
|
||||
|
||||
@ -79,4 +71,4 @@ namespace RageCoop.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
internal class BulletShot : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.BulletShot;
|
||||
@ -18,9 +17,6 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Write OwnerID
|
||||
m.Write(OwnerID);
|
||||
|
||||
@ -32,17 +28,12 @@ namespace RageCoop.Core
|
||||
|
||||
// Write EndPosition
|
||||
m.Write(EndPosition);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
// Read OwnerID
|
||||
OwnerID = m.ReadInt32();
|
||||
|
||||
@ -54,12 +45,9 @@ namespace RageCoop.Core
|
||||
|
||||
// Read EndPosition
|
||||
EndPosition = m.ReadVector3();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
|
||||
using Lidgren.Network;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
@ -14,14 +13,8 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
m.Write(VehicleID);
|
||||
m.Write(Hover);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
@ -34,9 +27,5 @@ namespace RageCoop.Core
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
|
||||
using Lidgren.Network;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
internal class OwnerChanged : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.OwnerChanged;
|
||||
@ -23,16 +21,11 @@ namespace RageCoop.Core
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
ID = m.ReadInt32();
|
||||
NewOwnerID = m.ReadInt32();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
|
||||
using Lidgren.Network;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
internal class PedKilled : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.PedKilled;
|
||||
@ -13,27 +11,17 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
m.Write(VictimID);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
VictimID = m.ReadInt32();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
internal class VehicleBulletShot : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.VehicleBulletShot;
|
||||
@ -18,35 +17,25 @@ namespace RageCoop.Core
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
|
||||
m.Write(OwnerID);
|
||||
m.Write(Bone);
|
||||
m.Write(WeaponHash);
|
||||
m.Write(StartPosition);
|
||||
m.Write(EndPosition);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
|
||||
|
||||
OwnerID = m.ReadInt32();
|
||||
Bone = m.ReadUInt16();
|
||||
WeaponHash = m.ReadUInt32();
|
||||
StartPosition = m.ReadVector3();
|
||||
EndPosition = m.ReadVector3();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
using GTA;
|
||||
using System.Collections.Generic;
|
||||
using GTA;
|
||||
using GTA.Math;
|
||||
using Lidgren.Network;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
internal partial class Packets
|
||||
{
|
||||
|
||||
public class VehicleSync : Packet
|
||||
{
|
||||
public override PacketType Type => PacketType.VehicleSync;
|
||||
@ -31,34 +30,8 @@ namespace RageCoop.Core
|
||||
public float SteeringAngle { get; set; }
|
||||
public float DeluxoWingRatio { get; set; } = -1;
|
||||
|
||||
#region FULL-SYNC
|
||||
public int ModelHash { get; set; }
|
||||
|
||||
public float EngineHealth { get; set; }
|
||||
|
||||
public byte[] Colors { get; set; }
|
||||
|
||||
public Dictionary<int, int> Mods { get; set; }
|
||||
|
||||
public VehicleDamageModel DamageModel { get; set; }
|
||||
|
||||
public byte LandingGear { get; set; }
|
||||
public byte RoofState { get; set; }
|
||||
|
||||
|
||||
|
||||
public VehicleLockStatus LockStatus { get; set; }
|
||||
|
||||
public int Livery { get; set; } = -1;
|
||||
|
||||
public byte RadioStation { get; set; } = 255;
|
||||
public string LicensePlate { get; set; }
|
||||
#endregion
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
|
||||
|
||||
m.Write(ID);
|
||||
m.Write(OwnerID);
|
||||
m.Write((ushort)Flags);
|
||||
@ -70,10 +43,7 @@ namespace RageCoop.Core
|
||||
m.Write(BrakePower);
|
||||
m.Write(SteeringAngle);
|
||||
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering))
|
||||
{
|
||||
m.Write(DeluxoWingRatio);
|
||||
}
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering)) m.Write(DeluxoWingRatio);
|
||||
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
|
||||
{
|
||||
@ -82,14 +52,9 @@ namespace RageCoop.Core
|
||||
|
||||
// Check
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft))
|
||||
{
|
||||
// Write the vehicle landing gear
|
||||
m.Write(LandingGear);
|
||||
}
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof))
|
||||
{
|
||||
m.Write(RoofState);
|
||||
}
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof)) m.Write(RoofState);
|
||||
|
||||
// Write vehicle colors
|
||||
m.Write(Colors[0]);
|
||||
@ -99,7 +64,7 @@ namespace RageCoop.Core
|
||||
// Write the count of mods
|
||||
m.Write((short)Mods.Count);
|
||||
// Loop the dictionary and add the values
|
||||
foreach (KeyValuePair<int, int> mod in Mods)
|
||||
foreach (var mod in Mods)
|
||||
{
|
||||
// Write the mod value
|
||||
m.Write(mod.Key);
|
||||
@ -153,10 +118,7 @@ namespace RageCoop.Core
|
||||
SteeringAngle = m.ReadFloat();
|
||||
|
||||
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering))
|
||||
{
|
||||
DeluxoWingRatio = m.ReadFloat();
|
||||
}
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsDeluxoHovering)) DeluxoWingRatio = m.ReadFloat();
|
||||
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
|
||||
{
|
||||
@ -169,36 +131,28 @@ namespace RageCoop.Core
|
||||
|
||||
// Check
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.IsAircraft))
|
||||
{
|
||||
// Read vehicle landing gear
|
||||
LandingGear = m.ReadByte();
|
||||
}
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof))
|
||||
{
|
||||
RoofState = m.ReadByte();
|
||||
}
|
||||
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof)) RoofState = m.ReadByte();
|
||||
|
||||
// Read vehicle colors
|
||||
byte vehColor1 = m.ReadByte();
|
||||
byte vehColor2 = m.ReadByte();
|
||||
Colors = new byte[] { vehColor1, vehColor2 };
|
||||
var vehColor1 = m.ReadByte();
|
||||
var vehColor2 = m.ReadByte();
|
||||
Colors = new[] { vehColor1, vehColor2 };
|
||||
|
||||
// Read vehicle mods
|
||||
// Create new Dictionary
|
||||
Mods = new Dictionary<int, int>();
|
||||
// Read count of mods
|
||||
short vehModCount = m.ReadInt16();
|
||||
var vehModCount = m.ReadInt16();
|
||||
// Loop
|
||||
for (int i = 0; i < vehModCount; i++)
|
||||
{
|
||||
for (var i = 0; i < vehModCount; i++)
|
||||
// Read the mod value
|
||||
Mods.Add(m.ReadInt32(), m.ReadInt32());
|
||||
}
|
||||
|
||||
if (m.ReadBoolean())
|
||||
{
|
||||
// Read vehicle damage model
|
||||
DamageModel = new VehicleDamageModel()
|
||||
DamageModel = new VehicleDamageModel
|
||||
{
|
||||
BrokenDoors = m.ReadByte(),
|
||||
OpenedDoors = m.ReadByte(),
|
||||
@ -207,7 +161,6 @@ namespace RageCoop.Core
|
||||
LeftHeadLightBroken = m.ReadByte(),
|
||||
RightHeadLightBroken = m.ReadByte()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Read LockStatus
|
||||
@ -220,8 +173,34 @@ namespace RageCoop.Core
|
||||
|
||||
Livery = m.ReadByte() - 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region FULL-SYNC
|
||||
|
||||
public int ModelHash { get; set; }
|
||||
|
||||
public float EngineHealth { get; set; }
|
||||
|
||||
public byte[] Colors { get; set; }
|
||||
|
||||
public Dictionary<int, int> Mods { get; set; }
|
||||
|
||||
public VehicleDamageModel DamageModel { get; set; }
|
||||
|
||||
public byte LandingGear { get; set; }
|
||||
public byte RoofState { get; set; }
|
||||
|
||||
|
||||
public VehicleLockStatus LockStatus { get; set; }
|
||||
|
||||
public int Livery { get; set; } = -1;
|
||||
|
||||
public byte RadioStation { get; set; } = 255;
|
||||
public string LicensePlate { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -10,20 +10,20 @@ namespace RageCoop.Core
|
||||
public byte[] Buffer { get; set; }
|
||||
public int Recorded { get; set; }
|
||||
public override PacketType Type => PacketType.Voice;
|
||||
|
||||
protected override void Serialize(NetOutgoingMessage m)
|
||||
{
|
||||
m.Write(ID);
|
||||
m.Write(Buffer);
|
||||
m.Write(Recorded);
|
||||
|
||||
}
|
||||
|
||||
public override void Deserialize(NetIncomingMessage m)
|
||||
{
|
||||
|
||||
ID = m.ReadInt32();
|
||||
Buffer = m.ReadByteArray();
|
||||
Recorded = m.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,69 +6,73 @@ using System.Text;
|
||||
namespace RageCoop.Core.Scripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes how the event should be sent or processed
|
||||
/// Describes how the event should be sent or processed
|
||||
/// </summary>
|
||||
public enum CustomEventFlags : byte
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Data will be encrypted and decrypted on target client
|
||||
/// Data will be encrypted and decrypted on target client
|
||||
/// </summary>
|
||||
Encrypted = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Event will be queued and fired in script thread, specify this flag if your handler will call native functions.
|
||||
/// Event will be queued and fired in script thread, specify this flag if your handler will call native functions.
|
||||
/// </summary>
|
||||
Queued = 2,
|
||||
|
||||
Queued = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Struct to identify different event using hash
|
||||
/// Struct to identify different event using hash
|
||||
/// </summary>
|
||||
public struct CustomEventHash
|
||||
{
|
||||
private static readonly MD5 Hasher = MD5.Create();
|
||||
private static readonly Dictionary<int, string> Hashed = new Dictionary<int, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Hash value
|
||||
/// Hash value
|
||||
/// </summary>
|
||||
public int Hash;
|
||||
|
||||
/// <summary>
|
||||
/// Create from hash
|
||||
/// Create from hash
|
||||
/// </summary>
|
||||
/// <param name="hash"></param>
|
||||
public static implicit operator CustomEventHash(int hash)
|
||||
{
|
||||
return new CustomEventHash() { Hash = hash };
|
||||
return new CustomEventHash { Hash = hash };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create from string
|
||||
/// Create from string
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public static implicit operator CustomEventHash(string name)
|
||||
{
|
||||
return new CustomEventHash() { Hash = FromString(name) };
|
||||
|
||||
return new CustomEventHash { Hash = FromString(name) };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a Int32 hash of a string.
|
||||
/// Get a Int32 hash of a string.
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException">The exception is thrown when the name did not match a previously computed one and the hash was the same.</exception>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The exception is thrown when the name did not match a previously computed one and
|
||||
/// the hash was the same.
|
||||
/// </exception>
|
||||
public static int FromString(string s)
|
||||
{
|
||||
var hash = BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0);
|
||||
lock (Hashed)
|
||||
{
|
||||
if (Hashed.TryGetValue(hash, out string name))
|
||||
if (Hashed.TryGetValue(hash, out var name))
|
||||
{
|
||||
if (name != s)
|
||||
{
|
||||
throw new ArgumentException($"Hashed value has collision with another name:{name}, hashed value:{hash}");
|
||||
}
|
||||
throw new ArgumentException(
|
||||
$"Hashed value has collision with another name:{name}, hashed value:{hash}");
|
||||
|
||||
return hash;
|
||||
}
|
||||
@ -77,8 +81,9 @@ namespace RageCoop.Core.Scripting
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To int
|
||||
/// To int
|
||||
/// </summary>
|
||||
/// <param name="h"></param>
|
||||
public static implicit operator int(CustomEventHash h)
|
||||
@ -86,8 +91,8 @@ namespace RageCoop.Core.Scripting
|
||||
return h.Hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class CustomEvents
|
||||
{
|
||||
@ -110,15 +115,18 @@ namespace RageCoop.Core.Scripting
|
||||
internal static readonly CustomEventHash CreateVehicle = "RageCoop.CreateVehicle";
|
||||
internal static readonly CustomEventHash WeatherTimeSync = "RageCoop.WeatherTimeSync";
|
||||
internal static readonly CustomEventHash IsHost = "RageCoop.IsHost";
|
||||
|
||||
/// <summary>
|
||||
/// Get event hash from string.
|
||||
/// Get event hash from string.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>This method is obsoete, you should use implicit operator or <see cref="CustomEventHash.FromString(string)"/></remarks>
|
||||
/// <remarks>
|
||||
/// This method is obsoete, you should use implicit operator or <see cref="CustomEventHash.FromString(string)" />
|
||||
/// </remarks>
|
||||
[Obsolete]
|
||||
public static int Hash(string s)
|
||||
{
|
||||
return CustomEventHash.FromString(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,21 +4,22 @@ using System.IO;
|
||||
namespace RageCoop.Core.Scripting
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ResourceFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Full name with relative path of this file
|
||||
/// Full name with relative path of this file
|
||||
/// </summary>
|
||||
public string Name { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this is a directory
|
||||
/// Whether this is a directory
|
||||
/// </summary>
|
||||
public bool IsDirectory { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a stream that can be used to read file content.
|
||||
/// Get a stream that can be used to read file content.
|
||||
/// </summary>
|
||||
public Func<Stream> GetStream { get; internal set; }
|
||||
}
|
||||
}
|
||||
}
|
108
Core/Worker.cs
108
Core/Worker.cs
@ -5,55 +5,70 @@ using System.Threading;
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A worker that constantly execute jobs in a background thread.
|
||||
/// A worker that constantly execute jobs in a background thread.
|
||||
/// </summary>
|
||||
public class Worker : IDisposable
|
||||
{
|
||||
private readonly SemaphoreSlim _semaphoreSlim;
|
||||
private readonly Thread _workerThread;
|
||||
private bool _stopping = false;
|
||||
/// <summary>
|
||||
/// Name of the worker
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Whether this worker is busy executing job(s).
|
||||
/// </summary>
|
||||
public bool IsBusy { get; private set; }
|
||||
internal Worker(string name, Logger logger, int maxJobs = Int32.MaxValue)
|
||||
private readonly ConcurrentQueue<Action> Jobs = new ConcurrentQueue<Action>();
|
||||
private bool _stopping;
|
||||
|
||||
internal Worker(string name, Logger logger, int maxJobs = int.MaxValue)
|
||||
{
|
||||
Name = name;
|
||||
_semaphoreSlim = new SemaphoreSlim(0, maxJobs);
|
||||
_workerThread = new Thread(() =>
|
||||
{
|
||||
while (!_stopping)
|
||||
{
|
||||
IsBusy = false;
|
||||
_semaphoreSlim.Wait();
|
||||
if (Jobs.TryDequeue(out var job))
|
||||
{
|
||||
IsBusy = true;
|
||||
try
|
||||
{
|
||||
job.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error("Error occurred when executing queued job:");
|
||||
logger.Error(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Hmm... that's unexpected.");
|
||||
}
|
||||
}
|
||||
IsBusy = false;
|
||||
});
|
||||
{
|
||||
while (!_stopping)
|
||||
{
|
||||
IsBusy = false;
|
||||
_semaphoreSlim.Wait();
|
||||
if (Jobs.TryDequeue(out var job))
|
||||
{
|
||||
IsBusy = true;
|
||||
try
|
||||
{
|
||||
job.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error("Error occurred when executing queued job:");
|
||||
logger.Error(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Hmm... that's unexpected.");
|
||||
}
|
||||
}
|
||||
|
||||
IsBusy = false;
|
||||
});
|
||||
_workerThread.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queue a job to be executed
|
||||
/// Name of the worker
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this worker is busy executing job(s).
|
||||
/// </summary>
|
||||
public bool IsBusy { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Finish current job and stop the worker.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
_semaphoreSlim.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queue a job to be executed
|
||||
/// </summary>
|
||||
/// <param name="work"></param>
|
||||
public void QueueJob(Action work)
|
||||
@ -61,26 +76,15 @@ namespace RageCoop.Core
|
||||
Jobs.Enqueue(work);
|
||||
_semaphoreSlim.Release();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finish current job and stop the worker.
|
||||
/// Finish current job and stop the worker.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
_stopping = true;
|
||||
QueueJob(() => { });
|
||||
if (_workerThread.IsAlive)
|
||||
{
|
||||
_workerThread.Join();
|
||||
}
|
||||
if (_workerThread.IsAlive) _workerThread.Join();
|
||||
}
|
||||
/// <summary>
|
||||
/// Finish current job and stop the worker.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
_semaphoreSlim.Dispose();
|
||||
}
|
||||
private readonly ConcurrentQueue<Action> Jobs = new ConcurrentQueue<Action>();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user