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.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows;
namespace RageCoop.Client.Installer
{

View File

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

View File

@ -1,27 +1,17 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
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 Path = System.IO.Path;
using System.Windows.Input;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using Path = System.IO.Path;
using RageCoop.Core;
namespace RageCoop.Client.Installer
{
@ -41,11 +31,12 @@ namespace RageCoop.Client.Installer
var od = new OpenFileDialog()
{
Filter = "GTA 5 executable |GTA5.exe;PlayGTAV.exe",
Title="Select you GTAV executable"
Title = "Select you GTAV executable"
};
if (od.ShowDialog() ?? false == true)
{
Task.Run(() => {
Task.Run(() =>
{
try
{
Install(Directory.GetParent(od.FileName).FullName);
@ -62,7 +53,8 @@ namespace RageCoop.Client.Installer
Environment.Exit(0);
}
}
void Install(string root)
private void Install(string root)
{
UpdateStatus("Checking requirements");
var shvPath = Path.Combine(root, "ScriptHookV.dll");
@ -70,7 +62,7 @@ namespace RageCoop.Client.Installer
var scriptsPath = Path.Combine(root, "Scripts");
var lemonPath = Path.Combine(scriptsPath, "LemonUI.SHVDN3.dll");
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.");
}
@ -86,7 +78,7 @@ namespace RageCoop.Client.Installer
Environment.Exit(1);
}
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!" +
$"\nCurrent version is {shvdnVer}, 3.5.1 or higher is required");
@ -94,11 +86,11 @@ namespace RageCoop.Client.Installer
}
if (File.Exists(lemonPath))
{
var lemonVer=GetVer(lemonPath);
if(lemonVer<new Version(1, 7))
var lemonVer = GetVer(lemonPath);
if (lemonVer < new Version(1, 7))
{
UpdateStatus("Updating LemonUI");
File.WriteAllBytes(lemonPath,getLemon());
File.WriteAllBytes(lemonPath, getLemon());
}
}
@ -144,28 +136,28 @@ namespace RageCoop.Client.Installer
}
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(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)
+ "\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");
Dispatcher.BeginInvoke(new Action(() =>
KeyDown += (s,e) =>
KeyDown += (s, e) =>
{
settings.MenuKey = (Keys)KeyInterop.VirtualKeyFromKey(e.Key);
ae.Set();
}));
ae.WaitOne();
if (!Util.SaveSettings(settingsPath,settings))
if (!Util.SaveSettings(settingsPath, settings))
{
MessageBox.Show("Error occurred when saving settings");
Environment.Exit(1);
}
MessageBox.Show("Menu key changed to "+settings.MenuKey);
MessageBox.Show("Menu key changed to " + settings.MenuKey);
goto checkKeys;
}
}
@ -178,10 +170,10 @@ namespace RageCoop.Client.Installer
}
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";
UpdateStatus("Downloading ZeroTier from "+url);
UpdateStatus("Downloading ZeroTier from " + url);
try
{
HttpHelper.DownloadFile(url, "ZeroTier.msi", (p) => UpdateStatus("Downloading ZeroTier " + p + "%"));
@ -201,15 +193,18 @@ namespace RageCoop.Client.Installer
Environment.Exit(0);
}
}
void UpdateStatus(string status)
private void UpdateStatus(string status)
{
Dispatcher.BeginInvoke(new Action(() => Status.Content = status));
}
Version GetVer(string location)
private Version GetVer(string location)
{
return Version.Parse(FileVersionInfo.GetVersionInfo(location).FileVersion);
}
byte[] getLemon()
private byte[] getLemon()
{
return (byte[])Resource.ResourceManager.GetObject("LemonUI_SHVDN3");
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -333,7 +333,7 @@ namespace RageCoop.Client
if (p.MainProjectile.AttachedEntity == null)
{
// 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;
}

View File

@ -159,7 +159,7 @@ namespace RageCoop.Client
WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash),
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)
{

View File

@ -1,15 +1,13 @@
using System;
using System.Text;
using System.Linq;
using GTA.Math;
using GTA.Math;
using System.IO;
using System.Text;
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 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 GTA.Math;
using Lidgren.Network;
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 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.Client")]
@ -36,12 +34,12 @@ namespace RageCoop.Core
{
return ToIgnore.Contains(name);
}
public static void GetBytesFromObject(object obj,NetOutgoingMessage m)
public static void GetBytesFromObject(object obj, NetOutgoingMessage m)
{
switch (obj)
{
case byte value:
m.Write((byte)0x01);m.Write(value);break;
m.Write((byte)0x01); m.Write(value); break;
case short value:
m.Write((byte)0x02); m.Write(value); break;
case ushort value:
@ -140,9 +138,8 @@ namespace RageCoop.Core
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.MaxPort)
{
@ -151,7 +148,7 @@ namespace RageCoop.Core
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))
{
@ -277,7 +274,7 @@ namespace RageCoop.Core
// 16 bytes
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();
p.Deserialize(msg);
@ -285,20 +282,20 @@ namespace RageCoop.Core
}
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)
{
return (flagToCheck & flag)!=0;
return (flagToCheck & flag) != 0;
}
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)
{
return (flagToCheck & flag)!=0;
return (flagToCheck & flag) != 0;
}
public static Type GetActualType(this TypeCode code)
{
@ -365,9 +362,9 @@ namespace RageCoop.Core
public static string DumpWithType(this IEnumerable<object> objects)
{
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();
}
@ -375,9 +372,9 @@ namespace RageCoop.Core
{
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);
}
@ -399,10 +396,10 @@ namespace RageCoop.Core
stream.CopyTo(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]; }
var output = lengthPerArray== -1 ? new byte[arrays.Sum(arr => arr.Length)] : new byte[arrays.Count*lengthPerArray];
if (arrays.Count == 1) { return arrays[0]; }
var output = lengthPerArray == -1 ? new byte[arrays.Sum(arr => arr.Length)] : new byte[arrays.Count * lengthPerArray];
int writeIdx = 0;
foreach (var byteArr in arrays)
{

View File

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

View File

@ -1,11 +1,11 @@
using System;
using GTA.Math;
using GTA.Math;
using System;
namespace RageCoop.Core
{
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 static Vector3 ToDirection(this Vector3 rotation)
@ -81,14 +81,14 @@ namespace RageCoop.Core
vect = vect.ToRadians();
float rollOver2 = vect.Z * 0.5f;
float sinRollOver2 = (float)Math.Sin((double)rollOver2);
float cosRollOver2 = (float)Math.Cos((double)rollOver2);
float sinRollOver2 = (float)Math.Sin(rollOver2);
float cosRollOver2 = (float)Math.Cos(rollOver2);
float pitchOver2 = vect.Y * 0.5f;
float sinPitchOver2 = (float)Math.Sin((double)pitchOver2);
float cosPitchOver2 = (float)Math.Cos((double)pitchOver2);
float sinPitchOver2 = (float)Math.Sin(pitchOver2);
float cosPitchOver2 = (float)Math.Cos(pitchOver2);
float yawOver2 = vect.X * 0.5f; // pitch
float sinYawOver2 = (float)Math.Sin((double)yawOver2);
float cosYawOver2 = (float)Math.Cos((double)yawOver2);
float sinYawOver2 = (float)Math.Sin(yawOver2);
float cosYawOver2 = (float)Math.Cos(yawOver2);
Quaternion result = new Quaternion()
{
X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2,
@ -110,7 +110,7 @@ namespace RageCoop.Core
}
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)
{
@ -158,7 +158,7 @@ namespace RageCoop.Core
}
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.Text;
using Lidgren.Network;
using System.Threading;
namespace RageCoop.Core
@ -10,19 +9,19 @@ namespace RageCoop.Core
{
public EventHandler<NetIncomingMessage> OnMessageReceived;
private readonly Thread ListenerThread;
private bool _stopping=false;
public CoopPeer(NetPeerConfiguration config):base(config)
private bool _stopping = false;
public CoopPeer(NetPeerConfiguration config) : base(config)
{
Start();
NetIncomingMessage msg;
ListenerThread=new Thread(() =>
ListenerThread = new Thread(() =>
{
while (!_stopping)
{
msg=WaitMessage(200);
if (msg!=null)
msg = WaitMessage(200);
if (msg != null)
{
OnMessageReceived?.Invoke(this,msg);
OnMessageReceived?.Invoke(this, msg);
}
}
});
@ -34,7 +33,7 @@ namespace RageCoop.Core
/// </summary>
public void Dispose()
{
_stopping=true;
_stopping = true;
Shutdown("Bye!");
ListenerThread.Join();
}
@ -51,7 +50,7 @@ namespace RageCoop.Core
p.Pack(outgoingMessage);
SendMessage(outgoingMessage, connections, method, (int)channel);
}
public void Send(Packet p,IList<NetConnection> cons, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
public void Send(Packet p, IList<NetConnection> cons, ConnectionChannel channel = ConnectionChannel.Default, NetDeliveryMethod method = NetDeliveryMethod.UnreliableSequenced)
{
NetOutgoingMessage outgoingMessage = CreateMessage();
p.Pack(outgoingMessage);

View File

@ -1,18 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Threading;
using System.IO;
namespace RageCoop.Core
{
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); }
AutoResetEvent ae=new AutoResetEvent(false);
AutoResetEvent ae = new AutoResetEvent(false);
WebClient client = new WebClient();
// TLS only

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using System.Net;
using GTA.Math;
using Lidgren.Network;
using System.Net;
namespace RageCoop.Core
{
@ -80,14 +77,14 @@ namespace RageCoop.Core
// Read ModVersion
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
}
}
@ -98,7 +95,7 @@ namespace RageCoop.Core
protected override void Serialize(NetOutgoingMessage m)
{
m.Write(Players.Length);
foreach(var p in Players)
foreach (var p in Players)
{
m.Write(p.ID);
m.Write(p.Username);
@ -107,13 +104,13 @@ namespace RageCoop.Core
public override void Deserialize(NetIncomingMessage m)
{
Players=new PlayerData[m.ReadInt32()];
for(int i = 0; i<Players.Length; i++)
Players = new PlayerData[m.ReadInt32()];
for (int i = 0; i < Players.Length; i++)
{
Players[i]=new PlayerData()
Players[i] = new PlayerData()
{
ID=m.ReadInt32(),
Username=m.ReadString(),
ID = m.ReadInt32(),
Username = m.ReadString(),
};
}
}
@ -206,11 +203,11 @@ namespace RageCoop.Core
// Read Username
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
Modulus=m.ReadByteArray();
Exponent=m.ReadByteArray();
Modulus = m.ReadByteArray();
Exponent = m.ReadByteArray();
#endregion
}

View File

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

View File

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

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

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

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

using Lidgren.Network;
namespace RageCoop.Core
@ -27,8 +24,8 @@ namespace RageCoop.Core
#region NetIncomingMessageToPacket
ID=m.ReadInt32();
NewOwnerID=m.ReadInt32();
ID = m.ReadInt32();
NewOwnerID = m.ReadInt32();
#endregion
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +1,17 @@
using System;
using System.Threading;
using System.Collections.Concurrent;
using System.Threading;
namespace RageCoop.Core
{
/// <summary>
/// A worker that constantly execute jobs in a background thread.
/// </summary>
public class Worker:IDisposable
public class Worker : IDisposable
{
private SemaphoreSlim _semaphoreSlim;
private Thread _workerThread;
private bool _stopping=false;
private readonly SemaphoreSlim _semaphoreSlim;
private readonly Thread _workerThread;
private bool _stopping = false;
/// <summary>
/// Name of the worker
/// </summary>
@ -19,20 +19,20 @@ namespace RageCoop.Core
/// <summary>
/// Whether this worker is busy executing job(s).
/// </summary>
public bool IsBusy { get;private set; }
internal Worker(string name,Logger logger,int maxJobs = Int32.MaxValue)
public bool IsBusy { get; private set; }
internal Worker(string name, Logger logger, int maxJobs = Int32.MaxValue)
{
Name = name;
_semaphoreSlim = new SemaphoreSlim(0,maxJobs);
_workerThread=new Thread(() =>
_semaphoreSlim = new SemaphoreSlim(0, maxJobs);
_workerThread = new Thread(() =>
{
while (!_stopping)
{
IsBusy=false;
IsBusy = false;
_semaphoreSlim.Wait();
if(Jobs.TryDequeue(out var job))
if (Jobs.TryDequeue(out var job))
{
IsBusy=true;
IsBusy = true;
try
{
job.Invoke();
@ -48,7 +48,7 @@ namespace RageCoop.Core
throw new InvalidOperationException("Hmm... that's unexpected.");
}
}
IsBusy=false;
IsBusy = false;
});
_workerThread.Start();
}
@ -66,7 +66,7 @@ namespace RageCoop.Core
/// </summary>
public void Stop()
{
_stopping=true;
_stopping = true;
QueueJob(() => { });
if (_workerThread.IsAlive)
{
@ -81,6 +81,6 @@ namespace RageCoop.Core
Stop();
_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 System.Collections.Generic;
using Lidgren.Network;
using RageCoop.Core;
using Lidgren.Network;
using System.Diagnostics;
using RageCoop.Core.Scripting;
using System.Security.Cryptography;
using RageCoop.Server.Scripting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Security.Cryptography;
namespace RageCoop.Server
{
@ -18,7 +18,7 @@ namespace RageCoop.Server
private readonly Server Server;
internal Client(Server server)
{
Server=server;
Server = server;
}
/// <summary>
@ -36,7 +36,7 @@ namespace RageCoop.Server
public IPEndPoint InternalEndPoint { get; internal set; }
internal long NetHandle = 0;
internal NetConnection Connection { get;set; }
internal NetConnection Connection { get; set; }
/// <summary>
/// The <see cref="ServerPed"/> instance representing the client's main character.
/// </summary>
@ -44,34 +44,36 @@ namespace RageCoop.Server
/// <summary>
/// The client's latency in seconds.
/// </summary>
public float Latency => Connection.AverageRoundtripTime/2;
public float Latency => Connection.AverageRoundtripTime / 2;
internal readonly Dictionary<int, Action<object>> Callbacks = new();
internal byte[] PublicKey { get; set; }
/// <summary>
/// Indicates whether the client has succefully loaded all resources.
/// </summary>
public bool IsReady { get; internal set; }=false;
public bool IsReady { get; internal set; } = false;
/// <summary>
/// The client's username.
/// </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>
/// Gets or sets whether to enable automatic respawn for this client's main ped.
/// </summary>
public bool EnableAutoRespawn {
public bool EnableAutoRespawn
{
get => _autoRespawn;
set {
BaseScript.SetAutoRespawn(this,value);
_autoRespawn=value;
set
{
BaseScript.SetAutoRespawn(this, value);
_autoRespawn = value;
}
}
private bool _displayNameTag=true;
private Stopwatch _latencyWatch = new Stopwatch();
private bool _displayNameTag = true;
private readonly Stopwatch _latencyWatch = new Stopwatch();
/// <summary>
/// Gets or sets whether to enable automatic respawn for this client's main ped.
@ -81,8 +83,8 @@ namespace RageCoop.Server
get => _displayNameTag;
set
{
Server.BaseScript.SetNameTag(this,value);
_displayNameTag=value;
Server.BaseScript.SetNameTag(this, value);
_displayNameTag = value;
}
}
#region FUNCTIONS
@ -90,7 +92,7 @@ namespace RageCoop.Server
/// Kick this client
/// </summary>
/// <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);
}
@ -129,7 +131,7 @@ namespace RageCoop.Server
/// <param name="args"></param>
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 });
SendCustomEventQueued(CustomEvents.NativeCall, argsList.ToArray());
@ -142,7 +144,7 @@ namespace RageCoop.Server
public void SendNativeCall(GTA.Native.Hash hash, params 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());
SendCustomEventQueued(CustomEvents.NativeCall, argsList.ToArray());
}
@ -151,7 +153,7 @@ namespace RageCoop.Server
int ID = 0;
lock (Callbacks)
{
while ((ID==0)
while ((ID == 0)
|| Callbacks.ContainsKey(ID))
{
byte[] rngBytes = new byte[4];
@ -170,7 +172,7 @@ namespace RageCoop.Server
/// </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="args">Arguments</param>
public void SendCustomEvent(int hash,params object[] args)
public void SendCustomEvent(int hash, params object[] args)
{
if (!IsReady)
{
@ -183,8 +185,8 @@ namespace RageCoop.Server
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.CustomEvent()
{
Hash=hash,
Args=args
Hash = hash,
Args = args
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event);
@ -211,10 +213,10 @@ namespace RageCoop.Server
{
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.CustomEvent(null,true)
new Packets.CustomEvent(null, true)
{
Hash=hash,
Args=args
Hash = hash,
Args = args
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event);

View File

@ -1,16 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RageCoop.Server
namespace RageCoop.Server
{
internal class FileTransfer
{
public int ID { get; set; }
public float Progress { 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;
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
namespace RageCoop.Server
{
internal class HolePunch
{

View File

@ -1,25 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
using Lidgren.Network;
using Newtonsoft.Json;
using RageCoop.Core;
using RageCoop.Server.Scripting;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using Newtonsoft.Json;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Diagnostics;
using System.Text;
using System.Threading;
namespace RageCoop.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()
{
foreach (var c in ClientsByNetHandle.Values.ToArray())
@ -157,18 +155,18 @@ namespace RageCoop.Server
MainNetServer.Shutdown("Server updating");
Logger.Info("Server shutting down!");
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);
}
catch(Exception ex)
catch (Exception ex)
{
Logger?.Error("Update",ex);
Logger?.Error("Update", ex);
}
}
private void KickAssholes()
{
foreach(var c in ClientsByNetHandle.Values.ToArray())
foreach (var c in ClientsByNetHandle.Values.ToArray())
{
if (c.EntitiesCount > Settings.SpamLimit && Settings.KickSpamming)
{

View File

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

View File

@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using Lidgren.Network;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
namespace RageCoop.Server
@ -16,7 +10,7 @@ namespace RageCoop.Server
{
QueueJob(() => Entities.Update(packet, client));
bool isPlayer = packet.ID==client.Player.ID;
bool isPlayer = packet.ID == client.Player.ID;
if (isPlayer)
{
QueueJob(() => API.Events.InvokePlayerUpdate(client));
@ -27,17 +21,17 @@ namespace RageCoop.Server
{
// Don't send data back
if (c.NetHandle==client.NetHandle) { continue; }
if (c.NetHandle == client.NetHandle) { continue; }
// Check streaming distance
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;
}
}
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;
}
@ -50,22 +44,22 @@ namespace RageCoop.Server
private void VehicleSync(Packets.VehicleSync packet, Client 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; }
foreach (var c in ClientsByNetHandle.Values)
{
if (c.NetHandle==client.NetHandle) { continue; }
if (c.NetHandle == client.NetHandle) { continue; }
if (isPlayer)
{
// 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;
}
}
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;
}

View File

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

View File

@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using Lidgren.Network;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
using System;
namespace RageCoop.Server
{
@ -141,7 +136,7 @@ namespace RageCoop.Server
{
var outgoingMessage = MainNetServer.CreateMessage();
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);
}
}

View File

@ -1,24 +1,16 @@
using System;
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 Lidgren.Network;
using RageCoop.Core;
using Newtonsoft.Json;
using Lidgren.Network;
using System.Timers;
using System.Security.Cryptography;
using RageCoop.Server.Scripting;
using Timer = System.Timers.Timer;
using System.Net.Sockets;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
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
{
@ -38,12 +30,12 @@ namespace RageCoop.Server
internal ServerEntities Entities;
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<int, Client> ClientsByID = new();
internal Client _hostClient;
private Dictionary<int,FileTransfer> InProgressFileTransfers=new();
private readonly Dictionary<int, FileTransfer> InProgressFileTransfers = new();
internal Resources Resources;
internal Logger Logger;
internal Security Security;
@ -55,8 +47,8 @@ namespace RageCoop.Server
private readonly Timer _updateTimer = new();
private readonly Worker _worker;
private readonly HashSet<char> _allowedCharacterSet;
private Dictionary<int,Action<PacketType,NetIncomingMessage>> PendingResponses=new();
internal Dictionary<PacketType, Func<NetIncomingMessage,Client,Packet>> RequestHandlers=new();
private readonly Dictionary<int, Action<PacketType, NetIncomingMessage>> PendingResponses = new();
internal Dictionary<PacketType, Func<NetIncomingMessage, Client, Packet>> RequestHandlers = new();
/// <summary>
/// Get the current server version
/// </summary>
@ -67,23 +59,23 @@ namespace RageCoop.Server
/// <param name="settings"></param>
/// <param name="logger"></param>
/// <exception cref="ArgumentNullException"></exception>
public Server(Settings settings,Logger logger=null)
public Server(Settings settings, Logger logger = null)
{
Settings = settings;
if (settings==null) { throw new ArgumentNullException("Server settings cannot be null!"); }
Logger=logger;
if (Logger!=null) { Logger.LogLevel=Settings.LogLevel;}
API=new API(this);
Resources=new Resources(this);
Security=new Security(Logger);
Entities=new ServerEntities(this);
BaseScript=new BaseScript(this);
_allowedCharacterSet=new HashSet<char>(Settings.AllowedUsernameChars.ToCharArray());
if (settings == null) { throw new ArgumentNullException("Server settings cannot be null!"); }
Logger = logger;
if (Logger != null) { Logger.LogLevel = Settings.LogLevel; }
API = new API(this);
Resources = new Resources(this);
Security = new Security(Logger);
Entities = new ServerEntities(this);
BaseScript = new BaseScript(this);
_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.Elapsed += (s, e) =>
@ -105,7 +97,7 @@ namespace RageCoop.Server
_updateTimer.Interval = 1;
_updateTimer.Elapsed += (s, e) =>
{
_updateTimer.Interval= 1000 * 60 * 10; // 10 minutes
_updateTimer.Interval = 1000 * 60 * 10; // 10 minutes
_updateTimer.Stop();
CheckUpdate();
_updateTimer.Start();
@ -137,8 +129,8 @@ namespace RageCoop.Server
}
if (Settings.UseZeroTier)
{
Logger?.Info($"Joining ZeroTier network: "+Settings.ZeroTierNetworkID);
if (ZeroTierHelper.Join(Settings.ZeroTierNetworkID)==null)
Logger?.Info($"Joining ZeroTier network: " + Settings.ZeroTierNetworkID);
if (ZeroTierHelper.Join(Settings.ZeroTierNetworkID) == null)
{
throw new Exception("Failed to obtain ZeroTier network IP");
}
@ -155,7 +147,7 @@ namespace RageCoop.Server
MaximumConnections = Settings.MaxPlayers,
EnableUPnP = false,
AutoFlushSendQueue = true,
PingInterval=5
PingInterval = 5
};
config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
@ -163,16 +155,16 @@ namespace RageCoop.Server
MainNetServer = new NetServer(config);
MainNetServer.Start();
BaseScript.API=API;
BaseScript.API = API;
BaseScript.OnStart();
Resources.LoadAll();
_listenerThread.Start();
Logger?.Info("Listening for clients");
_playerUpdateTimer.Enabled=true;
_playerUpdateTimer.Enabled = true;
if (Settings.AnnounceSelf)
{
_announceTimer.Enabled=true;
_announceTimer.Enabled = true;
}
if (Settings.AutoUpdate)
{
@ -201,20 +193,20 @@ namespace RageCoop.Server
}
// 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('/'))
{
string[] cmdArgs = message.Split(" ");
string cmdName = cmdArgs[0].Remove(0, 1);
QueueJob(()=>API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender));
QueueJob(() => API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender));
return;
}
message = message.Replace("~", "");
QueueJob(() => API.Events.InvokeOnChatMessage(message, sender));
foreach(var c in ClientsByNetHandle.Values)
foreach (var c in ClientsByNetHandle.Values)
{
var msg = MainNetServer.CreateMessage();
var crypt = new Func<string, byte[]>((s) =>
@ -223,23 +215,23 @@ namespace RageCoop.Server
});
new Packets.ChatMessage(crypt)
{
Username=name,
Message=message
Username = name,
Message = message
}.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)
{
if(target == null) { return; }
if (target == null) { return; }
var msg = MainNetServer.CreateMessage();
new Packets.ChatMessage(new Func<string, byte[]>((s) =>
{
return Security.Encrypt(s.GetBytes(), target.EndPoint);
}))
{
Username= name,
Message=message,
Username = name,
Message = message,
}.Pack(msg);
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));
}
}
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!");
}
var received =new AutoResetEvent(false);
T response=new T();
var received = new AutoResetEvent(false);
T response = new T();
var id = NewRequestID();
PendingResponses.Add(id, (type,m) =>
PendingResponses.Add(id, (type, m) =>
{
response.Deserialize(m);
received.Set();
@ -297,7 +289,7 @@ namespace RageCoop.Server
msg.Write((byte)PacketType.Request);
msg.Write(id);
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))
{
return response;
@ -305,25 +297,25 @@ namespace RageCoop.Server
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);
SendFile(fs, name,client,NewFileID(),updateCallback);
SendFile(fs, name, client, NewFileID(), updateCallback);
fs.Close();
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);
id = id ==default? NewFileID(): id ;
id = id == default ? NewFileID() : id;
var total = stream.Length;
Logger?.Debug($"Requesting file transfer:{name}, {total}");
if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferRequest()
{
FileLength= total,
Name=name,
ID=id,
}, ConnectionChannel.File)?.Response!=FileResponse.NeedToDownload)
FileLength = total,
Name = name,
ID = id,
}, ConnectionChannel.File)?.Response != FileResponse.NeedToDownload)
{
Logger?.Info($"Skipping file transfer \"{name}\" to {client.Username}");
return;
@ -331,7 +323,7 @@ namespace RageCoop.Server
Logger?.Debug($"Initiating file transfer:{name}, {total}");
FileTransfer transfer = new()
{
ID=id,
ID = id,
Name = name,
};
InProgressFileTransfers.Add(id, transfer);
@ -341,30 +333,30 @@ namespace RageCoop.Server
{
// 4 KB chunk
byte[] chunk = new byte[4096];
read += thisRead=stream.Read(chunk, 0, 4096);
if (thisRead!=chunk.Length)
read += thisRead = stream.Read(chunk, 0, 4096);
if (thisRead != chunk.Length)
{
if (thisRead==0) { break; }
if (thisRead == 0) { break; }
Logger?.Trace($"Purging chunk:{thisRead}");
Array.Resize(ref chunk, thisRead);
}
Send(
new Packets.FileTransferChunk()
{
ID=id,
FileChunk=chunk,
ID = id,
FileChunk = chunk,
},
client, ConnectionChannel.File, NetDeliveryMethod.ReliableOrdered);
transfer.Progress=read/stream.Length;
if (updateCallback!=null) { updateCallback(transfer.Progress); }
transfer.Progress = read / stream.Length;
if (updateCallback != null) { updateCallback(transfer.Progress); }
} while (thisRead>0);
} while (thisRead > 0);
if (GetResponse<Packets.FileTransferResponse>(client, new Packets.FileTransferComplete()
{
ID= id,
}, ConnectionChannel.File)?.Response!=FileResponse.Completed)
ID = id,
}, 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}");
InProgressFileTransfers.Remove(id);
@ -372,7 +364,7 @@ namespace RageCoop.Server
internal int NewFileID()
{
int ID = 0;
while ((ID==0)
while ((ID == 0)
|| InProgressFileTransfers.ContainsKey(ID))
{
byte[] rngBytes = new byte[4];
@ -387,7 +379,7 @@ namespace RageCoop.Server
private int NewRequestID()
{
int ID = 0;
while ((ID==0)
while ((ID == 0)
|| PendingResponses.ContainsKey(ID))
{
byte[] rngBytes = new byte[4];
@ -399,11 +391,11 @@ namespace RageCoop.Server
}
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();
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)
{

View File

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

View File

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

View File

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using Lidgren.Network;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting
{
@ -54,14 +53,14 @@ namespace RageCoop.Server.Scripting
public event EventHandler<Client> OnPlayerUpdate;
internal void ClearHandlers()
{
OnChatMessage=null;
OnPlayerHandshake=null;
OnPlayerConnected=null;
OnPlayerReady=null;
OnPlayerDisconnected=null;
OnChatMessage = null;
OnPlayerHandshake = null;
OnPlayerConnected = null;
OnPlayerReady = null;
OnPlayerDisconnected = null;
// OnCustomEventReceived=null;
OnCommandReceived=null;
OnPlayerUpdate=null;
OnCommandReceived = null;
OnPlayerUpdate = null;
}
#region INVOKE
internal void InvokePlayerHandshake(HandshakeEventArgs args)
@ -70,9 +69,9 @@ namespace RageCoop.Server.Scripting
{
var args = new OnCommandEventArgs()
{
Name=cmdName,
Args=cmdArgs,
Client=sender
Name = cmdName,
Args = cmdArgs,
Client = sender
};
OnCommandReceived?.Invoke(this, args);
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()
{
Client=sender,
Message=msg,
ClaimedSender=clamiedSender
Client = sender,
Message = msg,
ClaimedSender = clamiedSender
});
}
internal void InvokePlayerConnected(Client client)
{ OnPlayerConnected?.Invoke(this,client); }
{ OnPlayerConnected?.Invoke(this, client); }
internal void InvokePlayerReady(Client client)
{ OnPlayerReady?.Invoke(this, client); }
internal void InvokePlayerDisconnected(Client client)
{ OnPlayerDisconnected?.Invoke(this,client); }
{ OnPlayerDisconnected?.Invoke(this, client); }
internal void InvokeCustomEventReceived(Packets.CustomEvent p, Client sender)
{
var args = new CustomEventReceivedArgs() { Hash=p.Hash, Args=p.Args, Client=sender };
List<Action<CustomEventReceivedArgs>> handlers;
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
var args = new CustomEventReceivedArgs() { Hash = p.Hash, Args = p.Args, Client = sender };
if (CustomEventHandlers.TryGetValue(p.Hash, out List<Action<CustomEventReceivedArgs>> handlers))
{
handlers.ForEach((x) => { x.Invoke(args); });
}
@ -136,32 +134,32 @@ namespace RageCoop.Server.Scripting
public class API
{
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)
{
Server=server;
Events=new(server);
Server.RequestHandlers.Add(PacketType.FileTransferRequest, (data,client) =>
Server = server;
Events = new(server);
Server.RequestHandlers.Add(PacketType.FileTransferRequest, (data, client) =>
{
var p = new Packets.FileTransferRequest();
p.Deserialize(data);
var id=Server.NewFileID();
if(RegisteredFiles.TryGetValue(p.Name,out var s))
var id = Server.NewFileID();
if (RegisteredFiles.TryGetValue(p.Name, out var s))
{
Task.Run(() =>
{
Server.SendFile(s(), p.Name, client,id);
Server.SendFile(s(), p.Name, client, id);
});
return new Packets.FileTransferResponse()
{
ID=id,
Response=FileResponse.Loaded
ID = id,
Response = FileResponse.Loaded
};
}
return new Packets.FileTransferResponse()
{
ID=id,
Response=FileResponse.LoadFailed
ID = id,
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="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>
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
{
if (Server.MainNetServer.ConnectionsCount != 0)
@ -233,7 +231,7 @@ namespace RageCoop.Server.Scripting
/// </summary>
/// <param name="name">name of 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); });
}
@ -300,7 +298,7 @@ namespace RageCoop.Server.Scripting
/// <param name="hash"></param>
/// <param name="args"></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);
argsList.InsertRange(0, new object[] { (byte)TypeCode.Empty, (ulong)hash });
@ -320,8 +318,8 @@ namespace RageCoop.Server.Scripting
targets ??= new(Server.ClientsByNetHandle.Values);
var p = new Packets.CustomEvent()
{
Args=args,
Hash=eventHash
Args = args,
Hash = eventHash
};
foreach (var c in targets)
{
@ -339,10 +337,10 @@ namespace RageCoop.Server.Scripting
{
targets ??= new(Server.ClientsByNetHandle.Values);
var p = new Packets.CustomEvent(null,true)
var p = new Packets.CustomEvent(null, true)
{
Args=args,
Hash=eventHash
Args = args,
Hash = eventHash
};
foreach (var c in targets)
{
@ -354,12 +352,11 @@ namespace RageCoop.Server.Scripting
/// </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="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)
{
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>>());
}
@ -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>
/// <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>
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))
{
@ -399,7 +396,7 @@ namespace RageCoop.Server.Scripting
}
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;
}
@ -424,7 +421,8 @@ namespace RageCoop.Server.Scripting
public Client Host
{
get => Server._hostClient;
set {
set
{
if (Server._hostClient != value)
{
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.
/// 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>
public Dictionary<string,ServerResource> LoadedResources
public Dictionary<string, ServerResource> LoadedResources
{
get
{

View File

@ -1,17 +1,14 @@
using System;
using RageCoop.Core.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using RageCoop.Core;
namespace RageCoop.Server.Scripting
{
internal class BaseScript:ServerScript
internal class BaseScript : ServerScript
{
private readonly Server Server;
public BaseScript(Server server) { Server=server; }
public BaseScript(Server server) { Server = server; }
public override void OnStart()
{
API.RegisterCustomEventHandler(CustomEvents.NativeResponse, NativeResponse);
@ -31,7 +28,7 @@ namespace RageCoop.Server.Scripting
foreach (var c in API.GetAllClients().Values)
{
if (c==e.Client)
if (c == e.Client)
{
continue;
}
@ -41,49 +38,49 @@ namespace RageCoop.Server.Scripting
});
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);
}
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)
{
foreach(var other in API.GetAllClients().Values)
foreach (var other in API.GetAllClients().Values)
{
if (c==other) { continue; }
other.SendCustomEvent(CustomEvents.SetDisplayNameTag,c.Player.ID, toggle);
if (c == other) { continue; }
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)
{
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
{
int id = (int)e.Args[0];
Action<object> callback;
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]);
e.Client.Callbacks.Remove(id);

View File

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

View File

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

View File

@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GTA;
using GTA.Native;
using GTA;
using GTA.Math;
using GTA.Native;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting
{
@ -22,7 +19,7 @@ namespace RageCoop.Server.Scripting
/// Server that this object belongs to
/// </summary>
internal readonly Server Server;
internal ServerObject(Server server) { Server=server; }
internal ServerObject(Server server) { Server = server; }
/// <summary>
/// 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
{
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;
@ -81,7 +78,7 @@ namespace RageCoop.Server.Scripting
public virtual Vector3 Rotation
{
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;
@ -105,7 +102,7 @@ namespace RageCoop.Server.Scripting
/// <exception cref="InvalidOperationException"></exception>
public virtual void Freeze(bool toggle)
{
if (GetTypeByte()==50)
if (GetTypeByte() == 50)
{
throw new InvalidOperationException("Can't freeze or unfreeze static server object");
}
@ -128,7 +125,7 @@ namespace RageCoop.Server.Scripting
/// </summary>
public override void Delete()
{
Server.API.SendCustomEventQueued(null,CustomEvents.DeleteServerProp,ID);
Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerProp, ID);
Server.API.Entities.RemoveProp(ID);
}
@ -138,7 +135,7 @@ namespace RageCoop.Server.Scripting
public override Vector3 Position
{
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>
@ -147,7 +144,7 @@ namespace RageCoop.Server.Scripting
public override Vector3 Rotation
{
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>
/// Get or set whether this ped is invincible
/// </summary>
public bool IsInvincible {
public bool IsInvincible
{
get => _isInvincible;
set => Owner.SendNativeCall(Hash.SET_ENTITY_INVINCIBLE,Handle,value);
set => Owner.SendNativeCall(Hash.SET_ENTITY_INVINCIBLE, Handle, value);
}
}
/// <summary>
@ -216,7 +214,7 @@ namespace RageCoop.Server.Scripting
public override Vector3 Rotation
{
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;
@ -226,7 +224,7 @@ namespace RageCoop.Server.Scripting
public Quaternion Quaternion
{
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>
/// Color of this blip
/// </summary>
public BlipColor Color {
public BlipColor Color
{
get => _color;
set { _color=value; Update(); }
set { _color = value; Update(); }
}
internal BlipSprite _sprite=BlipSprite.Standard;
internal BlipSprite _sprite = BlipSprite.Standard;
/// <summary>
/// Sprite of this blip
/// </summary>
public BlipSprite Sprite {
public BlipSprite Sprite
{
get => _sprite;
set { _sprite=value; Update();}
set { _sprite = value; Update(); }
}
internal float _scale =1;
internal float _scale = 1;
/// <summary>
/// Scale of this blip
/// </summary>
public float Scale
{
get => _scale;
set { _scale=value;Update(); }
set { _scale = value; Update(); }
}
internal Vector3 _pos = new();
@ -294,7 +294,7 @@ namespace RageCoop.Server.Scripting
public Vector3 Position
{
get => _pos;
set { _pos=value; Update(); }
set { _pos = value; Update(); }
}
internal int _rot;
@ -304,17 +304,17 @@ namespace RageCoop.Server.Scripting
public int Rotation
{
get => _rot;
set { _rot=value; Update(); }
set { _rot = value; Update(); }
}
internal string _name="Beeeeeee";
internal string _name = "Beeeeeee";
/// <summary>
/// Name of this blip
/// </summary>
public string Name
{
get => _name;
set { _name=value; Update(); }
set { _name = value; Update(); }
}
/// <summary>
@ -322,23 +322,23 @@ namespace RageCoop.Server.Scripting
/// </summary>
public void Delete()
{
Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerBlip,ID);
Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerBlip, ID);
Server.Entities.RemoveServerBlip(ID);
}
private bool _bouncing=false;
private bool _bouncing = false;
internal void Update()
{
// 5ms debounce
if (!_bouncing)
{
_bouncing=true;
_bouncing = true;
Task.Run(() =>
{
Thread.Sleep(5);
DoUpdate();
_bouncing=false;
_bouncing = false;
});
}
}
@ -359,7 +359,7 @@ namespace RageCoop.Server.Scripting
/// <summary>
/// Get the <see cref="ServerPed"/> that this blip attached to.
/// </summary>
public ServerPed Ped { get;internal set; }
public ServerPed Ped { get; internal set; }
internal PedBlip(ServerPed ped)
{
Ped = ped;
@ -373,17 +373,17 @@ namespace RageCoop.Server.Scripting
public BlipColor Color
{
get => _color;
set { _color=value; Update(); }
set { _color = value; Update(); }
}
internal BlipSprite _sprite=BlipSprite.Standard;
internal BlipSprite _sprite = BlipSprite.Standard;
/// <summary>
/// Sprite of this blip
/// </summary>
public BlipSprite Sprite
{
get => _sprite;
set { _sprite=value; Update(); }
set { _sprite = value; Update(); }
}
internal float _scale = 1;
@ -393,7 +393,7 @@ namespace RageCoop.Server.Scripting
public float Scale
{
get => _scale;
set { _scale=value; Update(); }
set { _scale = value; Update(); }
}
private bool _bouncing = false;
@ -402,18 +402,18 @@ namespace RageCoop.Server.Scripting
// 5ms debounce
if (!_bouncing)
{
_bouncing=true;
_bouncing = true;
Task.Run(() =>
{
Thread.Sleep(5);
DoUpdate();
_bouncing=false;
_bouncing = false;
});
}
}
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 System.Collections.Generic;
using System.Linq;
using RageCoop.Core;
using System.Reflection;
using ICSharpCode.SharpZipLib.Zip;
using McMaster.NETCore.Plugins;
using System.IO;
using RageCoop.Core;
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;
namespace RageCoop.Server.Scripting
@ -23,7 +23,7 @@ namespace RageCoop.Server.Scripting
var runtimeLibs = Path.Combine(resDir, "RuntimeLibs", CoreUtils.GetInvariantRID());
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));
}
@ -34,44 +34,44 @@ namespace RageCoop.Server.Scripting
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,
EnableHotReload=false,
IsUnloadable=false,
LoadInMemory=true,
EnableHotReload = false,
IsUnloadable = false,
LoadInMemory = true,
};
ServerResource r = new(conf);
r.Logger= logger;
r.Name=Path.GetFileName(resDir);
r.Logger = logger;
r.Name = Path.GetFileName(resDir);
if (!File.Exists(conf.MainAssemblyPath))
{
r.Dispose();
throw new FileNotFoundException($"Main assembly for resource \"{r.Name}\" cannot be found.");
}
r.Scripts = new();
r.DataFolder=Path.Combine(dataFolder, r.Name);
r.Reloaded+=(s, e) => { r.Logger?.Info($"Resource: {r.Name} has been reloaded"); };
r.DataFolder = Path.Combine(dataFolder, r.Name);
r.Reloaded += (s, e) => { r.Logger?.Info($"Resource: {r.Name} has been reloaded"); };
Directory.CreateDirectory(r.DataFolder);
foreach (var dir in Directory.GetDirectories(resDir, "*", SearchOption.AllDirectories))
{
r.Files.Add(dir, new ResourceFile()
{
IsDirectory=true,
Name=dir.Substring(resDir.Length+1).Replace('\\','/')
});;
IsDirectory = true,
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))
{
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()
{
GetStream=() => { return new FileStream(file, FileMode.Open, FileAccess.Read); },
IsDirectory=false,
Name=relativeName
GetStream = () => { return new FileStream(file, FileMode.Open, FileAccess.Read); },
IsDirectory = false,
Name = relativeName
};
if (file.EndsWith(".dll") && !relativeName.Contains('/') && IsManagedAssembly(file))
{
@ -79,9 +79,9 @@ namespace RageCoop.Server.Scripting
}
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
@ -100,12 +100,12 @@ namespace RageCoop.Server.Scripting
}
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);
if (Directory.Exists(tmpDir)) { Directory.Delete(tmpDir,true); }
tmpDir = Path.Combine(tmpDir, name);
if (Directory.Exists(tmpDir)) { Directory.Delete(tmpDir, true); }
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);
}
/// <summary>
@ -119,7 +119,7 @@ namespace RageCoop.Server.Scripting
/// <summary>
/// Get all <see cref="ServerScript"/> instance in this resource
/// </summary>
public Dictionary<string,ServerScript> Scripts { get; internal set; } = new();
public Dictionary<string, ServerScript> Scripts { get; internal set; } = new();
/// <summary>
/// Get all <see cref="ResourceFile"/> that can be used to acces files in this resource
/// </summary>
@ -145,8 +145,8 @@ namespace RageCoop.Server.Scripting
// Invoke script constructor
var script = constructor.Invoke(null) as ServerScript;
script.CurrentResource = this;
script.CurrentFile=rfile;
Scripts.Add(script.GetType().FullName,script);
script.CurrentFile = rfile;
Scripts.Add(script.GetType().FullName, script);
count++;
}
catch (Exception ex)
@ -171,7 +171,7 @@ namespace RageCoop.Server.Scripting
}
return false;
}
if(count != 0)
if (count != 0)
{
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
{

View File

@ -1,12 +1,7 @@
using System;
using RageCoop.Core;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using RageCoop.Core;
using System.Runtime.Serialization;
using System.Net;
using System.Security.Cryptography;
namespace RageCoop.Server
{
@ -15,10 +10,10 @@ namespace RageCoop.Server
private readonly Logger Logger;
public Security(Logger logger)
{
Logger= logger;
Logger = logger;
}
public RSA RSA=RSA.Create(2048);
private Dictionary<IPEndPoint, Aes> SecuredConnections = new Dictionary<IPEndPoint, Aes>();
public RSA RSA = RSA.Create(2048);
private readonly Dictionary<IPEndPoint, Aes> SecuredConnections = new Dictionary<IPEndPoint, Aes>();
public bool HasSecuredConnection(IPEndPoint target)
{
@ -27,7 +22,7 @@ namespace RageCoop.Server
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))
{
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();
}
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 iv = RSA.Decrypt(cryptedIV, RSAEncryptionPadding.Pkcs1);
@ -49,7 +44,7 @@ namespace RageCoop.Server
conAes.IV = iv;
if (!SecuredConnections.ContainsKey(endpoint))
{
SecuredConnections.Add(endpoint,conAes);
SecuredConnections.Add(endpoint, conAes);
}
else
{

View File

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

View File

@ -1,16 +1,16 @@
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Linq;
using Lidgren.Network;
using System;
using System.Collections.Generic;
using Lidgren.Network;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Xml;
using System.Xml.Serialization;
namespace RageCoop.Server
{
static partial class Util
internal static partial class Util
{
public static string DownloadString(string url)
@ -35,7 +35,7 @@ namespace RageCoop.Server
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));
}
@ -89,7 +89,7 @@ namespace RageCoop.Server
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)