We're almost here...

This commit is contained in:
Sardelka
2022-06-22 14:18:20 +08:00
parent 42c038d8ab
commit 84171e2949
35 changed files with 269 additions and 50651 deletions

Binary file not shown.

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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:

View File

@ -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; }
}
}

View File

@ -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>

View File

@ -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
}
}

View 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];
}
}
}

View File

@ -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;

View File

@ -116,5 +116,9 @@ namespace RageCoop.Core
{
return (flagToCheck & flag)!=0;
}
public static bool HasConfigFlag(this PlayerConfigFlags flagToCheck, PlayerConfigFlags flag)
{
return (flagToCheck & flag)!=0;
}
}
}

View File

@ -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)
{

View File

@ -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
{

View File

@ -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();
}
}
}

View File

@ -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>

View 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);
}
}
}

View File

@ -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);

View File

@ -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>

View File

@ -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);
}

View 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 });
}
}
}

View File

@ -102,6 +102,10 @@ namespace RageCoop.Server.Scripting
});
}
else
{
client.IsReady=true;
}
}
}
}

View File

@ -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)
{