Fixed three players issue, some work on API and resources management.
This commit is contained in:
parent
0914afc4ed
commit
a1dda2ffa4
@ -1,192 +0,0 @@
|
||||
#undef DEBUG
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using RageCoop.Core;
|
||||
|
||||
namespace RageCoop.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
public static class COOPAPI
|
||||
{
|
||||
|
||||
#region DELEGATES
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
/// <param name="connected"></param>
|
||||
/// <param name="from">The player's id</param>
|
||||
/// <param name="reason"></param>
|
||||
public delegate void ConnectEvent(bool connected, int from, string reason = null);
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
/// <param name="from"></param>
|
||||
/// <param name="message">The Lidgren-Network net handle</param>
|
||||
/// <param name="args"></param>
|
||||
public delegate void ChatMessage(string from, string message, CancelEventArgs args);
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
/// <param name="from">The Lidgren-Network net handle</param>
|
||||
/// <param name="mod"></param>
|
||||
/// <param name="customID"></param>
|
||||
/// <param name="bytes"></param>
|
||||
public delegate void ModEvent(long from, string mod, byte customID, byte[] bytes);
|
||||
#endregion
|
||||
|
||||
#region EVENTS
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
public static event ConnectEvent OnConnection;
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
public static event ChatMessage OnChatMessage;
|
||||
|
||||
public static void Connected()
|
||||
{
|
||||
OnConnection?.Invoke(true, GetPlayerID());
|
||||
}
|
||||
|
||||
public static void Disconnected(string reason)
|
||||
{
|
||||
OnConnection?.Invoke(false, GetPlayerID(), reason);
|
||||
}
|
||||
|
||||
public static void Connected(int playerID)
|
||||
{
|
||||
OnConnection?.Invoke(true, playerID);
|
||||
}
|
||||
|
||||
public static void Disconnected(int playerID)
|
||||
{
|
||||
OnConnection?.Invoke(false, playerID);
|
||||
}
|
||||
|
||||
public static bool ChatMessageReceived(string from, string message)
|
||||
{
|
||||
CancelEventArgs args = new CancelEventArgs(false);
|
||||
OnChatMessage?.Invoke(from, message, args);
|
||||
return args.Cancel;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Send a local chat message to this player
|
||||
/// </summary>
|
||||
/// <param name="from">Username of the player who sent this message</param>
|
||||
/// <param name="message">The player's message</param>
|
||||
public static void LocalChatMessage(string from, string message)
|
||||
{
|
||||
Main.MainChat.AddMessage(from, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connect to any server
|
||||
/// </summary>
|
||||
/// <param name="serverAddress">The server address to connect. Example: 127.0.0.1:4499</param>
|
||||
public static void Connect(string serverAddress)
|
||||
{
|
||||
Networking.ToggleConnection(serverAddress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
public static void Disconnect()
|
||||
{
|
||||
Networking.ToggleConnection(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the player is already on a server
|
||||
/// </summary>
|
||||
public static bool IsOnServer()
|
||||
{
|
||||
return Networking.IsOnServer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the local player's ID
|
||||
/// </summary>
|
||||
/// <returns>PlayerID</returns>
|
||||
public static int GetPlayerID()
|
||||
{
|
||||
return Main.LocalPlayerID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a RAGECOOP menu is visible
|
||||
/// </summary>
|
||||
public static bool IsMenuVisible()
|
||||
{
|
||||
#if NON_INTERACTIVE
|
||||
return false;
|
||||
#else
|
||||
return Menus.CoopMenu.MenuPool.AreAnyVisible;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the RAGECOOP chat is visible
|
||||
/// </summary>
|
||||
public static bool IsChatFocused()
|
||||
{
|
||||
return Main.MainChat.Focused;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the RAGECOOP list of players is visible
|
||||
/// </summary>
|
||||
public static bool IsPlayerListVisible()
|
||||
{
|
||||
return Util.GetTickCount64() - PlayerList.Pressed < 5000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the version of RAGECOOP
|
||||
/// </summary>
|
||||
public static string GetCurrentVersion()
|
||||
{
|
||||
return Main.CurrentVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get that player's local username
|
||||
/// </summary>
|
||||
public static string GetUsername()
|
||||
{
|
||||
return Main.Settings.Username;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a new username for this player
|
||||
/// </summary>
|
||||
/// <param name="username">The new username</param>
|
||||
/// <returns>false if the player already joined a server or the username is null or empty otherwise true</returns>
|
||||
public static bool SetUsername(string username)
|
||||
{
|
||||
if (IsOnServer() || string.IsNullOrEmpty(username))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Main.Settings.Username = username;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get or set the client's settings.
|
||||
/// </summary>
|
||||
/// <returns>The client's settings, you should NEVER change settings without notifying the player.</returns>
|
||||
public static Settings Settings()
|
||||
{
|
||||
return Main.Settings;
|
||||
}
|
||||
}
|
||||
}
|
@ -159,7 +159,7 @@ namespace RageCoop.Client
|
||||
|
||||
MainChat.Tick();
|
||||
PlayerList.Tick();
|
||||
if (Settings.DisableAutoRespawn)
|
||||
if (!API.Config.EnableAutoRespawn)
|
||||
{
|
||||
Function.Call(Hash.PAUSE_DEATH_ARREST_RESTART, true);
|
||||
Function.Call(Hash.FORCE_GAME_STATE_PLAYING);
|
||||
|
@ -7,11 +7,11 @@ namespace RageCoop.Client
|
||||
internal static class DownloadManager
|
||||
{
|
||||
private static readonly List<DownloadFile> _downloadFiles = new List<DownloadFile>();
|
||||
private static readonly Dictionary<byte, FileStream> _streams = new Dictionary<byte, FileStream>();
|
||||
private static readonly List<byte> _filesFinished = new List<byte>();
|
||||
private static readonly Dictionary<int, FileStream> _streams = new Dictionary<int, FileStream>();
|
||||
private static readonly List<int> _filesFinished = new List<int>();
|
||||
public static bool DownloadComplete = false;
|
||||
|
||||
public static void AddFile(byte id, string name, long length)
|
||||
public static void AddFile(int id, string name, long length)
|
||||
{
|
||||
string downloadFolder = $"Scripts\\RageCoop\\Resources\\{Main.Settings.LastServerAddress.Replace(":", ".")}";
|
||||
|
||||
@ -29,7 +29,7 @@ namespace RageCoop.Client
|
||||
return;
|
||||
}
|
||||
|
||||
if (!new string[] { ".js", ".xml" }.Any(x => x == Path.GetExtension(name)))
|
||||
if (!Path.GetExtension(name).EndsWith(".zip"))
|
||||
{
|
||||
Cancel(id);
|
||||
|
||||
@ -92,7 +92,7 @@ namespace RageCoop.Client
|
||||
}
|
||||
}
|
||||
|
||||
public static void Write(byte id, byte[] chunk)
|
||||
public static void Write(int id, byte[] chunk)
|
||||
{
|
||||
lock (_filesFinished)
|
||||
{
|
||||
@ -132,7 +132,7 @@ namespace RageCoop.Client
|
||||
}
|
||||
}
|
||||
|
||||
public static void Cancel(byte id)
|
||||
public static void Cancel(int id)
|
||||
{
|
||||
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
|
||||
{
|
||||
@ -158,7 +158,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
|
||||
{
|
||||
foreach (KeyValuePair<byte, FileStream> stream in _streams)
|
||||
foreach (var stream in _streams)
|
||||
{
|
||||
stream.Value.Close();
|
||||
stream.Value.Dispose();
|
||||
@ -177,7 +177,7 @@ namespace RageCoop.Client
|
||||
|
||||
public class DownloadFile
|
||||
{
|
||||
public byte FileID { get; set; } = 0;
|
||||
public int FileID { get; set; } = 0;
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
public long FileLength { get; set; } = 0;
|
||||
public long FileWritten { get; set; } = 0;
|
||||
|
@ -53,9 +53,10 @@ namespace RageCoop.Client
|
||||
{
|
||||
throw new Exception("Malformed URL");
|
||||
}
|
||||
|
||||
// Send HandshakePacket
|
||||
|
||||
EntityPool.AddPlayer();
|
||||
|
||||
// Send HandshakePacket
|
||||
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
|
||||
new Packets.Handshake()
|
||||
{
|
||||
@ -109,13 +110,11 @@ namespace RageCoop.Client
|
||||
|
||||
Main.Logger.Debug($"player connected:{p.Username}");
|
||||
Main.DumpCharacters();
|
||||
COOPAPI.Connected(packet.PedID);
|
||||
}
|
||||
private static void PlayerDisconnect(Packets.PlayerDisconnect packet)
|
||||
{
|
||||
var name=PlayerList.GetPlayer(packet.PedID).Username;
|
||||
GTA.UI.Notification.Show($"{name} left.");
|
||||
COOPAPI.Disconnected(packet.PedID);
|
||||
PlayerList.RemovePlayer(packet.PedID);
|
||||
EntityPool.RemoveAllFromPlayer(packet.PedID);
|
||||
|
||||
|
@ -58,7 +58,6 @@ namespace RageCoop.Client
|
||||
|
||||
#endif
|
||||
|
||||
COOPAPI.Connected();
|
||||
Main.QueueAction(() => {
|
||||
CoopMenu.ConnectedMenuSetting();
|
||||
Main.MainChat.Init();
|
||||
@ -88,7 +87,6 @@ namespace RageCoop.Client
|
||||
CoopMenu.DisconnectedMenuSetting();
|
||||
#endif
|
||||
|
||||
COOPAPI.Disconnected(reason);
|
||||
Main.QueueAction(() =>
|
||||
GTA.UI.Notification.Show("~r~Disconnected: " + reason));
|
||||
|
||||
@ -191,10 +189,8 @@ namespace RageCoop.Client
|
||||
Packets.ChatMessage packet = new Packets.ChatMessage();
|
||||
packet.Unpack(data);
|
||||
|
||||
if (!COOPAPI.ChatMessageReceived(packet.Username, packet.Message))
|
||||
{
|
||||
Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message);return true; });
|
||||
}
|
||||
Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message); return true; });
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
@ -218,16 +214,9 @@ namespace RageCoop.Client
|
||||
|
||||
}
|
||||
break;
|
||||
case PacketTypes.Mod:
|
||||
case PacketTypes.FileTransferChunk:
|
||||
{
|
||||
Packets.Mod packet = new Packets.Mod();
|
||||
packet.Unpack(data);
|
||||
// Need to do some stuff here
|
||||
}
|
||||
break;
|
||||
case PacketTypes.FileTransferTick:
|
||||
{
|
||||
Packets.FileTransferTick packet = new Packets.FileTransferTick();
|
||||
Packets.FileTransferChunk packet = new Packets.FileTransferChunk();
|
||||
packet.Unpack(data);
|
||||
|
||||
DownloadManager.Write(packet.ID, packet.FileChunk);
|
||||
@ -239,7 +228,7 @@ namespace RageCoop.Client
|
||||
Packets.FileTransferRequest packet = new Packets.FileTransferRequest();
|
||||
packet.Unpack(data);
|
||||
|
||||
DownloadManager.AddFile(packet.ID, packet.FileName, packet.FileLength);
|
||||
DownloadManager.AddFile(packet.ID, packet.Name, packet.FileLength);
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -162,7 +162,7 @@ namespace RageCoop.Client
|
||||
}
|
||||
#endif
|
||||
}
|
||||
public static void SendDownloadFinish(byte id)
|
||||
public static void SendDownloadFinish(int id)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
|
||||
|
||||
|
@ -43,6 +43,9 @@
|
||||
</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DotNetZip, Version=1.16.0.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNetZip.1.16.0\lib\net40\DotNetZip.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="LemonUI.SHVDN3, Version=1.5.1.0, Culture=neutral, processorArchitecture=AMD64">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Libs\Release\scripts\LemonUI.SHVDN3.dll</HintPath>
|
||||
@ -88,7 +91,7 @@
|
||||
<Compile Include="Util\VehicleExtensions.cs" />
|
||||
<Compile Include="Util\WeaponUtil.cs" />
|
||||
<Compile Include="Networking\Chat.cs" />
|
||||
<Compile Include="COOPAPI.cs" />
|
||||
<Compile Include="Scripting\API.cs" />
|
||||
<Compile Include="Debug.cs" />
|
||||
<Compile Include="Networking\DownloadManager.cs" />
|
||||
<Compile Include="Util\TaskType.cs" />
|
||||
@ -113,6 +116,7 @@
|
||||
<Compile Include="Util\PedExtensions.cs" />
|
||||
<Compile Include="WorldThread.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\RageCoop.Core.csproj">
|
||||
|
141
Client/Scripting/API.cs
Normal file
141
Client/Scripting/API.cs
Normal file
@ -0,0 +1,141 @@
|
||||
#undef DEBUG
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using RageCoop.Core;
|
||||
|
||||
namespace RageCoop.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
public static class API
|
||||
{
|
||||
public static class Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Enable automatic respawn.
|
||||
/// </summary>
|
||||
public static bool EnableAutoRespawn { get; set; } = true;
|
||||
/// <summary>
|
||||
/// Don't show other player's name tag
|
||||
/// </summary>
|
||||
public static bool DisplayNameTag { get; set; }=true;
|
||||
/// <summary>
|
||||
/// Show other players' blip on map
|
||||
/// </summary>
|
||||
public static bool DisplayBlip { get; set; } = true;
|
||||
}
|
||||
|
||||
#region DELEGATES
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
/// <param name="connected"></param>
|
||||
/// <param name="from">The player's id</param>
|
||||
/// <param name="reason"></param>
|
||||
public delegate void ConnectEvent(bool connected, int from, string reason = null);
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
/// <param name="from"></param>
|
||||
/// <param name="message">The Lidgren-Network net handle</param>
|
||||
/// <param name="args"></param>
|
||||
public delegate void ChatMessage(string from, string message, CancelEventArgs args);
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
/// <param name="from">The Lidgren-Network net handle</param>
|
||||
/// <param name="mod"></param>
|
||||
/// <param name="customID"></param>
|
||||
/// <param name="bytes"></param>
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
public static event ChatMessage OnChatMessage;
|
||||
/// <summary>
|
||||
/// Send a local chat message to this player
|
||||
/// </summary>
|
||||
/// <param name="from">Username of the player who sent this message</param>
|
||||
/// <param name="message">The player's message</param>
|
||||
public static void LocalChatMessage(string from, string message)
|
||||
{
|
||||
Main.MainChat.AddMessage(from, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect from the server
|
||||
/// </summary>
|
||||
public static void Disconnect()
|
||||
{
|
||||
Networking.ToggleConnection(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the player is already on a server
|
||||
/// </summary>
|
||||
public static bool IsOnServer
|
||||
{
|
||||
get { return Networking.IsOnServer; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the local player's ID
|
||||
/// </summary>
|
||||
/// <returns>PlayerID</returns>
|
||||
public static int LocalPlayerID
|
||||
{
|
||||
get { return Main.LocalPlayerID; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a RAGECOOP menu is visible
|
||||
/// </summary>
|
||||
public static bool IsMenuVisible
|
||||
{
|
||||
get { return Menus.CoopMenu.MenuPool.AreAnyVisible; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the RAGECOOP chat is visible
|
||||
/// </summary>
|
||||
public static bool IsChatFocused
|
||||
{
|
||||
get { return Main.MainChat.Focused; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the RAGECOOP list of players is visible
|
||||
/// </summary>
|
||||
public static bool IsPlayerListVisible
|
||||
{
|
||||
get { return Util.GetTickCount64() - PlayerList.Pressed < 5000; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the version of RAGECOOP
|
||||
/// </summary>
|
||||
public static string CurrentVersion
|
||||
{
|
||||
get { return Main.CurrentVersion; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get or set local player's username, set won't be effective if already connected to a server.
|
||||
/// </summary>
|
||||
public static string Username
|
||||
{
|
||||
get { return Main.Settings.Username; }
|
||||
set
|
||||
{
|
||||
if (IsOnServer || string.IsNullOrEmpty(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Main.Settings.Username = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -54,10 +54,5 @@ namespace RageCoop.Client
|
||||
/// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended).
|
||||
/// </summary>
|
||||
public int WorldVehicleSoftLimit { get; set; } = 35;
|
||||
|
||||
/// <summary>
|
||||
/// Disable automatic respawn.
|
||||
/// </summary>
|
||||
public bool DisableAutoRespawn { get; set; } = false;
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ namespace RageCoop.Client
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (IsPlayer && PedBlip!=null)
|
||||
if (IsPlayer)
|
||||
{
|
||||
|
||||
if (Username=="N/A")
|
||||
@ -95,10 +95,18 @@ namespace RageCoop.Client
|
||||
if (p!=null)
|
||||
{
|
||||
Username=p.Username;
|
||||
PedBlip.Name=Username;
|
||||
if (PedBlip!=null)
|
||||
{
|
||||
PedBlip.Name=Username;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if((!API.Config.DisplayBlip) && (PedBlip!=null))
|
||||
{
|
||||
PedBlip.Delete();
|
||||
PedBlip=null;
|
||||
}
|
||||
RenderNameTag();
|
||||
}
|
||||
|
||||
@ -112,10 +120,6 @@ namespace RageCoop.Client
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool characterExist = (MainPed != null) && MainPed.Exists();
|
||||
|
||||
if (!characterExist)
|
||||
@ -167,7 +171,6 @@ namespace RageCoop.Client
|
||||
if (Health <= 0 && !MainPed.IsDead)
|
||||
{
|
||||
MainPed.IsInvincible = false;
|
||||
Main.Logger.Debug($"Killing ped {ID}. Reason:PedDied");
|
||||
MainPed.Kill();
|
||||
return;
|
||||
}
|
||||
@ -188,7 +191,7 @@ namespace RageCoop.Client
|
||||
|
||||
private void RenderNameTag()
|
||||
{
|
||||
if (!IsPlayer || !MainPed.IsVisible || !MainPed.IsInRange(Game.Player.Character.Position, 20f))
|
||||
if (!API.Config.DisplayNameTag || (MainPed==null) || !MainPed.IsVisible || !MainPed.IsInRange(Game.Player.Character.Position, 20f))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -269,13 +272,15 @@ namespace RageCoop.Client
|
||||
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableShockingEvents, true);
|
||||
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
|
||||
|
||||
|
||||
SetClothes();
|
||||
|
||||
if (IsPlayer)
|
||||
{
|
||||
// Add a new blip for the ped
|
||||
PedBlip=MainPed.AddBlip();
|
||||
if (API.Config.DisplayBlip)
|
||||
{
|
||||
// Add a new blip for the ped
|
||||
PedBlip=MainPed.AddBlip();
|
||||
}
|
||||
MainPed.AttachedBlip.Color = BlipColor.White;
|
||||
MainPed.AttachedBlip.Scale = 0.8f;
|
||||
MainPed.AttachedBlip.Name =Username;
|
||||
@ -295,7 +300,7 @@ namespace RageCoop.Client
|
||||
}
|
||||
_lastClothes = Clothes;
|
||||
}
|
||||
#region Onfoot
|
||||
#region ONFOOT
|
||||
#region -- VARIABLES --
|
||||
/// <summary>
|
||||
/// The latest character rotation (may not have been applied yet)
|
||||
@ -567,14 +572,6 @@ namespace RageCoop.Client
|
||||
WalkTo();
|
||||
}
|
||||
}
|
||||
private void DisplayInVehicle()
|
||||
{
|
||||
if (MainPed.IsOnTurretSeat())
|
||||
{
|
||||
Function.Call(Hash.SET_VEHICLE_TURRET_SPEED_THIS_FRAME, MainPed.CurrentVehicle, 100);
|
||||
Function.Call(Hash.TASK_VEHICLE_AIM_AT_COORD, MainPed.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z);
|
||||
}
|
||||
}
|
||||
|
||||
#region WEAPON
|
||||
private void CheckCurrentWeapon()
|
||||
@ -716,5 +713,14 @@ namespace RageCoop.Client
|
||||
return anim;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void DisplayInVehicle()
|
||||
{
|
||||
if (MainPed.IsOnTurretSeat())
|
||||
{
|
||||
Function.Call(Hash.SET_VEHICLE_TURRET_SPEED_THIS_FRAME, MainPed.CurrentVehicle, 100);
|
||||
Function.Call(Hash.TASK_VEHICLE_AIM_AT_COORD, MainPed.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
Client/packages.config
Normal file
4
Client/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="DotNetZip" version="1.16.0" targetFramework="net48" />
|
||||
</packages>
|
@ -74,7 +74,7 @@ namespace RageCoop.Core.Logging
|
||||
if (LogLevel>4) { return; }
|
||||
lock (Buffer)
|
||||
{
|
||||
string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(),string.Join("\r\n",ex.Message,ex.StackTrace,ex.ToString()), Process.GetCurrentProcess().Id);
|
||||
string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(),"\r\n"+ex.ToString(), Process.GetCurrentProcess().Id);
|
||||
|
||||
Buffer+=msg+"\r\n";
|
||||
}
|
||||
|
@ -6,13 +6,18 @@ using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Core
|
||||
{
|
||||
public enum FileType:byte
|
||||
{
|
||||
Resource=0,
|
||||
Custom=1,
|
||||
}
|
||||
public partial class Packets
|
||||
{
|
||||
public class FileTransferRequest : Packet
|
||||
{
|
||||
public byte ID { get; set; }
|
||||
public int ID { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public long FileLength { get; set; }
|
||||
|
||||
@ -24,10 +29,11 @@ namespace RageCoop.Core
|
||||
List<byte> byteArray = new List<byte>();
|
||||
|
||||
// The ID from the download
|
||||
byteArray.Add(ID);
|
||||
byteArray.AddInt(ID);
|
||||
|
||||
|
||||
// The name of the file
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(FileName);
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(Name);
|
||||
byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length));
|
||||
byteArray.AddRange(nameBytes);
|
||||
|
||||
@ -46,29 +52,29 @@ namespace RageCoop.Core
|
||||
#region NetIncomingMessageToPacket
|
||||
BitReader reader = new BitReader(array);
|
||||
|
||||
ID = reader.ReadByte();
|
||||
ID = reader.ReadInt();
|
||||
int nameArrayLength = reader.ReadInt();
|
||||
FileName = reader.ReadString(nameArrayLength);
|
||||
Name = reader.ReadString(nameArrayLength);
|
||||
FileLength = reader.ReadLong();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
public class FileTransferTick : Packet
|
||||
public class FileTransferChunk : Packet
|
||||
{
|
||||
public byte ID { get; set; }
|
||||
public int ID { get; set; }
|
||||
|
||||
public byte[] FileChunk { get; set; }
|
||||
|
||||
public override void Pack(NetOutgoingMessage message)
|
||||
{
|
||||
#region PacketToNetOutGoingMessage
|
||||
message.Write((byte)PacketTypes.FileTransferTick);
|
||||
message.Write((byte)PacketTypes.FileTransferChunk);
|
||||
|
||||
List<byte> byteArray = new List<byte>();
|
||||
|
||||
// The ID from the download
|
||||
byteArray.Add(ID);
|
||||
byteArray.AddInt(ID);
|
||||
|
||||
// The chunk of the file
|
||||
byteArray.AddRange(BitConverter.GetBytes(FileChunk.Length));
|
||||
@ -86,7 +92,7 @@ namespace RageCoop.Core
|
||||
#region NetIncomingMessageToPacket
|
||||
BitReader reader = new BitReader(array);
|
||||
|
||||
ID = reader.ReadByte();
|
||||
ID = reader.ReadInt();
|
||||
int chunkLength = reader.ReadInt();
|
||||
FileChunk = reader.ReadByteArray(chunkLength);
|
||||
#endregion
|
||||
@ -95,7 +101,7 @@ namespace RageCoop.Core
|
||||
|
||||
public class FileTransferComplete : Packet
|
||||
{
|
||||
public byte ID { get; set; }
|
||||
public int ID { get; set; }
|
||||
|
||||
public override void Pack(NetOutgoingMessage message)
|
||||
{
|
||||
@ -105,7 +111,7 @@ namespace RageCoop.Core
|
||||
List<byte> byteArray = new List<byte>();
|
||||
|
||||
// The ID from the download
|
||||
byteArray.Add(ID);
|
||||
byteArray.AddInt(ID);
|
||||
|
||||
byte[] result = byteArray.ToArray();
|
||||
|
||||
@ -119,7 +125,7 @@ namespace RageCoop.Core
|
||||
#region NetIncomingMessageToPacket
|
||||
BitReader reader = new BitReader(array);
|
||||
|
||||
ID = reader.ReadByte();
|
||||
ID = reader.ReadInt();
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -123,13 +123,14 @@ namespace RageCoop.Core
|
||||
ChatMessage=10,
|
||||
NativeCall=11,
|
||||
NativeResponse=12,
|
||||
Mod=13,
|
||||
//Mod=13,
|
||||
CleanUpWorld=14,
|
||||
FileTransferTick=15,
|
||||
|
||||
FileTransferChunk=15,
|
||||
FileTransferRequest=16,
|
||||
FileTransferComplete=17,
|
||||
ServerClientEvent=18,
|
||||
|
||||
|
||||
ServerClientEvent = 18,
|
||||
#region Sync
|
||||
|
||||
#region INTERVAL
|
||||
@ -236,58 +237,6 @@ namespace RageCoop.Core
|
||||
|
||||
public partial class Packets
|
||||
{
|
||||
public class Mod : Packet
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public byte CustomPacketID { get; set; }
|
||||
|
||||
public byte[] Bytes { get; set; }
|
||||
|
||||
public override void Pack(NetOutgoingMessage message)
|
||||
{
|
||||
#region PacketToNetOutGoingMessage
|
||||
message.Write((byte)PacketTypes.Mod);
|
||||
|
||||
List<byte> byteArray = new List<byte>();
|
||||
|
||||
// Write Name
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(Name);
|
||||
byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length));
|
||||
byteArray.AddRange(nameBytes);
|
||||
|
||||
// Write CustomPacketID
|
||||
byteArray.Add(CustomPacketID);
|
||||
|
||||
// Write Bytes
|
||||
byteArray.AddRange(BitConverter.GetBytes(Bytes.Length));
|
||||
byteArray.AddRange(Bytes);
|
||||
|
||||
byte[] result = byteArray.ToArray();
|
||||
|
||||
message.Write(result.Length);
|
||||
message.Write(result);
|
||||
#endregion
|
||||
}
|
||||
|
||||
public override void Unpack(byte[] array)
|
||||
{
|
||||
#region NetIncomingMessageToPacket
|
||||
BitReader reader = new BitReader(array);
|
||||
|
||||
// Read Name
|
||||
int nameLength = reader.ReadInt();
|
||||
Name = reader.ReadString(nameLength);
|
||||
|
||||
// Read CustomPacketID
|
||||
CustomPacketID = reader.ReadByte();
|
||||
|
||||
// Read Bytes
|
||||
int bytesLength = reader.ReadInt();
|
||||
Bytes = reader.ReadByteArray(bytesLength);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
public class ChatMessage : Packet
|
||||
{
|
||||
|
15
RAGECOOP.sln
15
RAGECOOP.sln
@ -9,10 +9,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RageCoop.Client", "Client\R
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RageCoop.Core", "Core\RageCoop.Core.csproj", "{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RageCoop.Resources.Base", "Resources\Base\RageCoop.Resources.Base.csproj", "{9DC11623-8A8B-4D17-B18B-91852922163D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Resources", "Resources", "{F49A2617-832B-44DA-9D42-29B5DD09A186}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -45,21 +41,10 @@ Global
|
||||
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{9DC11623-8A8B-4D17-B18B-91852922163D} = {F49A2617-832B-44DA-9D42-29B5DD09A186}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6CC7EA75-E4FF-4534-8EB6-0AEECF2620B7}
|
||||
EndGlobalSection
|
||||
|
@ -1,17 +1,5 @@
|
||||
using RageCoop.Server.Scripting;
|
||||
namespace RageCoop.Resources.Base
|
||||
{
|
||||
public class ServerBase :ServerScript
|
||||
{
|
||||
public ServerBase()
|
||||
{
|
||||
API.RegisterCommand("kick", (ctx) =>
|
||||
{
|
||||
if (ctx.Args.Length<1) { return; }
|
||||
var reason = "EAT POOP!";
|
||||
if(ctx.Args.Length>=2) { reason=ctx.Args[1]; }
|
||||
API.GetClientByUsername(ctx.Args[0]).Kick(reason);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
using System.Collections.Generic;
|
@ -14,9 +14,7 @@ namespace RageCoop.Server
|
||||
private readonly Dictionary<string, object> _customData = new();
|
||||
private long _callbacksCount = 0;
|
||||
public readonly Dictionary<long, Action<object>> Callbacks = new();
|
||||
public bool FilesReceived { get;internal set; } = false;
|
||||
public bool FilesSent = false;
|
||||
|
||||
public bool IsReady { get; internal set; }=false;
|
||||
#region CUSTOMDATA FUNCTIONS
|
||||
public void SetData<T>(string name, T data)
|
||||
{
|
||||
@ -189,9 +187,9 @@ namespace RageCoop.Server
|
||||
|
||||
public void SendTriggerEvent(string eventName, params object[] args)
|
||||
{
|
||||
if (!FilesReceived)
|
||||
if (!IsReady)
|
||||
{
|
||||
Program.Logger.Warning($"Player \"{Player.Username}\" doesn't have all the files yet!");
|
||||
Program.Logger.Warning($"Player \"{Player.Username}\" is not ready!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using RageCoop.Core;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace RageCoop.Server
|
||||
/*
|
||||
namespace RageCoop.Server.Obsolete
|
||||
{
|
||||
public static class DownloadManager
|
||||
{
|
||||
@ -276,3 +276,4 @@ namespace RageCoop.Server
|
||||
public List<byte[]> FileChunks { get; set; } = null;
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using RageCoop.Core;
|
||||
|
||||
namespace RageCoop.Server
|
||||
{
|
||||
internal static class EntitiesBlah
|
||||
{
|
||||
public static Dictionary<long,SyncedCharacter> Peds=new Dictionary<long,SyncedCharacter>();
|
||||
public static Dictionary<long, SyncedVehicle> Vehicles = new Dictionary<long, SyncedVehicle>();
|
||||
|
||||
}
|
||||
internal class SyncedVehicle
|
||||
{
|
||||
public long Owner { get; set; }
|
||||
// <index, (enum)VehicleSeat>
|
||||
// public Dictionary<int, int> Seats=new Dictionary<int, int>();
|
||||
}
|
||||
internal class SyncedCharacter
|
||||
{
|
||||
public long Owner { get; set; }
|
||||
}
|
||||
}
|
16
Server/FileTransfer.cs
Normal file
16
Server/FileTransfer.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -33,11 +33,6 @@ namespace RageCoop.Server
|
||||
Console.Title = "RAGECOOP";
|
||||
#endif
|
||||
|
||||
if (File.Exists("log.txt"))
|
||||
{
|
||||
File.WriteAllText("log.txt", string.Empty);
|
||||
}
|
||||
|
||||
Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
|
||||
{
|
||||
if (e.SpecialKey == ConsoleSpecialKey.ControlC)
|
||||
@ -51,8 +46,7 @@ namespace RageCoop.Server
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Program.Logger.Error(e.InnerException?.Message ?? e.Message);
|
||||
Console.ReadLine();
|
||||
Logger.Error($"Fatal error occurred, server shutting down:{e}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@
|
||||
<None Remove="Obsolete\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\RageCoop.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
47
Server/Resources.cs
Normal file
47
Server/Resources.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using RageCoop.Server.Scripting;
|
||||
using System.IO;
|
||||
using Ionic.Zip;
|
||||
|
||||
namespace RageCoop.Server
|
||||
{
|
||||
internal static class Resources
|
||||
{
|
||||
public static readonly Engine ScriptingEngine = new();
|
||||
/// <summary>
|
||||
/// Pack client-side resources as a zip file
|
||||
/// </summary>
|
||||
public static void PackClientFiles()
|
||||
{
|
||||
Program.Logger.Info("Packing client side resources");
|
||||
}
|
||||
|
||||
public static void LoadAll()
|
||||
{
|
||||
var path = Path.Combine("Resources", "Client");
|
||||
Directory.CreateDirectory(path);
|
||||
var clientResources = Directory.GetDirectories(path);
|
||||
if (clientResources.Length!=0)
|
||||
{
|
||||
// Pack client side resources as a zip file
|
||||
Program.Logger.Info("Packing client-side resources");
|
||||
|
||||
var zippath = Path.Combine(path, "Resources.zip");
|
||||
if (File.Exists(zippath))
|
||||
{
|
||||
File.Delete(zippath);
|
||||
}
|
||||
using (ZipFile zip = new ZipFile())
|
||||
{
|
||||
zip.AddDirectory(path);
|
||||
zip.Save(zippath);
|
||||
}
|
||||
}
|
||||
ScriptingEngine.LoadAll();
|
||||
}
|
||||
}
|
||||
}
|
@ -24,8 +24,6 @@ namespace RageCoop.Server.Scripting
|
||||
public static event EventHandler<HandshakeEventArgs> OnPlayerHandshake;
|
||||
public static event PlayerConnect OnPlayerConnected;
|
||||
public static event PlayerDisconnect OnPlayerDisconnected;
|
||||
// public static event EventHandler OnPlayerUpdate;
|
||||
|
||||
#region INVOKE
|
||||
internal static void InvokeOnStop() { OnStop?.Invoke(); }
|
||||
internal static void InvokeOnChatMessage(Packets.ChatMessage p,NetConnection con)
|
||||
|
@ -24,7 +24,7 @@ namespace RageCoop.Server.Scripting
|
||||
}
|
||||
private void LoadResource(string path)
|
||||
{
|
||||
foreach(var assembly in Directory.GetFiles(path,"*.dll"))
|
||||
foreach(var assembly in Directory.GetFiles(path,"*.dll",SearchOption.AllDirectories))
|
||||
{
|
||||
LoadScriptsFromAssembly(assembly);
|
||||
}
|
||||
|
521
Server/Server.cs
521
Server/Server.cs
@ -12,6 +12,7 @@ using Newtonsoft.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Lidgren.Network;
|
||||
using System.Timers;
|
||||
using System.Security.Cryptography;
|
||||
using RageCoop.Server.Scripting;
|
||||
|
||||
namespace RageCoop.Server
|
||||
@ -35,7 +36,8 @@ namespace RageCoop.Server
|
||||
|
||||
public static readonly Dictionary<long,Client> Clients = new();
|
||||
private static System.Timers.Timer SendLatencyTimer = new System.Timers.Timer(5000);
|
||||
public static readonly Engine ScriptingEngine = new();
|
||||
|
||||
private static Dictionary<int,FileTransfer> InProgressFileTransfers=new();
|
||||
public Server()
|
||||
{
|
||||
Program.Logger.Info("================");
|
||||
@ -169,10 +171,7 @@ namespace RageCoop.Server
|
||||
}).Start();
|
||||
#endregion
|
||||
}
|
||||
ScriptingEngine.LoadAll();
|
||||
Program.Logger.Info("Searching for client-side files...");
|
||||
DownloadManager.CheckForDirectoryAndFiles();
|
||||
|
||||
Resources.LoadAll();
|
||||
|
||||
Listen();
|
||||
}
|
||||
@ -192,25 +191,6 @@ namespace RageCoop.Server
|
||||
while (!Program.ReadyToStop)
|
||||
{
|
||||
|
||||
// Only new clients that did not receive files on connection will receive the current files in "clientside"
|
||||
if (DownloadManager.AnyFileExists)
|
||||
{
|
||||
lock (Clients)
|
||||
{
|
||||
Clients.Values.ToList().ForEach(client =>
|
||||
{
|
||||
if (!client.FilesSent)
|
||||
{
|
||||
DownloadManager.InsertClient(client.NetID);
|
||||
client.FilesSent = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DownloadManager.Tick();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 15 milliseconds to sleep to reduce CPU usage
|
||||
Thread.Sleep(15);
|
||||
@ -269,7 +249,6 @@ namespace RageCoop.Server
|
||||
{
|
||||
long nethandle = message.SenderConnection.RemoteUniqueIdentifier;
|
||||
|
||||
DownloadManager.RemoveClient(nethandle);
|
||||
|
||||
SendPlayerDisconnectPacket(nethandle);
|
||||
}
|
||||
@ -280,251 +259,182 @@ namespace RageCoop.Server
|
||||
break;
|
||||
}
|
||||
case NetIncomingMessageType.Data:
|
||||
// Get packet type
|
||||
byte btype = message.ReadByte();
|
||||
var type = (PacketTypes)btype;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// Get packet type
|
||||
byte btype = message.ReadByte();
|
||||
var type = (PacketTypes)btype;
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
try
|
||||
{
|
||||
|
||||
#region SyncData
|
||||
|
||||
case PacketTypes.PedStateSync:
|
||||
switch (type)
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.PedStateSync packet = new();
|
||||
packet.Unpack(data);
|
||||
#region SyncData
|
||||
|
||||
PedStateSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PacketTypes.VehicleStateSync:
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.VehicleStateSync packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
VehicleStateSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PacketTypes.PedSync:
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.PedSync packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
PedSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PacketTypes.VehicleSync:
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.VehicleSync packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
VehicleSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PacketTypes.ProjectileSync:
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.ProjectileSync packet = new();
|
||||
packet.Unpack(data);
|
||||
ProjectileSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
case PacketTypes.ChatMessage:
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.ChatMessage packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
API.Events.InvokeOnChatMessage(packet,message.SenderConnection);
|
||||
SendChatMessage(packet);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PacketTypes.NativeResponse:
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.NativeResponse packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
Client client = Util.GetClientByNetID(message.SenderConnection.RemoteUniqueIdentifier);
|
||||
if (client != null)
|
||||
case PacketTypes.PedStateSync:
|
||||
{
|
||||
if (client.Callbacks.ContainsKey(packet.ID))
|
||||
Packets.PedStateSync packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
PedStateSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
break;
|
||||
}
|
||||
case PacketTypes.VehicleStateSync:
|
||||
{
|
||||
Packets.VehicleStateSync packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
VehicleStateSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
|
||||
break;
|
||||
}
|
||||
case PacketTypes.PedSync:
|
||||
{
|
||||
|
||||
Packets.PedSync packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
PedSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
|
||||
}
|
||||
break;
|
||||
case PacketTypes.VehicleSync:
|
||||
{
|
||||
Packets.VehicleSync packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
VehicleSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
|
||||
}
|
||||
break;
|
||||
case PacketTypes.ProjectileSync:
|
||||
{
|
||||
|
||||
Packets.ProjectileSync packet = new();
|
||||
packet.Unpack(data);
|
||||
ProjectileSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
case PacketTypes.ChatMessage:
|
||||
{
|
||||
try
|
||||
{
|
||||
client.Callbacks[packet.ID].Invoke(packet.Args[0]);
|
||||
client.Callbacks.Remove(packet.ID);
|
||||
|
||||
Packets.ChatMessage packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
API.Events.InvokeOnChatMessage(packet, message.SenderConnection);
|
||||
SendChatMessage(packet);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PacketTypes.FileTransferComplete:
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DownloadManager.AnyFileExists)
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
break;
|
||||
|
||||
Packets.FileTransferComplete packet = new();
|
||||
case PacketTypes.NativeResponse:
|
||||
{
|
||||
Packets.NativeResponse packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
Client client = Util.GetClientByNetID(message.SenderConnection.RemoteUniqueIdentifier);
|
||||
if (client != null && !client.FilesReceived)
|
||||
if (client != null)
|
||||
{
|
||||
DownloadManager.TryToRemoveClient(client.NetID, packet.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PacketTypes.ServerClientEvent:
|
||||
{
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
|
||||
Packets.ServerClientEvent packet = new Packets.ServerClientEvent();
|
||||
packet.Unpack(data);
|
||||
|
||||
long senderNetHandle = message.SenderConnection.RemoteUniqueIdentifier;
|
||||
Client client = null;
|
||||
lock (Clients)
|
||||
{
|
||||
client = Util.GetClientByNetID(senderNetHandle);
|
||||
}
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
if (TriggerEvents.Any(x => x.Key.EventName == packet.EventName))
|
||||
{
|
||||
EventContext ctx = new()
|
||||
if (client.Callbacks.ContainsKey(packet.ID))
|
||||
{
|
||||
Client = client,
|
||||
Args = packet.Args.ToArray()
|
||||
};
|
||||
|
||||
TriggerEvents.FirstOrDefault(x => x.Key.EventName == packet.EventName).Value?.Invoke(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.Logger.Warning($"Player \"{client.Player.Username}\" attempted to trigger an unknown event! [{packet.EventName}]");
|
||||
client.Callbacks[packet.ID].Invoke(packet.Args[0]);
|
||||
client.Callbacks.Remove(packet.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (type.IsSyncEvent())
|
||||
{
|
||||
// Sync Events
|
||||
try
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
byte[] data = message.ReadBytes(len);
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
outgoingMessage.Write(btype);
|
||||
outgoingMessage.Write(len);
|
||||
outgoingMessage.Write(data);
|
||||
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != message.SenderConnection.RemoteUniqueIdentifier).ForEach(x =>
|
||||
break;
|
||||
case PacketTypes.ServerClientEvent:
|
||||
{
|
||||
Packets.ServerClientEvent packet = new Packets.ServerClientEvent();
|
||||
packet.Unpack(data);
|
||||
|
||||
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync);
|
||||
long senderNetHandle = message.SenderConnection.RemoteUniqueIdentifier;
|
||||
Client client = null;
|
||||
lock (Clients)
|
||||
{
|
||||
client = Util.GetClientByNetID(senderNetHandle);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
if (client != null)
|
||||
{
|
||||
if (TriggerEvents.Any(x => x.Key.EventName == packet.EventName))
|
||||
{
|
||||
EventContext ctx = new()
|
||||
{
|
||||
Client = client,
|
||||
Args = packet.Args.ToArray()
|
||||
};
|
||||
|
||||
TriggerEvents.FirstOrDefault(x => x.Key.EventName == packet.EventName).Value?.Invoke(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.Logger.Warning($"Player \"{client.Player.Username}\" attempted to trigger an unknown event! [{packet.EventName}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PacketTypes.FileTransferComplete:
|
||||
{
|
||||
Packets.FileTransferComplete packet = new Packets.FileTransferComplete();
|
||||
packet.Unpack(data);
|
||||
FileTransfer toRemove;
|
||||
|
||||
// Cancel the download if it's in progress
|
||||
if (InProgressFileTransfers.TryGetValue(packet.ID,out toRemove))
|
||||
{
|
||||
toRemove.Cancel=true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (type.IsSyncEvent())
|
||||
{
|
||||
// Sync Events
|
||||
try
|
||||
{
|
||||
var outgoingMessage = MainNetServer.CreateMessage();
|
||||
outgoingMessage.Write(btype);
|
||||
outgoingMessage.Write(len);
|
||||
outgoingMessage.Write(data);
|
||||
var toSend = MainNetServer.Connections.Exclude(message.SenderConnection);
|
||||
if (toSend.Count!=0)
|
||||
{
|
||||
MainNetServer.SendMessage(outgoingMessage, toSend, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.SyncEvents);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.Logger.Error("Unhandled Data / Packet type");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.Logger.Error("Unhandled Data / Packet type");
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DisconnectAndLog(message.SenderConnection, type, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.ConnectionLatencyUpdated:
|
||||
{
|
||||
Client client = Util.GetClientByNetID(message.SenderConnection.RemoteUniqueIdentifier);
|
||||
@ -579,7 +489,7 @@ namespace RageCoop.Server
|
||||
senderConnection.Disconnect(e.Message);
|
||||
}
|
||||
|
||||
#region -- PLAYER --
|
||||
#region -- SYNC --
|
||||
// Before we approve the connection, we must shake hands
|
||||
private void GetHandshake(NetConnection connection, Packets.Handshake packet)
|
||||
{
|
||||
@ -649,7 +559,7 @@ namespace RageCoop.Server
|
||||
return;
|
||||
}
|
||||
|
||||
Program.Logger.Info($"Handshake sucess, Player:{packet.Username} PedID:{packet.PedID}");
|
||||
Program.Logger.Debug($"Handshake sucess, Player:{packet.Username} PedID:{packet.PedID}");
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
|
||||
// Create a new handshake packet
|
||||
@ -673,18 +583,20 @@ namespace RageCoop.Server
|
||||
return;
|
||||
}
|
||||
|
||||
List<NetConnection> clients;
|
||||
if ((clients = Util.FilterAllLocal(local)).Count > 0)
|
||||
List<NetConnection> clients=MainNetServer.Connections.Exclude(local);
|
||||
// Send all players to local
|
||||
|
||||
|
||||
if (clients.Count > 0)
|
||||
{
|
||||
// Send all players to local
|
||||
clients.ForEach(targetPlayer =>
|
||||
clients.ForEach(targetPlayer =>
|
||||
{
|
||||
long targetNetHandle = targetPlayer.RemoteUniqueIdentifier;
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
|
||||
Client targetClient = Util.GetClientByNetID(targetNetHandle);
|
||||
if (targetClient != null)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
new Packets.PlayerConnect()
|
||||
{
|
||||
// NetHandle = targetNetHandle,
|
||||
@ -700,11 +612,13 @@ namespace RageCoop.Server
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
new Packets.PlayerConnect()
|
||||
{
|
||||
// NetHandle = local.RemoteUniqueIdentifier,
|
||||
PedID=localClient.Player.PedID,
|
||||
Username = localClient.Player.Username
|
||||
}.Pack(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
if(clients.Count > 0)
|
||||
{
|
||||
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
}
|
||||
API.Events.InvokePlayerConnected(localClient);
|
||||
|
||||
@ -757,10 +671,11 @@ namespace RageCoop.Server
|
||||
}
|
||||
|
||||
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
packet.Pack(outgoingMessage);
|
||||
|
||||
foreach (var c in Clients.Values)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
packet.Pack(outgoingMessage);
|
||||
if (c.NetID==client.NetID) { continue; }
|
||||
MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync);
|
||||
}
|
||||
@ -796,8 +711,7 @@ namespace RageCoop.Server
|
||||
}
|
||||
bool isPlayer = packet.ID==client.Player.PedID;
|
||||
if (isPlayer) { client.Player.Position=packet.Position; }
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
packet.Pack(outgoingMessage);
|
||||
|
||||
foreach (var c in Clients.Values)
|
||||
{
|
||||
|
||||
@ -816,6 +730,9 @@ namespace RageCoop.Server
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
packet.Pack(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage,c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync);
|
||||
}
|
||||
}
|
||||
@ -990,5 +907,89 @@ namespace RageCoop.Server
|
||||
RegisterEvent(attribute.EventName, (Action<EventContext>)Delegate.CreateDelegate(typeof(Action<EventContext>), method));
|
||||
}
|
||||
}
|
||||
public static void SendFile(FileStream fs,string name,Client client,Action<float> updateCallback=null)
|
||||
{
|
||||
int id = RequestFileID();
|
||||
FileTransfer transfer = new()
|
||||
{
|
||||
ID=id,
|
||||
Name = name,
|
||||
};
|
||||
InProgressFileTransfers.Add(id,transfer);
|
||||
fs.Seek(0, SeekOrigin.Begin);
|
||||
Send(
|
||||
new Packets.FileTransferRequest()
|
||||
{
|
||||
FileLength= fs.Length,
|
||||
Name=name,
|
||||
ID=id,
|
||||
},
|
||||
client, ConnectionChannel.File, NetDeliveryMethod.ReliableOrdered
|
||||
);
|
||||
while (fs.CanRead && (!transfer.Cancel))
|
||||
{
|
||||
// 4 KB chunk
|
||||
byte[] chunk = new byte[4096];
|
||||
int read = fs.Read(chunk, 0, chunk.Length);
|
||||
if (read!=chunk.Length)
|
||||
{
|
||||
// EOF reached
|
||||
var newchunk = new byte[read];
|
||||
Array.Copy(chunk, 0, newchunk, 0, read);
|
||||
chunk=newchunk;
|
||||
}
|
||||
Send(
|
||||
new Packets.FileTransferChunk()
|
||||
{
|
||||
ID=id,
|
||||
FileChunk=chunk,
|
||||
},
|
||||
client, ConnectionChannel.File, NetDeliveryMethod.ReliableOrdered
|
||||
);
|
||||
transfer.Progress=fs.Position/fs.Length;
|
||||
if (updateCallback!=null) { updateCallback(transfer.Progress);}
|
||||
};
|
||||
Send(
|
||||
new Packets.FileTransferComplete()
|
||||
{
|
||||
ID= id,
|
||||
}
|
||||
, client, ConnectionChannel.File, NetDeliveryMethod.ReliableOrdered
|
||||
);
|
||||
InProgressFileTransfers.Remove(id);
|
||||
}
|
||||
public static async void SendFileAsync(FileStream fs, string name, Client client,Action<float> updateCallback=null,Action completedCallback=null)
|
||||
{
|
||||
SendFile(fs, name, client,updateCallback);
|
||||
if(completedCallback!=null) { completedCallback(); }
|
||||
}
|
||||
public static int RequestFileID()
|
||||
{
|
||||
int ID = 0;
|
||||
while ((ID==0)
|
||||
|| InProgressFileTransfers.ContainsKey(ID))
|
||||
{
|
||||
byte[] rngBytes = new byte[4];
|
||||
|
||||
RandomNumberGenerator.Create().GetBytes(rngBytes);
|
||||
|
||||
// Convert the bytes into an integer
|
||||
ID = BitConverter.ToInt32(rngBytes, 0);
|
||||
}
|
||||
return ID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pack the packet then send to server.
|
||||
/// </summary>
|
||||
/// <param name="p"></param>
|
||||
/// <param name="channel"></param>
|
||||
/// <param name="method"></param>
|
||||
public static 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,9 +76,9 @@ namespace RageCoop.Server
|
||||
}
|
||||
|
||||
// Return a list of all connections but not the local connection
|
||||
public static List<NetConnection> FilterAllLocal(NetConnection local)
|
||||
public static List<NetConnection> Exclude(this IEnumerable<NetConnection> connections,NetConnection toExclude)
|
||||
{
|
||||
return new(Server.MainNetServer.Connections.Where(e => e != local));
|
||||
return new(connections.Where(e => e != toExclude));
|
||||
}
|
||||
public static List<NetConnection> FilterAllLocal(long local)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user