never gonna give~
BIN
Images/LOGO.png
Before Width: | Height: | Size: 106 KiB |
@ -7,9 +7,10 @@
|
|||||||
[![Issues][issues-shield]][issues-url]
|
[![Issues][issues-shield]][issues-url]
|
||||||
|
|
||||||
|
|
||||||
# Disclaimer
|
# ⚠ Notice
|
||||||
The original author of this project is [EntenKoeniq](https://github.com/EntenKoeniq).
|
The original author of this project is [EntenKoeniq](https://github.com/EntenKoeniq).
|
||||||
The project has been reworked and is currently maintained by [Sardelka9515](https://github.com/Sardelka9515).
|
The project has been reworked and is currently maintained by [Sardelka9515](https://github.com/Sardelka9515).
|
||||||
|
To download the legacy versions, go to [this repository](https://github.com/RAGECOOP/RAGECOOP-V.OLD)
|
||||||
|
|
||||||
# 🧠 That's it
|
# 🧠 That's it
|
||||||
RAGECOOP is a multiplayer mod to play story mode or some mods made for RAGECOOP or just drive around with your buddy.
|
RAGECOOP is a multiplayer mod to play story mode or some mods made for RAGECOOP or just drive around with your buddy.
|
||||||
@ -28,6 +29,7 @@ _Old name: GTACOOP:R_
|
|||||||
- - No new features (only improvements)
|
- - No new features (only improvements)
|
||||||
- [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json/13.0.1)
|
- [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json/13.0.1)
|
||||||
- [ClearScript](https://github.com/microsoft/ClearScript)
|
- [ClearScript](https://github.com/microsoft/ClearScript)
|
||||||
|
- [SharpZipLib](https://github.com/icsharpcode/SharpZipLib)
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<Description>An API reference for developing client-side resource for RAGECOOP</Description>
|
<Description>An API reference for developing client-side resource for RAGECOOP</Description>
|
||||||
<PackageProjectUrl>https://ragecoop.online/</PackageProjectUrl>
|
<PackageProjectUrl>https://ragecoop.online/</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/RAGECOOP/RAGECOOP-V</RepositoryUrl>
|
<RepositoryUrl>https://github.com/RAGECOOP/RAGECOOP-V</RepositoryUrl>
|
||||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="favicon.ico" />
|
<Content Include="icon.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@ -48,7 +48,7 @@ namespace RageCoop.Server
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = new Server(mainLogger);
|
_ = new Server(Util.Read<ServerSettings>("Settings.xml"), mainLogger);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<Description>An library for hosting a RAGECOOP server or API reference for developing a resource.</Description>
|
<Description>An library for hosting a RAGECOOP server or API reference for developing a resource.</Description>
|
||||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -26,7 +27,14 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="favicon.ico" />
|
<Content Include="icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\images\icon.png">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -17,45 +17,40 @@ namespace RageCoop.Server.Scripting
|
|||||||
Server = server;
|
Server = server;
|
||||||
}
|
}
|
||||||
private List<string> ClientResourceZips=new List<string>();
|
private List<string> ClientResourceZips=new List<string>();
|
||||||
public bool HasClientResources { get; private set; }
|
|
||||||
public void LoadAll()
|
public void LoadAll()
|
||||||
{
|
{
|
||||||
#region CLIENT
|
// Client
|
||||||
|
{
|
||||||
var path = Path.Combine("Resources", "Client");
|
var path = Path.Combine("Resources", "Client");
|
||||||
var tmp = Path.Combine("Resources", "ClientTemp");
|
var tmpDir = Path.Combine("Resources", "Temp");
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
if (Directory.Exists(tmp))
|
if (Directory.Exists(tmpDir))
|
||||||
{
|
{
|
||||||
foreach(var dir in Directory.GetDirectories(tmp))
|
Directory.Delete(tmpDir, true);
|
||||||
{
|
|
||||||
Directory.Delete(dir, true);
|
|
||||||
}
|
}
|
||||||
}
|
Directory.CreateDirectory(tmpDir);
|
||||||
else
|
var resourceFolders = Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly);
|
||||||
{
|
|
||||||
Directory.CreateDirectory(tmp);
|
|
||||||
}
|
|
||||||
var resourceFolders = Directory.GetDirectories(path,"*",SearchOption.TopDirectoryOnly);
|
|
||||||
if (resourceFolders.Length!=0)
|
if (resourceFolders.Length!=0)
|
||||||
{
|
{
|
||||||
HasClientResources=true;
|
|
||||||
foreach (var resourceFolder in resourceFolders)
|
foreach (var resourceFolder in resourceFolders)
|
||||||
{
|
{
|
||||||
// Pack client side resource as a zip file
|
// Pack client side resource as a zip file
|
||||||
Logger?.Info("Packing client-side resource:"+resourceFolder);
|
Logger?.Info("Packing client-side resource: "+resourceFolder);
|
||||||
var zipPath = Path.Combine(tmp, Path.GetFileName(resourceFolder));
|
var zipPath = Path.Combine(tmpDir, Path.GetFileName(resourceFolder))+".zip";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (ZipFile zip = ZipFile.Create(zipPath))
|
using (ZipFile zip = ZipFile.Create(zipPath))
|
||||||
{
|
{
|
||||||
|
zip.BeginUpdate();
|
||||||
foreach (var dir in Directory.GetDirectories(resourceFolder, "*", SearchOption.AllDirectories))
|
foreach (var dir in Directory.GetDirectories(resourceFolder, "*", SearchOption.AllDirectories))
|
||||||
{
|
{
|
||||||
zip.AddDirectory(dir.Substring(resourceFolder.Length+1));
|
zip.AddDirectory(dir.Substring(resourceFolder.Length+1));
|
||||||
}
|
}
|
||||||
foreach (var file in Directory.GetFiles(resourceFolder, "*", SearchOption.AllDirectories))
|
foreach (var file in Directory.GetFiles(resourceFolder, "*", SearchOption.AllDirectories))
|
||||||
{
|
{
|
||||||
zip.Add(file,file.Substring(resourceFolder.Length+1));
|
zip.Add(file, file.Substring(resourceFolder.Length+1));
|
||||||
}
|
}
|
||||||
|
zip.CommitUpdate();
|
||||||
zip.Close();
|
zip.Close();
|
||||||
ClientResourceZips.Add(zipPath);
|
ClientResourceZips.Add(zipPath);
|
||||||
}
|
}
|
||||||
@ -70,22 +65,22 @@ namespace RageCoop.Server.Scripting
|
|||||||
var packed = Directory.GetFiles(path, "*.zip", SearchOption.TopDirectoryOnly);
|
var packed = Directory.GetFiles(path, "*.zip", SearchOption.TopDirectoryOnly);
|
||||||
if (packed.Length>0)
|
if (packed.Length>0)
|
||||||
{
|
{
|
||||||
HasClientResources =true;
|
|
||||||
ClientResourceZips.AddRange(packed);
|
ClientResourceZips.AddRange(packed);
|
||||||
}
|
}
|
||||||
#endregion
|
}
|
||||||
|
|
||||||
#region SERVER
|
// Server
|
||||||
path = Path.Combine("Resources", "Server");
|
{
|
||||||
|
var path = Path.Combine("Resources", "Server");
|
||||||
var dataFolder = Path.Combine(path, "data");
|
var dataFolder = Path.Combine(path, "data");
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
foreach (var resource in Directory.GetDirectories(path))
|
foreach (var resource in Directory.GetDirectories(path))
|
||||||
{
|
{
|
||||||
if (Path.GetFileName(resource).ToLower()=="data") { continue; }
|
if (Path.GetFileName(resource).ToLower()=="data") { continue; }
|
||||||
Logger?.Info($"Loading resource: {Path.GetFileName(resource)}");
|
Logger?.Info($"Loading resource: {Path.GetFileName(resource)}");
|
||||||
LoadResource(resource,dataFolder);
|
LoadResource(resource, dataFolder);
|
||||||
}
|
}
|
||||||
foreach(var resource in Directory.GetFiles(path, "*.zip", SearchOption.TopDirectoryOnly))
|
foreach (var resource in Directory.GetFiles(path, "*.zip", SearchOption.TopDirectoryOnly))
|
||||||
{
|
{
|
||||||
Logger?.Info($"Loading resource: {Path.GetFileName(resource)}");
|
Logger?.Info($"Loading resource: {Path.GetFileName(resource)}");
|
||||||
LoadResource(new ZipFile(resource), dataFolder);
|
LoadResource(new ZipFile(resource), dataFolder);
|
||||||
@ -104,11 +99,11 @@ namespace RageCoop.Server.Scripting
|
|||||||
Logger?.Debug("Starting script:"+s.CurrentFile.Name);
|
Logger?.Debug("Starting script:"+s.CurrentFile.Name);
|
||||||
s.OnStart();
|
s.OnStart();
|
||||||
}
|
}
|
||||||
catch(Exception ex) {Logger?.Error($"Failed to start resource: {r.Name}"); Logger?.Error(ex); }
|
catch (Exception ex) { Logger?.Error($"Failed to start resource: {r.Name}"); Logger?.Error(ex); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopAll()
|
public void StopAll()
|
||||||
@ -135,13 +130,13 @@ namespace RageCoop.Server.Scripting
|
|||||||
public void SendTo(Client client)
|
public void SendTo(Client client)
|
||||||
{
|
{
|
||||||
|
|
||||||
string path;
|
if (ClientResourceZips.Count!=0)
|
||||||
if (HasClientResources && File.Exists(path = Path.Combine("Resources", "Client", "Resources.zip")))
|
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
Logger?.Info($"Sending resources to client:{client.Username}");
|
Logger?.Info($"Sending resources to client:{client.Username}");
|
||||||
Server.SendFile(path, "Resources.zip", client);
|
|
||||||
|
|
||||||
Logger?.Info($"Resources sent to:{client.Username}");
|
Logger?.Info($"Resources sent to:{client.Username}");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -28,7 +28,7 @@ namespace RageCoop.Server
|
|||||||
{
|
{
|
||||||
private readonly string _compatibleVersion = "V0_5";
|
private readonly string _compatibleVersion = "V0_5";
|
||||||
internal BaseScript BaseScript { get; set; }=new BaseScript();
|
internal BaseScript BaseScript { get; set; }=new BaseScript();
|
||||||
internal readonly Settings MainSettings = Util.Read<Settings>("Settings.xml");
|
internal readonly ServerSettings Settings;
|
||||||
internal NetServer MainNetServer;
|
internal NetServer MainNetServer;
|
||||||
|
|
||||||
internal readonly Dictionary<Command, Action<CommandContext>> Commands = new();
|
internal readonly Dictionary<Command, Action<CommandContext>> Commands = new();
|
||||||
@ -40,14 +40,17 @@ namespace RageCoop.Server
|
|||||||
public API API { get; private set; }
|
public API API { get; private set; }
|
||||||
internal Logger Logger;
|
internal Logger Logger;
|
||||||
private Security Security;
|
private Security Security;
|
||||||
public Server(Logger logger=null)
|
public Server(ServerSettings settings,Logger logger=null)
|
||||||
{
|
{
|
||||||
|
Settings = settings;
|
||||||
|
if (settings==null) { throw new ArgumentNullException("Server settings cannot be null!"); }
|
||||||
Logger=logger;
|
Logger=logger;
|
||||||
|
if (Logger!=null) { Logger.LogLevel=Settings.LogLevel;}
|
||||||
API=new API(this);
|
API=new API(this);
|
||||||
Resources=new Resources(this);
|
Resources=new Resources(this);
|
||||||
Security=new Security(Logger);
|
Security=new Security(Logger);
|
||||||
Logger?.Info("================");
|
Logger?.Info("================");
|
||||||
Logger?.Info($"Server bound to: 0.0.0.0:{MainSettings.Port}");
|
Logger?.Info($"Server bound to: 0.0.0.0:{Settings.Port}");
|
||||||
Logger?.Info($"Server version: {Assembly.GetCallingAssembly().GetName().Version}");
|
Logger?.Info($"Server version: {Assembly.GetCallingAssembly().GetName().Version}");
|
||||||
Logger?.Info($"Compatible RAGECOOP versions: {_compatibleVersion.Replace('_', '.')}.x");
|
Logger?.Info($"Compatible RAGECOOP versions: {_compatibleVersion.Replace('_', '.')}.x");
|
||||||
Logger?.Info("================");
|
Logger?.Info("================");
|
||||||
@ -55,8 +58,8 @@ namespace RageCoop.Server
|
|||||||
// 623c92c287cc392406e7aaaac1c0f3b0 = RAGECOOP
|
// 623c92c287cc392406e7aaaac1c0f3b0 = RAGECOOP
|
||||||
NetPeerConfiguration config = new("623c92c287cc392406e7aaaac1c0f3b0")
|
NetPeerConfiguration config = new("623c92c287cc392406e7aaaac1c0f3b0")
|
||||||
{
|
{
|
||||||
Port = MainSettings.Port,
|
Port = Settings.Port,
|
||||||
MaximumConnections = MainSettings.MaxPlayers,
|
MaximumConnections = Settings.MaxPlayers,
|
||||||
EnableUPnP = false,
|
EnableUPnP = false,
|
||||||
AutoFlushSendQueue = true
|
AutoFlushSendQueue = true
|
||||||
};
|
};
|
||||||
@ -71,7 +74,7 @@ namespace RageCoop.Server
|
|||||||
SendPlayerTimer.AutoReset=true;
|
SendPlayerTimer.AutoReset=true;
|
||||||
SendPlayerTimer.Enabled=true;
|
SendPlayerTimer.Enabled=true;
|
||||||
Logger?.Info(string.Format("Server listening on {0}:{1}", config.LocalAddress.ToString(), config.Port));
|
Logger?.Info(string.Format("Server listening on {0}:{1}", config.LocalAddress.ToString(), config.Port));
|
||||||
if (MainSettings.AnnounceSelf)
|
if (Settings.AnnounceSelf)
|
||||||
{
|
{
|
||||||
|
|
||||||
#region -- MASTERSERVER --
|
#region -- MASTERSERVER --
|
||||||
@ -104,17 +107,17 @@ namespace RageCoop.Server
|
|||||||
Logger?.Error(ex.InnerException?.Message ?? ex.Message);
|
Logger?.Error(ex.InnerException?.Message ?? ex.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var realMaster = MainSettings.MasterServer=="[AUTO]" ? Util.DownloadString("https://ragecoop.online/stuff/masterserver") : MainSettings.MasterServer;
|
var realMaster = Settings.MasterServer=="[AUTO]" ? Util.DownloadString("https://ragecoop.online/stuff/masterserver") : Settings.MasterServer;
|
||||||
while (!Program.ReadyToStop)
|
while (!Program.ReadyToStop)
|
||||||
{
|
{
|
||||||
string msg =
|
string msg =
|
||||||
"{ " +
|
"{ " +
|
||||||
"\"address\": \"" + info.Address + "\", " +
|
"\"address\": \"" + info.Address + "\", " +
|
||||||
"\"port\": \"" + MainSettings.Port + "\", " +
|
"\"port\": \"" + Settings.Port + "\", " +
|
||||||
"\"name\": \"" + MainSettings.Name + "\", " +
|
"\"name\": \"" + Settings.Name + "\", " +
|
||||||
"\"version\": \"" + _compatibleVersion.Replace("_", ".") + "\", " +
|
"\"version\": \"" + _compatibleVersion.Replace("_", ".") + "\", " +
|
||||||
"\"players\": \"" + MainNetServer.ConnectionsCount + "\", " +
|
"\"players\": \"" + MainNetServer.ConnectionsCount + "\", " +
|
||||||
"\"maxPlayers\": \"" + MainSettings.MaxPlayers + "\"" +
|
"\"maxPlayers\": \"" + Settings.MaxPlayers + "\"" +
|
||||||
" }";
|
" }";
|
||||||
HttpResponseMessage response = null;
|
HttpResponseMessage response = null;
|
||||||
try
|
try
|
||||||
@ -583,9 +586,9 @@ namespace RageCoop.Server
|
|||||||
|
|
||||||
Logger?.Info($"Player {newClient.Username} connected!");
|
Logger?.Info($"Player {newClient.Username} connected!");
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(MainSettings.WelcomeMessage))
|
if (!string.IsNullOrEmpty(Settings.WelcomeMessage))
|
||||||
{
|
{
|
||||||
SendChatMessage(new Packets.ChatMessage() { Username = "Server", Message = MainSettings.WelcomeMessage }, null,new List<NetConnection>() { newClient.Connection });
|
SendChatMessage(new Packets.ChatMessage() { Username = "Server", Message = Settings.WelcomeMessage }, null,new List<NetConnection>() { newClient.Connection });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,12 +662,12 @@ namespace RageCoop.Server
|
|||||||
// Check streaming distance
|
// Check streaming distance
|
||||||
if (isPlayer)
|
if (isPlayer)
|
||||||
{
|
{
|
||||||
if ((MainSettings.PlayerStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>MainSettings.PlayerStreamingDistance))
|
if ((Settings.PlayerStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.PlayerStreamingDistance))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((MainSettings.NpcStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>MainSettings.NpcStreamingDistance))
|
else if ((Settings.NpcStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.NpcStreamingDistance))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -683,13 +686,13 @@ namespace RageCoop.Server
|
|||||||
if (isPlayer)
|
if (isPlayer)
|
||||||
{
|
{
|
||||||
// Player's vehicle
|
// Player's vehicle
|
||||||
if ((MainSettings.PlayerStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>MainSettings.PlayerStreamingDistance))
|
if ((Settings.PlayerStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.PlayerStreamingDistance))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if((MainSettings.NpcStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>MainSettings.NpcStreamingDistance))
|
else if((Settings.NpcStreamingDistance!=-1)&&(packet.Position.DistanceTo(c.Player.Position)>Settings.NpcStreamingDistance))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
namespace RageCoop.Server
|
namespace RageCoop.Server
|
||||||
{
|
{
|
||||||
public class Settings
|
public class ServerSettings
|
||||||
{
|
{
|
||||||
public int Port { get; set; } = 4499;
|
public int Port { get; set; } = 4499;
|
||||||
public int MaxPlayers { get; set; } = 32;
|
public int MaxPlayers { get; set; } = 32;
|
||||||
@ -10,7 +10,11 @@
|
|||||||
public bool HolePunch { get; set; } = true;
|
public bool HolePunch { get; set; } = true;
|
||||||
public bool AnnounceSelf { get; set; } = false;
|
public bool AnnounceSelf { get; set; } = false;
|
||||||
public string MasterServer { get; set; } = "[AUTO]";
|
public string MasterServer { get; set; } = "[AUTO]";
|
||||||
public bool DebugMode { get; set; } = false;
|
|
||||||
|
/// <summary>
|
||||||
|
/// See <see cref="Core.Logger.LogLevel"/>.
|
||||||
|
/// </summary>
|
||||||
|
public int LogLevel=2;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NPC data won't be sent to a player if their distance is greater than this value. -1 for unlimited.
|
/// NPC data won't be sent to a player if their distance is greater than this value. -1 for unlimited.
|
||||||
/// </summary>
|
/// </summary>
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
BIN
images/icon.ico
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
images/icon.png
Normal file
After Width: | Height: | Size: 1.9 KiB |