Fixed three players issue, some work on API and resources management.
This commit is contained in:
@ -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();
|
MainChat.Tick();
|
||||||
PlayerList.Tick();
|
PlayerList.Tick();
|
||||||
if (Settings.DisableAutoRespawn)
|
if (!API.Config.EnableAutoRespawn)
|
||||||
{
|
{
|
||||||
Function.Call(Hash.PAUSE_DEATH_ARREST_RESTART, true);
|
Function.Call(Hash.PAUSE_DEATH_ARREST_RESTART, true);
|
||||||
Function.Call(Hash.FORCE_GAME_STATE_PLAYING);
|
Function.Call(Hash.FORCE_GAME_STATE_PLAYING);
|
||||||
|
@ -7,11 +7,11 @@ namespace RageCoop.Client
|
|||||||
internal static class DownloadManager
|
internal static class DownloadManager
|
||||||
{
|
{
|
||||||
private static readonly List<DownloadFile> _downloadFiles = new List<DownloadFile>();
|
private static readonly List<DownloadFile> _downloadFiles = new List<DownloadFile>();
|
||||||
private static readonly Dictionary<byte, FileStream> _streams = new Dictionary<byte, FileStream>();
|
private static readonly Dictionary<int, FileStream> _streams = new Dictionary<int, FileStream>();
|
||||||
private static readonly List<byte> _filesFinished = new List<byte>();
|
private static readonly List<int> _filesFinished = new List<int>();
|
||||||
public static bool DownloadComplete = false;
|
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(":", ".")}";
|
string downloadFolder = $"Scripts\\RageCoop\\Resources\\{Main.Settings.LastServerAddress.Replace(":", ".")}";
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ namespace RageCoop.Client
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!new string[] { ".js", ".xml" }.Any(x => x == Path.GetExtension(name)))
|
if (!Path.GetExtension(name).EndsWith(".zip"))
|
||||||
{
|
{
|
||||||
Cancel(id);
|
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)
|
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)
|
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
|
||||||
{
|
{
|
||||||
@ -158,7 +158,7 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
|
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<byte, FileStream> stream in _streams)
|
foreach (var stream in _streams)
|
||||||
{
|
{
|
||||||
stream.Value.Close();
|
stream.Value.Close();
|
||||||
stream.Value.Dispose();
|
stream.Value.Dispose();
|
||||||
@ -177,7 +177,7 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
public class DownloadFile
|
public class DownloadFile
|
||||||
{
|
{
|
||||||
public byte FileID { get; set; } = 0;
|
public int FileID { get; set; } = 0;
|
||||||
public string FileName { get; set; } = string.Empty;
|
public string FileName { get; set; } = string.Empty;
|
||||||
public long FileLength { get; set; } = 0;
|
public long FileLength { get; set; } = 0;
|
||||||
public long FileWritten { get; set; } = 0;
|
public long FileWritten { get; set; } = 0;
|
||||||
|
@ -53,9 +53,10 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
throw new Exception("Malformed URL");
|
throw new Exception("Malformed URL");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send HandshakePacket
|
|
||||||
EntityPool.AddPlayer();
|
EntityPool.AddPlayer();
|
||||||
|
|
||||||
|
// Send HandshakePacket
|
||||||
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
|
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
|
||||||
new Packets.Handshake()
|
new Packets.Handshake()
|
||||||
{
|
{
|
||||||
@ -109,13 +110,11 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
Main.Logger.Debug($"player connected:{p.Username}");
|
Main.Logger.Debug($"player connected:{p.Username}");
|
||||||
Main.DumpCharacters();
|
Main.DumpCharacters();
|
||||||
COOPAPI.Connected(packet.PedID);
|
|
||||||
}
|
}
|
||||||
private static void PlayerDisconnect(Packets.PlayerDisconnect packet)
|
private static void PlayerDisconnect(Packets.PlayerDisconnect packet)
|
||||||
{
|
{
|
||||||
var name=PlayerList.GetPlayer(packet.PedID).Username;
|
var name=PlayerList.GetPlayer(packet.PedID).Username;
|
||||||
GTA.UI.Notification.Show($"{name} left.");
|
GTA.UI.Notification.Show($"{name} left.");
|
||||||
COOPAPI.Disconnected(packet.PedID);
|
|
||||||
PlayerList.RemovePlayer(packet.PedID);
|
PlayerList.RemovePlayer(packet.PedID);
|
||||||
EntityPool.RemoveAllFromPlayer(packet.PedID);
|
EntityPool.RemoveAllFromPlayer(packet.PedID);
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
COOPAPI.Connected();
|
|
||||||
Main.QueueAction(() => {
|
Main.QueueAction(() => {
|
||||||
CoopMenu.ConnectedMenuSetting();
|
CoopMenu.ConnectedMenuSetting();
|
||||||
Main.MainChat.Init();
|
Main.MainChat.Init();
|
||||||
@ -88,7 +87,6 @@ namespace RageCoop.Client
|
|||||||
CoopMenu.DisconnectedMenuSetting();
|
CoopMenu.DisconnectedMenuSetting();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
COOPAPI.Disconnected(reason);
|
|
||||||
Main.QueueAction(() =>
|
Main.QueueAction(() =>
|
||||||
GTA.UI.Notification.Show("~r~Disconnected: " + reason));
|
GTA.UI.Notification.Show("~r~Disconnected: " + reason));
|
||||||
|
|
||||||
@ -191,10 +189,8 @@ namespace RageCoop.Client
|
|||||||
Packets.ChatMessage packet = new Packets.ChatMessage();
|
Packets.ChatMessage packet = new Packets.ChatMessage();
|
||||||
packet.Unpack(data);
|
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;
|
break;
|
||||||
@ -218,16 +214,9 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PacketTypes.Mod:
|
case PacketTypes.FileTransferChunk:
|
||||||
{
|
{
|
||||||
Packets.Mod packet = new Packets.Mod();
|
Packets.FileTransferChunk packet = new Packets.FileTransferChunk();
|
||||||
packet.Unpack(data);
|
|
||||||
// Need to do some stuff here
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PacketTypes.FileTransferTick:
|
|
||||||
{
|
|
||||||
Packets.FileTransferTick packet = new Packets.FileTransferTick();
|
|
||||||
packet.Unpack(data);
|
packet.Unpack(data);
|
||||||
|
|
||||||
DownloadManager.Write(packet.ID, packet.FileChunk);
|
DownloadManager.Write(packet.ID, packet.FileChunk);
|
||||||
@ -239,7 +228,7 @@ namespace RageCoop.Client
|
|||||||
Packets.FileTransferRequest packet = new Packets.FileTransferRequest();
|
Packets.FileTransferRequest packet = new Packets.FileTransferRequest();
|
||||||
packet.Unpack(data);
|
packet.Unpack(data);
|
||||||
|
|
||||||
DownloadManager.AddFile(packet.ID, packet.FileName, packet.FileLength);
|
DownloadManager.AddFile(packet.ID, packet.Name, packet.FileLength);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -162,7 +162,7 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
public static void SendDownloadFinish(byte id)
|
public static void SendDownloadFinish(int id)
|
||||||
{
|
{
|
||||||
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
|
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
|
||||||
|
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
</DocumentationFile>
|
</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<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">
|
<Reference Include="LemonUI.SHVDN3, Version=1.5.1.0, Culture=neutral, processorArchitecture=AMD64">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\Libs\Release\scripts\LemonUI.SHVDN3.dll</HintPath>
|
<HintPath>..\Libs\Release\scripts\LemonUI.SHVDN3.dll</HintPath>
|
||||||
@ -88,7 +91,7 @@
|
|||||||
<Compile Include="Util\VehicleExtensions.cs" />
|
<Compile Include="Util\VehicleExtensions.cs" />
|
||||||
<Compile Include="Util\WeaponUtil.cs" />
|
<Compile Include="Util\WeaponUtil.cs" />
|
||||||
<Compile Include="Networking\Chat.cs" />
|
<Compile Include="Networking\Chat.cs" />
|
||||||
<Compile Include="COOPAPI.cs" />
|
<Compile Include="Scripting\API.cs" />
|
||||||
<Compile Include="Debug.cs" />
|
<Compile Include="Debug.cs" />
|
||||||
<Compile Include="Networking\DownloadManager.cs" />
|
<Compile Include="Networking\DownloadManager.cs" />
|
||||||
<Compile Include="Util\TaskType.cs" />
|
<Compile Include="Util\TaskType.cs" />
|
||||||
@ -113,6 +116,7 @@
|
|||||||
<Compile Include="Util\PedExtensions.cs" />
|
<Compile Include="Util\PedExtensions.cs" />
|
||||||
<Compile Include="WorldThread.cs" />
|
<Compile Include="WorldThread.cs" />
|
||||||
<Compile Include="Settings.cs" />
|
<Compile Include="Settings.cs" />
|
||||||
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Core\RageCoop.Core.csproj">
|
<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).
|
/// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int WorldVehicleSoftLimit { get; set; } = 35;
|
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()
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (IsPlayer && PedBlip!=null)
|
if (IsPlayer)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Username=="N/A")
|
if (Username=="N/A")
|
||||||
@ -95,10 +95,18 @@ namespace RageCoop.Client
|
|||||||
if (p!=null)
|
if (p!=null)
|
||||||
{
|
{
|
||||||
Username=p.Username;
|
Username=p.Username;
|
||||||
PedBlip.Name=Username;
|
if (PedBlip!=null)
|
||||||
|
{
|
||||||
|
PedBlip.Name=Username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if((!API.Config.DisplayBlip) && (PedBlip!=null))
|
||||||
|
{
|
||||||
|
PedBlip.Delete();
|
||||||
|
PedBlip=null;
|
||||||
|
}
|
||||||
RenderNameTag();
|
RenderNameTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,10 +120,6 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool characterExist = (MainPed != null) && MainPed.Exists();
|
bool characterExist = (MainPed != null) && MainPed.Exists();
|
||||||
|
|
||||||
if (!characterExist)
|
if (!characterExist)
|
||||||
@ -167,7 +171,6 @@ namespace RageCoop.Client
|
|||||||
if (Health <= 0 && !MainPed.IsDead)
|
if (Health <= 0 && !MainPed.IsDead)
|
||||||
{
|
{
|
||||||
MainPed.IsInvincible = false;
|
MainPed.IsInvincible = false;
|
||||||
Main.Logger.Debug($"Killing ped {ID}. Reason:PedDied");
|
|
||||||
MainPed.Kill();
|
MainPed.Kill();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -188,7 +191,7 @@ namespace RageCoop.Client
|
|||||||
|
|
||||||
private void RenderNameTag()
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -269,13 +272,15 @@ namespace RageCoop.Client
|
|||||||
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableShockingEvents, true);
|
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableShockingEvents, true);
|
||||||
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
|
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
|
||||||
|
|
||||||
|
|
||||||
SetClothes();
|
SetClothes();
|
||||||
|
|
||||||
if (IsPlayer)
|
if (IsPlayer)
|
||||||
{
|
{
|
||||||
// Add a new blip for the ped
|
if (API.Config.DisplayBlip)
|
||||||
PedBlip=MainPed.AddBlip();
|
{
|
||||||
|
// Add a new blip for the ped
|
||||||
|
PedBlip=MainPed.AddBlip();
|
||||||
|
}
|
||||||
MainPed.AttachedBlip.Color = BlipColor.White;
|
MainPed.AttachedBlip.Color = BlipColor.White;
|
||||||
MainPed.AttachedBlip.Scale = 0.8f;
|
MainPed.AttachedBlip.Scale = 0.8f;
|
||||||
MainPed.AttachedBlip.Name =Username;
|
MainPed.AttachedBlip.Name =Username;
|
||||||
@ -295,7 +300,7 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
_lastClothes = Clothes;
|
_lastClothes = Clothes;
|
||||||
}
|
}
|
||||||
#region Onfoot
|
#region ONFOOT
|
||||||
#region -- VARIABLES --
|
#region -- VARIABLES --
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The latest character rotation (may not have been applied yet)
|
/// The latest character rotation (may not have been applied yet)
|
||||||
@ -567,14 +572,6 @@ namespace RageCoop.Client
|
|||||||
WalkTo();
|
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
|
#region WEAPON
|
||||||
private void CheckCurrentWeapon()
|
private void CheckCurrentWeapon()
|
||||||
@ -716,5 +713,14 @@ namespace RageCoop.Client
|
|||||||
return anim;
|
return anim;
|
||||||
}
|
}
|
||||||
#endregion
|
#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; }
|
if (LogLevel>4) { return; }
|
||||||
lock (Buffer)
|
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";
|
Buffer+=msg+"\r\n";
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,18 @@ using Lidgren.Network;
|
|||||||
|
|
||||||
namespace RageCoop.Core
|
namespace RageCoop.Core
|
||||||
{
|
{
|
||||||
|
public enum FileType:byte
|
||||||
|
{
|
||||||
|
Resource=0,
|
||||||
|
Custom=1,
|
||||||
|
}
|
||||||
public partial class Packets
|
public partial class Packets
|
||||||
{
|
{
|
||||||
public class FileTransferRequest : Packet
|
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; }
|
public long FileLength { get; set; }
|
||||||
|
|
||||||
@ -24,10 +29,11 @@ namespace RageCoop.Core
|
|||||||
List<byte> byteArray = new List<byte>();
|
List<byte> byteArray = new List<byte>();
|
||||||
|
|
||||||
// The ID from the download
|
// The ID from the download
|
||||||
byteArray.Add(ID);
|
byteArray.AddInt(ID);
|
||||||
|
|
||||||
|
|
||||||
// The name of the file
|
// 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(BitConverter.GetBytes(nameBytes.Length));
|
||||||
byteArray.AddRange(nameBytes);
|
byteArray.AddRange(nameBytes);
|
||||||
|
|
||||||
@ -46,29 +52,29 @@ namespace RageCoop.Core
|
|||||||
#region NetIncomingMessageToPacket
|
#region NetIncomingMessageToPacket
|
||||||
BitReader reader = new BitReader(array);
|
BitReader reader = new BitReader(array);
|
||||||
|
|
||||||
ID = reader.ReadByte();
|
ID = reader.ReadInt();
|
||||||
int nameArrayLength = reader.ReadInt();
|
int nameArrayLength = reader.ReadInt();
|
||||||
FileName = reader.ReadString(nameArrayLength);
|
Name = reader.ReadString(nameArrayLength);
|
||||||
FileLength = reader.ReadLong();
|
FileLength = reader.ReadLong();
|
||||||
#endregion
|
#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 byte[] FileChunk { get; set; }
|
||||||
|
|
||||||
public override void Pack(NetOutgoingMessage message)
|
public override void Pack(NetOutgoingMessage message)
|
||||||
{
|
{
|
||||||
#region PacketToNetOutGoingMessage
|
#region PacketToNetOutGoingMessage
|
||||||
message.Write((byte)PacketTypes.FileTransferTick);
|
message.Write((byte)PacketTypes.FileTransferChunk);
|
||||||
|
|
||||||
List<byte> byteArray = new List<byte>();
|
List<byte> byteArray = new List<byte>();
|
||||||
|
|
||||||
// The ID from the download
|
// The ID from the download
|
||||||
byteArray.Add(ID);
|
byteArray.AddInt(ID);
|
||||||
|
|
||||||
// The chunk of the file
|
// The chunk of the file
|
||||||
byteArray.AddRange(BitConverter.GetBytes(FileChunk.Length));
|
byteArray.AddRange(BitConverter.GetBytes(FileChunk.Length));
|
||||||
@ -86,7 +92,7 @@ namespace RageCoop.Core
|
|||||||
#region NetIncomingMessageToPacket
|
#region NetIncomingMessageToPacket
|
||||||
BitReader reader = new BitReader(array);
|
BitReader reader = new BitReader(array);
|
||||||
|
|
||||||
ID = reader.ReadByte();
|
ID = reader.ReadInt();
|
||||||
int chunkLength = reader.ReadInt();
|
int chunkLength = reader.ReadInt();
|
||||||
FileChunk = reader.ReadByteArray(chunkLength);
|
FileChunk = reader.ReadByteArray(chunkLength);
|
||||||
#endregion
|
#endregion
|
||||||
@ -95,7 +101,7 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
public class FileTransferComplete : Packet
|
public class FileTransferComplete : Packet
|
||||||
{
|
{
|
||||||
public byte ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
public override void Pack(NetOutgoingMessage message)
|
public override void Pack(NetOutgoingMessage message)
|
||||||
{
|
{
|
||||||
@ -105,7 +111,7 @@ namespace RageCoop.Core
|
|||||||
List<byte> byteArray = new List<byte>();
|
List<byte> byteArray = new List<byte>();
|
||||||
|
|
||||||
// The ID from the download
|
// The ID from the download
|
||||||
byteArray.Add(ID);
|
byteArray.AddInt(ID);
|
||||||
|
|
||||||
byte[] result = byteArray.ToArray();
|
byte[] result = byteArray.ToArray();
|
||||||
|
|
||||||
@ -119,7 +125,7 @@ namespace RageCoop.Core
|
|||||||
#region NetIncomingMessageToPacket
|
#region NetIncomingMessageToPacket
|
||||||
BitReader reader = new BitReader(array);
|
BitReader reader = new BitReader(array);
|
||||||
|
|
||||||
ID = reader.ReadByte();
|
ID = reader.ReadInt();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -123,13 +123,14 @@ namespace RageCoop.Core
|
|||||||
ChatMessage=10,
|
ChatMessage=10,
|
||||||
NativeCall=11,
|
NativeCall=11,
|
||||||
NativeResponse=12,
|
NativeResponse=12,
|
||||||
Mod=13,
|
//Mod=13,
|
||||||
CleanUpWorld=14,
|
CleanUpWorld=14,
|
||||||
FileTransferTick=15,
|
|
||||||
|
FileTransferChunk=15,
|
||||||
FileTransferRequest=16,
|
FileTransferRequest=16,
|
||||||
FileTransferComplete=17,
|
FileTransferComplete=17,
|
||||||
ServerClientEvent=18,
|
|
||||||
|
ServerClientEvent = 18,
|
||||||
#region Sync
|
#region Sync
|
||||||
|
|
||||||
#region INTERVAL
|
#region INTERVAL
|
||||||
@ -236,58 +237,6 @@ namespace RageCoop.Core
|
|||||||
|
|
||||||
public partial class Packets
|
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
|
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
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RageCoop.Core", "Core\RageCoop.Core.csproj", "{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RageCoop.Core", "Core\RageCoop.Core.csproj", "{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}"
|
||||||
EndProject
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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|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.ActiveCfg = Release|Any CPU
|
||||||
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|x64.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
|
||||||
{9DC11623-8A8B-4D17-B18B-91852922163D} = {F49A2617-832B-44DA-9D42-29B5DD09A186}
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {6CC7EA75-E4FF-4534-8EB6-0AEECF2620B7}
|
SolutionGuid = {6CC7EA75-E4FF-4534-8EB6-0AEECF2620B7}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
@ -1,17 +1,5 @@
|
|||||||
using RageCoop.Server.Scripting;
|
using RageCoop.Server.Scripting;
|
||||||
namespace RageCoop.Resources.Base
|
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 readonly Dictionary<string, object> _customData = new();
|
||||||
private long _callbacksCount = 0;
|
private long _callbacksCount = 0;
|
||||||
public readonly Dictionary<long, Action<object>> Callbacks = new();
|
public readonly Dictionary<long, Action<object>> Callbacks = new();
|
||||||
public bool FilesReceived { get;internal set; } = false;
|
public bool IsReady { get; internal set; }=false;
|
||||||
public bool FilesSent = false;
|
|
||||||
|
|
||||||
#region CUSTOMDATA FUNCTIONS
|
#region CUSTOMDATA FUNCTIONS
|
||||||
public void SetData<T>(string name, T data)
|
public void SetData<T>(string name, T data)
|
||||||
{
|
{
|
||||||
@ -189,9 +187,9 @@ namespace RageCoop.Server
|
|||||||
|
|
||||||
public void SendTriggerEvent(string eventName, params object[] args)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ using System.Linq;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using RageCoop.Core;
|
using RageCoop.Core;
|
||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
|
/*
|
||||||
namespace RageCoop.Server
|
namespace RageCoop.Server.Obsolete
|
||||||
{
|
{
|
||||||
public static class DownloadManager
|
public static class DownloadManager
|
||||||
{
|
{
|
||||||
@ -276,3 +276,4 @@ namespace RageCoop.Server
|
|||||||
public List<byte[]> FileChunks { get; set; } = null;
|
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";
|
Console.Title = "RAGECOOP";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (File.Exists("log.txt"))
|
|
||||||
{
|
|
||||||
File.WriteAllText("log.txt", string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
|
Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.SpecialKey == ConsoleSpecialKey.ControlC)
|
if (e.SpecialKey == ConsoleSpecialKey.ControlC)
|
||||||
@ -51,8 +46,7 @@ namespace RageCoop.Server
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Program.Logger.Error(e.InnerException?.Message ?? e.Message);
|
Logger.Error($"Fatal error occurred, server shutting down:{e}");
|
||||||
Console.ReadLine();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
<None Remove="Obsolete\**" />
|
<None Remove="Obsolete\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Core\RageCoop.Core.csproj" />
|
<ProjectReference Include="..\Core\RageCoop.Core.csproj" />
|
||||||
</ItemGroup>
|
</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 EventHandler<HandshakeEventArgs> OnPlayerHandshake;
|
||||||
public static event PlayerConnect OnPlayerConnected;
|
public static event PlayerConnect OnPlayerConnected;
|
||||||
public static event PlayerDisconnect OnPlayerDisconnected;
|
public static event PlayerDisconnect OnPlayerDisconnected;
|
||||||
// public static event EventHandler OnPlayerUpdate;
|
|
||||||
|
|
||||||
#region INVOKE
|
#region INVOKE
|
||||||
internal static void InvokeOnStop() { OnStop?.Invoke(); }
|
internal static void InvokeOnStop() { OnStop?.Invoke(); }
|
||||||
internal static void InvokeOnChatMessage(Packets.ChatMessage p,NetConnection con)
|
internal static void InvokeOnChatMessage(Packets.ChatMessage p,NetConnection con)
|
||||||
|
@ -24,7 +24,7 @@ namespace RageCoop.Server.Scripting
|
|||||||
}
|
}
|
||||||
private void LoadResource(string path)
|
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);
|
LoadScriptsFromAssembly(assembly);
|
||||||
}
|
}
|
||||||
|
521
Server/Server.cs
521
Server/Server.cs
@ -12,6 +12,7 @@ using Newtonsoft.Json;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using RageCoop.Server.Scripting;
|
using RageCoop.Server.Scripting;
|
||||||
|
|
||||||
namespace RageCoop.Server
|
namespace RageCoop.Server
|
||||||
@ -35,7 +36,8 @@ namespace RageCoop.Server
|
|||||||
|
|
||||||
public static readonly Dictionary<long,Client> Clients = 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 SendLatencyTimer = new System.Timers.Timer(5000);
|
||||||
public static readonly Engine ScriptingEngine = new();
|
|
||||||
|
private static Dictionary<int,FileTransfer> InProgressFileTransfers=new();
|
||||||
public Server()
|
public Server()
|
||||||
{
|
{
|
||||||
Program.Logger.Info("================");
|
Program.Logger.Info("================");
|
||||||
@ -169,10 +171,7 @@ namespace RageCoop.Server
|
|||||||
}).Start();
|
}).Start();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
ScriptingEngine.LoadAll();
|
Resources.LoadAll();
|
||||||
Program.Logger.Info("Searching for client-side files...");
|
|
||||||
DownloadManager.CheckForDirectoryAndFiles();
|
|
||||||
|
|
||||||
|
|
||||||
Listen();
|
Listen();
|
||||||
}
|
}
|
||||||
@ -192,25 +191,6 @@ namespace RageCoop.Server
|
|||||||
while (!Program.ReadyToStop)
|
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
|
// 15 milliseconds to sleep to reduce CPU usage
|
||||||
Thread.Sleep(15);
|
Thread.Sleep(15);
|
||||||
@ -269,7 +249,6 @@ namespace RageCoop.Server
|
|||||||
{
|
{
|
||||||
long nethandle = message.SenderConnection.RemoteUniqueIdentifier;
|
long nethandle = message.SenderConnection.RemoteUniqueIdentifier;
|
||||||
|
|
||||||
DownloadManager.RemoveClient(nethandle);
|
|
||||||
|
|
||||||
SendPlayerDisconnectPacket(nethandle);
|
SendPlayerDisconnectPacket(nethandle);
|
||||||
}
|
}
|
||||||
@ -280,251 +259,182 @@ namespace RageCoop.Server
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NetIncomingMessageType.Data:
|
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
|
switch (type)
|
||||||
|
|
||||||
case PacketTypes.PedStateSync:
|
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
int len = message.ReadInt32();
|
|
||||||
byte[] data = message.ReadBytes(len);
|
|
||||||
|
|
||||||
Packets.PedStateSync packet = new();
|
#region SyncData
|
||||||
packet.Unpack(data);
|
|
||||||
|
|
||||||
PedStateSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
|
case PacketTypes.PedStateSync:
|
||||||
}
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
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);
|
|
||||||
|
|
||||||
Packets.FileTransferComplete packet = new();
|
case PacketTypes.NativeResponse:
|
||||||
|
{
|
||||||
|
Packets.NativeResponse packet = new();
|
||||||
packet.Unpack(data);
|
packet.Unpack(data);
|
||||||
|
|
||||||
Client client = Util.GetClientByNetID(message.SenderConnection.RemoteUniqueIdentifier);
|
Client client = Util.GetClientByNetID(message.SenderConnection.RemoteUniqueIdentifier);
|
||||||
if (client != null && !client.FilesReceived)
|
if (client != null)
|
||||||
{
|
{
|
||||||
DownloadManager.TryToRemoveClient(client.NetID, packet.ID);
|
if (client.Callbacks.ContainsKey(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()
|
|
||||||
{
|
{
|
||||||
Client = client,
|
client.Callbacks[packet.ID].Invoke(packet.Args[0]);
|
||||||
Args = packet.Args.ToArray()
|
client.Callbacks.Remove(packet.ID);
|
||||||
};
|
}
|
||||||
|
|
||||||
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;
|
||||||
catch (Exception e)
|
case PacketTypes.ServerClientEvent:
|
||||||
{
|
|
||||||
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 =>
|
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
if (client != null)
|
||||||
}
|
{
|
||||||
catch (Exception e)
|
if (TriggerEvents.Any(x => x.Key.EventName == packet.EventName))
|
||||||
{
|
{
|
||||||
DisconnectAndLog(message.SenderConnection, type, e);
|
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
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
Program.Logger.Error("Unhandled Data / Packet type");
|
{
|
||||||
}
|
DisconnectAndLog(message.SenderConnection, type, e);
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case NetIncomingMessageType.ConnectionLatencyUpdated:
|
case NetIncomingMessageType.ConnectionLatencyUpdated:
|
||||||
{
|
{
|
||||||
Client client = Util.GetClientByNetID(message.SenderConnection.RemoteUniqueIdentifier);
|
Client client = Util.GetClientByNetID(message.SenderConnection.RemoteUniqueIdentifier);
|
||||||
@ -579,7 +489,7 @@ namespace RageCoop.Server
|
|||||||
senderConnection.Disconnect(e.Message);
|
senderConnection.Disconnect(e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region -- PLAYER --
|
#region -- SYNC --
|
||||||
// Before we approve the connection, we must shake hands
|
// Before we approve the connection, we must shake hands
|
||||||
private void GetHandshake(NetConnection connection, Packets.Handshake packet)
|
private void GetHandshake(NetConnection connection, Packets.Handshake packet)
|
||||||
{
|
{
|
||||||
@ -649,7 +559,7 @@ namespace RageCoop.Server
|
|||||||
return;
|
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();
|
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||||
|
|
||||||
// Create a new handshake packet
|
// Create a new handshake packet
|
||||||
@ -673,18 +583,20 @@ namespace RageCoop.Server
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<NetConnection> clients;
|
List<NetConnection> clients=MainNetServer.Connections.Exclude(local);
|
||||||
if ((clients = Util.FilterAllLocal(local)).Count > 0)
|
// Send all players to local
|
||||||
|
|
||||||
|
|
||||||
|
if (clients.Count > 0)
|
||||||
{
|
{
|
||||||
// Send all players to local
|
clients.ForEach(targetPlayer =>
|
||||||
clients.ForEach(targetPlayer =>
|
|
||||||
{
|
{
|
||||||
long targetNetHandle = targetPlayer.RemoteUniqueIdentifier;
|
long targetNetHandle = targetPlayer.RemoteUniqueIdentifier;
|
||||||
|
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||||
|
|
||||||
Client targetClient = Util.GetClientByNetID(targetNetHandle);
|
Client targetClient = Util.GetClientByNetID(targetNetHandle);
|
||||||
if (targetClient != null)
|
if (targetClient != null)
|
||||||
{
|
{
|
||||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
|
||||||
new Packets.PlayerConnect()
|
new Packets.PlayerConnect()
|
||||||
{
|
{
|
||||||
// NetHandle = targetNetHandle,
|
// NetHandle = targetNetHandle,
|
||||||
@ -700,11 +612,13 @@ namespace RageCoop.Server
|
|||||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||||
new Packets.PlayerConnect()
|
new Packets.PlayerConnect()
|
||||||
{
|
{
|
||||||
// NetHandle = local.RemoteUniqueIdentifier,
|
|
||||||
PedID=localClient.Player.PedID,
|
PedID=localClient.Player.PedID,
|
||||||
Username = localClient.Player.Username
|
Username = localClient.Player.Username
|
||||||
}.Pack(outgoingMessage);
|
}.Pack(outgoingMessage);
|
||||||
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
|
if(clients.Count > 0)
|
||||||
|
{
|
||||||
|
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
API.Events.InvokePlayerConnected(localClient);
|
API.Events.InvokePlayerConnected(localClient);
|
||||||
|
|
||||||
@ -757,10 +671,11 @@ namespace RageCoop.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
|
||||||
packet.Pack(outgoingMessage);
|
|
||||||
foreach (var c in Clients.Values)
|
foreach (var c in Clients.Values)
|
||||||
{
|
{
|
||||||
|
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||||
|
packet.Pack(outgoingMessage);
|
||||||
if (c.NetID==client.NetID) { continue; }
|
if (c.NetID==client.NetID) { continue; }
|
||||||
MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync);
|
MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync);
|
||||||
}
|
}
|
||||||
@ -796,8 +711,7 @@ namespace RageCoop.Server
|
|||||||
}
|
}
|
||||||
bool isPlayer = packet.ID==client.Player.PedID;
|
bool isPlayer = packet.ID==client.Player.PedID;
|
||||||
if (isPlayer) { client.Player.Position=packet.Position; }
|
if (isPlayer) { client.Player.Position=packet.Position; }
|
||||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
|
||||||
packet.Pack(outgoingMessage);
|
|
||||||
foreach (var c in Clients.Values)
|
foreach (var c in Clients.Values)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -816,6 +730,9 @@ namespace RageCoop.Server
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||||
|
packet.Pack(outgoingMessage);
|
||||||
MainNetServer.SendMessage(outgoingMessage,c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync);
|
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));
|
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
|
// 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)
|
public static List<NetConnection> FilterAllLocal(long local)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user