Yet another code cleanup

This commit is contained in:
sardelka9515
2022-09-08 12:41:56 -07:00
parent 76c529f1d1
commit 884e2f39f0
63 changed files with 1252 additions and 1391 deletions

View File

@ -1,10 +1,4 @@
using System; using System.Windows;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace RageCoop.Client.Installer namespace RageCoop.Client.Installer
{ {

View File

@ -1,6 +1,6 @@
using System.Windows; using System.Windows;
[assembly:ThemeInfo( [assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page, //(used if a resource is not found in the page,
// or application resource dictionaries) // or application resource dictionaries)

View File

@ -1,27 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Reflection;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using RageCoop.Core;
using System.Threading;
using System.Net;
using System.Windows.Forms; using System.Windows.Forms;
using Path = System.IO.Path; using System.Windows.Input;
using MessageBox = System.Windows.MessageBox; using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog; using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using Path = System.IO.Path;
using RageCoop.Core;
namespace RageCoop.Client.Installer namespace RageCoop.Client.Installer
{ {
@ -41,11 +31,12 @@ namespace RageCoop.Client.Installer
var od = new OpenFileDialog() var od = new OpenFileDialog()
{ {
Filter = "GTA 5 executable |GTA5.exe;PlayGTAV.exe", Filter = "GTA 5 executable |GTA5.exe;PlayGTAV.exe",
Title="Select you GTAV executable" Title = "Select you GTAV executable"
}; };
if (od.ShowDialog() ?? false == true) if (od.ShowDialog() ?? false == true)
{ {
Task.Run(() => { Task.Run(() =>
{
try try
{ {
Install(Directory.GetParent(od.FileName).FullName); Install(Directory.GetParent(od.FileName).FullName);
@ -62,7 +53,8 @@ namespace RageCoop.Client.Installer
Environment.Exit(0); Environment.Exit(0);
} }
} }
void Install(string root)
private void Install(string root)
{ {
UpdateStatus("Checking requirements"); UpdateStatus("Checking requirements");
var shvPath = Path.Combine(root, "ScriptHookV.dll"); var shvPath = Path.Combine(root, "ScriptHookV.dll");
@ -70,7 +62,7 @@ namespace RageCoop.Client.Installer
var scriptsPath = Path.Combine(root, "Scripts"); var scriptsPath = Path.Combine(root, "Scripts");
var lemonPath = Path.Combine(scriptsPath, "LemonUI.SHVDN3.dll"); var lemonPath = Path.Combine(scriptsPath, "LemonUI.SHVDN3.dll");
var installPath = Path.Combine(scriptsPath, "RageCoop"); var installPath = Path.Combine(scriptsPath, "RageCoop");
if(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName == installPath) if (Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName == installPath)
{ {
throw new InvalidOperationException("The installer is not meant to be run in the game folder, please extract the zip to somewhere else and run again."); throw new InvalidOperationException("The installer is not meant to be run in the game folder, please extract the zip to somewhere else and run again.");
} }
@ -86,7 +78,7 @@ namespace RageCoop.Client.Installer
Environment.Exit(1); Environment.Exit(1);
} }
var shvdnVer = GetVer(shvdnPath); var shvdnVer = GetVer(shvdnPath);
if (shvdnVer<new Version(3,5,1)) if (shvdnVer < new Version(3, 5, 1))
{ {
MessageBox.Show("Please update ScriptHookVDotNet to latest version!" + MessageBox.Show("Please update ScriptHookVDotNet to latest version!" +
$"\nCurrent version is {shvdnVer}, 3.5.1 or higher is required"); $"\nCurrent version is {shvdnVer}, 3.5.1 or higher is required");
@ -94,11 +86,11 @@ namespace RageCoop.Client.Installer
} }
if (File.Exists(lemonPath)) if (File.Exists(lemonPath))
{ {
var lemonVer=GetVer(lemonPath); var lemonVer = GetVer(lemonPath);
if(lemonVer<new Version(1, 7)) if (lemonVer < new Version(1, 7))
{ {
UpdateStatus("Updating LemonUI"); UpdateStatus("Updating LemonUI");
File.WriteAllBytes(lemonPath,getLemon()); File.WriteAllBytes(lemonPath, getLemon());
} }
} }
@ -144,28 +136,28 @@ namespace RageCoop.Client.Installer
} }
if (File.Exists(menyooConfig)) if (File.Exists(menyooConfig))
{ {
var lines = File.ReadAllLines(menyooConfig).Where(x => !x.StartsWith(";") && x.EndsWith(" = " +(int)settings.MenuKey)); var lines = File.ReadAllLines(menyooConfig).Where(x => !x.StartsWith(";") && x.EndsWith(" = " + (int)settings.MenuKey));
if (lines.Any()) if (lines.Any())
{ {
if(MessageBox.Show("Following menyoo config value will conflict with RAGECOOP menu key\n" + if (MessageBox.Show("Following menyoo config value will conflict with RAGECOOP menu key\n" +
string.Join("\n", lines) string.Join("\n", lines)
+ "\nDo you wish to change the Menu Key?", "Warning!", MessageBoxButton.YesNo) == MessageBoxResult.Yes) + "\nDo you wish to change the Menu Key?", "Warning!", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {
var ae=new AutoResetEvent(false); var ae = new AutoResetEvent(false);
UpdateStatus("Press the key you wish to change to"); UpdateStatus("Press the key you wish to change to");
Dispatcher.BeginInvoke(new Action(() => Dispatcher.BeginInvoke(new Action(() =>
KeyDown += (s,e) => KeyDown += (s, e) =>
{ {
settings.MenuKey = (Keys)KeyInterop.VirtualKeyFromKey(e.Key); settings.MenuKey = (Keys)KeyInterop.VirtualKeyFromKey(e.Key);
ae.Set(); ae.Set();
})); }));
ae.WaitOne(); ae.WaitOne();
if (!Util.SaveSettings(settingsPath,settings)) if (!Util.SaveSettings(settingsPath, settings))
{ {
MessageBox.Show("Error occurred when saving settings"); MessageBox.Show("Error occurred when saving settings");
Environment.Exit(1); Environment.Exit(1);
} }
MessageBox.Show("Menu key changed to "+settings.MenuKey); MessageBox.Show("Menu key changed to " + settings.MenuKey);
goto checkKeys; goto checkKeys;
} }
} }
@ -178,10 +170,10 @@ namespace RageCoop.Client.Installer
} }
catch catch
{ {
if (MessageBox.Show("You can't join ZeroTier server unless ZeroTier is installed, do you want to download and install it?","Install ZeroTier",MessageBoxButton.YesNo)==MessageBoxResult.Yes) if (MessageBox.Show("You can't join ZeroTier server unless ZeroTier is installed, do you want to download and install it?", "Install ZeroTier", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {
var url = "https://download.zerotier.com/dist/ZeroTier%20One.msi"; var url = "https://download.zerotier.com/dist/ZeroTier%20One.msi";
UpdateStatus("Downloading ZeroTier from "+url); UpdateStatus("Downloading ZeroTier from " + url);
try try
{ {
HttpHelper.DownloadFile(url, "ZeroTier.msi", (p) => UpdateStatus("Downloading ZeroTier " + p + "%")); HttpHelper.DownloadFile(url, "ZeroTier.msi", (p) => UpdateStatus("Downloading ZeroTier " + p + "%"));
@ -201,15 +193,18 @@ namespace RageCoop.Client.Installer
Environment.Exit(0); Environment.Exit(0);
} }
} }
void UpdateStatus(string status)
private void UpdateStatus(string status)
{ {
Dispatcher.BeginInvoke(new Action(() => Status.Content = status)); Dispatcher.BeginInvoke(new Action(() => Status.Content = status));
} }
Version GetVer(string location)
private Version GetVer(string location)
{ {
return Version.Parse(FileVersionInfo.GetVersionInfo(location).FileVersion); return Version.Parse(FileVersionInfo.GetVersionInfo(location).FileVersion);
} }
byte[] getLemon()
private byte[] getLemon()
{ {
return (byte[])Resource.ResourceManager.GetObject("LemonUI_SHVDN3"); return (byte[])Resource.ResourceManager.GetObject("LemonUI_SHVDN3");
} }

View File

@ -122,8 +122,7 @@ namespace RageCoop.Client
{ {
lock (InProgressDownloads) lock (InProgressDownloads)
{ {
DownloadFile file; if (InProgressDownloads.TryGetValue(id, out DownloadFile file))
if (InProgressDownloads.TryGetValue(id, out file))
{ {
file.Stream.Write(chunk, 0, chunk.Length); file.Stream.Write(chunk, 0, chunk.Length);
@ -137,9 +136,8 @@ namespace RageCoop.Client
public static void Complete(int id) public static void Complete(int id)
{ {
DownloadFile f;
if (InProgressDownloads.TryGetValue(id, out f)) if (InProgressDownloads.TryGetValue(id, out DownloadFile f))
{ {
InProgressDownloads.Remove(id); InProgressDownloads.Remove(id);
f.Dispose(); f.Dispose();

View File

@ -142,7 +142,7 @@ namespace RageCoop.Client
default: default:
{ {
HandlePacket(packetType, message, message.SenderConnection,ref _recycle); HandlePacket(packetType, message, message.SenderConnection, ref _recycle);
break; break;
} }
} }

View File

@ -63,8 +63,7 @@ namespace RageCoop.Client
public static void SetPlayer(int id, string username, float latency = 0) public static void SetPlayer(int id, string username, float latency = 0)
{ {
Main.Logger.Debug($"{id},{username},{latency}"); Main.Logger.Debug($"{id},{username},{latency}");
Player p; if (Players.TryGetValue(id, out Player p))
if (Players.TryGetValue(id, out p))
{ {
p.Username = username; p.Username = username;
p.ID = id; p.ID = id;
@ -108,8 +107,7 @@ namespace RageCoop.Client
} }
public static Player GetPlayer(int id) public static Player GetPlayer(int id)
{ {
Player p; Players.TryGetValue(id, out Player p);
Players.TryGetValue(id, out p);
return p; return p;
} }
public static Player GetPlayer(SyncedPed p) public static Player GetPlayer(SyncedPed p)

View File

@ -16,7 +16,7 @@ using System.Resources;
// Version informationr( // Version informationr(
[assembly: AssemblyVersion("1.5.3.188")] [assembly: AssemblyVersion("1.5.3.191")]
[assembly: AssemblyFileVersion("1.5.3.188")] [assembly: AssemblyFileVersion("1.5.3.191")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )] [assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -146,8 +146,7 @@ namespace RageCoop.Client.Scripting
// Main.Logger.Debug($"CustomEvent:\n"+args.Args.DumpWithType()); // Main.Logger.Debug($"CustomEvent:\n"+args.Args.DumpWithType());
List<Action<CustomEventReceivedArgs>> handlers; if (CustomEventHandlers.TryGetValue(p.Hash, out List<Action<CustomEventReceivedArgs>> handlers))
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
{ {
handlers.ForEach((x) => { x.Invoke(args); }); handlers.ForEach((x) => { x.Invoke(args); });
} }

View File

@ -127,8 +127,7 @@ namespace RageCoop.Client.Scripting
var pos = (Vector3)obj.Args[4]; var pos = (Vector3)obj.Args[4];
int rot = (int)obj.Args[5]; int rot = (int)obj.Args[5];
var name = (string)obj.Args[6]; var name = (string)obj.Args[6];
Blip blip; if (!EntityPool.ServerBlips.TryGetValue(id, out Blip blip))
if (!EntityPool.ServerBlips.TryGetValue(id, out blip))
{ {
EntityPool.ServerBlips.Add(id, blip = World.CreateBlip(pos)); EntityPool.ServerBlips.Add(id, blip = World.CreateBlip(pos));
} }

View File

@ -100,7 +100,7 @@ namespace RageCoop.Client
CreateProjectile(); CreateProjectile();
return; return;
} }
MainProjectile.Velocity = Velocity + 10*(Predict(Position) - MainProjectile.Position); MainProjectile.Velocity = Velocity + 10 * (Predict(Position) - MainProjectile.Position);
MainProjectile.Rotation = Rotation; MainProjectile.Rotation = Rotation;
LastUpdated = Main.Ticked; LastUpdated = Main.Ticked;
} }

View File

@ -333,7 +333,7 @@ namespace RageCoop.Client
if (p.MainProjectile.AttachedEntity == null) if (p.MainProjectile.AttachedEntity == null)
{ {
// Prevent projectiles from exploding next to vehicle // Prevent projectiles from exploding next to vehicle
if (p.WeaponHash == (WeaponHash)VehicleWeaponHash.Tank || (p.MainProjectile.OwnerEntity?.EntityType==EntityType.Vehicle && p.MainProjectile.Position.DistanceTo(p.Origin) < 2)) if (p.WeaponHash == (WeaponHash)VehicleWeaponHash.Tank || (p.MainProjectile.OwnerEntity?.EntityType == EntityType.Vehicle && p.MainProjectile.Position.DistanceTo(p.Origin) < 2))
{ {
continue; continue;
} }

View File

@ -159,7 +159,7 @@ namespace RageCoop.Client
WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash), WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash),
b.Position, b.ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1); b.Position, b.ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1);
} }
public static void HandleEvent(PacketType type,NetIncomingMessage msg) public static void HandleEvent(PacketType type, NetIncomingMessage msg)
{ {
switch (type) switch (type)
{ {

View File

@ -1,15 +1,13 @@
using System; using GTA.Math;
using System.Text;
using System.Linq;
using GTA.Math;
using System.IO; using System.IO;
using System.Text;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal class BitReader:BinaryReader internal class BitReader : BinaryReader
{ {
public BitReader(byte[] array):base(new MemoryStream(array)) public BitReader(byte[] array) : base(new MemoryStream(array))
{ {
} }

View File

@ -1,20 +1,18 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA.Math;
using System.Security.Cryptography;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.IO;
using System.Runtime.CompilerServices;
using Lidgren.Network; using Lidgren.Network;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Runtime.InteropServices; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using Newtonsoft.Json.Linq; using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
[assembly: InternalsVisibleTo("RageCoop.Server")] [assembly: InternalsVisibleTo("RageCoop.Server")]
[assembly: InternalsVisibleTo("RageCoop.Client")] [assembly: InternalsVisibleTo("RageCoop.Client")]
@ -36,12 +34,12 @@ namespace RageCoop.Core
{ {
return ToIgnore.Contains(name); return ToIgnore.Contains(name);
} }
public static void GetBytesFromObject(object obj,NetOutgoingMessage m) public static void GetBytesFromObject(object obj, NetOutgoingMessage m)
{ {
switch (obj) switch (obj)
{ {
case byte value: case byte value:
m.Write((byte)0x01);m.Write(value);break; m.Write((byte)0x01); m.Write(value); break;
case short value: case short value:
m.Write((byte)0x02); m.Write(value); break; m.Write((byte)0x02); m.Write(value); break;
case ushort value: case ushort value:
@ -140,9 +138,8 @@ namespace RageCoop.Core
private static int getPort(string p) private static int getPort(string p)
{ {
int port;
if (!int.TryParse(p, out port) if (!int.TryParse(p, out int port)
|| port < IPEndPoint.MinPort || port < IPEndPoint.MinPort
|| port > IPEndPoint.MaxPort) || port > IPEndPoint.MaxPort)
{ {
@ -151,7 +148,7 @@ namespace RageCoop.Core
return port; return port;
} }
public static IPAddress GetLocalAddress(string target= "8.8.8.8") public static IPAddress GetLocalAddress(string target = "8.8.8.8")
{ {
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0)) using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{ {
@ -277,7 +274,7 @@ namespace RageCoop.Core
// 16 bytes // 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() public static T GetPacket<T>(this NetIncomingMessage msg) where T : Packet, new()
{ {
var p = new T(); var p = new T();
p.Deserialize(msg); p.Deserialize(msg);
@ -285,20 +282,20 @@ namespace RageCoop.Core
} }
public static bool HasPedFlag(this PedDataFlags flagToCheck, PedDataFlags flag) public static bool HasPedFlag(this PedDataFlags flagToCheck, PedDataFlags flag)
{ {
return (flagToCheck & flag)!=0; return (flagToCheck & flag) != 0;
} }
public static bool HasProjDataFlag(this ProjectileDataFlags flagToCheck, ProjectileDataFlags flag) public static bool HasProjDataFlag(this ProjectileDataFlags flagToCheck, ProjectileDataFlags flag)
{ {
return (flagToCheck & flag)!=0; return (flagToCheck & flag) != 0;
} }
public static bool HasVehFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag) public static bool HasVehFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag)
{ {
return (flagToCheck & flag)!=0; return (flagToCheck & flag) != 0;
} }
public static bool HasConfigFlag(this PlayerConfigFlags flagToCheck, PlayerConfigFlags flag) public static bool HasConfigFlag(this PlayerConfigFlags flagToCheck, PlayerConfigFlags flag)
{ {
return (flagToCheck & flag)!=0; return (flagToCheck & flag) != 0;
} }
public static Type GetActualType(this TypeCode code) public static Type GetActualType(this TypeCode code)
{ {
@ -365,9 +362,9 @@ namespace RageCoop.Core
public static string DumpWithType(this IEnumerable<object> objects) public static string DumpWithType(this IEnumerable<object> objects)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
foreach(var obj in objects) foreach (var obj in objects)
{ {
sb.Append(obj.GetType()+":"+obj.ToString()+"\n"); sb.Append(obj.GetType() + ":" + obj.ToString() + "\n");
} }
return sb.ToString(); return sb.ToString();
} }
@ -375,9 +372,9 @@ namespace RageCoop.Core
{ {
return $"{{{string.Join(",", objects)}}}"; return $"{{{string.Join(",", objects)}}}";
} }
public static void ForEach<T>(this IEnumerable<T> objects,Action<T> action) public static void ForEach<T>(this IEnumerable<T> objects, Action<T> action)
{ {
foreach(var obj in objects) foreach (var obj in objects)
{ {
action(obj); action(obj);
} }
@ -399,10 +396,10 @@ namespace RageCoop.Core
stream.CopyTo(memoryStream); stream.CopyTo(memoryStream);
return memoryStream; return memoryStream;
} }
public static byte[] Join(this List<byte[]> arrays,int lengthPerArray=-1) public static byte[] Join(this List<byte[]> arrays, int lengthPerArray = -1)
{ {
if (arrays.Count==1) { return arrays[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 output = lengthPerArray == -1 ? new byte[arrays.Sum(arr => arr.Length)] : new byte[arrays.Count * lengthPerArray];
int writeIdx = 0; int writeIdx = 0;
foreach (var byteArr in arrays) foreach (var byteArr in arrays)
{ {

View File

@ -1,8 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Text;
using System.Threading; using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
@ -32,26 +31,26 @@ namespace RageCoop.Core
private StreamWriter logWriter; private StreamWriter logWriter;
private string Buffer = ""; private string Buffer = "";
private Thread LoggerThread; private readonly Thread LoggerThread;
private bool Stopping = false; private bool Stopping = false;
private bool FlushImmediately; private readonly bool FlushImmediately;
internal Logger(bool flushImmediately = false, bool overwrite = true) internal Logger(bool flushImmediately = false, bool overwrite = true)
{ {
FlushImmediately = flushImmediately; FlushImmediately = flushImmediately;
if (File.Exists(LogPath)&&overwrite) { File.Delete(LogPath); } if (File.Exists(LogPath) && overwrite) { File.Delete(LogPath); }
Name=Process.GetCurrentProcess().Id.ToString(); Name = Process.GetCurrentProcess().Id.ToString();
if (!flushImmediately) if (!flushImmediately)
{ {
LoggerThread=new Thread(() => LoggerThread = new Thread(() =>
{ {
if (!UseConsole) if (!UseConsole)
{ {
while (LogPath==default) while (LogPath == default)
{ {
Thread.Sleep(100); Thread.Sleep(100);
} }
if (File.Exists(LogPath)&&overwrite) { File.Delete(LogPath); } if (File.Exists(LogPath) && overwrite) { File.Delete(LogPath); }
} }
while (!Stopping) while (!Stopping)
{ {
@ -69,12 +68,12 @@ namespace RageCoop.Core
/// <param name="message"></param> /// <param name="message"></param>
public void Info(string message) public void Info(string message)
{ {
if (LogLevel>2) { return; } if (LogLevel > 2) { return; }
lock (Buffer) lock (Buffer)
{ {
string msg = string.Format("[{0}][{2}] [INF] {1}", Date(), message, Name); string msg = string.Format("[{0}][{2}] [INF] {1}", Date(), message, Name);
Buffer+=msg+"\r\n"; Buffer += msg + "\r\n";
} }
if (FlushImmediately) if (FlushImmediately)
{ {
@ -87,12 +86,12 @@ namespace RageCoop.Core
/// <param name="message"></param> /// <param name="message"></param>
public void Warning(string message) public void Warning(string message)
{ {
if (LogLevel>3) { return; } if (LogLevel > 3) { return; }
lock (Buffer) lock (Buffer)
{ {
string msg = string.Format("[{0}][{2}] [WRN] {1}", Date(), message, Name); string msg = string.Format("[{0}][{2}] [WRN] {1}", Date(), message, Name);
Buffer+=msg+"\r\n"; Buffer += msg + "\r\n";
} }
if (FlushImmediately) if (FlushImmediately)
@ -106,12 +105,12 @@ namespace RageCoop.Core
/// <param name="message"></param> /// <param name="message"></param>
public void Error(string message) public void Error(string message)
{ {
if (LogLevel>4) { return; } if (LogLevel > 4) { return; }
lock (Buffer) lock (Buffer)
{ {
string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(), message, Name); string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(), message, Name);
Buffer+=msg+"\r\n"; Buffer += msg + "\r\n";
} }
if (FlushImmediately) if (FlushImmediately)
{ {
@ -125,11 +124,11 @@ namespace RageCoop.Core
/// <param name="error"></param> /// <param name="error"></param>
public void Error(string message, Exception error) public void Error(string message, Exception error)
{ {
if (LogLevel>4) { return; } if (LogLevel > 4) { return; }
lock (Buffer) lock (Buffer)
{ {
string msg = string.Format("[{0}][{2}] [ERR] {1}:{3}", Date(), message, Name,error.Message); string msg = string.Format("[{0}][{2}] [ERR] {1}:{3}", Date(), message, Name, error.Message);
Buffer+=msg+"\r\n"; Buffer += msg + "\r\n";
Trace(error.ToString()); Trace(error.ToString());
} }
@ -144,11 +143,11 @@ namespace RageCoop.Core
/// <param name="ex"></param> /// <param name="ex"></param>
public void Error(Exception ex) public void Error(Exception ex)
{ {
if (LogLevel>4) { return; } if (LogLevel > 4) { return; }
lock (Buffer) lock (Buffer)
{ {
string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(), "\r\n"+ex.Message, Name); string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(), "\r\n" + ex.Message, Name);
Buffer+=msg+"\r\n"; Buffer += msg + "\r\n";
Trace(ex.ToString()); Trace(ex.ToString());
} }
if (FlushImmediately) if (FlushImmediately)
@ -163,12 +162,12 @@ namespace RageCoop.Core
public void Debug(string message) public void Debug(string message)
{ {
if (LogLevel>1) { return; } if (LogLevel > 1) { return; }
lock (Buffer) lock (Buffer)
{ {
string msg = string.Format("[{0}][{2}] [DBG] {1}", Date(), message, Name); string msg = string.Format("[{0}][{2}] [DBG] {1}", Date(), message, Name);
Buffer+=msg+"\r\n"; Buffer += msg + "\r\n";
} }
if (FlushImmediately) if (FlushImmediately)
{ {
@ -181,12 +180,12 @@ namespace RageCoop.Core
/// <param name="message"></param> /// <param name="message"></param>
public void Trace(string message) public void Trace(string message)
{ {
if (LogLevel>0) { return; } if (LogLevel > 0) { return; }
lock (Buffer) lock (Buffer)
{ {
string msg = string.Format("[{0}][{2}] [TRC] {1}", Date(), message, Name); string msg = string.Format("[{0}][{2}] [TRC] {1}", Date(), message, Name);
Buffer+=msg+"\r\n"; Buffer += msg + "\r\n";
} }
if (FlushImmediately) if (FlushImmediately)
{ {
@ -205,21 +204,21 @@ namespace RageCoop.Core
{ {
lock (Buffer) lock (Buffer)
{ {
if (Buffer!="") if (Buffer != "")
{ {
if (UseConsole) if (UseConsole)
{ {
Console.Write(Buffer); Console.Write(Buffer);
Buffer=""; Buffer = "";
} }
else else
{ {
try try
{ {
logWriter=new StreamWriter(LogPath, true, Encoding.UTF8); logWriter = new StreamWriter(LogPath, true, Encoding.UTF8);
logWriter.Write(Buffer); logWriter.Write(Buffer);
logWriter.Close(); logWriter.Close();
Buffer=""; Buffer = "";
} }
catch { } catch { }
} }
@ -232,7 +231,7 @@ namespace RageCoop.Core
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
Stopping=true; Stopping = true;
LoggerThread?.Join(); LoggerThread?.Join();
} }
} }

View File

@ -1,11 +1,11 @@
using System; using GTA.Math;
using GTA.Math; using System;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal static class MathExtensions internal static class MathExtensions
{ {
public const float Deg2Rad=(float)(Math.PI* 2) / 360; public const float Deg2Rad = (float)(Math.PI * 2) / 360;
public const float Rad2Deg = 360 / (float)(Math.PI * 2); public const float Rad2Deg = 360 / (float)(Math.PI * 2);
public static Vector3 ToDirection(this Vector3 rotation) public static Vector3 ToDirection(this Vector3 rotation)
@ -81,14 +81,14 @@ namespace RageCoop.Core
vect = vect.ToRadians(); vect = vect.ToRadians();
float rollOver2 = vect.Z * 0.5f; float rollOver2 = vect.Z * 0.5f;
float sinRollOver2 = (float)Math.Sin((double)rollOver2); float sinRollOver2 = (float)Math.Sin(rollOver2);
float cosRollOver2 = (float)Math.Cos((double)rollOver2); float cosRollOver2 = (float)Math.Cos(rollOver2);
float pitchOver2 = vect.Y * 0.5f; float pitchOver2 = vect.Y * 0.5f;
float sinPitchOver2 = (float)Math.Sin((double)pitchOver2); float sinPitchOver2 = (float)Math.Sin(pitchOver2);
float cosPitchOver2 = (float)Math.Cos((double)pitchOver2); float cosPitchOver2 = (float)Math.Cos(pitchOver2);
float yawOver2 = vect.X * 0.5f; // pitch float yawOver2 = vect.X * 0.5f; // pitch
float sinYawOver2 = (float)Math.Sin((double)yawOver2); float sinYawOver2 = (float)Math.Sin(yawOver2);
float cosYawOver2 = (float)Math.Cos((double)yawOver2); float cosYawOver2 = (float)Math.Cos(yawOver2);
Quaternion result = new Quaternion() Quaternion result = new Quaternion()
{ {
X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2, X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2,
@ -110,7 +110,7 @@ namespace RageCoop.Core
} }
public static Vector3 ToDegree(this Vector3 radian) public static Vector3 ToDegree(this Vector3 radian)
{ {
return radian*(float)(180/Math.PI); return radian * (float)(180 / Math.PI);
} }
public static Vector3 ToEulerDegrees(this Quaternion q) public static Vector3 ToEulerDegrees(this Quaternion q)
{ {
@ -158,7 +158,7 @@ namespace RageCoop.Core
} }
public static float GetCosTheta(this Vector3 v1, Vector3 v2) public static float GetCosTheta(this Vector3 v1, Vector3 v2)
{ {
return Vector3.Dot(v1, v2)/(v1.Length()*v2.Length()); return Vector3.Dot(v1, v2) / (v1.Length() * v2.Length());
} }
} }

View File

@ -1,7 +1,6 @@
using System; using Lidgren.Network;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using System.Threading; using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
@ -10,19 +9,19 @@ namespace RageCoop.Core
{ {
public EventHandler<NetIncomingMessage> OnMessageReceived; public EventHandler<NetIncomingMessage> OnMessageReceived;
private readonly Thread ListenerThread; private readonly Thread ListenerThread;
private bool _stopping=false; private bool _stopping = false;
public CoopPeer(NetPeerConfiguration config):base(config) public CoopPeer(NetPeerConfiguration config) : base(config)
{ {
Start(); Start();
NetIncomingMessage msg; NetIncomingMessage msg;
ListenerThread=new Thread(() => ListenerThread = new Thread(() =>
{ {
while (!_stopping) while (!_stopping)
{ {
msg=WaitMessage(200); msg = WaitMessage(200);
if (msg!=null) if (msg != null)
{ {
OnMessageReceived?.Invoke(this,msg); OnMessageReceived?.Invoke(this, msg);
} }
} }
}); });
@ -34,7 +33,7 @@ namespace RageCoop.Core
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
_stopping=true; _stopping = true;
Shutdown("Bye!"); Shutdown("Bye!");
ListenerThread.Join(); ListenerThread.Join();
} }
@ -51,7 +50,7 @@ namespace RageCoop.Core
p.Pack(outgoingMessage); p.Pack(outgoingMessage);
SendMessage(outgoingMessage, connections, method, (int)channel); 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(); NetOutgoingMessage outgoingMessage = CreateMessage();
p.Pack(outgoingMessage); p.Pack(outgoingMessage);

View File

@ -1,18 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.IO;
using System.Text;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.IO;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal static class HttpHelper internal static class HttpHelper
{ {
public static void DownloadFile(string url,string destination,Action<int> progressCallback) public static void DownloadFile(string url, string destination, Action<int> progressCallback)
{ {
if (File.Exists(destination)) { File.Delete(destination); } if (File.Exists(destination)) { File.Delete(destination); }
AutoResetEvent ae=new AutoResetEvent(false); AutoResetEvent ae = new AutoResetEvent(false);
WebClient client = new WebClient(); WebClient client = new WebClient();
// TLS only // TLS only

View File

@ -1,19 +1,19 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal class PublicKey{ internal class PublicKey
public PublicKey(){ {
public PublicKey()
{
} }
public static PublicKey FromServerInfo(ServerInfo info){ public static PublicKey FromServerInfo(ServerInfo info)
return new PublicKey{ {
Modulus=Convert.FromBase64String(info.publicKeyModulus), return new PublicKey
Exponent=Convert.FromBase64String(info.publicKeyExponent) {
Modulus = Convert.FromBase64String(info.publicKeyModulus),
Exponent = Convert.FromBase64String(info.publicKeyExponent)
}; };
} }
public byte[] Modulus; public byte[] Modulus;

View File

@ -1,9 +1,4 @@
using System; namespace RageCoop.Core
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
namespace RageCoop.Core
{ {
/// <summary> /// <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.
@ -30,8 +25,8 @@ namespace RageCoop.Core
public string ztID { get; set; } public string ztID { get; set; }
public string ztAddress { get; set; } public string ztAddress { get; set; }
public string publicKeyModulus{get;set;} public string publicKeyModulus { get; set; }
public string publicKeyExponent{get;set;} public string publicKeyExponent { get; set; }
} }
} }

View File

@ -1,11 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;
using System.Net;
using Newtonsoft.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace RageCoop.Core namespace RageCoop.Core
@ -15,13 +13,13 @@ namespace RageCoop.Core
public ZeroTierNetwork(string line) public ZeroTierNetwork(string line)
{ {
// <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips> // <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips>
var v = Regex.Split(line," ").Skip(2).ToArray(); var v = Regex.Split(line, " ").Skip(2).ToArray();
ID=v[0]; ID = v[0];
Name=v[1]; Name = v[1];
Mac=v[2]; Mac = v[2];
Status=v[3]; Status = v[3];
Type=v[4]; Type = v[4];
Device=v[5]; Device = v[5];
foreach (var i in v[6].Split(',')) foreach (var i in v[6].Split(','))
{ {
Addresses.Add(i.Split('/')[0]); Addresses.Add(i.Split('/')[0]);
@ -33,43 +31,43 @@ namespace RageCoop.Core
public string Status; public string Status;
public string Type; public string Type;
public string Device; public string Device;
public List<string> Addresses=new List<string>(); public List<string> Addresses = new List<string>();
} }
internal static class ZeroTierHelper internal static class ZeroTierHelper
{ {
private static readonly string _path="zerotier-cli"; private static readonly string _path = "zerotier-cli";
private static readonly string _arg = ""; private static readonly string _arg = "";
static ZeroTierHelper() static ZeroTierHelper()
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 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}\" "; _arg = $"/c \"{batpath}\" ";
_path="cmd.exe"; _path = "cmd.exe";
} }
var status = RunCommand("status"); var status = RunCommand("status");
if (!status.StartsWith("200")) if (!status.StartsWith("200"))
{ {
throw new Exception("ZeroTier not ready: "+status); throw new Exception("ZeroTier not ready: " + status);
} }
} }
public static ZeroTierNetwork Join(string networkId, int timeout=10000) public static ZeroTierNetwork Join(string networkId, int timeout = 10000)
{ {
var p = Run("join "+networkId); var p = Run("join " + networkId);
var o = p.StandardOutput.ReadToEnd(); var o = p.StandardOutput.ReadToEnd();
if (!o.StartsWith("200 join OK")) if (!o.StartsWith("200 join OK"))
{ {
throw new Exception(o+p.StandardError.ReadToEnd()); throw new Exception(o + p.StandardError.ReadToEnd());
} }
if (timeout==0) { return Networks[networkId]; } if (timeout == 0) { return Networks[networkId]; }
int i = 0; int i = 0;
while (i<=timeout) while (i <= timeout)
{ {
i+=100; i += 100;
if(Networks.TryGetValue(networkId,out var n)) if (Networks.TryGetValue(networkId, out var n))
{ {
if (n.Addresses.Count!=0 && (!n.Addresses.Where(x=>x=="-").Any())) if (n.Addresses.Count != 0 && (!n.Addresses.Where(x => x == "-").Any()))
{ {
return n; return n;
} }
@ -84,16 +82,17 @@ namespace RageCoop.Core
} }
public static void Leave(string networkId) public static void Leave(string networkId)
{ {
var p = Run("leave "+networkId); var p = Run("leave " + networkId);
var o = p.StandardOutput.ReadToEnd(); var o = p.StandardOutput.ReadToEnd();
if (!o.StartsWith("200 leave OK")) if (!o.StartsWith("200 leave OK"))
{ {
throw new Exception(o+p.StandardError.ReadToEnd()); throw new Exception(o + p.StandardError.ReadToEnd());
} }
} }
public static Dictionary<string, ZeroTierNetwork> Networks public static Dictionary<string, ZeroTierNetwork> Networks
{ {
get { get
{
Dictionary<string, ZeroTierNetwork> networks = new Dictionary<string, ZeroTierNetwork>(); Dictionary<string, ZeroTierNetwork> networks = new Dictionary<string, ZeroTierNetwork>();
var p = Run("listnetworks"); var p = Run("listnetworks");
var lines = Regex.Split(p.StandardOutput.ReadToEnd(), "\n").Skip(1); var lines = Regex.Split(p.StandardOutput.ReadToEnd(), "\n").Skip(1);
@ -113,14 +112,14 @@ namespace RageCoop.Core
private static Process Run(string args) private static Process Run(string args)
{ {
var p = new Process(); var p = new Process();
p.StartInfo=new ProcessStartInfo() p.StartInfo = new ProcessStartInfo()
{ {
FileName = _path, FileName = _path,
Arguments =_arg+args, Arguments = _arg + args,
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true, RedirectStandardOutput = true,
RedirectStandardError = true, RedirectStandardError = true,
CreateNoWindow=true, CreateNoWindow = true,
}; };
p.Start(); p.Start();
p.WaitForExit(); p.WaitForExit();
@ -129,7 +128,7 @@ namespace RageCoop.Core
private static string RunCommand(string command) private static string RunCommand(string command)
{ {
var p = Run(command); var p = Run(command);
return p.StandardOutput.ReadToEnd()+p.StandardError.ReadToEnd(); return p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd();
} }
public static void Check() public static void Check()
{ {

View File

@ -1,8 +1,8 @@
using System; using GTA.Math;
using Lidgren.Network;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using GTA.Math;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -43,7 +43,7 @@ namespace RageCoop.Core
#endregion #endregion
#region MESSAGE-WRITE #region MESSAGE-WRITE
public static void Write(this NetOutgoingMessage m,Vector3 v) public static void Write(this NetOutgoingMessage m, Vector3 v)
{ {
m.Write(v.X); m.Write(v.X);
m.Write(v.Y); m.Write(v.Y);
@ -120,7 +120,7 @@ namespace RageCoop.Core
bytes.AddInt(toadd.Length); bytes.AddInt(toadd.Length);
bytes.AddRange(toadd); bytes.AddRange(toadd);
} }
#endregion #endregion
internal static bool IsSyncEvent(this PacketType p) internal static bool IsSyncEvent(this PacketType p)
{ {

View File

@ -1,6 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -11,8 +10,8 @@ namespace RageCoop.Core
internal class ChatMessage : Packet internal class ChatMessage : Packet
{ {
public override PacketType Type => PacketType.ChatMessage; public override PacketType Type => PacketType.ChatMessage;
private Func<string, byte[]> crypt; private readonly Func<string, byte[]> crypt;
private Func<byte[], byte[]> decrypt; private readonly Func<byte[], byte[]> decrypt;
public ChatMessage(Func<string, byte[]> crypter) public ChatMessage(Func<string, byte[]> crypter)
{ {
crypt = crypter; crypt = crypter;

View File

@ -1,7 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal partial class Packets internal partial class Packets
@ -10,25 +8,25 @@ namespace RageCoop.Core
internal class CustomEvent : Packet internal class CustomEvent : Packet
{ {
public override PacketType Type => (_queued ? PacketType.CustomEventQueued : PacketType.CustomEvent); public override PacketType Type => (_queued ? PacketType.CustomEventQueued : PacketType.CustomEvent);
public CustomEvent(Func<byte,NetIncomingMessage,object> onResolve = null,bool queued=false) public CustomEvent(Func<byte, NetIncomingMessage, object> onResolve = null, bool queued = false)
{ {
_resolve= onResolve; _resolve = onResolve;
_queued= queued; _queued = queued;
} }
private bool _queued; private readonly bool _queued;
private Func<byte, NetIncomingMessage, object> _resolve { get; set; } private Func<byte, NetIncomingMessage, object> _resolve { get; set; }
public int Hash { get; set; } public int Hash { get; set; }
public object[] Args { get; set; } public object[] Args { get; set; }
protected override void Serialize(NetOutgoingMessage m) protected override void Serialize(NetOutgoingMessage m)
{ {
Args= Args ?? new object[] { }; Args = Args ?? new object[] { };
m.Write(Hash); m.Write(Hash);
m.Write(Args.Length); m.Write(Args.Length);
foreach (var arg in Args) foreach (var arg in Args)
{ {
CoreUtils.GetBytesFromObject(arg,m); CoreUtils.GetBytesFromObject(arg, m);
} }
} }
@ -37,51 +35,51 @@ namespace RageCoop.Core
Hash = m.ReadInt32(); Hash = m.ReadInt32();
var len=m.ReadInt32(); var len = m.ReadInt32();
Args=new object[len]; Args = new object[len];
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
byte type = m.ReadByte(); byte type = m.ReadByte();
switch (type) switch (type)
{ {
case 0x01: case 0x01:
Args[i]=m.ReadByte(); break; Args[i] = m.ReadByte(); break;
case 0x02: case 0x02:
Args[i]=m.ReadInt32(); break; Args[i] = m.ReadInt32(); break;
case 0x03: case 0x03:
Args[i]=m.ReadUInt16(); break; Args[i] = m.ReadUInt16(); break;
case 0x04: case 0x04:
Args[i]=m.ReadInt32(); break; Args[i] = m.ReadInt32(); break;
case 0x05: case 0x05:
Args[i]=m.ReadUInt32(); break; Args[i] = m.ReadUInt32(); break;
case 0x06: case 0x06:
Args[i]=m.ReadInt64(); break; Args[i] = m.ReadInt64(); break;
case 0x07: case 0x07:
Args[i]=m.ReadUInt64(); break; Args[i] = m.ReadUInt64(); break;
case 0x08: case 0x08:
Args[i]=m.ReadFloat(); break; Args[i] = m.ReadFloat(); break;
case 0x09: case 0x09:
Args[i]=m.ReadBoolean(); break; Args[i] = m.ReadBoolean(); break;
case 0x10: case 0x10:
Args[i]=m.ReadString(); break; Args[i] = m.ReadString(); break;
case 0x11: case 0x11:
Args[i]=m.ReadVector3(); break; Args[i] = m.ReadVector3(); break;
case 0x12: case 0x12:
Args[i]=m.ReadQuaternion(); break; Args[i] = m.ReadQuaternion(); break;
case 0x13: case 0x13:
Args[i]=(GTA.Model)m.ReadInt32(); break; Args[i] = (GTA.Model)m.ReadInt32(); break;
case 0x14: case 0x14:
Args[i]=m.ReadVector2(); break; Args[i] = m.ReadVector2(); break;
case 0x15: case 0x15:
Args[i] = m.ReadByteArray(); break; Args[i] = m.ReadByteArray(); break;
default: default:
if (_resolve==null) if (_resolve == null)
{ {
throw new InvalidOperationException($"Unexpected type: {type}"); throw new InvalidOperationException($"Unexpected type: {type}");
} }
else else
{ {
Args[i]=_resolve(type, m); break; Args[i] = _resolve(type, m); break;
} }
} }
} }

View File

@ -1,18 +1,15 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal enum FileResponse:byte internal enum FileResponse : byte
{ {
NeedToDownload=0, NeedToDownload = 0,
AlreadyExists=1, AlreadyExists = 1,
Completed=2, Completed = 2,
Loaded=3, Loaded = 3,
LoadFailed=4, LoadFailed = 4,
} }
internal partial class Packets internal partial class Packets
{ {

View File

@ -1,6 +1,4 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -33,7 +31,7 @@ namespace RageCoop.Core
TargetID = m.ReadInt32(); TargetID = m.ReadInt32();
TargetInternal = m.ReadString(); TargetInternal = m.ReadString();
TargetExternal = m.ReadString(); TargetExternal = m.ReadString();
Connect=m.ReadBoolean(); Connect = m.ReadBoolean();
#endregion #endregion
} }
} }
@ -45,7 +43,7 @@ namespace RageCoop.Core
/// <summary> /// <summary>
/// 1:initial, 2:acknowledged, 3:confirmed /// 1:initial, 2:acknowledged, 3:confirmed
/// </summary> /// </summary>
public byte Status { get;set;} public byte Status { get; set; }
protected override void Serialize(NetOutgoingMessage m) protected override void Serialize(NetOutgoingMessage m)
{ {

View File

@ -1,6 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System.Collections.Generic;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -15,7 +14,7 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.ConnectionRequest; public override PacketType Type => PacketType.ConnectionRequest;
protected override void Serialize(NetOutgoingMessage m) protected override void Serialize(NetOutgoingMessage m)
{ {
var data=new List<byte>(10); var data = new List<byte>(10);
m.Write(TargetID); m.Write(TargetID);
} }
public override void Deserialize(NetIncomingMessage m) public override void Deserialize(NetIncomingMessage m)

View File

@ -1,59 +1,55 @@
using System; using Lidgren.Network;
using System.Collections.Generic; using System;
using System.Text;
using Lidgren.Network;
using Newtonsoft.Json;
using GTA.Math;
namespace RageCoop.Core namespace RageCoop.Core
{ {
internal enum PacketType:byte internal enum PacketType : byte
{ {
Handshake=0, Handshake = 0,
PlayerConnect=1, PlayerConnect = 1,
PlayerDisconnect=2, PlayerDisconnect = 2,
PlayerInfoUpdate=3, PlayerInfoUpdate = 3,
PublicKeyRequest=4, PublicKeyRequest = 4,
PublicKeyResponse=5, PublicKeyResponse = 5,
Request=6, Request = 6,
Response=7, Response = 7,
PingPong = 8, PingPong = 8,
HandshakeSuccess = 9, HandshakeSuccess = 9,
ChatMessage =10, ChatMessage = 10,
FileTransferChunk=11, FileTransferChunk = 11,
FileTransferRequest=12, FileTransferRequest = 12,
FileTransferResponse = 13, FileTransferResponse = 13,
FileTransferComplete =14, FileTransferComplete = 14,
AllResourcesSent=15, AllResourcesSent = 15,
CustomEvent = 16, CustomEvent = 16,
CustomEventQueued = 17, CustomEventQueued = 17,
ConnectionRequest=18, ConnectionRequest = 18,
P2PConnect = 19, P2PConnect = 19,
HolePunchInit=20, HolePunchInit = 20,
HolePunch=21, HolePunch = 21,
Voice = 22, Voice = 22,
#region Sync #region Sync
PedSync = 23, PedSync = 23,
VehicleSync = 24, VehicleSync = 24,
ProjectileSync =25, ProjectileSync = 25,
#endregion #endregion
#region EVENT #region EVENT
PedKilled=30, PedKilled = 30,
BulletShot=31, BulletShot = 31,
VehicleBulletShot = 32, VehicleBulletShot = 32,
OwnerChanged =35, OwnerChanged = 35,
NozzleTransform=37, NozzleTransform = 37,
#endregion #endregion
Unknown=255 Unknown = 255
} }
internal enum ConnectionChannel internal enum ConnectionChannel
{ {
@ -64,18 +60,18 @@ namespace RageCoop.Core
Mod = 4, Mod = 4,
File = 5, File = 5,
Event = 6, Event = 6,
RequestResponse=7, RequestResponse = 7,
PingPong = 8, PingPong = 8,
VehicleSync = 9, VehicleSync = 9,
PedSync= 10, PedSync = 10,
ProjectileSync = 11, ProjectileSync = 11,
SyncEvents = 12, SyncEvents = 12,
} }
[Flags] [Flags]
internal enum PedDataFlags:ushort internal enum PedDataFlags : ushort
{ {
None=0, None = 0,
IsAiming = 1 << 0, IsAiming = 1 << 0,
IsInStealthMode = 1 << 1, IsInStealthMode = 1 << 1,
IsReloading = 1 << 2, IsReloading = 1 << 2,
@ -91,10 +87,10 @@ namespace RageCoop.Core
IsInCoverFacingLeft = 1 << 12, IsInCoverFacingLeft = 1 << 12,
IsBlindFiring = 1 << 13, IsBlindFiring = 1 << 13,
IsInvincible = 1 << 14, IsInvincible = 1 << 14,
IsFullSync = 1<<15 , IsFullSync = 1 << 15,
} }
internal enum ProjectileDataFlags:byte internal enum ProjectileDataFlags : byte
{ {
None = 0, None = 0,
Exploded = 1 << 0, Exploded = 1 << 0,
@ -103,9 +99,9 @@ namespace RageCoop.Core
IsShotByVehicle = 1 << 3, IsShotByVehicle = 1 << 3,
} }
#region ===== VEHICLE DATA ===== #region ===== VEHICLE DATA =====
internal enum VehicleDataFlags:ushort internal enum VehicleDataFlags : ushort
{ {
None=0, None = 0,
IsEngineRunning = 1 << 0, IsEngineRunning = 1 << 0,
AreLightsOn = 1 << 1, AreLightsOn = 1 << 1,
AreBrakeLightsOn = 1 << 2, AreBrakeLightsOn = 1 << 2,
@ -117,18 +113,18 @@ namespace RageCoop.Core
IsParachuteActive = 1 << 8, IsParachuteActive = 1 << 8,
IsRocketBoostActive = 1 << 9, IsRocketBoostActive = 1 << 9,
IsAircraft = 1 << 10, IsAircraft = 1 << 10,
IsDeluxoHovering=1 << 11, IsDeluxoHovering = 1 << 11,
HasRoof=1 << 12, HasRoof = 1 << 12,
IsFullSync = 1<<13, IsFullSync = 1 << 13,
IsOnFire = 1<<14, IsOnFire = 1 << 14,
Repaired = 1<<15, Repaired = 1 << 15,
} }
internal enum PlayerConfigFlags : byte internal enum PlayerConfigFlags : byte
{ {
None = 0, None = 0,
ShowBlip= 1 << 0, ShowBlip = 1 << 0,
ShowNameTag= 1 << 1 ShowNameTag = 1 << 1
} }
internal struct VehicleDamageModel internal struct VehicleDamageModel

View File

@ -1,9 +1,7 @@
using System; using GTA;
using System.Collections.Generic;
using System.Text;
using GTA.Math; using GTA.Math;
using GTA;
using Lidgren.Network; using Lidgren.Network;
using System.Collections.Generic;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -59,7 +57,7 @@ namespace RageCoop.Core
public BlipSprite BlipSprite { get; set; } = 0; public BlipSprite BlipSprite { get; set; } = 0;
public float BlipScale { get; set; } = 1; public float BlipScale { get; set; } = 1;
#endregion #endregion
protected override void Serialize(NetOutgoingMessage m) protected override void Serialize(NetOutgoingMessage m)
{ {
@ -79,10 +77,10 @@ namespace RageCoop.Core
} }
else else
{ {
if (Speed>=4) if (Speed >= 4)
{ {
m.Write(VehicleID); m.Write(VehicleID);
m.Write((byte)(Seat+3)); m.Write((byte)(Seat + 3));
} }
m.Write(Position); m.Write(Position);
} }
@ -121,7 +119,7 @@ namespace RageCoop.Core
m.Write(WeaponTint); m.Write(WeaponTint);
m.Write((byte)BlipColor); m.Write((byte)BlipColor);
if ((byte)BlipColor!=255) if ((byte)BlipColor != 255)
{ {
m.Write((ushort)BlipSprite); m.Write((ushort)BlipSprite);
m.Write(BlipScale); m.Write(BlipScale);
@ -137,25 +135,25 @@ namespace RageCoop.Core
ID = m.ReadInt32(); ID = m.ReadInt32();
OwnerID=m.ReadInt32(); OwnerID = m.ReadInt32();
Flags = (PedDataFlags)m.ReadUInt16(); Flags = (PedDataFlags)m.ReadUInt16();
Health = m.ReadInt32(); Health = m.ReadInt32();
Speed = m.ReadByte(); Speed = m.ReadByte();
if (Flags.HasPedFlag(PedDataFlags.IsRagdoll)) if (Flags.HasPedFlag(PedDataFlags.IsRagdoll))
{ {
HeadPosition=m.ReadVector3(); HeadPosition = m.ReadVector3();
RightFootPosition=m.ReadVector3(); RightFootPosition = m.ReadVector3();
LeftFootPosition=m.ReadVector3(); LeftFootPosition = m.ReadVector3();
Position=HeadPosition; Position = HeadPosition;
} }
else else
{ {
// Vehicle related // Vehicle related
if (Speed>=4) if (Speed >= 4)
{ {
VehicleID=m.ReadInt32(); VehicleID = m.ReadInt32();
Seat=(VehicleSeat)(m.ReadByte()-3); Seat = (VehicleSeat)(m.ReadByte() - 3);
} }
// Read player position // Read player position
@ -171,7 +169,7 @@ namespace RageCoop.Core
AimCoords = m.ReadVector3(); AimCoords = m.ReadVector3();
} }
Heading=m.ReadFloat(); Heading = m.ReadFloat();
if (Flags.HasPedFlag(PedDataFlags.IsFullSync)) if (Flags.HasPedFlag(PedDataFlags.IsFullSync))
{ {
@ -182,7 +180,7 @@ namespace RageCoop.Core
CurrentWeaponHash = m.ReadUInt32(); CurrentWeaponHash = m.ReadUInt32();
// Read player clothes // Read player clothes
Clothes =m.ReadBytes(36); Clothes = m.ReadBytes(36);
// Read player weapon components // Read player weapon components
if (m.ReadBoolean()) if (m.ReadBoolean())
@ -194,14 +192,14 @@ namespace RageCoop.Core
WeaponComponents.Add(m.ReadUInt32(), m.ReadBoolean()); WeaponComponents.Add(m.ReadUInt32(), m.ReadBoolean());
} }
} }
WeaponTint=m.ReadByte(); WeaponTint = m.ReadByte();
BlipColor=(BlipColor)m.ReadByte(); BlipColor = (BlipColor)m.ReadByte();
if ((byte)BlipColor!=255) if ((byte)BlipColor != 255)
{ {
BlipSprite=(BlipSprite)m.ReadUInt16(); BlipSprite = (BlipSprite)m.ReadUInt16();
BlipScale=m.ReadFloat(); BlipScale = m.ReadFloat();
} }
} }
#endregion #endregion

View File

@ -1,9 +1,6 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using System.Net;
using Lidgren.Network; using Lidgren.Network;
using System.Net;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -80,14 +77,14 @@ namespace RageCoop.Core
// Read ModVersion // Read ModVersion
ModVersion = m.ReadString(); ModVersion = m.ReadString();
InternalEndPoint=CoreUtils.StringToEndPoint(m.ReadString()); InternalEndPoint = CoreUtils.StringToEndPoint(m.ReadString());
AesKeyCrypted=m.ReadByteArray(); AesKeyCrypted = m.ReadByteArray();
AesIVCrypted=m.ReadByteArray(); AesIVCrypted = m.ReadByteArray();
PasswordEncrypted=m.ReadByteArray(); PasswordEncrypted = m.ReadByteArray();
#endregion #endregion
} }
} }
@ -98,7 +95,7 @@ namespace RageCoop.Core
protected override void Serialize(NetOutgoingMessage m) protected override void Serialize(NetOutgoingMessage m)
{ {
m.Write(Players.Length); m.Write(Players.Length);
foreach(var p in Players) foreach (var p in Players)
{ {
m.Write(p.ID); m.Write(p.ID);
m.Write(p.Username); m.Write(p.Username);
@ -107,13 +104,13 @@ namespace RageCoop.Core
public override void Deserialize(NetIncomingMessage m) public override void Deserialize(NetIncomingMessage m)
{ {
Players=new PlayerData[m.ReadInt32()]; Players = new PlayerData[m.ReadInt32()];
for(int i = 0; i<Players.Length; i++) for (int i = 0; i < Players.Length; i++)
{ {
Players[i]=new PlayerData() Players[i] = new PlayerData()
{ {
ID=m.ReadInt32(), ID = m.ReadInt32(),
Username=m.ReadString(), Username = m.ReadString(),
}; };
} }
} }
@ -206,11 +203,11 @@ namespace RageCoop.Core
// Read Username // Read Username
Username = m.ReadString(); Username = m.ReadString();
Latency=m.ReadFloat(); Latency = m.ReadFloat();
Position=m.ReadVector3(); Position = m.ReadVector3();
IsHost=m.ReadBoolean(); IsHost = m.ReadBoolean();
} }
} }
@ -237,8 +234,8 @@ namespace RageCoop.Core
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
Modulus=m.ReadByteArray(); Modulus = m.ReadByteArray();
Exponent=m.ReadByteArray(); Exponent = m.ReadByteArray();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -63,9 +60,9 @@ namespace RageCoop.Core
ID = m.ReadInt32(); ID = m.ReadInt32();
// Read ShooterID // Read ShooterID
ShooterID= m.ReadInt32(); ShooterID = m.ReadInt32();
WeaponHash= m.ReadUInt32(); WeaponHash = m.ReadUInt32();
// Read position // Read position
Position = m.ReadVector3(); Position = m.ReadVector3();
@ -74,9 +71,9 @@ namespace RageCoop.Core
Rotation = m.ReadVector3(); Rotation = m.ReadVector3();
// Read velocity // Read velocity
Velocity =m.ReadVector3(); Velocity = m.ReadVector3();
Flags=(ProjectileDataFlags)m.ReadByte(); Flags = (ProjectileDataFlags)m.ReadByte();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -47,16 +44,16 @@ namespace RageCoop.Core
// Read OwnerID // Read OwnerID
OwnerID=m.ReadInt32(); OwnerID = m.ReadInt32();
// Read WeponHash // Read WeponHash
WeaponHash=m.ReadUInt32(); WeaponHash = m.ReadUInt32();
// Read StartPosition // Read StartPosition
StartPosition=m.ReadVector3(); StartPosition = m.ReadVector3();
// Read EndPosition // Read EndPosition
EndPosition=m.ReadVector3(); EndPosition = m.ReadVector3();
#endregion #endregion
} }
} }

View File

@ -1,7 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -31,8 +28,8 @@ namespace RageCoop.Core
{ {
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
VehicleID=m.ReadInt32(); VehicleID = m.ReadInt32();
Hover=m.ReadBoolean(); Hover = m.ReadBoolean();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -27,8 +24,8 @@ namespace RageCoop.Core
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
ID=m.ReadInt32(); ID = m.ReadInt32();
NewOwnerID=m.ReadInt32(); NewOwnerID = m.ReadInt32();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; 
using System.Collections.Generic;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -29,7 +26,7 @@ namespace RageCoop.Core
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
VictimID=m.ReadInt32(); VictimID = m.ReadInt32();
#endregion #endregion
} }

View File

@ -1,7 +1,4 @@
using System; using GTA.Math;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
@ -39,11 +36,11 @@ namespace RageCoop.Core
#region NetIncomingMessageToPacket #region NetIncomingMessageToPacket
OwnerID=m.ReadInt32(); OwnerID = m.ReadInt32();
Bone=m.ReadUInt16(); Bone = m.ReadUInt16();
WeaponHash=m.ReadUInt32(); WeaponHash = m.ReadUInt32();
StartPosition=m.ReadVector3(); StartPosition = m.ReadVector3();
EndPosition=m.ReadVector3(); EndPosition = m.ReadVector3();
#endregion #endregion
} }
} }

View File

@ -1,10 +1,7 @@
using System; using GTA;
using System.Collections.Generic;
using System.Text;
using GTA;
using GTA.Math; using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
using System.Linq; using System.Collections.Generic;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -136,7 +133,7 @@ namespace RageCoop.Core
// Write LicensePlate // Write LicensePlate
m.Write(LicensePlate); m.Write(LicensePlate);
m.Write((byte)(Livery+1)); m.Write((byte)(Livery + 1));
} }
} }
@ -146,13 +143,13 @@ namespace RageCoop.Core
ID = m.ReadInt32(); ID = m.ReadInt32();
OwnerID = m.ReadInt32(); OwnerID = m.ReadInt32();
Flags=(VehicleDataFlags)m.ReadUInt16(); Flags = (VehicleDataFlags)m.ReadUInt16();
Position = m.ReadVector3(); Position = m.ReadVector3();
Quaternion=m.ReadQuaternion(); Quaternion = m.ReadQuaternion();
Velocity =m.ReadVector3(); Velocity = m.ReadVector3();
RotationVelocity=m.ReadVector3(); RotationVelocity = m.ReadVector3();
ThrottlePower=m.ReadFloat(); ThrottlePower = m.ReadFloat();
BrakePower=m.ReadFloat(); BrakePower = m.ReadFloat();
SteeringAngle = m.ReadFloat(); SteeringAngle = m.ReadFloat();
@ -178,7 +175,7 @@ namespace RageCoop.Core
} }
if (Flags.HasVehFlag(VehicleDataFlags.HasRoof)) if (Flags.HasVehFlag(VehicleDataFlags.HasRoof))
{ {
RoofState=m.ReadByte(); RoofState = m.ReadByte();
} }
// Read vehicle colors // Read vehicle colors
@ -204,7 +201,7 @@ namespace RageCoop.Core
DamageModel = new VehicleDamageModel() DamageModel = new VehicleDamageModel()
{ {
BrokenDoors = m.ReadByte(), BrokenDoors = m.ReadByte(),
OpenedDoors=m.ReadByte(), OpenedDoors = m.ReadByte(),
BrokenWindows = m.ReadByte(), BrokenWindows = m.ReadByte(),
BurstedTires = m.ReadInt16(), BurstedTires = m.ReadInt16(),
LeftHeadLightBroken = m.ReadByte(), LeftHeadLightBroken = m.ReadByte(),
@ -214,14 +211,14 @@ namespace RageCoop.Core
// Read LockStatus // Read LockStatus
LockStatus=(VehicleLockStatus)m.ReadByte(); LockStatus = (VehicleLockStatus)m.ReadByte();
// Read RadioStation // Read RadioStation
RadioStation=m.ReadByte(); RadioStation = m.ReadByte();
LicensePlate=m.ReadString(); LicensePlate = m.ReadString();
Livery=(int)(m.ReadByte()-1); Livery = m.ReadByte() - 1;
} }
#endregion #endregion
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using Lidgren.Network;
using Lidgren.Network;
namespace RageCoop.Core namespace RageCoop.Core
{ {

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text;
namespace RageCoop.Core.Scripting namespace RageCoop.Core.Scripting
{ {
@ -10,8 +10,8 @@ namespace RageCoop.Core.Scripting
/// </summary> /// </summary>
public static class CustomEvents public static class CustomEvents
{ {
static MD5 Hasher = MD5.Create(); private static readonly MD5 Hasher = MD5.Create();
static Dictionary<int,string> Hashed=new Dictionary<int,string>(); private static readonly Dictionary<int, string> Hashed = new Dictionary<int, string>();
internal static readonly int OnPlayerDied = Hash("RageCoop.OnPlayerDied"); internal static readonly int OnPlayerDied = Hash("RageCoop.OnPlayerDied");
internal static readonly int SetWeather = Hash("RageCoop.SetWeather"); internal static readonly int SetWeather = Hash("RageCoop.SetWeather");
internal static readonly int OnPedDeleted = Hash("RageCoop.OnPedDeleted"); internal static readonly int OnPedDeleted = Hash("RageCoop.OnPedDeleted");
@ -40,12 +40,11 @@ namespace RageCoop.Core.Scripting
public static int Hash(string s) public static int Hash(string s)
{ {
var hash = BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0); var hash = BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0);
string name;
lock (Hashed) lock (Hashed)
{ {
if (Hashed.TryGetValue(hash, out name)) if (Hashed.TryGetValue(hash, out string name))
{ {
if (name!=s) 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}");
} }

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
namespace RageCoop.Core.Scripting namespace RageCoop.Core.Scripting

View File

@ -1,17 +1,17 @@
using System; using System;
using System.Threading;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading;
namespace RageCoop.Core namespace RageCoop.Core
{ {
/// <summary> /// <summary>
/// A worker that constantly execute jobs in a background thread. /// A worker that constantly execute jobs in a background thread.
/// </summary> /// </summary>
public class Worker:IDisposable public class Worker : IDisposable
{ {
private SemaphoreSlim _semaphoreSlim; private readonly SemaphoreSlim _semaphoreSlim;
private Thread _workerThread; private readonly Thread _workerThread;
private bool _stopping=false; private bool _stopping = false;
/// <summary> /// <summary>
/// Name of the worker /// Name of the worker
/// </summary> /// </summary>
@ -19,20 +19,20 @@ namespace RageCoop.Core
/// <summary> /// <summary>
/// Whether this worker is busy executing job(s). /// Whether this worker is busy executing job(s).
/// </summary> /// </summary>
public bool IsBusy { get;private set; } public bool IsBusy { get; private set; }
internal Worker(string name,Logger logger,int maxJobs = Int32.MaxValue) internal Worker(string name, Logger logger, int maxJobs = Int32.MaxValue)
{ {
Name = name; Name = name;
_semaphoreSlim = new SemaphoreSlim(0,maxJobs); _semaphoreSlim = new SemaphoreSlim(0, maxJobs);
_workerThread=new Thread(() => _workerThread = new Thread(() =>
{ {
while (!_stopping) while (!_stopping)
{ {
IsBusy=false; IsBusy = false;
_semaphoreSlim.Wait(); _semaphoreSlim.Wait();
if(Jobs.TryDequeue(out var job)) if (Jobs.TryDequeue(out var job))
{ {
IsBusy=true; IsBusy = true;
try try
{ {
job.Invoke(); job.Invoke();
@ -48,7 +48,7 @@ namespace RageCoop.Core
throw new InvalidOperationException("Hmm... that's unexpected."); throw new InvalidOperationException("Hmm... that's unexpected.");
} }
} }
IsBusy=false; IsBusy = false;
}); });
_workerThread.Start(); _workerThread.Start();
} }
@ -66,7 +66,7 @@ namespace RageCoop.Core
/// </summary> /// </summary>
public void Stop() public void Stop()
{ {
_stopping=true; _stopping = true;
QueueJob(() => { }); QueueJob(() => { });
if (_workerThread.IsAlive) if (_workerThread.IsAlive)
{ {
@ -81,6 +81,6 @@ namespace RageCoop.Core
Stop(); Stop();
_semaphoreSlim.Dispose(); _semaphoreSlim.Dispose();
} }
private ConcurrentQueue<Action> Jobs=new ConcurrentQueue<Action>(); private readonly ConcurrentQueue<Action> Jobs = new ConcurrentQueue<Action>();
} }
} }

View File

@ -1,12 +1,12 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using RageCoop.Core; using RageCoop.Core;
using Lidgren.Network;
using System.Diagnostics;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System.Security.Cryptography;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net; using System.Net;
using System.Security.Cryptography;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -18,7 +18,7 @@ namespace RageCoop.Server
private readonly Server Server; private readonly Server Server;
internal Client(Server server) internal Client(Server server)
{ {
Server=server; Server = server;
} }
/// <summary> /// <summary>
@ -36,7 +36,7 @@ namespace RageCoop.Server
public IPEndPoint InternalEndPoint { get; internal set; } public IPEndPoint InternalEndPoint { get; internal set; }
internal long NetHandle = 0; internal long NetHandle = 0;
internal NetConnection Connection { get;set; } internal NetConnection Connection { get; set; }
/// <summary> /// <summary>
/// The <see cref="ServerPed"/> instance representing the client's main character. /// The <see cref="ServerPed"/> instance representing the client's main character.
/// </summary> /// </summary>
@ -44,34 +44,36 @@ namespace RageCoop.Server
/// <summary> /// <summary>
/// The client's latency in seconds. /// The client's latency in seconds.
/// </summary> /// </summary>
public float Latency => Connection.AverageRoundtripTime/2; public float Latency => Connection.AverageRoundtripTime / 2;
internal readonly Dictionary<int, Action<object>> Callbacks = new(); internal readonly Dictionary<int, Action<object>> Callbacks = new();
internal byte[] PublicKey { get; set; } internal byte[] PublicKey { get; set; }
/// <summary> /// <summary>
/// Indicates whether the client has succefully loaded all resources. /// Indicates whether the client has succefully loaded all resources.
/// </summary> /// </summary>
public bool IsReady { get; internal set; }=false; public bool IsReady { get; internal set; } = false;
/// <summary> /// <summary>
/// The client's username. /// The client's username.
/// </summary> /// </summary>
public string Username { get;internal set; } = "N/A"; public string Username { get; internal set; } = "N/A";
private bool _autoRespawn=true; private bool _autoRespawn = true;
/// <summary> /// <summary>
/// Gets or sets whether to enable automatic respawn for this client's main ped. /// Gets or sets whether to enable automatic respawn for this client's main ped.
/// </summary> /// </summary>
public bool EnableAutoRespawn { public bool EnableAutoRespawn
{
get => _autoRespawn; get => _autoRespawn;
set { set
BaseScript.SetAutoRespawn(this,value); {
_autoRespawn=value; BaseScript.SetAutoRespawn(this, value);
_autoRespawn = value;
} }
} }
private bool _displayNameTag=true; private bool _displayNameTag = true;
private Stopwatch _latencyWatch = new Stopwatch(); private readonly Stopwatch _latencyWatch = new Stopwatch();
/// <summary> /// <summary>
/// Gets or sets whether to enable automatic respawn for this client's main ped. /// Gets or sets whether to enable automatic respawn for this client's main ped.
@ -81,8 +83,8 @@ namespace RageCoop.Server
get => _displayNameTag; get => _displayNameTag;
set set
{ {
Server.BaseScript.SetNameTag(this,value); Server.BaseScript.SetNameTag(this, value);
_displayNameTag=value; _displayNameTag = value;
} }
} }
#region FUNCTIONS #region FUNCTIONS
@ -90,7 +92,7 @@ namespace RageCoop.Server
/// Kick this client /// Kick this client
/// </summary> /// </summary>
/// <param name="reason"></param> /// <param name="reason"></param>
public void Kick(string reason="You have been kicked!") public void Kick(string reason = "You have been kicked!")
{ {
Connection?.Disconnect(reason); Connection?.Disconnect(reason);
} }
@ -129,7 +131,7 @@ namespace RageCoop.Server
/// <param name="args"></param> /// <param name="args"></param>
public void SendNativeCall<T>(Action<object> callBack, GTA.Native.Hash hash, params object[] args) public void SendNativeCall<T>(Action<object> callBack, GTA.Native.Hash hash, params object[] args)
{ {
var argsList= new List<object>(args); var argsList = new List<object>(args);
argsList.InsertRange(0, new object[] { (byte)Type.GetTypeCode(typeof(T)), RequestNativeCallID<T>(callBack), (ulong)hash }); argsList.InsertRange(0, new object[] { (byte)Type.GetTypeCode(typeof(T)), RequestNativeCallID<T>(callBack), (ulong)hash });
SendCustomEventQueued(CustomEvents.NativeCall, argsList.ToArray()); SendCustomEventQueued(CustomEvents.NativeCall, argsList.ToArray());
@ -142,7 +144,7 @@ namespace RageCoop.Server
public void SendNativeCall(GTA.Native.Hash hash, params object[] args) public void SendNativeCall(GTA.Native.Hash hash, params object[] args)
{ {
var argsList = new List<object>(args); var argsList = new List<object>(args);
argsList.InsertRange(0, new object[] { (byte)TypeCode.Empty,(ulong)hash }); argsList.InsertRange(0, new object[] { (byte)TypeCode.Empty, (ulong)hash });
// Server.Logger?.Debug(argsList.DumpWithType()); // Server.Logger?.Debug(argsList.DumpWithType());
SendCustomEventQueued(CustomEvents.NativeCall, argsList.ToArray()); SendCustomEventQueued(CustomEvents.NativeCall, argsList.ToArray());
} }
@ -151,7 +153,7 @@ namespace RageCoop.Server
int ID = 0; int ID = 0;
lock (Callbacks) lock (Callbacks)
{ {
while ((ID==0) while ((ID == 0)
|| Callbacks.ContainsKey(ID)) || Callbacks.ContainsKey(ID))
{ {
byte[] rngBytes = new byte[4]; byte[] rngBytes = new byte[4];
@ -170,7 +172,7 @@ namespace RageCoop.Server
/// </summary> /// </summary>
/// <param name="hash">An unique identifier of the event, you can use <see cref="CustomEvents.Hash(string)"/> to get it from a string</param> /// <param name="hash">An unique identifier of the event, you can use <see cref="CustomEvents.Hash(string)"/> to get it from a string</param>
/// <param name="args">Arguments</param> /// <param name="args">Arguments</param>
public void SendCustomEvent(int hash,params object[] args) public void SendCustomEvent(int hash, params object[] args)
{ {
if (!IsReady) if (!IsReady)
{ {
@ -183,8 +185,8 @@ namespace RageCoop.Server
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.CustomEvent() new Packets.CustomEvent()
{ {
Hash=hash, Hash = hash,
Args=args Args = args
}.Pack(outgoingMessage); }.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event); Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event);
@ -211,10 +213,10 @@ namespace RageCoop.Server
{ {
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.CustomEvent(null,true) new Packets.CustomEvent(null, true)
{ {
Hash=hash, Hash = hash,
Args=args Args = args
}.Pack(outgoingMessage); }.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event); Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event);

View File

@ -1,16 +1,10 @@
using System; namespace RageCoop.Server
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RageCoop.Server
{ {
internal class FileTransfer internal class FileTransfer
{ {
public int ID { get; set; } public int ID { get; set; }
public float Progress { get; set; } public float Progress { get; set; }
public string Name { get; set; } public string Name { get; set; }
public bool Cancel { get; set; }=false; public bool Cancel { get; set; } = false;
} }
} }

View File

@ -1,12 +1,4 @@
using System; namespace RageCoop.Server
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using RageCoop.Core;
namespace RageCoop.Server
{ {
internal class HolePunch internal class HolePunch
{ {

View File

@ -1,25 +1,23 @@
using System; using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lidgren.Network; using Lidgren.Network;
using Newtonsoft.Json;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Server.Scripting;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using Newtonsoft.Json;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
using System.Threading;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.IO; using System.Text;
using ICSharpCode.SharpZipLib.Zip; using System.Threading;
using System.Diagnostics;
namespace RageCoop.Server namespace RageCoop.Server
{ {
public partial class Server public partial class Server
{ {
const string _versionURL = "https://raw.githubusercontent.com/RAGECOOP/RAGECOOP-V/main/RageCoop.Server/Properties/AssemblyInfo.cs"; private const string _versionURL = "https://raw.githubusercontent.com/RAGECOOP/RAGECOOP-V/main/RageCoop.Server/Properties/AssemblyInfo.cs";
private void SendPlayerUpdate() private void SendPlayerUpdate()
{ {
foreach (var c in ClientsByNetHandle.Values.ToArray()) foreach (var c in ClientsByNetHandle.Values.ToArray())
@ -157,18 +155,18 @@ namespace RageCoop.Server
MainNetServer.Shutdown("Server updating"); MainNetServer.Shutdown("Server updating");
Logger.Info("Server shutting down!"); Logger.Info("Server shutting down!");
Logger.Flush(); Logger.Flush();
Process.Start(Path.Combine("Update", RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "RageCoop.Server.exe": "RageCoop.Server"), "update \"" + AppDomain.CurrentDomain.BaseDirectory[0..^1] + "\""); Process.Start(Path.Combine("Update", RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "RageCoop.Server.exe" : "RageCoop.Server"), "update \"" + AppDomain.CurrentDomain.BaseDirectory[0..^1] + "\"");
Environment.Exit(0); Environment.Exit(0);
} }
catch(Exception ex) catch (Exception ex)
{ {
Logger?.Error("Update",ex); Logger?.Error("Update", ex);
} }
} }
private void KickAssholes() private void KickAssholes()
{ {
foreach(var c in ClientsByNetHandle.Values.ToArray()) foreach (var c in ClientsByNetHandle.Values.ToArray())
{ {
if (c.EntitiesCount > Settings.SpamLimit && Settings.KickSpamming) if (c.EntitiesCount > Settings.SpamLimit && Settings.KickSpamming)
{ {

View File

@ -1,12 +1,10 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using System;
using System.Linq;
using System.Text;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -50,10 +48,10 @@ namespace RageCoop.Server
var args = new HandshakeEventArgs() var args = new HandshakeEventArgs()
{ {
EndPoint=connection.RemoteEndPoint, EndPoint = connection.RemoteEndPoint,
ID=packet.PedID, ID = packet.PedID,
Username=packet.Username, Username = packet.Username,
PasswordHash=Security.Decrypt(packet.PasswordEncrypted, connection.RemoteEndPoint).GetString().GetSHA256Hash().ToHexString(), PasswordHash = Security.Decrypt(packet.PasswordEncrypted, connection.RemoteEndPoint).GetString().GetSHA256Hash().ToHexString(),
}; };
API.Events.InvokePlayerHandshake(args); API.Events.InvokePlayerHandshake(args);
if (args.Cancel) if (args.Cancel)
@ -73,18 +71,18 @@ namespace RageCoop.Server
var handshakeSuccess = MainNetServer.CreateMessage(); var handshakeSuccess = MainNetServer.CreateMessage();
var currentClients = ClientsByID.Values.ToArray(); var currentClients = ClientsByID.Values.ToArray();
var players = new Packets.PlayerData[currentClients.Length]; var players = new Packets.PlayerData[currentClients.Length];
for (int i = 0; i<players.Length; i++) for (int i = 0; i < players.Length; i++)
{ {
players[i]=new Packets.PlayerData() players[i] = new Packets.PlayerData()
{ {
ID=currentClients[i].Player.ID, ID = currentClients[i].Player.ID,
Username=currentClients[i].Username, Username = currentClients[i].Username,
}; };
} }
new Packets.HandshakeSuccess() new Packets.HandshakeSuccess()
{ {
Players=players Players = players
}.Pack(handshakeSuccess); }.Pack(handshakeSuccess);
connection.Approve(handshakeSuccess); connection.Approve(handshakeSuccess);
Client tmpClient; Client tmpClient;
@ -94,25 +92,25 @@ namespace RageCoop.Server
{ {
var player = new ServerPed(this) var player = new ServerPed(this)
{ {
ID= packet.PedID, ID = packet.PedID,
}; };
Entities.Add(player); Entities.Add(player);
ClientsByNetHandle.Add(connection.RemoteUniqueIdentifier, ClientsByNetHandle.Add(connection.RemoteUniqueIdentifier,
tmpClient = new Client(this) tmpClient = new Client(this)
{ {
NetHandle = connection.RemoteUniqueIdentifier, NetHandle = connection.RemoteUniqueIdentifier,
Connection=connection, Connection = connection,
Username=packet.Username, Username = packet.Username,
Player = player, Player = player,
InternalEndPoint=packet.InternalEndPoint, InternalEndPoint = packet.InternalEndPoint,
} }
); );
player.Owner=tmpClient; player.Owner = tmpClient;
ClientsByName.Add(packet.Username.ToLower(), tmpClient); ClientsByName.Add(packet.Username.ToLower(), tmpClient);
ClientsByID.Add(player.ID, tmpClient); ClientsByID.Add(player.ID, tmpClient);
if (ClientsByNetHandle.Count==1) if (ClientsByNetHandle.Count == 1)
{ {
_hostClient=tmpClient; _hostClient = tmpClient;
} }
} }
@ -123,19 +121,19 @@ namespace RageCoop.Server
// The connection has been approved, now we need to send all other players to the new player and the new player to all players // The connection has been approved, now we need to send all other players to the new player and the new player to all players
private void PlayerConnected(Client newClient) private void PlayerConnected(Client newClient)
{ {
if (newClient==_hostClient) if (newClient == _hostClient)
{ {
API.SendCustomEvent(new() { newClient }, CustomEvents.IsHost, true); API.SendCustomEvent(new() { newClient }, CustomEvents.IsHost, true);
} }
// Send new client to all players // Send new client to all players
var cons = MainNetServer.Connections.Exclude(newClient.Connection); var cons = MainNetServer.Connections.Exclude(newClient.Connection);
if (cons.Count!=0) if (cons.Count != 0)
{ {
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.PlayerConnect() new Packets.PlayerConnect()
{ {
PedID=newClient.Player.ID, PedID = newClient.Player.ID,
Username = newClient.Username Username = newClient.Username
}.Pack(outgoingMessage); }.Pack(outgoingMessage);
@ -154,8 +152,8 @@ namespace RageCoop.Server
{ {
ClientsByNetHandle.Values.ForEach(target => ClientsByNetHandle.Values.ForEach(target =>
{ {
if (target==newClient) { return; } if (target == newClient) { return; }
HolePunch(target,newClient); HolePunch(target, newClient);
}); });
} }
@ -171,12 +169,12 @@ namespace RageCoop.Server
private void PlayerDisconnected(Client localClient) private void PlayerDisconnected(Client localClient)
{ {
var cons = MainNetServer.Connections.Exclude(localClient.Connection); var cons = MainNetServer.Connections.Exclude(localClient.Connection);
if (cons.Count!=0) if (cons.Count != 0)
{ {
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.PlayerDisconnect() new Packets.PlayerDisconnect()
{ {
PedID=localClient.Player.ID, PedID = localClient.Player.ID,
}.Pack(outgoingMessage); }.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0); MainNetServer.SendMessage(outgoingMessage, cons, NetDeliveryMethod.ReliableOrdered, 0);
@ -187,7 +185,7 @@ namespace RageCoop.Server
if (ClientsByNetHandle.ContainsKey(localClient.NetHandle)) { ClientsByNetHandle.Remove(localClient.NetHandle); } if (ClientsByNetHandle.ContainsKey(localClient.NetHandle)) { ClientsByNetHandle.Remove(localClient.NetHandle); }
if (ClientsByName.ContainsKey(localClient.Username.ToLower())) { ClientsByName.Remove(localClient.Username.ToLower()); } if (ClientsByName.ContainsKey(localClient.Username.ToLower())) { ClientsByName.Remove(localClient.Username.ToLower()); }
if (ClientsByID.ContainsKey(localClient.Player.ID)) { ClientsByID.Remove(localClient.Player.ID); } if (ClientsByID.ContainsKey(localClient.Player.ID)) { ClientsByID.Remove(localClient.Player.ID); }
if (localClient==_hostClient) if (localClient == _hostClient)
{ {
_hostClient = ClientsByNetHandle.Values.FirstOrDefault(); _hostClient = ClientsByNetHandle.Values.FirstOrDefault();

View File

@ -1,11 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
namespace RageCoop.Server namespace RageCoop.Server
@ -16,7 +10,7 @@ namespace RageCoop.Server
{ {
QueueJob(() => Entities.Update(packet, client)); QueueJob(() => Entities.Update(packet, client));
bool isPlayer = packet.ID==client.Player.ID; bool isPlayer = packet.ID == client.Player.ID;
if (isPlayer) if (isPlayer)
{ {
QueueJob(() => API.Events.InvokePlayerUpdate(client)); QueueJob(() => API.Events.InvokePlayerUpdate(client));
@ -27,17 +21,17 @@ namespace RageCoop.Server
{ {
// Don't send data back // Don't send data back
if (c.NetHandle==client.NetHandle) { continue; } if (c.NetHandle == client.NetHandle) { continue; }
// Check streaming distance // Check streaming distance
if (isPlayer) if (isPlayer)
{ {
if ((Settings.PlayerStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.PlayerStreamingDistance)) if ((Settings.PlayerStreamingDistance != -1) && (packet.Position.DistanceTo(c.Player.Position) > Settings.PlayerStreamingDistance))
{ {
continue; continue;
} }
} }
else if ((Settings.NpcStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.NpcStreamingDistance)) else if ((Settings.NpcStreamingDistance != -1) && (packet.Position.DistanceTo(c.Player.Position) > Settings.NpcStreamingDistance))
{ {
continue; continue;
} }
@ -50,22 +44,22 @@ namespace RageCoop.Server
private void VehicleSync(Packets.VehicleSync packet, Client client) private void VehicleSync(Packets.VehicleSync packet, Client client)
{ {
QueueJob(() => Entities.Update(packet, client)); QueueJob(() => Entities.Update(packet, client));
bool isPlayer = packet.ID==client.Player?.LastVehicle?.ID; bool isPlayer = packet.ID == client.Player?.LastVehicle?.ID;
if (Settings.UseP2P) { return; } if (Settings.UseP2P) { return; }
foreach (var c in ClientsByNetHandle.Values) foreach (var c in ClientsByNetHandle.Values)
{ {
if (c.NetHandle==client.NetHandle) { continue; } if (c.NetHandle == client.NetHandle) { continue; }
if (isPlayer) if (isPlayer)
{ {
// Player's vehicle // Player's vehicle
if ((Settings.PlayerStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.PlayerStreamingDistance)) if ((Settings.PlayerStreamingDistance != -1) && (packet.Position.DistanceTo(c.Player.Position) > Settings.PlayerStreamingDistance))
{ {
continue; continue;
} }
} }
else if ((Settings.NpcStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.NpcStreamingDistance)) else if ((Settings.NpcStreamingDistance != -1) && (packet.Position.DistanceTo(c.Player.Position) > Settings.NpcStreamingDistance))
{ {
continue; continue;
} }

View File

@ -1,12 +1,5 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -17,19 +10,19 @@ namespace RageCoop.Server
// Send to host // Send to host
Send(new Packets.HolePunchInit Send(new Packets.HolePunchInit
{ {
Connect=false, Connect = false,
TargetID=client.Player.ID, TargetID = client.Player.ID,
TargetInternal=client.InternalEndPoint.ToString(), TargetInternal = client.InternalEndPoint.ToString(),
TargetExternal=client.EndPoint.ToString() TargetExternal = client.EndPoint.ToString()
}, host, ConnectionChannel.Default, NetDeliveryMethod.ReliableOrdered); }, host, ConnectionChannel.Default, NetDeliveryMethod.ReliableOrdered);
// Send to client // Send to client
Send(new Packets.HolePunchInit Send(new Packets.HolePunchInit
{ {
Connect=true, Connect = true,
TargetID=host.Player.ID, TargetID = host.Player.ID,
TargetInternal=host.InternalEndPoint.ToString(), TargetInternal = host.InternalEndPoint.ToString(),
TargetExternal=host.EndPoint.ToString() TargetExternal = host.EndPoint.ToString()
}, client, ConnectionChannel.Default, NetDeliveryMethod.ReliableOrdered); }, client, ConnectionChannel.Default, NetDeliveryMethod.ReliableOrdered);
} }
} }

View File

@ -1,12 +1,7 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using System;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -141,7 +136,7 @@ namespace RageCoop.Server
{ {
var outgoingMessage = MainNetServer.CreateMessage(); var outgoingMessage = MainNetServer.CreateMessage();
outgoingMessage.Write((byte)type); outgoingMessage.Write((byte)type);
outgoingMessage.Write(message.ReadBytes(message.LengthBytes-1)); outgoingMessage.Write(message.ReadBytes(message.LengthBytes - 1));
MainNetServer.SendMessage(outgoingMessage, toSend, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.SyncEvents); MainNetServer.SendMessage(outgoingMessage, toSend, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.SyncEvents);
} }
} }

View File

@ -1,24 +1,16 @@
using System; using Lidgren.Network;
using System.Diagnostics;
using System.Text;
using System.Net;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using System.Reflection;
using System.IO;
using System.Net.Http;
using RageCoop.Core; using RageCoop.Core;
using Newtonsoft.Json;
using Lidgren.Network;
using System.Timers;
using System.Security.Cryptography;
using RageCoop.Server.Scripting; using RageCoop.Server.Scripting;
using Timer = System.Timers.Timer; using System;
using System.Net.Sockets; using System.Collections.Generic;
using System.Threading.Tasks; using System.IO;
using RageCoop.Core.Scripting; using System.Linq;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Timer = System.Timers.Timer;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -38,12 +30,12 @@ namespace RageCoop.Server
internal ServerEntities Entities; internal ServerEntities Entities;
internal readonly Dictionary<Command, Action<CommandContext>> Commands = new(); internal readonly Dictionary<Command, Action<CommandContext>> Commands = new();
internal readonly Dictionary<long,Client> ClientsByNetHandle = new(); internal readonly Dictionary<long, Client> ClientsByNetHandle = new();
internal readonly Dictionary<string, Client> ClientsByName = new(); internal readonly Dictionary<string, Client> ClientsByName = new();
internal readonly Dictionary<int, Client> ClientsByID = new(); internal readonly Dictionary<int, Client> ClientsByID = new();
internal Client _hostClient; internal Client _hostClient;
private Dictionary<int,FileTransfer> InProgressFileTransfers=new(); private readonly Dictionary<int, FileTransfer> InProgressFileTransfers = new();
internal Resources Resources; internal Resources Resources;
internal Logger Logger; internal Logger Logger;
internal Security Security; internal Security Security;
@ -55,8 +47,8 @@ namespace RageCoop.Server
private readonly Timer _updateTimer = new(); private readonly Timer _updateTimer = new();
private readonly Worker _worker; private readonly Worker _worker;
private readonly HashSet<char> _allowedCharacterSet; private readonly HashSet<char> _allowedCharacterSet;
private Dictionary<int,Action<PacketType,NetIncomingMessage>> PendingResponses=new(); private readonly Dictionary<int, Action<PacketType, NetIncomingMessage>> PendingResponses = new();
internal Dictionary<PacketType, Func<NetIncomingMessage,Client,Packet>> RequestHandlers=new(); internal Dictionary<PacketType, Func<NetIncomingMessage, Client, Packet>> RequestHandlers = new();
/// <summary> /// <summary>
/// Get the current server version /// Get the current server version
/// </summary> /// </summary>
@ -67,23 +59,23 @@ namespace RageCoop.Server
/// <param name="settings"></param> /// <param name="settings"></param>
/// <param name="logger"></param> /// <param name="logger"></param>
/// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentNullException"></exception>
public Server(Settings settings,Logger logger=null) public Server(Settings settings, Logger logger = null)
{ {
Settings = settings; Settings = settings;
if (settings==null) { throw new ArgumentNullException("Server settings cannot be null!"); } if (settings == null) { throw new ArgumentNullException("Server settings cannot be null!"); }
Logger=logger; Logger = logger;
if (Logger!=null) { Logger.LogLevel=Settings.LogLevel;} if (Logger != null) { Logger.LogLevel = Settings.LogLevel; }
API=new API(this); API = new API(this);
Resources=new Resources(this); Resources = new Resources(this);
Security=new Security(Logger); Security = new Security(Logger);
Entities=new ServerEntities(this); Entities = new ServerEntities(this);
BaseScript=new BaseScript(this); BaseScript = new BaseScript(this);
_allowedCharacterSet=new HashSet<char>(Settings.AllowedUsernameChars.ToCharArray()); _allowedCharacterSet = new HashSet<char>(Settings.AllowedUsernameChars.ToCharArray());
_worker=new Worker("ServerWorker", Logger); _worker = new Worker("ServerWorker", Logger);
_listenerThread=new Thread(() => Listen()); _listenerThread = new Thread(() => Listen());
_announceTimer.Interval = 1; _announceTimer.Interval = 1;
_announceTimer.Elapsed += (s, e) => _announceTimer.Elapsed += (s, e) =>
@ -105,7 +97,7 @@ namespace RageCoop.Server
_updateTimer.Interval = 1; _updateTimer.Interval = 1;
_updateTimer.Elapsed += (s, e) => _updateTimer.Elapsed += (s, e) =>
{ {
_updateTimer.Interval= 1000 * 60 * 10; // 10 minutes _updateTimer.Interval = 1000 * 60 * 10; // 10 minutes
_updateTimer.Stop(); _updateTimer.Stop();
CheckUpdate(); CheckUpdate();
_updateTimer.Start(); _updateTimer.Start();
@ -137,8 +129,8 @@ namespace RageCoop.Server
} }
if (Settings.UseZeroTier) if (Settings.UseZeroTier)
{ {
Logger?.Info($"Joining ZeroTier network: "+Settings.ZeroTierNetworkID); Logger?.Info($"Joining ZeroTier network: " + Settings.ZeroTierNetworkID);
if (ZeroTierHelper.Join(Settings.ZeroTierNetworkID)==null) if (ZeroTierHelper.Join(Settings.ZeroTierNetworkID) == null)
{ {
throw new Exception("Failed to obtain ZeroTier network IP"); throw new Exception("Failed to obtain ZeroTier network IP");
} }
@ -155,7 +147,7 @@ namespace RageCoop.Server
MaximumConnections = Settings.MaxPlayers, MaximumConnections = Settings.MaxPlayers,
EnableUPnP = false, EnableUPnP = false,
AutoFlushSendQueue = true, AutoFlushSendQueue = true,
PingInterval=5 PingInterval = 5
}; };
config.EnableMessageType(NetIncomingMessageType.ConnectionApproval); config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
@ -163,16 +155,16 @@ namespace RageCoop.Server
MainNetServer = new NetServer(config); MainNetServer = new NetServer(config);
MainNetServer.Start(); MainNetServer.Start();
BaseScript.API=API; BaseScript.API = API;
BaseScript.OnStart(); BaseScript.OnStart();
Resources.LoadAll(); Resources.LoadAll();
_listenerThread.Start(); _listenerThread.Start();
Logger?.Info("Listening for clients"); Logger?.Info("Listening for clients");
_playerUpdateTimer.Enabled=true; _playerUpdateTimer.Enabled = true;
if (Settings.AnnounceSelf) if (Settings.AnnounceSelf)
{ {
_announceTimer.Enabled=true; _announceTimer.Enabled = true;
} }
if (Settings.AutoUpdate) if (Settings.AutoUpdate)
{ {
@ -201,20 +193,20 @@ namespace RageCoop.Server
} }
// Send a message to targets or all players // Send a message to targets or all players
internal void ChatMessageReceived(string name, string message,Client sender=null) internal void ChatMessageReceived(string name, string message, Client sender = null)
{ {
if (message.StartsWith('/')) if (message.StartsWith('/'))
{ {
string[] cmdArgs = message.Split(" "); string[] cmdArgs = message.Split(" ");
string cmdName = cmdArgs[0].Remove(0, 1); string cmdName = cmdArgs[0].Remove(0, 1);
QueueJob(()=>API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender)); QueueJob(() => API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender));
return; return;
} }
message = message.Replace("~", ""); message = message.Replace("~", "");
QueueJob(() => API.Events.InvokeOnChatMessage(message, sender)); QueueJob(() => API.Events.InvokeOnChatMessage(message, sender));
foreach(var c in ClientsByNetHandle.Values) foreach (var c in ClientsByNetHandle.Values)
{ {
var msg = MainNetServer.CreateMessage(); var msg = MainNetServer.CreateMessage();
var crypt = new Func<string, byte[]>((s) => var crypt = new Func<string, byte[]>((s) =>
@ -223,23 +215,23 @@ namespace RageCoop.Server
}); });
new Packets.ChatMessage(crypt) new Packets.ChatMessage(crypt)
{ {
Username=name, Username = name,
Message=message Message = message
}.Pack(msg); }.Pack(msg);
MainNetServer.SendMessage(msg,c.Connection, NetDeliveryMethod.ReliableOrdered, (int)ConnectionChannel.Chat); MainNetServer.SendMessage(msg, c.Connection, NetDeliveryMethod.ReliableOrdered, (int)ConnectionChannel.Chat);
} }
} }
internal void SendChatMessage(string name, string message, Client target) internal void SendChatMessage(string name, string message, Client target)
{ {
if(target == null) { return; } if (target == null) { return; }
var msg = MainNetServer.CreateMessage(); var msg = MainNetServer.CreateMessage();
new Packets.ChatMessage(new Func<string, byte[]>((s) => new Packets.ChatMessage(new Func<string, byte[]>((s) =>
{ {
return Security.Encrypt(s.GetBytes(), target.EndPoint); return Security.Encrypt(s.GetBytes(), target.EndPoint);
})) }))
{ {
Username= name, Username = name,
Message=message, Message = message,
}.Pack(msg); }.Pack(msg);
MainNetServer.SendMessage(msg, target.Connection, NetDeliveryMethod.ReliableOrdered, (int)ConnectionChannel.Chat); MainNetServer.SendMessage(msg, target.Connection, NetDeliveryMethod.ReliableOrdered, (int)ConnectionChannel.Chat);
} }
@ -278,17 +270,17 @@ namespace RageCoop.Server
RegisterCommand(attribute.Name, attribute.Usage, attribute.ArgsLength, (Action<CommandContext>)Delegate.CreateDelegate(typeof(Action<CommandContext>), method)); RegisterCommand(attribute.Name, attribute.Usage, attribute.ArgsLength, (Action<CommandContext>)Delegate.CreateDelegate(typeof(Action<CommandContext>), method));
} }
} }
internal T GetResponse<T>(Client client,Packet request, ConnectionChannel channel = ConnectionChannel.RequestResponse,int timeout=5000) where T:Packet, new() internal T GetResponse<T>(Client client, Packet request, ConnectionChannel channel = ConnectionChannel.RequestResponse, int timeout = 5000) where T : Packet, new()
{ {
if (Thread.CurrentThread==_listenerThread) if (Thread.CurrentThread == _listenerThread)
{ {
throw new InvalidOperationException("Cannot wait for response from the listener thread!"); throw new InvalidOperationException("Cannot wait for response from the listener thread!");
} }
var received =new AutoResetEvent(false); var received = new AutoResetEvent(false);
T response=new T(); T response = new T();
var id = NewRequestID(); var id = NewRequestID();
PendingResponses.Add(id, (type,m) => PendingResponses.Add(id, (type, m) =>
{ {
response.Deserialize(m); response.Deserialize(m);
received.Set(); received.Set();
@ -297,7 +289,7 @@ namespace RageCoop.Server
msg.Write((byte)PacketType.Request); msg.Write((byte)PacketType.Request);
msg.Write(id); msg.Write(id);
request.Pack(msg); request.Pack(msg);
MainNetServer.SendMessage(msg,client.Connection,NetDeliveryMethod.ReliableOrdered,(int)channel); MainNetServer.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableOrdered, (int)channel);
if (received.WaitOne(timeout)) if (received.WaitOne(timeout))
{ {
return response; return response;
@ -305,25 +297,25 @@ namespace RageCoop.Server
return null; return null;
} }
internal void SendFile(string path,string name,Client client,Action<float> updateCallback=null) internal void SendFile(string path, string name, Client client, Action<float> updateCallback = null)
{ {
var fs = File.OpenRead(path); var fs = File.OpenRead(path);
SendFile(fs, name,client,NewFileID(),updateCallback); SendFile(fs, name, client, NewFileID(), updateCallback);
fs.Close(); fs.Close();
fs.Dispose(); fs.Dispose();
} }
internal void SendFile(Stream stream, string name, Client client,int id=default, Action<float> updateCallback = null) internal void SendFile(Stream stream, string name, Client client, int id = default, Action<float> updateCallback = null)
{ {
stream.Seek(0, SeekOrigin.Begin); stream.Seek(0, SeekOrigin.Begin);
id = id ==default? NewFileID(): id ; id = id == default ? NewFileID() : id;
var total = stream.Length; var total = stream.Length;
Logger?.Debug($"Requesting file transfer:{name}, {total}"); Logger?.Debug($"Requesting file transfer:{name}, {total}");
if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferRequest() if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferRequest()
{ {
FileLength= total, FileLength = total,
Name=name, Name = name,
ID=id, ID = id,
}, ConnectionChannel.File)?.Response!=FileResponse.NeedToDownload) }, ConnectionChannel.File)?.Response != FileResponse.NeedToDownload)
{ {
Logger?.Info($"Skipping file transfer \"{name}\" to {client.Username}"); Logger?.Info($"Skipping file transfer \"{name}\" to {client.Username}");
return; return;
@ -331,7 +323,7 @@ namespace RageCoop.Server
Logger?.Debug($"Initiating file transfer:{name}, {total}"); Logger?.Debug($"Initiating file transfer:{name}, {total}");
FileTransfer transfer = new() FileTransfer transfer = new()
{ {
ID=id, ID = id,
Name = name, Name = name,
}; };
InProgressFileTransfers.Add(id, transfer); InProgressFileTransfers.Add(id, transfer);
@ -341,30 +333,30 @@ namespace RageCoop.Server
{ {
// 4 KB chunk // 4 KB chunk
byte[] chunk = new byte[4096]; byte[] chunk = new byte[4096];
read += thisRead=stream.Read(chunk, 0, 4096); read += thisRead = stream.Read(chunk, 0, 4096);
if (thisRead!=chunk.Length) if (thisRead != chunk.Length)
{ {
if (thisRead==0) { break; } if (thisRead == 0) { break; }
Logger?.Trace($"Purging chunk:{thisRead}"); Logger?.Trace($"Purging chunk:{thisRead}");
Array.Resize(ref chunk, thisRead); Array.Resize(ref chunk, thisRead);
} }
Send( Send(
new Packets.FileTransferChunk() new Packets.FileTransferChunk()
{ {
ID=id, ID = id,
FileChunk=chunk, FileChunk = chunk,
}, },
client, ConnectionChannel.File, NetDeliveryMethod.ReliableOrdered); client, ConnectionChannel.File, NetDeliveryMethod.ReliableOrdered);
transfer.Progress=read/stream.Length; transfer.Progress = read / stream.Length;
if (updateCallback!=null) { updateCallback(transfer.Progress); } if (updateCallback != null) { updateCallback(transfer.Progress); }
} while (thisRead>0); } while (thisRead > 0);
if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferComplete() if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferComplete()
{ {
ID= id, ID = id,
}, ConnectionChannel.File)?.Response!=FileResponse.Completed) }, ConnectionChannel.File)?.Response != FileResponse.Completed)
{ {
Logger.Warning($"File trasfer to {client.Username} failed: "+name); Logger.Warning($"File trasfer to {client.Username} failed: " + name);
} }
Logger?.Debug($"All file chunks sent:{name}"); Logger?.Debug($"All file chunks sent:{name}");
InProgressFileTransfers.Remove(id); InProgressFileTransfers.Remove(id);
@ -372,7 +364,7 @@ namespace RageCoop.Server
internal int NewFileID() internal int NewFileID()
{ {
int ID = 0; int ID = 0;
while ((ID==0) while ((ID == 0)
|| InProgressFileTransfers.ContainsKey(ID)) || InProgressFileTransfers.ContainsKey(ID))
{ {
byte[] rngBytes = new byte[4]; byte[] rngBytes = new byte[4];
@ -387,7 +379,7 @@ namespace RageCoop.Server
private int NewRequestID() private int NewRequestID()
{ {
int ID = 0; int ID = 0;
while ((ID==0) while ((ID == 0)
|| PendingResponses.ContainsKey(ID)) || PendingResponses.ContainsKey(ID))
{ {
byte[] rngBytes = new byte[4]; byte[] rngBytes = new byte[4];
@ -399,11 +391,11 @@ namespace RageCoop.Server
} }
return ID; return ID;
} }
internal void Send(Packet p,Client client, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced) internal void Send(Packet p, Client client, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
{ {
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
p.Pack(outgoingMessage); p.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, client.Connection,method,(int)channel); MainNetServer.SendMessage(outgoingMessage, client.Connection, method, (int)channel);
} }
internal void Forward(Packet p, Client except, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced) internal void Forward(Packet p, Client except, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
{ {

View File

@ -1,21 +1,19 @@
using System; using RageCoop.Core;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using RageCoop.Core;
using Newtonsoft.Json;
using System.Linq;
namespace RageCoop.Server namespace RageCoop.Server
{ {
class Program internal class Program
{ {
private static bool Stopping = false; private static bool Stopping = false;
static Logger mainLogger; private static Logger mainLogger;
static void Main(string[] args)
private static void Main(string[] args)
{ {
if (args.Length>=2 && args[0]=="update") if (args.Length >= 2 && args[0] == "update")
{ {
var target = args[1]; var target = args[1];
int i = 0; int i = 0;
@ -23,13 +21,13 @@ namespace RageCoop.Server
{ {
try try
{ {
Console.WriteLine("Applying update to "+target); Console.WriteLine("Applying update to " + target);
CoreUtils.CopyFilesRecursively(new(AppDomain.CurrentDomain.BaseDirectory), new(target)); CoreUtils.CopyFilesRecursively(new(AppDomain.CurrentDomain.BaseDirectory), new(target));
Process.Start(Path.Combine(target, "RageCoop.Server")); Process.Start(Path.Combine(target, "RageCoop.Server"));
Environment.Exit(0); Environment.Exit(0);
} }
catch(Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
Thread.Sleep(3000); Thread.Sleep(3000);
@ -37,22 +35,22 @@ namespace RageCoop.Server
} }
Environment.Exit(i); Environment.Exit(i);
} }
AppDomain.CurrentDomain.UnhandledException+=UnhandledException; AppDomain.CurrentDomain.UnhandledException += UnhandledException;
mainLogger = new Logger() mainLogger = new Logger()
{ {
LogPath="RageCoop.Server.log", LogPath = "RageCoop.Server.log",
UseConsole=true, UseConsole = true,
Name="Server" Name = "Server"
}; };
try try
{ {
Console.Title = "RAGECOOP"; Console.Title = "RAGECOOP";
var setting = Util.Read<Settings>("Settings.xml"); var setting = Util.Read<Settings>("Settings.xml");
#if DEBUG #if DEBUG
setting.LogLevel=0; setting.LogLevel = 0;
#endif #endif
var server = new Server(setting, mainLogger); var server = new Server(setting, mainLogger);
Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
{ {
mainLogger.Info("Initiating shutdown sequence..."); mainLogger.Info("Initiating shutdown sequence...");
mainLogger.Info("Press Ctrl+C again to commence an emergency shutdown."); mainLogger.Info("Press Ctrl+C again to commence an emergency shutdown.");
@ -82,8 +80,8 @@ namespace RageCoop.Server
while (true) while (true)
{ {
var s=Console.ReadLine(); var s = Console.ReadLine();
if (!Stopping && s!=null) if (!Stopping && s != null)
{ {
server.ChatMessageReceived("Server", s, null); server.ChatMessageReceived("Server", s, null);
} }
@ -98,11 +96,11 @@ namespace RageCoop.Server
private static void UnhandledException(object sender, UnhandledExceptionEventArgs e) private static void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
mainLogger.Error($"Unhandled exception thrown from user thread",e.ExceptionObject as Exception); mainLogger.Error($"Unhandled exception thrown from user thread", e.ExceptionObject as Exception);
mainLogger.Flush(); mainLogger.Flush();
} }
static void Fatal(Exception e) private static void Fatal(Exception e)
{ {
mainLogger.Error(e); mainLogger.Error(e);
mainLogger.Error($"Fatal error occurred, server shutting down."); mainLogger.Error($"Fatal error occurred, server shutting down.");

View File

@ -15,7 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Version information // Version information
[assembly: AssemblyVersion("1.5.3.176")] [assembly: AssemblyVersion("1.5.3.178")]
[assembly: AssemblyFileVersion("1.5.3.176")] [assembly: AssemblyFileVersion("1.5.3.178")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )] [assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -1,13 +1,12 @@
using System; using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System.Reflection; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -54,14 +53,14 @@ namespace RageCoop.Server.Scripting
public event EventHandler<Client> OnPlayerUpdate; public event EventHandler<Client> OnPlayerUpdate;
internal void ClearHandlers() internal void ClearHandlers()
{ {
OnChatMessage=null; OnChatMessage = null;
OnPlayerHandshake=null; OnPlayerHandshake = null;
OnPlayerConnected=null; OnPlayerConnected = null;
OnPlayerReady=null; OnPlayerReady = null;
OnPlayerDisconnected=null; OnPlayerDisconnected = null;
// OnCustomEventReceived=null; // OnCustomEventReceived=null;
OnCommandReceived=null; OnCommandReceived = null;
OnPlayerUpdate=null; OnPlayerUpdate = null;
} }
#region INVOKE #region INVOKE
internal void InvokePlayerHandshake(HandshakeEventArgs args) internal void InvokePlayerHandshake(HandshakeEventArgs args)
@ -70,9 +69,9 @@ namespace RageCoop.Server.Scripting
{ {
var args = new OnCommandEventArgs() var args = new OnCommandEventArgs()
{ {
Name=cmdName, Name = cmdName,
Args=cmdArgs, Args = cmdArgs,
Client=sender Client = sender
}; };
OnCommandReceived?.Invoke(this, args); OnCommandReceived?.Invoke(this, args);
if (args.Cancel) if (args.Cancel)
@ -99,27 +98,26 @@ namespace RageCoop.Server.Scripting
} }
} }
internal void InvokeOnChatMessage(string msg, Client sender, string clamiedSender=null) internal void InvokeOnChatMessage(string msg, Client sender, string clamiedSender = null)
{ {
OnChatMessage?.Invoke(this, new ChatEventArgs() OnChatMessage?.Invoke(this, new ChatEventArgs()
{ {
Client=sender, Client = sender,
Message=msg, Message = msg,
ClaimedSender=clamiedSender ClaimedSender = clamiedSender
}); });
} }
internal void InvokePlayerConnected(Client client) internal void InvokePlayerConnected(Client client)
{ OnPlayerConnected?.Invoke(this,client); } { OnPlayerConnected?.Invoke(this, client); }
internal void InvokePlayerReady(Client client) internal void InvokePlayerReady(Client client)
{ OnPlayerReady?.Invoke(this, client); } { OnPlayerReady?.Invoke(this, client); }
internal void InvokePlayerDisconnected(Client client) internal void InvokePlayerDisconnected(Client client)
{ OnPlayerDisconnected?.Invoke(this,client); } { OnPlayerDisconnected?.Invoke(this, client); }
internal void InvokeCustomEventReceived(Packets.CustomEvent p, Client sender) internal void InvokeCustomEventReceived(Packets.CustomEvent p, Client sender)
{ {
var args = new CustomEventReceivedArgs() { Hash=p.Hash, Args=p.Args, Client=sender }; var args = new CustomEventReceivedArgs() { Hash = p.Hash, Args = p.Args, Client = sender };
List<Action<CustomEventReceivedArgs>> handlers; if (CustomEventHandlers.TryGetValue(p.Hash, out List<Action<CustomEventReceivedArgs>> handlers))
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
{ {
handlers.ForEach((x) => { x.Invoke(args); }); handlers.ForEach((x) => { x.Invoke(args); });
} }
@ -136,32 +134,32 @@ namespace RageCoop.Server.Scripting
public class API public class API
{ {
internal readonly Server Server; internal readonly Server Server;
internal readonly Dictionary<string, Func<Stream>> RegisteredFiles=new Dictionary<string, Func<System.IO.Stream>>(); internal readonly Dictionary<string, Func<Stream>> RegisteredFiles = new Dictionary<string, Func<System.IO.Stream>>();
internal API(Server server) internal API(Server server)
{ {
Server=server; Server = server;
Events=new(server); Events = new(server);
Server.RequestHandlers.Add(PacketType.FileTransferRequest, (data,client) => Server.RequestHandlers.Add(PacketType.FileTransferRequest, (data, client) =>
{ {
var p = new Packets.FileTransferRequest(); var p = new Packets.FileTransferRequest();
p.Deserialize(data); p.Deserialize(data);
var id=Server.NewFileID(); var id = Server.NewFileID();
if(RegisteredFiles.TryGetValue(p.Name,out var s)) if (RegisteredFiles.TryGetValue(p.Name, out var s))
{ {
Task.Run(() => Task.Run(() =>
{ {
Server.SendFile(s(), p.Name, client,id); Server.SendFile(s(), p.Name, client, id);
}); });
return new Packets.FileTransferResponse() return new Packets.FileTransferResponse()
{ {
ID=id, ID = id,
Response=FileResponse.Loaded Response = FileResponse.Loaded
}; };
} }
return new Packets.FileTransferResponse() return new Packets.FileTransferResponse()
{ {
ID=id, ID = id,
Response=FileResponse.LoadFailed Response = FileResponse.LoadFailed
}; };
}); });
} }
@ -204,9 +202,9 @@ namespace RageCoop.Server.Scripting
/// <param name="username">The username which send this message (default = "Server")</param> /// <param name="username">The username which send this message (default = "Server")</param>
/// <param name="raiseEvent">Weather to raise the <see cref="ServerEvents.OnChatMessage"/> event defined in <see cref="API.Events"/></param> /// <param name="raiseEvent">Weather to raise the <see cref="ServerEvents.OnChatMessage"/> event defined in <see cref="API.Events"/></param>
/// <remarks>When <paramref name="raiseEvent"/> is unspecified and <paramref name="targets"/> is null or unspecified, <paramref name="raiseEvent"/> will be set to true</remarks> /// <remarks>When <paramref name="raiseEvent"/> is unspecified and <paramref name="targets"/> is null or unspecified, <paramref name="raiseEvent"/> will be set to true</remarks>
public void SendChatMessage(string message, List<Client> targets = null, string username = "Server",bool? raiseEvent=null) public void SendChatMessage(string message, List<Client> targets = null, string username = "Server", bool? raiseEvent = null)
{ {
raiseEvent ??= targets==null; raiseEvent ??= targets == null;
try try
{ {
if (Server.MainNetServer.ConnectionsCount != 0) if (Server.MainNetServer.ConnectionsCount != 0)
@ -233,7 +231,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
/// <param name="name">name of this file</param> /// <param name="name">name of this file</param>
/// <param name="path">path to this file</param> /// <param name="path">path to this file</param>
public void RegisterSharedFile(string name,string path) public void RegisterSharedFile(string name, string path)
{ {
RegisteredFiles.Add(name, () => { return File.OpenRead(path); }); RegisteredFiles.Add(name, () => { return File.OpenRead(path); });
} }
@ -300,7 +298,7 @@ namespace RageCoop.Server.Scripting
/// <param name="hash"></param> /// <param name="hash"></param>
/// <param name="args"></param> /// <param name="args"></param>
/// /// <param name="clients">Clients to send, null for all clients</param> /// /// <param name="clients">Clients to send, null for all clients</param>
public void SendNativeCall(List<Client> clients , GTA.Native.Hash hash, params object[] args) public void SendNativeCall(List<Client> clients, GTA.Native.Hash hash, params object[] args)
{ {
var argsList = new List<object>(args); var argsList = new List<object>(args);
argsList.InsertRange(0, new object[] { (byte)TypeCode.Empty, (ulong)hash }); argsList.InsertRange(0, new object[] { (byte)TypeCode.Empty, (ulong)hash });
@ -320,8 +318,8 @@ namespace RageCoop.Server.Scripting
targets ??= new(Server.ClientsByNetHandle.Values); targets ??= new(Server.ClientsByNetHandle.Values);
var p = new Packets.CustomEvent() var p = new Packets.CustomEvent()
{ {
Args=args, Args = args,
Hash=eventHash Hash = eventHash
}; };
foreach (var c in targets) foreach (var c in targets)
{ {
@ -339,10 +337,10 @@ namespace RageCoop.Server.Scripting
{ {
targets ??= new(Server.ClientsByNetHandle.Values); targets ??= new(Server.ClientsByNetHandle.Values);
var p = new Packets.CustomEvent(null,true) var p = new Packets.CustomEvent(null, true)
{ {
Args=args, Args = args,
Hash=eventHash Hash = eventHash
}; };
foreach (var c in targets) foreach (var c in targets)
{ {
@ -354,12 +352,11 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
/// <param name="hash">An unique identifier of the event, you can hash your event name with <see cref="CustomEvents.Hash(string)"/></param> /// <param name="hash">An unique identifier of the event, you can hash your event name with <see cref="CustomEvents.Hash(string)"/></param>
/// <param name="handler">An handler to be invoked when the event is received from the server.</param> /// <param name="handler">An handler to be invoked when the event is received from the server.</param>
public void RegisterCustomEventHandler(int hash,Action<CustomEventReceivedArgs> handler) public void RegisterCustomEventHandler(int hash, Action<CustomEventReceivedArgs> handler)
{ {
List<Action<CustomEventReceivedArgs>> handlers;
lock (Events.CustomEventHandlers) lock (Events.CustomEventHandlers)
{ {
if (!Events.CustomEventHandlers.TryGetValue(hash,out handlers)) if (!Events.CustomEventHandlers.TryGetValue(hash, out List<Action<CustomEventReceivedArgs>> handlers))
{ {
Events.CustomEventHandlers.Add(hash, handlers = new List<Action<CustomEventReceivedArgs>>()); Events.CustomEventHandlers.Add(hash, handlers = new List<Action<CustomEventReceivedArgs>>());
} }
@ -385,11 +382,11 @@ namespace RageCoop.Server.Scripting
/// <returns>A <see langword="dynamic"/> object reprensenting the script, or <see langword="null"/> if not found.</returns> /// <returns>A <see langword="dynamic"/> object reprensenting the script, or <see langword="null"/> if not found.</returns>
/// <remarks>Explicitly casting the return value to orginal type will case a exception to be thrown due to the dependency isolation mechanism in resource system. /// <remarks>Explicitly casting the return value to orginal type will case a exception to be thrown due to the dependency isolation mechanism in resource system.
/// You shouldn't reference the target resource assemblies either, since it causes the referenced assembly to be loaded and started in your resource.</remarks> /// You shouldn't reference the target resource assemblies either, since it causes the referenced assembly to be loaded and started in your resource.</remarks>
public dynamic FindScript(string scriptFullName,string resourceName=null) public dynamic FindScript(string scriptFullName, string resourceName = null)
{ {
if (resourceName==null) if (resourceName == null)
{ {
foreach(var res in LoadedResources.Values) foreach (var res in LoadedResources.Values)
{ {
if (res.Scripts.TryGetValue(scriptFullName, out var script)) if (res.Scripts.TryGetValue(scriptFullName, out var script))
{ {
@ -399,7 +396,7 @@ namespace RageCoop.Server.Scripting
} }
else if (LoadedResources.TryGetValue(resourceName, out var res)) else if (LoadedResources.TryGetValue(resourceName, out var res))
{ {
if(res.Scripts.TryGetValue(scriptFullName, out var script)) if (res.Scripts.TryGetValue(scriptFullName, out var script))
{ {
return script; return script;
} }
@ -424,7 +421,8 @@ namespace RageCoop.Server.Scripting
public Client Host public Client Host
{ {
get => Server._hostClient; get => Server._hostClient;
set { set
{
if (Server._hostClient != value) if (Server._hostClient != value)
{ {
Server._hostClient?.SendCustomEvent(CustomEvents.IsHost, false); Server._hostClient?.SendCustomEvent(CustomEvents.IsHost, false);
@ -440,7 +438,7 @@ namespace RageCoop.Server.Scripting
/// <remarks>Accessing this property from script constructor is stronly discouraged since other scripts and resources might have yet been loaded. /// <remarks>Accessing this property from script constructor is stronly discouraged since other scripts and resources might have yet been loaded.
/// Accessing from <see cref="ServerScript.OnStart"/> is not recommended either. Although all script assemblies will have been loaded to memory and instantiated, <see cref="ServerScript.OnStart"/> invocation of other scripts are not guaranteed. /// Accessing from <see cref="ServerScript.OnStart"/> is not recommended either. Although all script assemblies will have been loaded to memory and instantiated, <see cref="ServerScript.OnStart"/> invocation of other scripts are not guaranteed.
/// </remarks> /// </remarks>
public Dictionary<string,ServerResource> LoadedResources public Dictionary<string, ServerResource> LoadedResources
{ {
get get
{ {

View File

@ -1,17 +1,14 @@
using System; using RageCoop.Core.Scripting;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using RageCoop.Core;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
internal class BaseScript:ServerScript internal class BaseScript : ServerScript
{ {
private readonly Server Server; private readonly Server Server;
public BaseScript(Server server) { Server=server; } public BaseScript(Server server) { Server = server; }
public override void OnStart() public override void OnStart()
{ {
API.RegisterCustomEventHandler(CustomEvents.NativeResponse, NativeResponse); API.RegisterCustomEventHandler(CustomEvents.NativeResponse, NativeResponse);
@ -31,7 +28,7 @@ namespace RageCoop.Server.Scripting
foreach (var c in API.GetAllClients().Values) foreach (var c in API.GetAllClients().Values)
{ {
if (c==e.Client) if (c == e.Client)
{ {
continue; continue;
} }
@ -41,49 +38,49 @@ namespace RageCoop.Server.Scripting
}); });
API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) => API.RegisterCustomEventHandler(CustomEvents.OnPlayerDied, (e) =>
{ {
API.SendCustomEventQueued(API.GetAllClients().Values.Where(x=>x!=e.Client).ToList(),CustomEvents.OnPlayerDied,e.Client.Username); API.SendCustomEventQueued(API.GetAllClients().Values.Where(x => x != e.Client).ToList(), CustomEvents.OnPlayerDied, e.Client.Username);
}); });
API.Events.OnChatMessage+=(s,e) => API.Events.OnChatMessage += (s, e) =>
Server.Logger?.Info((e.Client?.Username ?? e.ClaimedSender ?? "Unknown") + ": " + e.Message); Server.Logger?.Info((e.Client?.Username ?? e.ClaimedSender ?? "Unknown") + ": " + e.Message);
} }
public override void OnStop() public override void OnStop()
{ {
} }
public static void SetAutoRespawn(Client c,bool toggle) public static void SetAutoRespawn(Client c, bool toggle)
{ {
c.SendCustomEvent(CustomEvents.SetAutoRespawn, toggle ); c.SendCustomEvent(CustomEvents.SetAutoRespawn, toggle);
} }
public void SetNameTag(Client c, bool toggle) public void SetNameTag(Client c, bool toggle)
{ {
foreach(var other in API.GetAllClients().Values) foreach (var other in API.GetAllClients().Values)
{ {
if (c==other) { continue; } if (c == other) { continue; }
other.SendCustomEvent(CustomEvents.SetDisplayNameTag,c.Player.ID, toggle); other.SendCustomEvent(CustomEvents.SetDisplayNameTag, c.Player.ID, toggle);
} }
} }
public void SendServerPropsTo(List<ServerProp> objects,List<Client> clients=null) public void SendServerPropsTo(List<ServerProp> objects, List<Client> clients = null)
{ {
foreach(var obj in objects) foreach (var obj in objects)
{ {
API.SendCustomEventQueued(clients, CustomEvents.ServerPropSync,obj.ID, obj.Model ,obj.Position,obj.Rotation ); API.SendCustomEventQueued(clients, CustomEvents.ServerPropSync, obj.ID, obj.Model, obj.Position, obj.Rotation);
} }
} }
public void SendServerBlipsTo(List<ServerBlip> objects, List<Client> clients = null) public void SendServerBlipsTo(List<ServerBlip> objects, List<Client> clients = null)
{ {
foreach (var obj in objects) foreach (var obj in objects)
{ {
API.SendCustomEventQueued(clients, CustomEvents.ServerBlipSync, obj.ID, (ushort)obj.Sprite, (byte)obj.Color, obj.Scale,obj.Position,obj.Rotation,obj.Name ); API.SendCustomEventQueued(clients, CustomEvents.ServerBlipSync, obj.ID, (ushort)obj.Sprite, (byte)obj.Color, obj.Scale, obj.Position, obj.Rotation, obj.Name);
} }
} }
void NativeResponse(CustomEventReceivedArgs e)
private void NativeResponse(CustomEventReceivedArgs e)
{ {
try try
{ {
int id = (int)e.Args[0]; int id = (int)e.Args[0];
Action<object> callback;
lock (e.Client.Callbacks) lock (e.Client.Callbacks)
{ {
if (e.Client.Callbacks.TryGetValue(id, out callback)) if (e.Client.Callbacks.TryGetValue(id, out Action<object> callback))
{ {
callback(e.Args[1]); callback(e.Args[1]);
e.Client.Callbacks.Remove(id); e.Client.Callbacks.Remove(id);

View File

@ -1,8 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net; using System.Net;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
@ -97,10 +94,10 @@ namespace RageCoop.Server.Scripting
/// <param name="reason"></param> /// <param name="reason"></param>
public void Deny(string reason) public void Deny(string reason)
{ {
DenyReason=reason; DenyReason = reason;
Cancel=true; Cancel = true;
} }
internal string DenyReason { get; set; } internal string DenyReason { get; set; }
internal bool Cancel { get; set; }=false; internal bool Cancel { get; set; } = false;
} }
} }

View File

@ -1,36 +1,31 @@
using System; using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using RageCoop.Core; using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using ICSharpCode.SharpZipLib.Zip; using System.Threading.Tasks;
using System.Reflection;
using McMaster.NETCore.Plugins;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
internal class Resources internal class Resources
{ {
public Dictionary<string,ServerResource> LoadedResources=new(); public Dictionary<string, ServerResource> LoadedResources = new();
private readonly Server Server; private readonly Server Server;
private readonly Logger Logger; private readonly Logger Logger;
public bool IsLoaded { get; private set; } = false; public bool IsLoaded { get; private set; } = false;
public Resources(Server server) public Resources(Server server)
{ {
Server = server; Server = server;
Logger=server.Logger; Logger = server.Logger;
} }
private Dictionary<string,Stream> ClientResources=new(); private readonly Dictionary<string, Stream> ClientResources = new();
private Dictionary<string,Stream> ResourceStreams=new(); private readonly Dictionary<string, Stream> ResourceStreams = new();
public void LoadAll() public void LoadAll()
{ {
// Packages // Packages
{ {
var path = Path.Combine("Resources", "Packages"); var path = Path.Combine("Resources", "Packages");
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
foreach (var pkg in Directory.GetFiles(path,"*.respkg",SearchOption.AllDirectories)) foreach (var pkg in Directory.GetFiles(path, "*.respkg", SearchOption.AllDirectories))
{ {
Logger?.Debug($"Adding resources from package \"{Path.GetFileNameWithoutExtension(pkg)}\""); Logger?.Debug($"Adding resources from package \"{Path.GetFileNameWithoutExtension(pkg)}\"");
var pkgZip = new ZipFile(pkg); var pkgZip = new ZipFile(pkg);
@ -41,7 +36,7 @@ namespace RageCoop.Server.Scripting
{ {
var stream = pkgZip.GetInputStream(e).ToMemStream(); var stream = pkgZip.GetInputStream(e).ToMemStream();
ClientResources.Add(Path.GetFileNameWithoutExtension(e.Name), stream); ClientResources.Add(Path.GetFileNameWithoutExtension(e.Name), stream);
Logger?.Debug("Resource added: "+ Path.GetFileNameWithoutExtension(e.Name)); Logger?.Debug("Resource added: " + Path.GetFileNameWithoutExtension(e.Name));
} }
else if (e.Name.StartsWith("Server") && e.Name.EndsWith(".res")) else if (e.Name.StartsWith("Server") && e.Name.EndsWith(".res"))
{ {
@ -58,7 +53,7 @@ namespace RageCoop.Server.Scripting
// Client // Client
{ {
var path = Path.Combine("Resources", "Client"); var path = Path.Combine("Resources", "Client");
var tmpDir = Path.Combine("Resources", "Temp","Client"); var tmpDir = Path.Combine("Resources", "Temp", "Client");
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
if (Directory.Exists(tmpDir)) if (Directory.Exists(tmpDir))
{ {
@ -66,13 +61,13 @@ namespace RageCoop.Server.Scripting
} }
Directory.CreateDirectory(tmpDir); Directory.CreateDirectory(tmpDir);
var resourceFolders = Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly); var resourceFolders = Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly);
if (resourceFolders.Length!=0) if (resourceFolders.Length != 0)
{ {
foreach (var resourceFolder in resourceFolders) foreach (var resourceFolder in resourceFolders)
{ {
// Pack client side resource as a zip file // Pack client side resource as a zip file
Logger?.Info("Packing client-side resource: "+resourceFolder); Logger?.Info("Packing client-side resource: " + resourceFolder);
var zipPath = Path.Combine(tmpDir, Path.GetFileName(resourceFolder))+".res"; var zipPath = Path.Combine(tmpDir, Path.GetFileName(resourceFolder)) + ".res";
try try
{ {
using ZipFile zip = ZipFile.Create(zipPath); using ZipFile zip = ZipFile.Create(zipPath);
@ -98,11 +93,11 @@ namespace RageCoop.Server.Scripting
} }
} }
var packed = Directory.GetFiles(path, "*.res", SearchOption.TopDirectoryOnly); var packed = Directory.GetFiles(path, "*.res", SearchOption.TopDirectoryOnly);
if (packed.Length>0) if (packed.Length > 0)
{ {
foreach(var file in packed) foreach (var file in packed)
{ {
ClientResources.Add(Path.GetFileNameWithoutExtension(file),File.OpenRead(file)); ClientResources.Add(Path.GetFileNameWithoutExtension(file), File.OpenRead(file));
} }
} }
} }
@ -122,12 +117,12 @@ namespace RageCoop.Server.Scripting
Logger?.Warning($"Resource \"{name}\" has already been loaded, ignoring..."); Logger?.Warning($"Resource \"{name}\" has already been loaded, ignoring...");
continue; continue;
} }
if (name.ToLower()=="data") { continue; } if (name.ToLower() == "data") { continue; }
Logger?.Info($"Loading resource: {name}"); Logger?.Info($"Loading resource: {name}");
var r = ServerResource.LoadFrom(resource, dataFolder, Logger); var r = ServerResource.LoadFrom(resource, dataFolder, Logger);
LoadedResources.Add(r.Name, r); LoadedResources.Add(r.Name, r);
} }
catch(Exception ex) catch (Exception ex)
{ {
Logger?.Error($"Failed to load resource: {Path.GetFileName(resource)}"); Logger?.Error($"Failed to load resource: {Path.GetFileName(resource)}");
Logger?.Error(ex); Logger?.Error(ex);
@ -135,13 +130,13 @@ namespace RageCoop.Server.Scripting
} }
foreach (var res in Directory.GetFiles(path, "*.res", SearchOption.TopDirectoryOnly)) foreach (var res in Directory.GetFiles(path, "*.res", SearchOption.TopDirectoryOnly))
{ {
if (!ResourceStreams.TryAdd(Path.GetFileNameWithoutExtension(res),File.OpenRead(res))) if (!ResourceStreams.TryAdd(Path.GetFileNameWithoutExtension(res), File.OpenRead(res)))
{ {
Logger?.Warning($"Resource \"{res}\" cannot be loaded, ignoring..."); Logger?.Warning($"Resource \"{res}\" cannot be loaded, ignoring...");
continue; continue;
} }
} }
foreach(var res in ResourceStreams) foreach (var res in ResourceStreams)
{ {
try try
{ {
@ -151,11 +146,11 @@ namespace RageCoop.Server.Scripting
Logger?.Warning($"Resource \"{name}\" has already been loaded, ignoring..."); Logger?.Warning($"Resource \"{name}\" has already been loaded, ignoring...");
continue; continue;
} }
Logger?.Info($"Loading resource: "+name); Logger?.Info($"Loading resource: " + name);
var r = ServerResource.LoadFrom(res.Value, name, Path.Combine("Resources", "Temp", "Server"), dataFolder, Logger); var r = ServerResource.LoadFrom(res.Value, name, Path.Combine("Resources", "Temp", "Server"), dataFolder, Logger);
LoadedResources.Add(r.Name, r); LoadedResources.Add(r.Name, r);
} }
catch(Exception ex) catch (Exception ex)
{ {
Logger?.Error($"Failed to load resource: {res.Key}"); Logger?.Error($"Failed to load resource: {res.Key}");
Logger?.Error(ex); Logger?.Error(ex);
@ -169,17 +164,17 @@ namespace RageCoop.Server.Scripting
{ {
foreach (ServerScript s in r.Scripts.Values) foreach (ServerScript s in r.Scripts.Values)
{ {
s.API=Server.API; s.API = Server.API;
try try
{ {
Logger?.Debug("Starting script:"+s.CurrentFile.Name); Logger?.Debug("Starting script:" + s.CurrentFile.Name);
s.OnStart(); s.OnStart();
} }
catch (Exception ex) { Logger?.Error($"Failed to start resource: {r.Name}"); Logger?.Error(ex); } catch (Exception ex) { Logger?.Error($"Failed to start resource: {r.Name}"); Logger?.Error(ex); }
} }
} }
} }
IsLoaded=true; IsLoaded = true;
} }
} }
@ -195,7 +190,7 @@ namespace RageCoop.Server.Scripting
{ {
s.OnStop(); s.OnStop();
} }
catch(Exception ex) catch (Exception ex)
{ {
Logger?.Error(ex); Logger?.Error(ex);
} }
@ -204,7 +199,7 @@ namespace RageCoop.Server.Scripting
{ {
d.Dispose(); d.Dispose();
} }
catch(Exception ex) catch (Exception ex)
{ {
Logger.Error($"Resource \"{d.Name}\" cannot be unloaded."); Logger.Error($"Resource \"{d.Name}\" cannot be unloaded.");
Logger.Error(ex); Logger.Error(ex);
@ -212,16 +207,16 @@ namespace RageCoop.Server.Scripting
} }
LoadedResources.Clear(); LoadedResources.Clear();
} }
foreach(var s in ResourceStreams.Values) foreach (var s in ResourceStreams.Values)
{ {
try try
{ {
s.Close(); s.Close();
s.Dispose(); s.Dispose();
} }
catch(Exception ex) catch (Exception ex)
{ {
Logger?.Error("[Resources.CloseStream]",ex); Logger?.Error("[Resources.CloseStream]", ex);
} }
} }
foreach (var s in ClientResources.Values) foreach (var s in ClientResources.Values)
@ -265,7 +260,7 @@ namespace RageCoop.Server.Scripting
Logger?.Warning($"Client {client.Username} failed to load resource."); Logger?.Warning($"Client {client.Username} failed to load resource.");
} }
} }
catch(Exception ex) catch (Exception ex)
{ {
Logger.Error("Failed to send resource to client: " + client.Username, ex); Logger.Error("Failed to send resource to client: " + client.Username, ex);
client.Kick("Resource error!"); client.Kick("Resource error!");

View File

@ -1,14 +1,11 @@
using System; using GTA;
using System.Collections.Generic; using GTA.Math;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using GTA.Math;
using GTA;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -25,8 +22,8 @@ namespace RageCoop.Server.Scripting
} }
internal ConcurrentDictionary<int, ServerPed> Peds { get; set; } = new(); internal ConcurrentDictionary<int, ServerPed> Peds { get; set; } = new();
internal ConcurrentDictionary<int, ServerVehicle> Vehicles { get; set; } = new(); internal ConcurrentDictionary<int, ServerVehicle> Vehicles { get; set; } = new();
internal ConcurrentDictionary<int,ServerProp> ServerProps { get; set; }=new(); internal ConcurrentDictionary<int, ServerProp> ServerProps { get; set; } = new();
internal ConcurrentDictionary<int,ServerBlip> Blips { get; set; } = new(); internal ConcurrentDictionary<int, ServerBlip> Blips { get; set; } = new();
/// <summary> /// <summary>
/// Get a <see cref="ServerPed"/> by it's id /// Get a <see cref="ServerPed"/> by it's id
@ -63,16 +60,16 @@ namespace RageCoop.Server.Scripting
/// <param name="pos"></param> /// <param name="pos"></param>
/// <param name="rot"></param> /// <param name="rot"></param>
/// <returns></returns> /// <returns></returns>
public ServerProp CreateProp(Model model,Vector3 pos,Vector3 rot) public ServerProp CreateProp(Model model, Vector3 pos, Vector3 rot)
{ {
int id = RequestNetworkID(); int id = RequestNetworkID();
ServerProp prop; ServerProp prop;
ServerProps.TryAdd(id,prop=new ServerProp(Server) ServerProps.TryAdd(id, prop = new ServerProp(Server)
{ {
ID=id, ID = id,
Model=model, Model = model,
_pos=pos, _pos = pos,
_rot=rot _rot = rot
}); });
prop.Update(); prop.Update();
return prop; return prop;
@ -86,17 +83,17 @@ namespace RageCoop.Server.Scripting
/// <param name="pos">position</param> /// <param name="pos">position</param>
/// <param name="heading">heading of this vehicle</param> /// <param name="heading">heading of this vehicle</param>
/// <returns></returns> /// <returns></returns>
public ServerVehicle CreateVehicle(Client owner,Model model,Vector3 pos,float heading) public ServerVehicle CreateVehicle(Client owner, Model model, Vector3 pos, float heading)
{ {
if(owner == null) { throw new ArgumentNullException("Owner cannot be null"); } if (owner == null) { throw new ArgumentNullException("Owner cannot be null"); }
ServerVehicle veh = new(Server) ServerVehicle veh = new(Server)
{ {
Owner=owner, Owner = owner,
ID=RequestNetworkID(), ID = RequestNetworkID(),
Model=model, Model = model,
_pos= pos, _pos = pos,
}; };
owner.SendCustomEventQueued(CustomEvents.CreateVehicle,veh.ID, model, pos, heading); owner.SendCustomEventQueued(CustomEvents.CreateVehicle, veh.ID, model, pos, heading);
Vehicles.TryAdd(veh.ID, veh); Vehicles.TryAdd(veh.ID, veh);
return veh; return veh;
} }
@ -107,15 +104,15 @@ namespace RageCoop.Server.Scripting
/// <param name="pos"></param> /// <param name="pos"></param>
/// <param name="rotation"></param> /// <param name="rotation"></param>
/// <returns></returns> /// <returns></returns>
public ServerBlip CreateBlip(Vector3 pos,int rotation) public ServerBlip CreateBlip(Vector3 pos, int rotation)
{ {
var b = new ServerBlip(Server) var b = new ServerBlip(Server)
{ {
ID=RequestNetworkID(), ID = RequestNetworkID(),
Position=pos, Position = pos,
Rotation=rotation Rotation = rotation
}; };
Blips.TryAdd(b.ID,b); Blips.TryAdd(b.ID, b);
b.Update(); b.Update();
return b; return b;
} }
@ -147,21 +144,21 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Not thread safe /// Not thread safe
/// </summary> /// </summary>
internal void Update(Packets.PedSync p,Client sender) internal void Update(Packets.PedSync p, Client sender)
{ {
if(!Peds.TryGetValue(p.ID,out ServerPed ped)) if (!Peds.TryGetValue(p.ID, out ServerPed ped))
{ {
Peds.TryAdd(p.ID,ped=new ServerPed(Server)); Peds.TryAdd(p.ID, ped = new ServerPed(Server));
ped.ID=p.ID; ped.ID = p.ID;
} }
ped._pos = p.Position; ped._pos = p.Position;
ped.Owner=sender; ped.Owner = sender;
ped.Health=p.Health; ped.Health = p.Health;
ped._rot=p.Rotation; ped._rot = p.Rotation;
ped._isInvincible = p.Flags.HasPedFlag(PedDataFlags.IsInvincible); ped._isInvincible = p.Flags.HasPedFlag(PedDataFlags.IsInvincible);
if (p.Speed>=4 && Vehicles.TryGetValue(p.VehicleID,out var v)) if (p.Speed >= 4 && Vehicles.TryGetValue(p.VehicleID, out var v))
{ {
ped.LastVehicle=v; ped.LastVehicle = v;
} }
if (ped.Owner != sender) if (ped.Owner != sender)
@ -178,12 +175,12 @@ namespace RageCoop.Server.Scripting
{ {
if (!Vehicles.TryGetValue(p.ID, out ServerVehicle veh)) if (!Vehicles.TryGetValue(p.ID, out ServerVehicle veh))
{ {
Vehicles.TryAdd(p.ID, veh=new ServerVehicle(Server)); Vehicles.TryAdd(p.ID, veh = new ServerVehicle(Server));
veh.ID=p.ID; veh.ID = p.ID;
} }
veh._pos = p.Position+p.Velocity*sender.Latency; veh._pos = p.Position + p.Velocity * sender.Latency;
veh._quat=p.Quaternion; veh._quat = p.Quaternion;
if(veh.Owner != sender) if (veh.Owner != sender)
{ {
if (veh.Owner != null) if (veh.Owner != null)
{ {
@ -199,14 +196,14 @@ namespace RageCoop.Server.Scripting
foreach (var pair in Peds) foreach (var pair in Peds)
{ {
if (pair.Value.Owner==left) if (pair.Value.Owner == left)
{ {
Server.QueueJob(()=>Peds.TryRemove(pair.Key,out _)); Server.QueueJob(() => Peds.TryRemove(pair.Key, out _));
} }
} }
foreach (var pair in Vehicles) foreach (var pair in Vehicles)
{ {
if (pair.Value.Owner==left) if (pair.Value.Owner == left)
{ {
Server.QueueJob(() => Vehicles.TryRemove(pair.Key, out _)); Server.QueueJob(() => Vehicles.TryRemove(pair.Key, out _));
} }
@ -238,7 +235,7 @@ namespace RageCoop.Server.Scripting
{ {
if (Peds.ContainsKey(ped.ID)) if (Peds.ContainsKey(ped.ID))
{ {
Peds[ped.ID]=ped; Peds[ped.ID] = ped;
return; return;
} }
@ -247,7 +244,7 @@ namespace RageCoop.Server.Scripting
internal int RequestNetworkID() internal int RequestNetworkID()
{ {
int ID = 0; int ID = 0;
while ((ID==0) while ((ID == 0)
|| ServerProps.ContainsKey(ID) || ServerProps.ContainsKey(ID)
|| Peds.ContainsKey(ID) || Peds.ContainsKey(ID)
|| Vehicles.ContainsKey(ID) || Vehicles.ContainsKey(ID)

View File

@ -1,14 +1,11 @@
using System; using GTA;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GTA;
using GTA.Native;
using GTA.Math; using GTA.Math;
using GTA.Native;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {
@ -22,7 +19,7 @@ namespace RageCoop.Server.Scripting
/// Server that this object belongs to /// Server that this object belongs to
/// </summary> /// </summary>
internal readonly Server Server; internal readonly Server Server;
internal ServerObject(Server server) { Server=server; } internal ServerObject(Server server) { Server = server; }
/// <summary> /// <summary>
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side. /// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
@ -71,7 +68,7 @@ namespace RageCoop.Server.Scripting
public virtual Vector3 Position public virtual Vector3 Position
{ {
get => _pos; get => _pos;
set { _pos=value; Owner.SendNativeCall(Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z,1, 1,1 ); } set { _pos = value; Owner.SendNativeCall(Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1); }
} }
internal Vector3 _pos; internal Vector3 _pos;
@ -81,7 +78,7 @@ namespace RageCoop.Server.Scripting
public virtual Vector3 Rotation public virtual Vector3 Rotation
{ {
get => _rot; get => _rot;
set { _rot=value; Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z ,2,1); } set { _rot = value; Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1); }
} }
internal Vector3 _rot; internal Vector3 _rot;
@ -105,7 +102,7 @@ namespace RageCoop.Server.Scripting
/// <exception cref="InvalidOperationException"></exception> /// <exception cref="InvalidOperationException"></exception>
public virtual void Freeze(bool toggle) public virtual void Freeze(bool toggle)
{ {
if (GetTypeByte()==50) if (GetTypeByte() == 50)
{ {
throw new InvalidOperationException("Can't freeze or unfreeze static server object"); throw new InvalidOperationException("Can't freeze or unfreeze static server object");
} }
@ -128,7 +125,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public override void Delete() public override void Delete()
{ {
Server.API.SendCustomEventQueued(null,CustomEvents.DeleteServerProp,ID); Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerProp, ID);
Server.API.Entities.RemoveProp(ID); Server.API.Entities.RemoveProp(ID);
} }
@ -138,7 +135,7 @@ namespace RageCoop.Server.Scripting
public override Vector3 Position public override Vector3 Position
{ {
get => _pos; get => _pos;
set { _pos=value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1); } set { _pos = value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1); }
} }
/// <summary> /// <summary>
@ -147,7 +144,7 @@ namespace RageCoop.Server.Scripting
public override Vector3 Rotation public override Vector3 Rotation
{ {
get => _rot; get => _rot;
set { _rot=value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1); } set { _rot = value; Server.API.SendNativeCall(null, Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1); }
} }
@ -198,9 +195,10 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Get or set whether this ped is invincible /// Get or set whether this ped is invincible
/// </summary> /// </summary>
public bool IsInvincible { public bool IsInvincible
{
get => _isInvincible; get => _isInvincible;
set => Owner.SendNativeCall(Hash.SET_ENTITY_INVINCIBLE,Handle,value); set => Owner.SendNativeCall(Hash.SET_ENTITY_INVINCIBLE, Handle, value);
} }
} }
/// <summary> /// <summary>
@ -216,7 +214,7 @@ namespace RageCoop.Server.Scripting
public override Vector3 Rotation public override Vector3 Rotation
{ {
get => _quat.ToEulerAngles().ToDegree(); get => _quat.ToEulerAngles().ToDegree();
set { Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle ,value.X, value.Y ,value.Z); } set { Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z); }
} }
internal Quaternion _quat; internal Quaternion _quat;
@ -226,7 +224,7 @@ namespace RageCoop.Server.Scripting
public Quaternion Quaternion public Quaternion Quaternion
{ {
get => _quat; get => _quat;
set { _quat = value ;Owner.SendNativeCall(Hash.SET_ENTITY_QUATERNION, Handle, value.X, value.Y, value.Z, value.W); } set { _quat = value; Owner.SendNativeCall(Hash.SET_ENTITY_QUATERNION, Handle, value.X, value.Y, value.Z, value.W); }
} }
} }
@ -263,28 +261,30 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Color of this blip /// Color of this blip
/// </summary> /// </summary>
public BlipColor Color { public BlipColor Color
{
get => _color; get => _color;
set { _color=value; Update(); } set { _color = value; Update(); }
} }
internal BlipSprite _sprite=BlipSprite.Standard; internal BlipSprite _sprite = BlipSprite.Standard;
/// <summary> /// <summary>
/// Sprite of this blip /// Sprite of this blip
/// </summary> /// </summary>
public BlipSprite Sprite { public BlipSprite Sprite
{
get => _sprite; get => _sprite;
set { _sprite=value; Update();} set { _sprite = value; Update(); }
} }
internal float _scale =1; internal float _scale = 1;
/// <summary> /// <summary>
/// Scale of this blip /// Scale of this blip
/// </summary> /// </summary>
public float Scale public float Scale
{ {
get => _scale; get => _scale;
set { _scale=value;Update(); } set { _scale = value; Update(); }
} }
internal Vector3 _pos = new(); internal Vector3 _pos = new();
@ -294,7 +294,7 @@ namespace RageCoop.Server.Scripting
public Vector3 Position public Vector3 Position
{ {
get => _pos; get => _pos;
set { _pos=value; Update(); } set { _pos = value; Update(); }
} }
internal int _rot; internal int _rot;
@ -304,17 +304,17 @@ namespace RageCoop.Server.Scripting
public int Rotation public int Rotation
{ {
get => _rot; get => _rot;
set { _rot=value; Update(); } set { _rot = value; Update(); }
} }
internal string _name="Beeeeeee"; internal string _name = "Beeeeeee";
/// <summary> /// <summary>
/// Name of this blip /// Name of this blip
/// </summary> /// </summary>
public string Name public string Name
{ {
get => _name; get => _name;
set { _name=value; Update(); } set { _name = value; Update(); }
} }
/// <summary> /// <summary>
@ -322,23 +322,23 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public void Delete() public void Delete()
{ {
Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerBlip,ID); Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerBlip, ID);
Server.Entities.RemoveServerBlip(ID); Server.Entities.RemoveServerBlip(ID);
} }
private bool _bouncing=false; private bool _bouncing = false;
internal void Update() internal void Update()
{ {
// 5ms debounce // 5ms debounce
if (!_bouncing) if (!_bouncing)
{ {
_bouncing=true; _bouncing = true;
Task.Run(() => Task.Run(() =>
{ {
Thread.Sleep(5); Thread.Sleep(5);
DoUpdate(); DoUpdate();
_bouncing=false; _bouncing = false;
}); });
} }
} }
@ -359,7 +359,7 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Get the <see cref="ServerPed"/> that this blip attached to. /// Get the <see cref="ServerPed"/> that this blip attached to.
/// </summary> /// </summary>
public ServerPed Ped { get;internal set; } public ServerPed Ped { get; internal set; }
internal PedBlip(ServerPed ped) internal PedBlip(ServerPed ped)
{ {
Ped = ped; Ped = ped;
@ -373,17 +373,17 @@ namespace RageCoop.Server.Scripting
public BlipColor Color public BlipColor Color
{ {
get => _color; get => _color;
set { _color=value; Update(); } set { _color = value; Update(); }
} }
internal BlipSprite _sprite=BlipSprite.Standard; internal BlipSprite _sprite = BlipSprite.Standard;
/// <summary> /// <summary>
/// Sprite of this blip /// Sprite of this blip
/// </summary> /// </summary>
public BlipSprite Sprite public BlipSprite Sprite
{ {
get => _sprite; get => _sprite;
set { _sprite=value; Update(); } set { _sprite = value; Update(); }
} }
internal float _scale = 1; internal float _scale = 1;
@ -393,7 +393,7 @@ namespace RageCoop.Server.Scripting
public float Scale public float Scale
{ {
get => _scale; get => _scale;
set { _scale=value; Update(); } set { _scale = value; Update(); }
} }
private bool _bouncing = false; private bool _bouncing = false;
@ -402,18 +402,18 @@ namespace RageCoop.Server.Scripting
// 5ms debounce // 5ms debounce
if (!_bouncing) if (!_bouncing)
{ {
_bouncing=true; _bouncing = true;
Task.Run(() => Task.Run(() =>
{ {
Thread.Sleep(5); Thread.Sleep(5);
DoUpdate(); DoUpdate();
_bouncing=false; _bouncing = false;
}); });
} }
} }
private void DoUpdate() private void DoUpdate()
{ {
Ped.Owner.SendCustomEventQueued(CustomEvents.UpdatePedBlip,Ped.Handle,(byte)Color,(ushort)Sprite,Scale); Ped.Owner.SendCustomEventQueued(CustomEvents.UpdatePedBlip, Ped.Handle, (byte)Color, (ushort)Sprite, Scale);
} }
} }

View File

@ -1,12 +1,12 @@
using System; using ICSharpCode.SharpZipLib.Zip;
using System.Collections.Generic;
using System.Linq;
using RageCoop.Core;
using System.Reflection;
using McMaster.NETCore.Plugins; using McMaster.NETCore.Plugins;
using System.IO; using RageCoop.Core;
using RageCoop.Core.Scripting; using RageCoop.Core.Scripting;
using ICSharpCode.SharpZipLib.Zip; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
@ -23,7 +23,7 @@ namespace RageCoop.Server.Scripting
var runtimeLibs = Path.Combine(resDir, "RuntimeLibs", CoreUtils.GetInvariantRID()); var runtimeLibs = Path.Combine(resDir, "RuntimeLibs", CoreUtils.GetInvariantRID());
if (Directory.Exists(runtimeLibs)) if (Directory.Exists(runtimeLibs))
{ {
logger?.Debug("Applying runtime libraries from "+ CoreUtils.GetInvariantRID()); logger?.Debug("Applying runtime libraries from " + CoreUtils.GetInvariantRID());
CoreUtils.CopyFilesRecursively(new(runtimeLibs), new(resDir)); CoreUtils.CopyFilesRecursively(new(runtimeLibs), new(resDir));
} }
@ -34,44 +34,44 @@ namespace RageCoop.Server.Scripting
CoreUtils.CopyFilesRecursively(new(runtimeLibs), new(resDir)); CoreUtils.CopyFilesRecursively(new(runtimeLibs), new(resDir));
} }
var conf = new PluginConfig(Path.GetFullPath(Path.Combine(resDir, Path.GetFileName(resDir)+".dll"))) var conf = new PluginConfig(Path.GetFullPath(Path.Combine(resDir, Path.GetFileName(resDir) + ".dll")))
{ {
PreferSharedTypes = true, PreferSharedTypes = true,
EnableHotReload=false, EnableHotReload = false,
IsUnloadable=false, IsUnloadable = false,
LoadInMemory=true, LoadInMemory = true,
}; };
ServerResource r = new(conf); ServerResource r = new(conf);
r.Logger= logger; r.Logger = logger;
r.Name=Path.GetFileName(resDir); r.Name = Path.GetFileName(resDir);
if (!File.Exists(conf.MainAssemblyPath)) if (!File.Exists(conf.MainAssemblyPath))
{ {
r.Dispose(); r.Dispose();
throw new FileNotFoundException($"Main assembly for resource \"{r.Name}\" cannot be found."); throw new FileNotFoundException($"Main assembly for resource \"{r.Name}\" cannot be found.");
} }
r.Scripts = new(); r.Scripts = new();
r.DataFolder=Path.Combine(dataFolder, r.Name); r.DataFolder = Path.Combine(dataFolder, r.Name);
r.Reloaded+=(s, e) => { r.Logger?.Info($"Resource: {r.Name} has been reloaded"); }; r.Reloaded += (s, e) => { r.Logger?.Info($"Resource: {r.Name} has been reloaded"); };
Directory.CreateDirectory(r.DataFolder); Directory.CreateDirectory(r.DataFolder);
foreach (var dir in Directory.GetDirectories(resDir, "*", SearchOption.AllDirectories)) foreach (var dir in Directory.GetDirectories(resDir, "*", SearchOption.AllDirectories))
{ {
r.Files.Add(dir, new ResourceFile() r.Files.Add(dir, new ResourceFile()
{ {
IsDirectory=true, IsDirectory = true,
Name=dir.Substring(resDir.Length+1).Replace('\\','/') Name = dir.Substring(resDir.Length + 1).Replace('\\', '/')
});; }); ;
} }
var assemblies=new Dictionary<ResourceFile,Assembly>(); var assemblies = new Dictionary<ResourceFile, Assembly>();
foreach (var file in Directory.GetFiles(resDir, "*", SearchOption.AllDirectories)) foreach (var file in Directory.GetFiles(resDir, "*", SearchOption.AllDirectories))
{ {
if (Path.GetFileName(file).CanBeIgnored()) { try { File.Delete(file); } catch { } continue; } if (Path.GetFileName(file).CanBeIgnored()) { try { File.Delete(file); } catch { } continue; }
var relativeName = file.Substring(resDir.Length+1).Replace('\\', '/'); var relativeName = file.Substring(resDir.Length + 1).Replace('\\', '/');
var rfile = new ResourceFile() var rfile = new ResourceFile()
{ {
GetStream=() => { return new FileStream(file, FileMode.Open, FileAccess.Read); }, GetStream = () => { return new FileStream(file, FileMode.Open, FileAccess.Read); },
IsDirectory=false, IsDirectory = false,
Name=relativeName Name = relativeName
}; };
if (file.EndsWith(".dll") && !relativeName.Contains('/') && IsManagedAssembly(file)) if (file.EndsWith(".dll") && !relativeName.Contains('/') && IsManagedAssembly(file))
{ {
@ -79,9 +79,9 @@ namespace RageCoop.Server.Scripting
} }
r.Files.Add(relativeName, rfile); r.Files.Add(relativeName, rfile);
} }
foreach(var a in assemblies) foreach (var a in assemblies)
{ {
if(a.Key.Name.ToLower() == r.Name.ToLower()+".dll") if (a.Key.Name.ToLower() == r.Name.ToLower() + ".dll")
{ {
try try
@ -100,12 +100,12 @@ namespace RageCoop.Server.Scripting
} }
return r; return r;
} }
internal static ServerResource LoadFrom(Stream input,string name, string tmpDir, string dataFolder, Logger logger = null) internal static ServerResource LoadFrom(Stream input, string name, string tmpDir, string dataFolder, Logger logger = null)
{ {
tmpDir=Path.Combine(tmpDir, name); tmpDir = Path.Combine(tmpDir, name);
if (Directory.Exists(tmpDir)) { Directory.Delete(tmpDir,true); } if (Directory.Exists(tmpDir)) { Directory.Delete(tmpDir, true); }
Directory.CreateDirectory(tmpDir); Directory.CreateDirectory(tmpDir);
new FastZip().ExtractZip(input, tmpDir, FastZip.Overwrite.Always,null,null,null,true,true); new FastZip().ExtractZip(input, tmpDir, FastZip.Overwrite.Always, null, null, null, true, true);
return LoadFrom(tmpDir, dataFolder, logger); return LoadFrom(tmpDir, dataFolder, logger);
} }
/// <summary> /// <summary>
@ -119,7 +119,7 @@ namespace RageCoop.Server.Scripting
/// <summary> /// <summary>
/// Get all <see cref="ServerScript"/> instance in this resource /// Get all <see cref="ServerScript"/> instance in this resource
/// </summary> /// </summary>
public Dictionary<string,ServerScript> Scripts { get; internal set; } = new(); public Dictionary<string, ServerScript> Scripts { get; internal set; } = new();
/// <summary> /// <summary>
/// Get all <see cref="ResourceFile"/> that can be used to acces files in this resource /// Get all <see cref="ResourceFile"/> that can be used to acces files in this resource
/// </summary> /// </summary>
@ -145,8 +145,8 @@ namespace RageCoop.Server.Scripting
// Invoke script constructor // Invoke script constructor
var script = constructor.Invoke(null) as ServerScript; var script = constructor.Invoke(null) as ServerScript;
script.CurrentResource = this; script.CurrentResource = this;
script.CurrentFile=rfile; script.CurrentFile = rfile;
Scripts.Add(script.GetType().FullName,script); Scripts.Add(script.GetType().FullName, script);
count++; count++;
} }
catch (Exception ex) catch (Exception ex)
@ -171,7 +171,7 @@ namespace RageCoop.Server.Scripting
} }
return false; return false;
} }
if(count != 0) if (count != 0)
{ {
Logger?.Info($"Loaded {count} script(s) in {rfile.Name}"); Logger?.Info($"Loaded {count} script(s) in {rfile.Name}");
} }

View File

@ -1,5 +1,5 @@
using System; using RageCoop.Core.Scripting;
using RageCoop.Core.Scripting; using System;
namespace RageCoop.Server.Scripting namespace RageCoop.Server.Scripting
{ {

View File

@ -1,12 +1,7 @@
using System; using RageCoop.Core;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO; using System.IO;
using RageCoop.Core; using System.Net;
using System.Runtime.Serialization;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace RageCoop.Server namespace RageCoop.Server
{ {
@ -15,10 +10,10 @@ namespace RageCoop.Server
private readonly Logger Logger; private readonly Logger Logger;
public Security(Logger logger) public Security(Logger logger)
{ {
Logger= logger; Logger = logger;
} }
public RSA RSA=RSA.Create(2048); public RSA RSA = RSA.Create(2048);
private Dictionary<IPEndPoint, Aes> SecuredConnections = new Dictionary<IPEndPoint, Aes>(); private readonly Dictionary<IPEndPoint, Aes> SecuredConnections = new Dictionary<IPEndPoint, Aes>();
public bool HasSecuredConnection(IPEndPoint target) public bool HasSecuredConnection(IPEndPoint target)
{ {
@ -27,7 +22,7 @@ namespace RageCoop.Server
public byte[] Encrypt(byte[] data, IPEndPoint target) public byte[] Encrypt(byte[] data, IPEndPoint target)
{ {
var ms=new MemoryStream(); var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, SecuredConnections[target].CreateEncryptor(), CryptoStreamMode.Write)) using (var cs = new CryptoStream(ms, SecuredConnections[target].CreateEncryptor(), CryptoStreamMode.Write))
{ {
cs.Write(data, 0, data.Length); cs.Write(data, 0, data.Length);
@ -39,7 +34,7 @@ namespace RageCoop.Server
return new CryptoStream(new MemoryStream(data), SecuredConnections[target].CreateDecryptor(), CryptoStreamMode.Read).ReadToEnd(); return new CryptoStream(new MemoryStream(data), SecuredConnections[target].CreateDecryptor(), CryptoStreamMode.Read).ReadToEnd();
} }
public void AddConnection(IPEndPoint endpoint, byte[] cryptedKey,byte[] cryptedIV) public void AddConnection(IPEndPoint endpoint, byte[] cryptedKey, byte[] cryptedIV)
{ {
var key = RSA.Decrypt(cryptedKey, RSAEncryptionPadding.Pkcs1); var key = RSA.Decrypt(cryptedKey, RSAEncryptionPadding.Pkcs1);
var iv = RSA.Decrypt(cryptedIV, RSAEncryptionPadding.Pkcs1); var iv = RSA.Decrypt(cryptedIV, RSAEncryptionPadding.Pkcs1);
@ -49,7 +44,7 @@ namespace RageCoop.Server
conAes.IV = iv; conAes.IV = iv;
if (!SecuredConnections.ContainsKey(endpoint)) if (!SecuredConnections.ContainsKey(endpoint))
{ {
SecuredConnections.Add(endpoint,conAes); SecuredConnections.Add(endpoint, conAes);
} }
else else
{ {

View File

@ -68,7 +68,7 @@
/// <summary> /// <summary>
/// NPC data won't be sent to a player if their distance is greater than this value. -1 for unlimited. /// NPC data won't be sent to a player if their distance is greater than this value. -1 for unlimited.
/// </summary> /// </summary>
public float NpcStreamingDistance { get; set; } = 500 ; public float NpcStreamingDistance { get; set; } = 500;
/// <summary> /// <summary>
/// Player's data won't be sent to another player if their distance is greater than this value. -1 for unlimited. /// Player's data won't be sent to another player if their distance is greater than this value. -1 for unlimited.
@ -123,6 +123,6 @@
/// <summary> /// <summary>
/// Player that spawned entities more than this amount will be kicked if <see cref="KickSpamming"/> is enabled. /// Player that spawned entities more than this amount will be kicked if <see cref="KickSpamming"/> is enabled.
/// </summary> /// </summary>
public int SpamLimit { get;set; } = 100; public int SpamLimit { get; set; } = 100;
} }
} }

View File

@ -1,16 +1,16 @@
using System; using Lidgren.Network;
using System.IO; using System;
using System.Xml;
using System.Xml.Serialization;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Lidgren.Network; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Xml;
using System.Xml.Serialization;
namespace RageCoop.Server namespace RageCoop.Server
{ {
static partial class Util internal static partial class Util
{ {
public static string DownloadString(string url) public static string DownloadString(string url)
@ -35,7 +35,7 @@ namespace RageCoop.Server
return ""; return "";
} }
} }
public static List<NetConnection> Exclude(this IEnumerable<NetConnection> connections,NetConnection toExclude) public static List<NetConnection> Exclude(this IEnumerable<NetConnection> connections, NetConnection toExclude)
{ {
return new(connections.Where(e => e != toExclude)); return new(connections.Where(e => e != toExclude));
} }
@ -89,7 +89,7 @@ namespace RageCoop.Server
public static T Next<T>(this T[] values) public static T Next<T>(this T[] values)
{ {
return values[new Random().Next(values.Length-1)]; return values[new Random().Next(values.Length - 1)];
} }
public static string GetFinalRedirect(string url) public static string GetFinalRedirect(string url)