Some works for the new resource system
Rewrite some parts of CustomEvent Expose some API as dll entry
This commit is contained in:
@ -49,9 +49,4 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="ScriptHookVDotNetCore">
|
|
||||||
<HintPath>..\..\libs\ScriptHookVDotNetCore.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
@ -42,6 +42,16 @@ namespace RageCoop.Client
|
|||||||
DiagnosticMenu.Add(
|
DiagnosticMenu.Add(
|
||||||
new NativeItem(pair.Key.ToString(), pair.Value.ToString(), pair.Value.ToString()));
|
new NativeItem(pair.Key.ToString(), pair.Value.ToString(), pair.Value.ToString()));
|
||||||
};
|
};
|
||||||
|
ShowNetworkInfoItem.CheckboxChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
Networking.ShowNetworkInfo = ShowNetworkInfoItem.Checked;
|
||||||
|
};
|
||||||
|
ShowOwnerItem.CheckboxChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
Main.Settings.ShowEntityOwnerName = ShowOwnerItem.Checked;
|
||||||
|
Util.SaveSettings();
|
||||||
|
};
|
||||||
|
#if DEBUG
|
||||||
SimulatedLatencyItem.Activated += (s, e) =>
|
SimulatedLatencyItem.Activated += (s, e) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -55,16 +65,8 @@ namespace RageCoop.Client
|
|||||||
Main.Logger.Error(ex);
|
Main.Logger.Error(ex);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ShowNetworkInfoItem.CheckboxChanged += (s, e) =>
|
|
||||||
{
|
|
||||||
Networking.ShowNetworkInfo = ShowNetworkInfoItem.Checked;
|
|
||||||
};
|
|
||||||
ShowOwnerItem.CheckboxChanged += (s, e) =>
|
|
||||||
{
|
|
||||||
Main.Settings.ShowEntityOwnerName = ShowOwnerItem.Checked;
|
|
||||||
Util.SaveSettings();
|
|
||||||
};
|
|
||||||
Menu.Add(SimulatedLatencyItem);
|
Menu.Add(SimulatedLatencyItem);
|
||||||
|
#endif
|
||||||
Menu.Add(ShowNetworkInfoItem);
|
Menu.Add(ShowNetworkInfoItem);
|
||||||
Menu.Add(ShowOwnerItem);
|
Menu.Add(ShowOwnerItem);
|
||||||
Menu.AddSubMenu(DiagnosticMenu);
|
Menu.AddSubMenu(DiagnosticMenu);
|
||||||
|
@ -31,7 +31,6 @@ namespace RageCoop.Client
|
|||||||
static Networking()
|
static Networking()
|
||||||
{
|
{
|
||||||
Security = new Security(Main.Logger);
|
Security = new Security(Main.Logger);
|
||||||
Packets.CustomEvent.ResolveHandle = _resolveHandle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Latency => ServerConnection.AverageRoundtripTime / 2;
|
public static float Latency => ServerConnection.AverageRoundtripTime / 2;
|
||||||
@ -65,12 +64,14 @@ namespace RageCoop.Client
|
|||||||
var config = new NetPeerConfiguration("623c92c287cc392406e7aaaac1c0f3b0")
|
var config = new NetPeerConfiguration("623c92c287cc392406e7aaaac1c0f3b0")
|
||||||
{
|
{
|
||||||
AutoFlushSendQueue = false,
|
AutoFlushSendQueue = false,
|
||||||
SimulatedMinimumLatency = SimulatedLatency,
|
|
||||||
SimulatedRandomLatency = 0,
|
|
||||||
AcceptIncomingConnections = true,
|
AcceptIncomingConnections = true,
|
||||||
MaximumConnections = 32,
|
MaximumConnections = 32,
|
||||||
PingInterval = 5
|
PingInterval = 5
|
||||||
};
|
};
|
||||||
|
#if DEBUG
|
||||||
|
config.SimulatedMinimumLatency = SimulatedLatency;
|
||||||
|
config.SimulatedRandomLatency = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
config.EnableMessageType(NetIncomingMessageType.UnconnectedData);
|
config.EnableMessageType(NetIncomingMessageType.UnconnectedData);
|
||||||
config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);
|
config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);
|
||||||
@ -153,7 +154,7 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
|
|
||||||
IsConnecting = false;
|
IsConnecting = false;
|
||||||
},"Connect");
|
}, "Connect");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,25 +12,7 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
internal static partial class Networking
|
internal static partial class Networking
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Used to reslove entity handle in a <see cref="Packets.CustomEvent" />
|
|
||||||
/// </summary>
|
|
||||||
private static readonly Func<byte, NetIncomingMessage, object> _resolveHandle = (t, reader) =>
|
|
||||||
{
|
|
||||||
switch (t)
|
|
||||||
{
|
|
||||||
case 50:
|
|
||||||
return EntityPool.ServerProps[reader.ReadInt32()].MainProp?.Handle;
|
|
||||||
case 51:
|
|
||||||
return EntityPool.GetPedByID(reader.ReadInt32())?.MainPed?.Handle;
|
|
||||||
case 52:
|
|
||||||
return EntityPool.GetVehicleByID(reader.ReadInt32())?.MainVehicle?.Handle;
|
|
||||||
case 60:
|
|
||||||
return EntityPool.ServerBlips[reader.ReadInt32()].Handle;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException("Cannot resolve server side argument: " + t);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
|
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
using System.Reflection;
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Resources;
|
using System.Resources;
|
||||||
|
|
||||||
// General Information
|
// General Information
|
||||||
@ -13,6 +16,7 @@ using System.Resources;
|
|||||||
|
|
||||||
|
|
||||||
// Version information
|
// Version information
|
||||||
[assembly: AssemblyVersion("1.6.0.24")]
|
[assembly: AssemblyVersion("1.6.0.27")]
|
||||||
[assembly: AssemblyFileVersion("1.6.0.24")]
|
[assembly: AssemblyFileVersion("1.6.0.27")]
|
||||||
[assembly: NeutralResourcesLanguageAttribute("en-US")]
|
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
||||||
|
|
||||||
|
@ -33,12 +33,6 @@
|
|||||||
<HintPath>..\..\libs\LemonUI.SHVDNC.dll</HintPath>
|
<HintPath>..\..\libs\LemonUI.SHVDNC.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="..\..\.editorconfig">
|
|
||||||
<Link>.editorconfig</Link>
|
|
||||||
</None>
|
|
||||||
<None Include="Scripting\API.Exports.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="icon.png">
|
<Content Include="icon.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
97
Client/Scripts/Scripting/API.Exports.cs
Normal file
97
Client/Scripts/Scripting/API.Exports.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
using Lidgren.Network;
|
||||||
|
using RageCoop.Core.Scripting;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using static RageCoop.Core.Scripting.CustomEvents;
|
||||||
|
|
||||||
|
namespace RageCoop.Client.Scripting
|
||||||
|
{
|
||||||
|
public static unsafe partial class API
|
||||||
|
{
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "Connect")]
|
||||||
|
public static void Connect(char* address) => Connect(new string(address));
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "GetLocalPlayerID")]
|
||||||
|
public static int GetLocalPlayerID() => LocalPlayerID;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get configuration value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="szName">The name of the config</param>
|
||||||
|
/// <param name="buf">Buffer to store retrived value</param>
|
||||||
|
/// <param name="bufSize">Buffer size</param>
|
||||||
|
/// <returns>The string length of returned value, not including the null terminator</returns>
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "GetConfigValue")]
|
||||||
|
public static int GetConfigValue(char* szName, char* buf, int bufSize)
|
||||||
|
{
|
||||||
|
var name = new string(szName);
|
||||||
|
var value = name switch
|
||||||
|
{
|
||||||
|
nameof(Config.EnableAutoRespawn) => Config.EnableAutoRespawn.ToString(),
|
||||||
|
nameof(Config.Username) => Config.Username.ToString(),
|
||||||
|
nameof(Config.BlipColor) => Config.BlipColor.ToString(),
|
||||||
|
nameof(Config.BlipScale) => Config.BlipScale.ToString(),
|
||||||
|
nameof(Config.BlipSprite) => Config.BlipSprite.ToString(),
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fixed (char* p = value)
|
||||||
|
{
|
||||||
|
var cbRequired = (value.Length + 1) * sizeof(char);
|
||||||
|
Buffer.MemoryCopy(p, buf, bufSize, cbRequired);
|
||||||
|
return value.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "SetConfigValue")]
|
||||||
|
public static void SetConfigValue(char* szName, char* szValue)
|
||||||
|
{
|
||||||
|
var name = new string(szName);
|
||||||
|
var value = new string(szValue);
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case nameof(Config.EnableAutoRespawn): Config.EnableAutoRespawn = bool.Parse(value); break;
|
||||||
|
case nameof(Config.Username): Config.Username = value; break;
|
||||||
|
case nameof(Config.BlipColor): Config.BlipColor = Enum.Parse<BlipColor>(value); break;
|
||||||
|
case nameof(Config.BlipScale): Config.BlipScale = float.Parse(value); break;
|
||||||
|
case nameof(Config.BlipSprite): Config.BlipSprite = Enum.Parse<BlipSprite>(value); break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "LocalChatMessage")]
|
||||||
|
public static void LocalChatMessage(char* from, char* msg) => LocalChatMessage(new string(from), new string(msg));
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "SendChatMessage")]
|
||||||
|
public static void SendChatMessage(char* msg) => SendChatMessage(new string(msg));
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "GetEventHash")]
|
||||||
|
public static CustomEventHash GetEventHash(char* name)=>new string(name);
|
||||||
|
|
||||||
|
public static void SendCustomEvent(int hash, CustomEventFlags flags, byte* data, int cbData)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert Entity ID to handle
|
||||||
|
/// </summary>
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "IdToHandle")]
|
||||||
|
public static int IdToHandle(byte type, int id)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
T_ID_PROP => EntityPool.GetPropByID(id)?.MainProp?.Handle ?? 0,
|
||||||
|
T_ID_PED => EntityPool.GetPedByID(id)?.MainPed?.Handle ?? 0,
|
||||||
|
T_ID_VEH => EntityPool.GetVehicleByID(id)?.MainVehicle?.Handle ?? 0,
|
||||||
|
T_ID_BLIP => EntityPool.GetBlipByID(id)?.Handle ?? 0,
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using GTA;
|
using GTA;
|
||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
@ -30,7 +31,7 @@ namespace RageCoop.Client.Scripting
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides vital functionality to interact with RAGECOOP
|
/// Provides vital functionality to interact with RAGECOOP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class API
|
public static unsafe partial class API
|
||||||
{
|
{
|
||||||
#region INTERNAL
|
#region INTERNAL
|
||||||
|
|
||||||
@ -270,6 +271,7 @@ namespace RageCoop.Client.Scripting
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnect from current server or cancel the connection attempt.
|
/// Disconnect from current server or cancel the connection attempt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[UnmanagedCallersOnly(EntryPoint = "Disconnect")]
|
||||||
public static void Disconnect()
|
public static void Disconnect()
|
||||||
{
|
{
|
||||||
if (Networking.IsOnServer || Networking.IsConnecting) Networking.ToggleConnection(null);
|
if (Networking.IsOnServer || Networking.IsConnecting) Networking.ToggleConnection(null);
|
||||||
@ -369,9 +371,9 @@ namespace RageCoop.Client.Scripting
|
|||||||
};
|
};
|
||||||
DownloadManager.DownloadCompleted += handler;
|
DownloadManager.DownloadCompleted += handler;
|
||||||
Networking.GetResponse<Packets.FileTransferResponse>(new Packets.FileTransferRequest
|
Networking.GetResponse<Packets.FileTransferResponse>(new Packets.FileTransferRequest
|
||||||
{
|
{
|
||||||
Name = name
|
Name = name
|
||||||
},
|
},
|
||||||
p =>
|
p =>
|
||||||
{
|
{
|
||||||
if (p.Response != FileResponse.Loaded)
|
if (p.Response != FileResponse.Loaded)
|
||||||
|
@ -84,14 +84,10 @@ namespace RageCoop.Client
|
|||||||
#region PEDS
|
#region PEDS
|
||||||
|
|
||||||
public static SyncedPed GetPedByID(int id)
|
public static SyncedPed GetPedByID(int id)
|
||||||
{
|
=> PedsByID.TryGetValue(id, out var p) ? p : null;
|
||||||
return PedsByID.TryGetValue(id, out var p) ? p : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SyncedPed GetPedByHandle(int handle)
|
public static SyncedPed GetPedByHandle(int handle)
|
||||||
{
|
=> PedsByHandle.TryGetValue(handle, out var p) ? p : null;
|
||||||
return PedsByHandle.TryGetValue(handle, out var p) ? p : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<int> GetPedIDs()
|
public static List<int> GetPedIDs()
|
||||||
{
|
{
|
||||||
@ -179,14 +175,10 @@ namespace RageCoop.Client
|
|||||||
#region VEHICLES
|
#region VEHICLES
|
||||||
|
|
||||||
public static SyncedVehicle GetVehicleByID(int id)
|
public static SyncedVehicle GetVehicleByID(int id)
|
||||||
{
|
=> VehiclesByID.TryGetValue(id, out var v) ? v : null;
|
||||||
return VehiclesByID.TryGetValue(id, out var v) ? v : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SyncedVehicle GetVehicleByHandle(int handle)
|
public static SyncedVehicle GetVehicleByHandle(int handle)
|
||||||
{
|
=> VehiclesByHandle.TryGetValue(handle, out var v) ? v : null;
|
||||||
return VehiclesByHandle.TryGetValue(handle, out var v) ? v : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<int> GetVehicleIDs()
|
public static List<int> GetVehicleIDs()
|
||||||
{
|
{
|
||||||
@ -233,9 +225,7 @@ namespace RageCoop.Client
|
|||||||
#region PROJECTILES
|
#region PROJECTILES
|
||||||
|
|
||||||
public static SyncedProjectile GetProjectileByID(int id)
|
public static SyncedProjectile GetProjectileByID(int id)
|
||||||
{
|
=> ProjectilesByID.TryGetValue(id, out var p) ? p : null;
|
||||||
return ProjectilesByID.TryGetValue(id, out var p) ? p : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Add(SyncedProjectile p)
|
public static void Add(SyncedProjectile p)
|
||||||
{
|
{
|
||||||
@ -290,6 +280,16 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region SERVER OBJECTS
|
||||||
|
|
||||||
|
public static SyncedProp GetPropByID(int id)
|
||||||
|
=> ServerProps.TryGetValue(id, out var p) ? p : null;
|
||||||
|
|
||||||
|
public static Blip GetBlipByID(int id)
|
||||||
|
=> ServerBlips.TryGetValue(id, out var p) ? p : null;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private static int vehStateIndex;
|
private static int vehStateIndex;
|
||||||
private static int pedStateIndex;
|
private static int pedStateIndex;
|
||||||
private static int vehStatesPerFrame;
|
private static int vehStatesPerFrame;
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using GTA.Math;
|
|
||||||
|
|
||||||
namespace RageCoop.Core
|
|
||||||
{
|
|
||||||
internal class BitReader : BinaryReader
|
|
||||||
{
|
|
||||||
public BitReader(byte[] array) : base(new MemoryStream(array))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~BitReader()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] ReadByteArray()
|
|
||||||
{
|
|
||||||
return base.ReadBytes(ReadInt32());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ReadString()
|
|
||||||
{
|
|
||||||
return Encoding.UTF8.GetString(ReadBytes(ReadInt32()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3 ReadVector3()
|
|
||||||
{
|
|
||||||
return new Vector3
|
|
||||||
{
|
|
||||||
X = ReadSingle(),
|
|
||||||
Y = ReadSingle(),
|
|
||||||
Z = ReadSingle()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 ReadVector2()
|
|
||||||
{
|
|
||||||
return new Vector2
|
|
||||||
{
|
|
||||||
X = ReadSingle(),
|
|
||||||
Y = ReadSingle()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Quaternion ReadQuaternion()
|
|
||||||
{
|
|
||||||
return new Quaternion
|
|
||||||
{
|
|
||||||
X = ReadSingle(),
|
|
||||||
Y = ReadSingle(),
|
|
||||||
Z = ReadSingle(),
|
|
||||||
W = ReadSingle()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
135
Core/Buffer.cs
135
Core/Buffer.cs
@ -5,10 +5,21 @@ using GTA.Math;
|
|||||||
|
|
||||||
namespace RageCoop.Core
|
namespace RageCoop.Core
|
||||||
{
|
{
|
||||||
internal unsafe abstract class BufferBase
|
public unsafe abstract class BufferBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Size of this buffer in memory
|
||||||
|
/// </summary>
|
||||||
public int Size { get; protected set; }
|
public int Size { get; protected set; }
|
||||||
public int CurrentIndex { get; protected set; }
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current read/write index
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pointer to the start of this buffer
|
||||||
|
/// </summary>
|
||||||
public byte* Address { get; protected set; }
|
public byte* Address { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -20,9 +31,17 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
protected T* Alloc<T>(int count = 1) where T : unmanaged
|
protected T* Alloc<T>(int count = 1) where T : unmanaged
|
||||||
=> (T*)Alloc(count * sizeof(T));
|
=> (T*)Alloc(count * sizeof(T));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset position to the start of this buffer
|
||||||
|
/// </summary>
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Position = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal unsafe sealed class WriteBuffer : BufferBase
|
public unsafe sealed class WriteBuffer : BufferBase
|
||||||
{
|
{
|
||||||
public WriteBuffer(int size)
|
public WriteBuffer(int size)
|
||||||
{
|
{
|
||||||
@ -49,12 +68,12 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
protected override byte* Alloc(int cbSize)
|
protected override byte* Alloc(int cbSize)
|
||||||
{
|
{
|
||||||
var index = CurrentIndex;
|
var index = Position;
|
||||||
CurrentIndex += cbSize;
|
Position += cbSize;
|
||||||
|
|
||||||
// Resize the buffer by at least 50% if there's no sufficient space
|
// Resize the buffer by at least 50% if there's no sufficient space
|
||||||
if (CurrentIndex > Size)
|
if (Position > Size)
|
||||||
Resize(Math.Max(CurrentIndex + 1, (int)(Size * 1.5f)));
|
Resize(Math.Max(Position + 1, (int)(Size * 1.5f)));
|
||||||
|
|
||||||
return Address + index;
|
return Address + index;
|
||||||
}
|
}
|
||||||
@ -113,22 +132,83 @@ namespace RageCoop.Core
|
|||||||
faddr[2] = quat.Z;
|
faddr[2] = quat.Z;
|
||||||
faddr[3] = quat.W;
|
faddr[3] = quat.W;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Write<T>(ReadOnlySpan<T> source) where T : unmanaged
|
||||||
|
{
|
||||||
|
var len = source.Length;
|
||||||
|
fixed (T* pSource = source)
|
||||||
|
{
|
||||||
|
Buffer.MemoryCopy(pSource, Alloc(sizeof(T) * len), len, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write<T>(Span<T> source) where T : unmanaged => Write((ReadOnlySpan<T>)source);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write an array, prefix the data with its length so it can latter be read using <see cref="ReadBuffer.ReadArray{T}"/>
|
||||||
|
/// </summary>
|
||||||
|
public void WriteArray<T>(T[] values) where T : unmanaged
|
||||||
|
{
|
||||||
|
var len = values.Length;
|
||||||
|
WriteVal(len);
|
||||||
|
fixed (T* pFrom = values)
|
||||||
|
{
|
||||||
|
Buffer.MemoryCopy(pFrom, Alloc(sizeof(T) * len), len, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allocate a byte array on managed heap and copy the data of specified size to it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cbSize"></param>
|
||||||
|
/// <returns>The newly created managed byte array</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
|
public byte[] ToByteArray(int cbSize)
|
||||||
|
{
|
||||||
|
if (cbSize > Size)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(cbSize));
|
||||||
|
|
||||||
|
var result = new byte[cbSize];
|
||||||
|
fixed (byte* pResult = result)
|
||||||
|
{
|
||||||
|
Buffer.MemoryCopy(Address, pResult, Size, Size);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Free the associated memory allocated on the unmanaged heap
|
||||||
|
/// </summary>
|
||||||
|
public void Free() => Marshal.FreeHGlobal((IntPtr)Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal unsafe sealed class ReadBuffer : BufferBase
|
public unsafe sealed class ReadBuffer : BufferBase
|
||||||
{
|
{
|
||||||
public ReadBuffer(byte* address, int size)
|
/// <summary>
|
||||||
|
/// Initialize an empty instance, needs to call <see cref="Initialise(byte*, int)"/> before reading data
|
||||||
|
/// </summary>
|
||||||
|
public ReadBuffer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public ReadBuffer(byte* address, int size) => Initialise(address, size);
|
||||||
|
|
||||||
|
public void Initialise(byte* address, int size)
|
||||||
{
|
{
|
||||||
Address = address;
|
Address = address;
|
||||||
Size = size;
|
Size = size;
|
||||||
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override byte* Alloc(int cbSize)
|
protected override byte* Alloc(int cbSize)
|
||||||
{
|
{
|
||||||
var index = CurrentIndex;
|
if (Address == null)
|
||||||
CurrentIndex += cbSize;
|
throw new NullReferenceException("Address is null");
|
||||||
|
|
||||||
if (CurrentIndex > Size)
|
var index = Position;
|
||||||
|
Position += cbSize;
|
||||||
|
|
||||||
|
if (Position > Size)
|
||||||
throw new InvalidOperationException("Attempting to read beyond the existing buffer");
|
throw new InvalidOperationException("Attempting to read beyond the existing buffer");
|
||||||
|
|
||||||
return Address + index;
|
return Address + index;
|
||||||
@ -178,5 +258,36 @@ namespace RageCoop.Core
|
|||||||
W = faddr[3],
|
W = faddr[3],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a span of type <typeparamref name="T"/> from current position to <paramref name="destination"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="destination"></param>
|
||||||
|
public void Read<T>(Span<T> destination) where T : unmanaged
|
||||||
|
{
|
||||||
|
var len = destination.Length;
|
||||||
|
fixed (T* pTo = destination)
|
||||||
|
{
|
||||||
|
Buffer.MemoryCopy(Alloc(len * sizeof(T)), pTo, len, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads an array previously written using <see cref="WriteBuffer.WriteArray{T}(T[])"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public T[] ReadArray<T>() where T : unmanaged
|
||||||
|
{
|
||||||
|
var len = ReadVal<int>();
|
||||||
|
var from = Alloc<T>(len);
|
||||||
|
var result = new T[len];
|
||||||
|
fixed (T* pTo = result)
|
||||||
|
{
|
||||||
|
Buffer.MemoryCopy(from, pTo, len, len);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ namespace RageCoop.Core
|
|||||||
{
|
{
|
||||||
internal class CustomEvent : Packet
|
internal class CustomEvent : Packet
|
||||||
{
|
{
|
||||||
public static Func<byte, NetIncomingMessage, object> ResolveHandle = null;
|
|
||||||
public CustomEventFlags Flags;
|
public CustomEventFlags Flags;
|
||||||
|
|
||||||
public CustomEvent(CustomEventFlags flags = CustomEventFlags.None)
|
public CustomEvent(CustomEventFlags flags = CustomEventFlags.None)
|
||||||
@ -19,77 +18,36 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
public override PacketType Type => PacketType.CustomEvent;
|
public override PacketType Type => PacketType.CustomEvent;
|
||||||
public int Hash { get; set; }
|
public int Hash { get; set; }
|
||||||
public object[] Args { get; set; }
|
public byte[] Payload;
|
||||||
|
public object[] Args;
|
||||||
|
|
||||||
protected override void Serialize(NetOutgoingMessage m)
|
protected override void Serialize(NetOutgoingMessage m)
|
||||||
{
|
{
|
||||||
Args = Args ?? new object[] { };
|
|
||||||
m.Write((byte)Flags);
|
m.Write((byte)Flags);
|
||||||
m.Write(Hash);
|
m.Write(Hash);
|
||||||
m.Write(Args.Length);
|
if (Args != null)
|
||||||
foreach (var arg in Args) CoreUtils.GetBytesFromObject(arg, m);
|
{
|
||||||
|
lock (WriteBufferShared)
|
||||||
|
{
|
||||||
|
WriteBufferShared.Reset();
|
||||||
|
CustomEvents.WriteObjects(WriteBufferShared, Args);
|
||||||
|
Payload = WriteBufferShared.ToByteArray(WriteBufferShared.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.Write(Payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Deserialize(NetIncomingMessage m)
|
public unsafe override void Deserialize(NetIncomingMessage m)
|
||||||
{
|
{
|
||||||
Flags = (CustomEventFlags)m.ReadByte();
|
Flags = (CustomEventFlags)m.ReadByte();
|
||||||
Hash = m.ReadInt32();
|
Hash = m.ReadInt32();
|
||||||
Args = new object[m.ReadInt32()];
|
Payload = m.ReadBytes(m.LengthBytes - m.PositionInBytes);
|
||||||
for (var i = 0; i < Args.Length; i++)
|
fixed (byte* p = Payload)
|
||||||
{
|
{
|
||||||
var type = m.ReadByte();
|
lock (ReadBufferShared)
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case 0x01:
|
ReadBufferShared.Initialise(p,Payload.Length);
|
||||||
Args[i] = m.ReadByte();
|
Args = CustomEvents.ReadObjects(ReadBufferShared);
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
Args[i] = m.ReadInt32();
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
Args[i] = m.ReadUInt16();
|
|
||||||
break;
|
|
||||||
case 0x04:
|
|
||||||
Args[i] = m.ReadInt32();
|
|
||||||
break;
|
|
||||||
case 0x05:
|
|
||||||
Args[i] = m.ReadUInt32();
|
|
||||||
break;
|
|
||||||
case 0x06:
|
|
||||||
Args[i] = m.ReadInt64();
|
|
||||||
break;
|
|
||||||
case 0x07:
|
|
||||||
Args[i] = m.ReadUInt64();
|
|
||||||
break;
|
|
||||||
case 0x08:
|
|
||||||
Args[i] = m.ReadFloat();
|
|
||||||
break;
|
|
||||||
case 0x09:
|
|
||||||
Args[i] = m.ReadBoolean();
|
|
||||||
break;
|
|
||||||
case 0x10:
|
|
||||||
Args[i] = m.ReadString();
|
|
||||||
break;
|
|
||||||
case 0x11:
|
|
||||||
Args[i] = m.ReadVector3();
|
|
||||||
break;
|
|
||||||
case 0x12:
|
|
||||||
Args[i] = m.ReadQuaternion();
|
|
||||||
break;
|
|
||||||
case 0x13:
|
|
||||||
Args[i] = (Model)m.ReadInt32();
|
|
||||||
break;
|
|
||||||
case 0x14:
|
|
||||||
Args[i] = m.ReadVector2();
|
|
||||||
break;
|
|
||||||
case 0x15:
|
|
||||||
Args[i] = m.ReadByteArray();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (ResolveHandle == null) throw new InvalidOperationException($"Unexpected type: {type}");
|
|
||||||
|
|
||||||
Args[i] = ResolveHandle(type, m);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,9 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
internal abstract class Packet : IPacket
|
internal abstract class Packet : IPacket
|
||||||
{
|
{
|
||||||
|
public static WriteBuffer WriteBufferShared = new(1024);
|
||||||
|
public static ReadBuffer ReadBufferShared = new();
|
||||||
|
|
||||||
public abstract PacketType Type { get; }
|
public abstract PacketType Type { get; }
|
||||||
|
|
||||||
public virtual void Deserialize(NetIncomingMessage m)
|
public virtual void Deserialize(NetIncomingMessage m)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
using System;
|
using GTA;
|
||||||
|
using GTA.Math;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@ -94,7 +97,7 @@ namespace RageCoop.Core.Scripting
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class CustomEvents
|
public static partial class CustomEvents
|
||||||
{
|
{
|
||||||
internal static readonly CustomEventHash OnPlayerDied = "RageCoop.OnPlayerDied";
|
internal static readonly CustomEventHash OnPlayerDied = "RageCoop.OnPlayerDied";
|
||||||
internal static readonly CustomEventHash SetWeather = "RageCoop.SetWeather";
|
internal static readonly CustomEventHash SetWeather = "RageCoop.SetWeather";
|
||||||
@ -116,17 +119,177 @@ namespace RageCoop.Core.Scripting
|
|||||||
internal static readonly CustomEventHash WeatherTimeSync = "RageCoop.WeatherTimeSync";
|
internal static readonly CustomEventHash WeatherTimeSync = "RageCoop.WeatherTimeSync";
|
||||||
internal static readonly CustomEventHash IsHost = "RageCoop.IsHost";
|
internal static readonly CustomEventHash IsHost = "RageCoop.IsHost";
|
||||||
|
|
||||||
/// <summary>
|
#region TYPE CONSTANTS
|
||||||
/// Get event hash from string.
|
|
||||||
/// </summary>
|
public const byte T_BYTE = 1;
|
||||||
/// <returns></returns>
|
public const byte T_SHORT = 2;
|
||||||
/// <remarks>
|
public const byte T_USHORT = 3;
|
||||||
/// This method is obsoete, you should use implicit operator or <see cref="CustomEventHash.FromString(string)" />
|
public const byte T_INT = 4;
|
||||||
/// </remarks>
|
public const byte T_UINT = 5;
|
||||||
[Obsolete]
|
public const byte T_LONG = 6;
|
||||||
public static int Hash(string s)
|
public const byte T_ULONG = 7;
|
||||||
|
public const byte T_FLOAT = 8;
|
||||||
|
public const byte T_BOOL = 9;
|
||||||
|
public const byte T_STR = 10;
|
||||||
|
public const byte T_VEC3 = 11;
|
||||||
|
public const byte T_QUAT = 12;
|
||||||
|
public const byte T_MODEL = 13;
|
||||||
|
public const byte T_VEC2 = 14;
|
||||||
|
public const byte T_BYTEARR = 15;
|
||||||
|
public const byte T_ID_PROP = 50;
|
||||||
|
public const byte T_ID_PED = 51;
|
||||||
|
public const byte T_ID_VEH = 52;
|
||||||
|
public const byte T_ID_BLIP = 60;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static void WriteObjects(WriteBuffer b, params object[] objs)
|
||||||
{
|
{
|
||||||
return CustomEventHash.FromString(s);
|
b.WriteVal(objs.Length);
|
||||||
|
foreach(var obj in objs)
|
||||||
|
{
|
||||||
|
switch (obj)
|
||||||
|
{
|
||||||
|
case byte value:
|
||||||
|
b.WriteVal(T_BYTE);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case short value:
|
||||||
|
b.WriteVal(T_SHORT);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case ushort value:
|
||||||
|
b.WriteVal(T_USHORT);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case int value:
|
||||||
|
b.WriteVal(T_INT);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case uint value:
|
||||||
|
b.WriteVal(T_UINT);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case long value:
|
||||||
|
b.WriteVal(T_LONG);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case ulong value:
|
||||||
|
b.WriteVal(T_ULONG);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case float value:
|
||||||
|
b.WriteVal(T_FLOAT);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case bool value:
|
||||||
|
b.WriteVal(T_BOOL);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case string value:
|
||||||
|
b.WriteVal(T_STR);
|
||||||
|
b.Write(value);
|
||||||
|
break;
|
||||||
|
case Vector2 value:
|
||||||
|
b.WriteVal(T_VEC2);
|
||||||
|
b.Write(ref value);
|
||||||
|
break;
|
||||||
|
case Vector3 value:
|
||||||
|
b.WriteVal(T_VEC3);
|
||||||
|
b.Write(ref value);
|
||||||
|
break;
|
||||||
|
case Quaternion value:
|
||||||
|
b.WriteVal(T_QUAT);
|
||||||
|
b.Write(ref value);
|
||||||
|
break;
|
||||||
|
case Model value:
|
||||||
|
b.WriteVal(T_MODEL);
|
||||||
|
b.WriteVal(value);
|
||||||
|
break;
|
||||||
|
case byte[] value:
|
||||||
|
b.WriteVal(T_BYTEARR);
|
||||||
|
b.WriteArray(value);
|
||||||
|
break;
|
||||||
|
case Tuple<byte, byte[]> value:
|
||||||
|
b.WriteVal(value.Item1);
|
||||||
|
b.Write(new ReadOnlySpan<byte>(value.Item2));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Unsupported object type: " + obj.GetType());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
public static object[] ReadObjects(ReadBuffer r)
|
||||||
|
{
|
||||||
|
var Args = new object[r.ReadVal<int>()];
|
||||||
|
for (var i = 0; i < Args.Length; i++)
|
||||||
|
{
|
||||||
|
var type = r.ReadVal<byte>();
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case T_BYTE:
|
||||||
|
Args[i] = r.ReadVal<byte>();
|
||||||
|
break;
|
||||||
|
case T_SHORT:
|
||||||
|
Args[i] = r.ReadVal<short>();
|
||||||
|
break;
|
||||||
|
case T_USHORT:
|
||||||
|
Args[i] = r.ReadVal<ushort>();
|
||||||
|
break;
|
||||||
|
case T_INT:
|
||||||
|
Args[i] = r.ReadVal<int>();
|
||||||
|
break;
|
||||||
|
case T_UINT:
|
||||||
|
Args[i] = r.ReadVal<uint>();
|
||||||
|
break;
|
||||||
|
case T_LONG:
|
||||||
|
Args[i] = r.ReadVal<long>();
|
||||||
|
break;
|
||||||
|
case T_ULONG:
|
||||||
|
Args[i] = r.ReadVal<ulong>();
|
||||||
|
break;
|
||||||
|
case T_FLOAT:
|
||||||
|
Args[i] = r.ReadVal<float>();
|
||||||
|
break;
|
||||||
|
case T_BOOL:
|
||||||
|
Args[i] = r.ReadVal<bool>();
|
||||||
|
break;
|
||||||
|
case T_STR:
|
||||||
|
r.Read(out string str);
|
||||||
|
Args[i] = str;
|
||||||
|
break;
|
||||||
|
case T_VEC3:
|
||||||
|
r.Read(out Vector3 vec);
|
||||||
|
Args[i] = vec;
|
||||||
|
break;
|
||||||
|
case T_QUAT:
|
||||||
|
r.Read(out Quaternion quat);
|
||||||
|
Args[i] = quat;
|
||||||
|
break;
|
||||||
|
case T_MODEL:
|
||||||
|
Args[i] = r.ReadVal<Model>();
|
||||||
|
break;
|
||||||
|
case T_VEC2:
|
||||||
|
r.Read(out Vector2 vec2);
|
||||||
|
Args[i] = vec2;
|
||||||
|
break;
|
||||||
|
case T_BYTEARR:
|
||||||
|
Args[i] = r.ReadArray<byte>();
|
||||||
|
break;
|
||||||
|
case T_ID_BLIP:
|
||||||
|
case T_ID_PED:
|
||||||
|
case T_ID_PROP:
|
||||||
|
case T_ID_VEH:
|
||||||
|
Args[i] = IdToHandle(type,r.ReadVal<int>());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Unexpected type: {type}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Args;
|
||||||
|
}
|
||||||
|
|
||||||
|
[LibraryImport("RageCoop.Client.dll")]
|
||||||
|
public static partial int IdToHandle(byte type,int id);
|
||||||
}
|
}
|
||||||
}
|
}
|
54
Core/XSpan.cs
Normal file
54
Core/XSpan.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RageCoop.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A light-weight and less restricted implementation of <see cref="Span{T}"/>, gonna be used at some point, maybe?
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public readonly unsafe struct XSpan<T> where T : unmanaged
|
||||||
|
{
|
||||||
|
public XSpan(void* address, int len)
|
||||||
|
{
|
||||||
|
Address = (T*)address;
|
||||||
|
Length = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T this[int i]
|
||||||
|
{
|
||||||
|
get { return Address[i]; }
|
||||||
|
set { Address[i] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly T* Address;
|
||||||
|
public readonly int Length;
|
||||||
|
|
||||||
|
public void CopyTo(XSpan<T> dest, int destStart = 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Length; i++)
|
||||||
|
{
|
||||||
|
dest[destStart + i] = this[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public XSpan<byte> Slice(int start) => new(Address + start, Length - start);
|
||||||
|
public XSpan<byte> Slice(int start, int len) => new(Address + start, len);
|
||||||
|
|
||||||
|
public static implicit operator Span<T>(XSpan<T> s)
|
||||||
|
{
|
||||||
|
return new Span<T>(s.Address, s.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator XSpan<T>(Span<T> s)
|
||||||
|
{
|
||||||
|
fixed (T* ptr = s)
|
||||||
|
{
|
||||||
|
return new XSpan<T>(ptr, s.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
RageCoop.Client.Scripting/API.cs
Normal file
7
RageCoop.Client.Scripting/API.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace RageCoop.Client.Scripting
|
||||||
|
{
|
||||||
|
public static class API
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
12
RageCoop.Client.Scripting/ClientScript.cs
Normal file
12
RageCoop.Client.Scripting/ClientScript.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RageCoop.Client.Scripting
|
||||||
|
{
|
||||||
|
internal class ClientScript
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
13
RageCoop.Client.Scripting/RageCoop.Client.Scripting.csproj
Normal file
13
RageCoop.Client.Scripting/RageCoop.Client.Scripting.csproj
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Core\RageCoop.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -15,7 +15,7 @@ using System.Resources;
|
|||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// Version information
|
// Version information
|
||||||
[assembly: AssemblyVersion("1.6.0.25")]
|
[assembly: AssemblyVersion("1.6.0.28")]
|
||||||
[assembly: AssemblyFileVersion("1.6.0.25")]
|
[assembly: AssemblyFileVersion("1.6.0.28")]
|
||||||
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ using GTA.Math;
|
|||||||
using GTA.Native;
|
using GTA.Native;
|
||||||
using RageCoop.Core;
|
using RageCoop.Core;
|
||||||
using RageCoop.Core.Scripting;
|
using RageCoop.Core.Scripting;
|
||||||
|
using static RageCoop.Core.Scripting.CustomEvents;
|
||||||
|
|
||||||
namespace RageCoop.Server.Scripting;
|
namespace RageCoop.Server.Scripting;
|
||||||
|
|
||||||
@ -78,11 +79,11 @@ public abstract class ServerObject
|
|||||||
switch (this)
|
switch (this)
|
||||||
{
|
{
|
||||||
case ServerProp _:
|
case ServerProp _:
|
||||||
return 50;
|
return T_ID_PROP;
|
||||||
case ServerPed _:
|
case ServerPed _:
|
||||||
return 51;
|
return T_ID_PED;
|
||||||
case ServerVehicle _:
|
case ServerVehicle _:
|
||||||
return 52;
|
return T_ID_VEH;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@ -280,7 +281,7 @@ public class ServerBlip
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
|
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Tuple<byte, byte[]> Handle => new(60, BitConverter.GetBytes(ID));
|
public Tuple<byte, byte[]> Handle => new(T_ID_BLIP, BitConverter.GetBytes(ID));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Network ID (not handle!)
|
/// Network ID (not handle!)
|
||||||
|
@ -39,7 +39,7 @@ namespace UnitTest
|
|||||||
buf.Write(e.str);
|
buf.Write(e.str);
|
||||||
}
|
}
|
||||||
Console.WriteLine($"Buffer size: {buf.Size}");
|
Console.WriteLine($"Buffer size: {buf.Size}");
|
||||||
Console.WriteLine($"Current position: {buf.CurrentIndex}");
|
Console.WriteLine($"Current position: {buf.Position}");
|
||||||
|
|
||||||
Console.WriteLine("Validating data");
|
Console.WriteLine("Validating data");
|
||||||
var reader = new ReadBuffer(buf.Address, buf.Size);
|
var reader = new ReadBuffer(buf.Address, buf.Size);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@ -11,10 +11,4 @@
|
|||||||
<ProjectReference Include="..\..\Core\RageCoop.Core.csproj" />
|
<ProjectReference Include="..\..\Core\RageCoop.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="ScriptHookVDotNetCore">
|
|
||||||
<HintPath>..\..\libs\ScriptHookVDotNetCore.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
Reference in New Issue
Block a user