We're almost here...
This commit is contained in:
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
ReloadKey=None
|
||||
ConsoleKey=F4
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,7 @@ namespace RageCoop.Client
|
||||
internal static RelationshipGroup SyncedPedsGroup;
|
||||
|
||||
internal static new Settings Settings = null;
|
||||
internal static Scripting.BaseScript BaseScript=new Scripting.BaseScript();
|
||||
|
||||
#if !NON_INTERACTIVE
|
||||
#endif
|
||||
@ -55,8 +56,7 @@ namespace RageCoop.Client
|
||||
#endif
|
||||
};
|
||||
Resources = new Scripting.Resources();
|
||||
// Required for some synchronization!
|
||||
/*if (Game.Version < GameVersion.v1_0_1290_1_Steam)
|
||||
if (Game.Version < GameVersion.v1_0_1290_1_Steam)
|
||||
{
|
||||
Tick += (object sender, EventArgs e) =>
|
||||
{
|
||||
@ -72,7 +72,8 @@ namespace RageCoop.Client
|
||||
}
|
||||
};
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
BaseScript.OnStart();
|
||||
SyncedPedsGroup=World.AddRelationshipGroup("SYNCPED");
|
||||
Game.Player.Character.RelationshipGroup.SetRelationshipBetweenGroups(SyncedPedsGroup, Relationship.Neutral, true);
|
||||
#if !NON_INTERACTIVE
|
||||
@ -157,11 +158,13 @@ namespace RageCoop.Client
|
||||
if (!Scripting.API.Config.EnableAutoRespawn)
|
||||
{
|
||||
Function.Call(Hash.PAUSE_DEATH_ARREST_RESTART, true);
|
||||
Function.Call(Hash.IGNORE_NEXT_RESTART, true);
|
||||
Function.Call(Hash.FORCE_GAME_STATE_PLAYING);
|
||||
Function.Call(Hash.TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME, "respawn_controller");
|
||||
|
||||
var P = Game.Player.Character;
|
||||
if (P.IsDead)
|
||||
{
|
||||
Function.Call(Hash.TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME, "respawn_controller");
|
||||
Function.Call(Hash.SET_FADE_OUT_AFTER_DEATH, false);
|
||||
|
||||
if (P.Health!=1)
|
||||
|
@ -126,7 +126,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
var packet = new Packets.PlayerInfoUpdate();
|
||||
packet.Unpack(data);
|
||||
PlayerList.SetPlayer(packet.PedID, packet.Username, packet.Latency);
|
||||
PlayerList.UpdatePlayer(packet);
|
||||
break;
|
||||
}
|
||||
#region ENTITY SYNC
|
||||
@ -210,7 +210,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
Packets.CustomEvent packet = new Packets.CustomEvent();
|
||||
packet.Unpack(data);
|
||||
Scripting.API.Events.InvokeCustomEventReceived(packet.Hash, packet.Args);
|
||||
Scripting.API.Events.InvokeCustomEventReceived(packet);
|
||||
}
|
||||
break;
|
||||
case PacketTypes.FileTransferChunk:
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using GTA;
|
||||
using GTA.Math;
|
||||
using RageCoop.Core;
|
||||
using GTA.Native;
|
||||
|
||||
namespace RageCoop.Client
|
||||
@ -15,7 +16,7 @@ namespace RageCoop.Client
|
||||
public static ulong Pressed { get; set; }
|
||||
|
||||
public static bool LeftAlign = true;
|
||||
public static List<PlayerData> Players=new List<PlayerData> { };
|
||||
public static Dictionary<int,PlayerData> Players=new Dictionary<int, PlayerData> { };
|
||||
public static void Tick()
|
||||
{
|
||||
if (!Networking.IsOnServer)
|
||||
@ -52,7 +53,7 @@ namespace RageCoop.Client
|
||||
|
||||
foreach (var player in Players)
|
||||
{
|
||||
_mainScaleform.CallFunction("SET_DATA_SLOT", i++, $"{player.Latency * 1000:N0}ms", player.Username, 116, 0, i - 1, "", "", 2, "", "", ' ');
|
||||
_mainScaleform.CallFunction("SET_DATA_SLOT", i++, $"{player.Value.Latency * 1000:N0}ms", player.Value.Username, 116, 0, i - 1, "", "", 2, "", "", ' ');
|
||||
}
|
||||
|
||||
_mainScaleform.CallFunction("SET_TITLE", "Player list", $"{Players.Count+1} players");
|
||||
@ -61,43 +62,67 @@ namespace RageCoop.Client
|
||||
public static void SetPlayer(int id, string username,float latency=0)
|
||||
{
|
||||
|
||||
var toset = Players.Where(x => x.PedID==id);
|
||||
if (toset.Any())
|
||||
PlayerData p;
|
||||
if (Players.TryGetValue(id,out p))
|
||||
{
|
||||
var p=toset.First();
|
||||
p.Username=username;
|
||||
p.PedID=id;
|
||||
p.Latency=latency;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerData p = new PlayerData { PedID=id, Username=username,Latency=latency };
|
||||
Players.Add(p);
|
||||
p = new PlayerData { PedID=id, Username=username,Latency=latency };
|
||||
Players.Add(id,p);
|
||||
}
|
||||
}
|
||||
public static void UpdatePlayer(Packets.PlayerInfoUpdate packet)
|
||||
{
|
||||
var p = GetPlayer(packet.PedID);
|
||||
if(p?.Character != null)
|
||||
{
|
||||
p.Character.DisplayNameTag=packet.Flags.HasConfigFlag(PlayerConfigFlags.ShowNameTag);
|
||||
p.Character.DisplayBlip=packet.Flags.HasConfigFlag(PlayerConfigFlags.ShowBlip);
|
||||
Main.Logger.Info($"blip color:{packet.BlipColor}");
|
||||
// Need to be dispatched to script thread.
|
||||
Main.QueueAction(() => {
|
||||
if (p.Character.PedBlip!=null && p.Character.PedBlip.Exists() && p.Character.PedBlip.Color!=packet.BlipColor)
|
||||
{
|
||||
p.Character.PedBlip.Color=packet.BlipColor;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
public static PlayerData GetPlayer(int id)
|
||||
{
|
||||
return Players.Find(x => x.PedID==id);
|
||||
PlayerData p;
|
||||
Players.TryGetValue(id, out p);
|
||||
return p;
|
||||
}
|
||||
public static PlayerData GetPlayer(SyncedPed p)
|
||||
{
|
||||
var player = GetPlayer(p.ID);
|
||||
player.Character=p;
|
||||
return player;
|
||||
}
|
||||
public static void RemovePlayer(int id)
|
||||
{
|
||||
var p = Players.Where(x => x.PedID==id);
|
||||
if (p.Any())
|
||||
if (Players.ContainsKey(id))
|
||||
{
|
||||
Players.Remove(p.First());
|
||||
Players.Remove(id);
|
||||
}
|
||||
}
|
||||
public static void Cleanup()
|
||||
{
|
||||
Players=new List<PlayerData> { };
|
||||
Players=new Dictionary<int, PlayerData>{ };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class PlayerData
|
||||
|
||||
internal class PlayerData
|
||||
{
|
||||
public string Username { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Universal character ID.
|
||||
/// </summary>
|
||||
@ -105,17 +130,11 @@ namespace RageCoop.Client
|
||||
{
|
||||
get; internal set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ID of player's last vehicle.
|
||||
/// </summary>
|
||||
public int VehicleID { get; internal set; }
|
||||
public Vector3 Position { get; internal set; }
|
||||
|
||||
public SyncedPed Character { get; set; }
|
||||
/// <summary>
|
||||
/// Player Latency in second.
|
||||
/// </summary>
|
||||
public float Latency { get; internal set; }
|
||||
public int Health { get; internal set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -21,20 +21,19 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RageCoop.Core\RageCoop.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="LemonUI.SHVDN3">
|
||||
<HintPath>..\Libs\Release\scripts\LemonUI.SHVDN3.dll</HintPath>
|
||||
<HintPath>..\libs\LemonUI.SHVDN3.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\Libs\Release\scripts\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\libs\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ScriptHookVDotNet3">
|
||||
<HintPath>..\Libs\Release\ScriptHookVDotNet3.dll</HintPath>
|
||||
<HintPath>..\libs\ScriptHookVDotNet3.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
|
@ -6,11 +6,19 @@ using RageCoop.Core;
|
||||
|
||||
namespace RageCoop.Client.Scripting
|
||||
{
|
||||
public class CustomEventReceivedArgs : EventArgs
|
||||
{
|
||||
public int Hash { get; set; }
|
||||
public List<object> Args { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Provides vital functionality to interact with RAGECOOP
|
||||
/// </summary>
|
||||
public static class API
|
||||
{
|
||||
#region INTERNAL
|
||||
internal static Dictionary<int, List<Action<CustomEventReceivedArgs>>> CustomEventHandlers = new Dictionary<int, List<Action<CustomEventReceivedArgs>>>();
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// Client configuration, this will conflict with server-side config.
|
||||
/// </summary>
|
||||
@ -75,10 +83,6 @@ namespace RageCoop.Client.Scripting
|
||||
/// </summary>
|
||||
public static event EmptyEvent OnTick;
|
||||
|
||||
/// <summary>
|
||||
/// This will be invoked when a CustomEvent is received from the server.
|
||||
/// </summary>
|
||||
public static event CustomEvent OnCustomEventReceived;
|
||||
|
||||
#region INVOKE
|
||||
internal static void InvokeVehicleSpawned(SyncedVehicle v) { OnVehicleSpawned?.Invoke(null, v); }
|
||||
@ -88,9 +92,14 @@ namespace RageCoop.Client.Scripting
|
||||
internal static void InvokePlayerDied() { OnPlayerDied?.Invoke(); }
|
||||
internal static void InvokeTick() { OnTick?.Invoke(); }
|
||||
|
||||
internal static void InvokeCustomEventReceived(int hash, List<object> args)
|
||||
internal static void InvokeCustomEventReceived(Packets.CustomEvent p)
|
||||
{
|
||||
OnCustomEventReceived?.Invoke(hash, args);
|
||||
var args = new CustomEventReceivedArgs() { Hash=p.Hash, Args=p.Args};
|
||||
List<Action<CustomEventReceivedArgs>> handlers;
|
||||
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
|
||||
{
|
||||
handlers.ForEach((x) => { x.Invoke(args); });
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
internal static void ClearHandlers()
|
||||
@ -101,7 +110,6 @@ namespace RageCoop.Client.Scripting
|
||||
OnPedSpawned=null;
|
||||
OnVehicleDeleted=null;
|
||||
OnVehicleSpawned=null;
|
||||
OnCustomEventReceived=null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,6 +212,24 @@ namespace RageCoop.Client.Scripting
|
||||
Networking.Send(p, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an handler to the specifed event hash, one event can have multiple handlers. This will be invoked from backgound thread, use <see cref="QueueAction(Action)"/> in the handler to dispatch code to script thread.
|
||||
/// </summary>
|
||||
/// <param name="hash">An unique identifier of the event, you can hash your event name with <see cref="Core.Scripting.CustomEvents.Hash(string)"/></param>
|
||||
/// <param name="handler">An handler to be invoked when the event is received from the server. </param>
|
||||
public static void RegisterCustomEventHandler(int hash, Action<CustomEventReceivedArgs> handler)
|
||||
{
|
||||
List<Action<CustomEventReceivedArgs>> handlers;
|
||||
lock (CustomEventHandlers)
|
||||
{
|
||||
if (!CustomEventHandlers.TryGetValue(hash, out handlers))
|
||||
{
|
||||
CustomEventHandlers.Add(hash, handlers = new List<Action<CustomEventReceivedArgs>>());
|
||||
}
|
||||
handlers.Add(handler);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
25
RageCoop.Client/Scripting/BaseScript.cs
Normal file
25
RageCoop.Client/Scripting/BaseScript.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using RageCoop.Core.Scripting;
|
||||
|
||||
namespace RageCoop.Client.Scripting
|
||||
{
|
||||
internal class BaseScript : ClientScript
|
||||
{
|
||||
public override void OnStart()
|
||||
{
|
||||
API.RegisterCustomEventHandler(CustomEvents.SetAutoRespawn,SetAutoRespawn);
|
||||
}
|
||||
|
||||
public override void OnStop()
|
||||
{
|
||||
}
|
||||
void SetAutoRespawn(CustomEventReceivedArgs args)
|
||||
{
|
||||
API.Config.EnableAutoRespawn=(bool)args.Args[0];
|
||||
}
|
||||
}
|
||||
}
|
@ -88,7 +88,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
if (Username=="N/A")
|
||||
{
|
||||
var p = PlayerList.GetPlayer(ID);
|
||||
var p = PlayerList.GetPlayer(this);
|
||||
if (p!=null)
|
||||
{
|
||||
Username=p.Username;
|
||||
|
@ -116,5 +116,9 @@ namespace RageCoop.Core
|
||||
{
|
||||
return (flagToCheck & flag)!=0;
|
||||
}
|
||||
public static bool HasConfigFlag(this PlayerConfigFlags flagToCheck, PlayerConfigFlags flag)
|
||||
{
|
||||
return (flagToCheck & flag)!=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ namespace RageCoop.Core
|
||||
public class CustomEvent : Packet
|
||||
{
|
||||
public int Hash { get; set; }
|
||||
public List<object> Args { get; set; }
|
||||
public List<object> Args { get; set; }=new List<object>();
|
||||
|
||||
public override void Pack(NetOutgoingMessage message)
|
||||
{
|
||||
|
@ -77,6 +77,7 @@ namespace RageCoop.Core
|
||||
{
|
||||
None=0,
|
||||
IsAiming = 1 << 0,
|
||||
IsInStealthMode = 1 << 1,
|
||||
IsReloading = 1 << 2,
|
||||
IsJumping = 1 << 3,
|
||||
IsRagdoll = 1 << 4,
|
||||
@ -86,12 +87,12 @@ namespace RageCoop.Core
|
||||
IsOnLadder = 1 << 8,
|
||||
IsVaulting = 1 << 9,
|
||||
IsInCover = 1<< 10,
|
||||
IsInStealthMode = 1 << 11,
|
||||
}
|
||||
|
||||
#region ===== VEHICLE DATA =====
|
||||
public enum VehicleDataFlags:ushort
|
||||
{
|
||||
None=0,
|
||||
IsEngineRunning = 1 << 0,
|
||||
AreLightsOn = 1 << 1,
|
||||
AreBrakeLightsOn = 1 << 2,
|
||||
@ -107,6 +108,12 @@ namespace RageCoop.Core
|
||||
HasRoof=1 << 12,
|
||||
}
|
||||
|
||||
public enum PlayerConfigFlags : byte
|
||||
{
|
||||
None = 0,
|
||||
ShowBlip= 1 << 0,
|
||||
ShowNameTag= 1 << 1
|
||||
}
|
||||
|
||||
public struct VehicleDamageModel
|
||||
{
|
||||
|
@ -138,7 +138,6 @@ namespace RageCoop.Core
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerInfoUpdate : Packet
|
||||
{
|
||||
/// <summary>
|
||||
@ -147,6 +146,8 @@ namespace RageCoop.Core
|
||||
public int PedID { get; set; }
|
||||
public string Username { get; set; }
|
||||
public float Latency { get; set; }
|
||||
public PlayerConfigFlags Flags { get; set; }
|
||||
public GTA.BlipColor BlipColor { get; set; }
|
||||
public override void Pack(NetOutgoingMessage message)
|
||||
{
|
||||
#region PacketToNetOutGoingMessage
|
||||
@ -170,6 +171,12 @@ namespace RageCoop.Core
|
||||
// Write Latency
|
||||
byteArray.AddFloat(Latency);
|
||||
|
||||
// Write Flags
|
||||
byteArray.Add((byte)Flags);
|
||||
|
||||
// Write BlipColor
|
||||
byteArray.Add((byte)BlipColor);
|
||||
|
||||
byte[] result = byteArray.ToArray();
|
||||
|
||||
message.Write(result.Length);
|
||||
@ -189,6 +196,10 @@ namespace RageCoop.Core
|
||||
Username = reader.ReadString(usernameLength);
|
||||
|
||||
Latency=reader.ReadFloat();
|
||||
|
||||
Flags=(PlayerConfigFlags)reader.ReadByte();
|
||||
|
||||
BlipColor=(GTA.BlipColor)reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,15 +24,11 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\Libs\Release\scripts\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\libs\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ScriptHookVDotNet3">
|
||||
<HintPath>..\Libs\Release\ScriptHookVDotNet3.dll</HintPath>
|
||||
<HintPath>..\libs\ScriptHookVDotNet3.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Scripting\Events\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
19
RageCoop.Core/Scripting/BuiltInEvents.cs
Normal file
19
RageCoop.Core/Scripting/BuiltInEvents.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace RageCoop.Core.Scripting
|
||||
{
|
||||
internal static class CustomEvents
|
||||
{
|
||||
static MD5 Hasher = MD5.Create();
|
||||
public static int SendWeather = Hash("RageCoop.SendWeather");
|
||||
public static int OnPlayerDied = Hash("RageCoop.OnPlayerDied");
|
||||
public static int SetAutoRespawn = Hash("RageCoop.SetAutoRespawn");
|
||||
public static int Hash(string s)
|
||||
{
|
||||
return BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,23 +7,48 @@ using RageCoop.Core.Scripting;
|
||||
|
||||
namespace RageCoop.Server
|
||||
{
|
||||
public class Player
|
||||
public class ServerPed
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID of player's last vehicle.
|
||||
/// The ID of the ped's last vehicle.
|
||||
/// </summary>
|
||||
public int VehicleID { get; internal set; }
|
||||
public Vector3 Position { get; internal set; }
|
||||
|
||||
public int Health { get; internal set; }
|
||||
}
|
||||
public class PlayerConfig
|
||||
{
|
||||
#region CLIENT
|
||||
public bool EnableAutoRespawn { get; set; }=true;
|
||||
#endregion
|
||||
public bool ShowBlip { get; set; } = true;
|
||||
public bool ShowNameTag { get; set; } = true;
|
||||
public GTA.BlipColor BlipColor { get; set; } = GTA.BlipColor.White;
|
||||
public PlayerConfigFlags GetFlags()
|
||||
{
|
||||
var flag=PlayerConfigFlags.None;
|
||||
if (ShowBlip)
|
||||
{
|
||||
flag|= PlayerConfigFlags.ShowBlip;
|
||||
}
|
||||
if (ShowNameTag)
|
||||
{
|
||||
flag |= PlayerConfigFlags.ShowNameTag;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
public class Client
|
||||
{
|
||||
internal long NetID = 0;
|
||||
public NetConnection Connection { get;internal set; }
|
||||
public Player Player { get; internal set; }
|
||||
public ServerPed Player { get; internal set; }
|
||||
public float Latency { get; internal set; }
|
||||
public int ID { get; internal set; }
|
||||
private PlayerConfig _config { get; set; }=new PlayerConfig();
|
||||
public PlayerConfig Config { get { return _config; }set { _config=value;Server.SendPlayerInfos(); } }
|
||||
|
||||
private readonly Dictionary<string, object> _customData = new();
|
||||
private long _callbacksCount = 0;
|
||||
public readonly Dictionary<long, Action<object>> Callbacks = new();
|
||||
@ -62,7 +87,7 @@ namespace RageCoop.Server
|
||||
#endregion
|
||||
|
||||
#region FUNCTIONS
|
||||
public void Kick(string reason="You has been kicked!")
|
||||
public void Kick(string reason="You have been kicked!")
|
||||
{
|
||||
Connection?.Disconnect(reason);
|
||||
}
|
||||
@ -204,7 +229,6 @@ namespace RageCoop.Server
|
||||
Program.Logger.Error($"[Client->SendCleanUpWorld()]: Connection \"{NetID}\" not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
outgoingMessage.Write((byte)PacketTypes.CleanUpWorld);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Default);
|
||||
|
@ -32,10 +32,10 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\Libs\Release\scripts\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\libs\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ScriptHookVDotNet3">
|
||||
<HintPath>..\Libs\Release\ScriptHookVDotNet3.dll</HintPath>
|
||||
<HintPath>..\libs\ScriptHookVDotNet3.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace RageCoop.Server.Scripting
|
||||
public static class API
|
||||
{
|
||||
#region INTERNAL
|
||||
internal static Dictionary<int, List<Action<List<object>>>> CustomEventHandlers = new();
|
||||
internal static Dictionary<int, List<Action<CustomEventReceivedArgs>>> CustomEventHandlers = new();
|
||||
#endregion
|
||||
public static class Events
|
||||
{
|
||||
@ -34,18 +34,19 @@ namespace RageCoop.Server.Scripting
|
||||
/// Invoked everytime a player's main ped has been updated
|
||||
/// </summary>
|
||||
public static event EventHandler<Client> OnPlayerUpdate;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// This will be invoked when a CustomEvent is received from one client.
|
||||
/// </summary>
|
||||
public static event EventHandler<CustomEventReceivedArgs> OnCustomEventReceived;
|
||||
*/
|
||||
internal static void ClearHandlers()
|
||||
{
|
||||
OnChatMessage=null;
|
||||
OnPlayerHandshake=null;
|
||||
OnPlayerConnected=null;
|
||||
OnPlayerDisconnected=null;
|
||||
OnCustomEventReceived=null;
|
||||
// OnCustomEventReceived=null;
|
||||
OnCommandReceived=null;
|
||||
OnPlayerUpdate=null;
|
||||
}
|
||||
@ -66,7 +67,12 @@ namespace RageCoop.Server.Scripting
|
||||
|
||||
internal static void InvokeCustomEventReceived(Packets.CustomEvent p,Client sender)
|
||||
{
|
||||
OnCustomEventReceived?.Invoke(null, new CustomEventReceivedArgs() { Hash=p.Hash, Args=p.Args,Sender=sender });
|
||||
var args = new CustomEventReceivedArgs() { Hash=p.Hash, Args=p.Args, Sender=sender };
|
||||
List<Action<CustomEventReceivedArgs>> handlers;
|
||||
if (CustomEventHandlers.TryGetValue(p.Hash,out handlers))
|
||||
{
|
||||
handlers.ForEach((x) => { x.Invoke(args); });
|
||||
}
|
||||
}
|
||||
internal static bool InvokeOnCommandReceived(string cname,string[] cargs,Client sender)
|
||||
{
|
||||
@ -247,14 +253,19 @@ namespace RageCoop.Server.Scripting
|
||||
Server.Send(p,c,ConnectionChannel.Event,NetDeliveryMethod.ReliableOrdered);
|
||||
}
|
||||
}
|
||||
public static void RegisterCustomEventHandler(int hash,Action<List<object>> handler)
|
||||
/// <summary>
|
||||
/// Register an handler to the specifed event hash, one event can have multiple handlers.
|
||||
/// </summary>
|
||||
/// <param name="hash">An unique identifier of the event, you can hash your event name with <see cref="Core.Scripting.CustomEvents.Hash(string)"/></param>
|
||||
/// <param name="handler">An handler to be invoked when the event is received from the server. This will be invoked from main thread.
|
||||
public static void RegisterCustomEventHandler(int hash,Action<CustomEventReceivedArgs> handler)
|
||||
{
|
||||
List<Action<List<object>>> handlers;
|
||||
List<Action<CustomEventReceivedArgs>> handlers;
|
||||
lock (CustomEventHandlers)
|
||||
{
|
||||
if (!CustomEventHandlers.TryGetValue(hash,out handlers))
|
||||
{
|
||||
CustomEventHandlers.Add(hash, handlers = new List<Action<List<object>>>());
|
||||
CustomEventHandlers.Add(hash, handlers = new List<Action<CustomEventReceivedArgs>>());
|
||||
}
|
||||
handlers.Add(handler);
|
||||
}
|
||||
|
23
RageCoop.Server/Scripting/BaseScript.cs
Normal file
23
RageCoop.Server/Scripting/BaseScript.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using RageCoop.Core.Scripting;
|
||||
|
||||
namespace RageCoop.Server.Scripting
|
||||
{
|
||||
internal class BaseScript:ServerScript
|
||||
{
|
||||
public override void OnStart()
|
||||
{
|
||||
}
|
||||
public override void OnStop()
|
||||
{
|
||||
}
|
||||
public void SetAutoRespawn(Client c,bool toggle)
|
||||
{
|
||||
c.SendCustomEvent(CustomEvents.SetAutoRespawn, new() { toggle });
|
||||
}
|
||||
}
|
||||
}
|
@ -102,6 +102,10 @@ namespace RageCoop.Server.Scripting
|
||||
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
client.IsReady=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,13 @@ namespace RageCoop.Server
|
||||
internal class Server
|
||||
{
|
||||
private static readonly string _compatibleVersion = "V0_5";
|
||||
|
||||
private static BaseScript BaseScript { get; set; }=new BaseScript();
|
||||
public static readonly Settings MainSettings = Util.Read<Settings>("Settings.xml");
|
||||
public static NetServer MainNetServer;
|
||||
|
||||
public static readonly Dictionary<Command, Action<CommandContext>> Commands = new();
|
||||
public static readonly Dictionary<long,Client> Clients = new();
|
||||
private static System.Timers.Timer SendLatencyTimer = new System.Timers.Timer(5000);
|
||||
private static System.Timers.Timer SendPlayerTimer = new System.Timers.Timer(5000);
|
||||
|
||||
private static Dictionary<int,FileTransfer> InProgressFileTransfers=new();
|
||||
private static Resources Resources = new Resources();
|
||||
@ -59,9 +59,9 @@ namespace RageCoop.Server
|
||||
|
||||
MainNetServer = new NetServer(config);
|
||||
MainNetServer.Start();
|
||||
SendLatencyTimer.Elapsed+=((s,e) => { SendLatency(); });
|
||||
SendLatencyTimer.AutoReset=true;
|
||||
SendLatencyTimer.Enabled=true;
|
||||
SendPlayerTimer.Elapsed+=(s,e) => { SendPlayerInfos(); };
|
||||
SendPlayerTimer.AutoReset=true;
|
||||
SendPlayerTimer.Enabled=true;
|
||||
Program.Logger.Info(string.Format("Server listening on {0}:{1}", config.LocalAddress.ToString(), config.Port));
|
||||
if (MainSettings.AnnounceSelf)
|
||||
{
|
||||
@ -155,7 +155,7 @@ namespace RageCoop.Server
|
||||
}).Start();
|
||||
#endregion
|
||||
}
|
||||
|
||||
BaseScript.OnStart();
|
||||
Resources.LoadAll();
|
||||
Listen();
|
||||
}
|
||||
@ -170,10 +170,10 @@ namespace RageCoop.Server
|
||||
{
|
||||
ProcessMessage(MainNetServer.WaitMessage(10));
|
||||
}
|
||||
|
||||
Program.Logger.Warning("Server is shutting down!");
|
||||
MainNetServer.Shutdown("Server is shutting down!");
|
||||
Program.Logger.Info("Waiting for resources to stop...Press Ctrl+C again to forcibly terminate the program.");
|
||||
BaseScript.OnStop();
|
||||
Resources.StopAll();
|
||||
Program.Logger.Dispose();
|
||||
}
|
||||
@ -410,24 +410,30 @@ namespace RageCoop.Server
|
||||
|
||||
MainNetServer.Recycle(message);
|
||||
}
|
||||
|
||||
private void SendLatency()
|
||||
static object _sendPlayersLock=new object();
|
||||
public static void SendPlayerInfos()
|
||||
{
|
||||
foreach (Client c in Clients.Values)
|
||||
lock (_sendPlayersLock)
|
||||
{
|
||||
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != c.NetID).ForEach(x =>
|
||||
foreach (Client c in Clients.Values)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
new Packets.PlayerInfoUpdate()
|
||||
BaseScript.SetAutoRespawn(c,c.Config.EnableAutoRespawn);
|
||||
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != c.NetID).ForEach(x =>
|
||||
{
|
||||
PedID=c.ID,
|
||||
Username=c.Username,
|
||||
Latency=c.Latency,
|
||||
}.Pack(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.ReliableSequenced, (byte)ConnectionChannel.Default);
|
||||
});
|
||||
}
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
new Packets.PlayerInfoUpdate()
|
||||
{
|
||||
PedID=c.ID,
|
||||
Username=c.Username,
|
||||
Latency=c.Latency,
|
||||
Flags=c.Config.GetFlags(),
|
||||
BlipColor=c.Config.BlipColor,
|
||||
}.Pack(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.ReliableSequenced, (byte)ConnectionChannel.Default);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void DisconnectAndLog(NetConnection senderConnection,PacketTypes type, Exception e)
|
||||
@ -633,7 +639,12 @@ namespace RageCoop.Server
|
||||
private static void PedSync(Packets.PedSync packet, Client client)
|
||||
{
|
||||
bool isPlayer = packet.ID==client.ID;
|
||||
if (isPlayer) { client.Player.Position=packet.Position; API.Events.InvokePlayerUpdate(client); }
|
||||
if (isPlayer)
|
||||
{
|
||||
client.Player.Position=packet.Position;
|
||||
client.Player.Health=packet.Health ;
|
||||
API.Events.InvokePlayerUpdate(client);
|
||||
}
|
||||
|
||||
foreach (var c in Clients.Values)
|
||||
{
|
||||
|
Reference in New Issue
Block a user