Files
RAGECOOP-V/Server/Scripting/Resources.cs

287 lines
10 KiB
C#
Raw Normal View History

2022-10-23 19:02:39 +08:00
using System;
using System.IO;
2022-09-08 12:41:56 -07:00
using System.Threading.Tasks;
2022-10-23 19:02:39 +08:00
using DiscUtils.Iso9660;
using ICSharpCode.SharpZipLib.Zip;
using RageCoop.Core;
namespace RageCoop.Server.Scripting;
2022-10-15 17:06:19 +08:00
2022-10-23 19:02:39 +08:00
internal class Resources
{
2022-10-23 19:02:39 +08:00
private readonly Dictionary<string, Stream> ClientResources = new();
private readonly Logger Logger;
private readonly Dictionary<CDReader, Stream> Packages = new();
private readonly Dictionary<string, Stream> ResourceStreams = new();
private readonly Server Server;
public Dictionary<string, ServerResource> LoadedResources = new();
public Resources(Server server)
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
Server = server;
Logger = server.Logger;
}
2023-02-27 11:54:02 +08:00
static Resources()
{
CoreUtils.ForceLoadAllAssemblies();
}
2022-10-23 19:02:39 +08:00
public bool IsLoaded { get; private set; }
public void LoadAll()
{
// Packages
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
var path = Path.Combine("Resources", "Packages");
Directory.CreateDirectory(path);
foreach (var pkg in Directory.GetFiles(path, "*.respkg", SearchOption.AllDirectories))
try
2022-08-23 12:21:17 +08:00
{
2022-10-23 19:02:39 +08:00
Logger?.Debug($"Adding resources from package \"{Path.GetFileNameWithoutExtension(pkg)}\"");
var pkgStream = File.Open(pkg, FileMode.Open, FileAccess.Read, FileShare.Read);
var reader = new CDReader(pkgStream, true);
foreach (var e in reader.Root.GetDirectories("Client")[0].GetFiles())
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
var name = Path.GetFileNameWithoutExtension(e.Name);
if (!ClientResources.TryAdd(name, e.Open(FileMode.Open)))
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
Logger?.Warning($"Resource \"{name}\" already added, ignoring");
continue;
2022-09-08 12:41:56 -07:00
}
2022-08-23 12:21:17 +08:00
2022-10-23 19:02:39 +08:00
Logger?.Debug("Resource added: " + name);
}
2022-08-23 12:21:17 +08:00
2022-10-23 19:02:39 +08:00
foreach (var e in reader.Root.GetDirectories("Server")[0].GetFiles())
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
var name = Path.GetFileNameWithoutExtension(e.Name);
if (!ResourceStreams.TryAdd(name, e.Open(FileMode.Open)))
2022-10-15 17:06:19 +08:00
{
2022-10-23 19:02:39 +08:00
Logger?.Warning($"Resource \"{name}\" already loaded, ignoring");
2022-10-15 17:06:19 +08:00
continue;
}
2022-10-23 19:02:39 +08:00
Logger?.Debug("Resource added: " + name);
2022-09-08 12:41:56 -07:00
}
2022-10-23 19:02:39 +08:00
Packages.Add(reader, pkgStream);
2022-09-08 12:41:56 -07:00
}
2022-10-23 19:02:39 +08:00
catch (Exception ex)
{
Logger?.Error("Failed to read resources from package: " + pkg, ex);
}
}
2022-10-23 19:02:39 +08:00
// Client
{
var path = Path.Combine("Resources", "Client");
var tmpDir = Path.Combine("Resources", "Temp", "Client");
Directory.CreateDirectory(path);
if (Directory.Exists(tmpDir)) Directory.Delete(tmpDir, true);
Directory.CreateDirectory(tmpDir);
var resourceFolders = Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly);
if (resourceFolders.Length != 0)
foreach (var resourceFolder in resourceFolders)
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
var zipPath = Path.Combine(tmpDir, Path.GetFileName(resourceFolder)) + ".res";
var name = Path.GetFileNameWithoutExtension(zipPath);
if (ClientResources.ContainsKey(name))
{
Logger?.Warning($"Client resource \"{name}\" already loaded, ignoring");
continue;
}
// Pack client side resource as a zip file
Logger?.Info("Packing client-side resource: " + resourceFolder);
2022-07-01 12:22:31 +08:00
try
{
2022-10-23 19:02:39 +08:00
using var zip = ZipFile.Create(zipPath);
zip.BeginUpdate();
foreach (var dir in Directory.GetDirectories(resourceFolder, "*", SearchOption.AllDirectories))
zip.AddDirectory(dir[(resourceFolder.Length + 1)..]);
foreach (var file in Directory.GetFiles(resourceFolder, "*", SearchOption.AllDirectories))
2022-07-01 12:22:31 +08:00
{
2022-10-23 19:02:39 +08:00
zip.Add(file, file[(resourceFolder.Length + 1)..]);
2022-09-08 12:41:56 -07:00
}
2022-10-23 19:02:39 +08:00
zip.CommitUpdate();
zip.Close();
ClientResources.Add(name, File.OpenRead(zipPath));
2022-09-08 12:41:56 -07:00
}
catch (Exception ex)
{
2022-10-23 19:02:39 +08:00
Logger?.Error($"Failed to pack client resource:{resourceFolder}");
2022-09-08 12:41:56 -07:00
Logger?.Error(ex);
}
}
2022-10-23 19:02:39 +08:00
}
// Server
{
var path = Path.Combine("Resources", "Server");
var dataFolder = Path.Combine(path, "data");
Directory.CreateDirectory(path);
foreach (var resource in Directory.GetDirectories(path))
try
2022-08-23 12:21:17 +08:00
{
2022-10-23 19:02:39 +08:00
var name = Path.GetFileName(resource);
if (LoadedResources.ContainsKey(name))
2022-07-01 12:22:31 +08:00
{
2022-10-23 19:02:39 +08:00
Logger?.Warning($"Resource \"{name}\" has already been loaded, ignoring...");
continue;
2022-07-01 12:22:31 +08:00
}
2022-10-23 19:02:39 +08:00
if (name.ToLower() == "data") continue;
Logger?.Info($"Loading resource: {name}");
var r = ServerResource.LoadFrom(resource, dataFolder, Logger);
LoadedResources.Add(r.Name, r);
}
catch (Exception ex)
{
Logger?.Error($"Failed to load resource: {Path.GetFileName(resource)}");
Logger?.Error(ex);
2022-08-23 12:21:17 +08:00
}
2022-10-23 19:02:39 +08:00
foreach (var res in ResourceStreams)
try
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
var name = res.Key;
if (LoadedResources.ContainsKey(name))
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
Logger?.Warning($"Resource \"{name}\" has already been loaded, ignoring...");
continue;
2022-09-08 12:41:56 -07:00
}
2022-10-23 19:02:39 +08:00
Logger?.Info("Loading resource: " + name);
var r = ServerResource.LoadFrom(res.Value, name, Path.Combine("Resources", "Temp", "Server"),
dataFolder, Logger);
LoadedResources.Add(r.Name, r);
}
catch (Exception ex)
{
Logger?.Error($"Failed to load resource: {res.Key}");
Logger?.Error(ex);
2022-09-08 12:41:56 -07:00
}
2022-10-23 19:02:39 +08:00
// Start scripts
2022-09-08 12:41:56 -07:00
lock (LoadedResources)
{
2022-10-23 19:02:39 +08:00
foreach (var r in LoadedResources.Values)
foreach (var s in r.Scripts.Values)
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
s.API = Server.API;
2022-07-01 12:22:31 +08:00
try
{
2022-10-23 19:02:39 +08:00
Logger?.Debug("Starting script:" + s.CurrentFile.Name);
s.OnStart();
2022-09-08 12:41:56 -07:00
}
catch (Exception ex)
2022-07-01 12:22:31 +08:00
{
2022-10-23 19:02:39 +08:00
Logger?.Error($"Failed to start resource: {r.Name}");
Logger?.Error(ex);
2022-07-01 12:22:31 +08:00
}
2022-09-08 12:41:56 -07:00
}
}
2022-10-23 19:02:39 +08:00
IsLoaded = true;
}
}
public void UnloadAll()
{
lock (LoadedResources)
{
foreach (var d in LoadedResources.Values)
2022-08-23 12:21:17 +08:00
{
2022-10-23 19:02:39 +08:00
foreach (var s in d.Scripts.Values)
try
{
s.OnStop();
}
catch (Exception ex)
{
Logger?.Error(ex);
}
2022-08-23 12:21:17 +08:00
try
{
2022-10-23 19:02:39 +08:00
d.Dispose();
2022-08-23 12:21:17 +08:00
}
2022-09-08 12:41:56 -07:00
catch (Exception ex)
2022-08-23 12:21:17 +08:00
{
2022-10-23 19:02:39 +08:00
Logger.Error($"Resource \"{d.Name}\" cannot be unloaded.");
Logger.Error(ex);
2022-08-23 12:21:17 +08:00
}
}
2022-10-23 19:02:39 +08:00
LoadedResources.Clear();
}
foreach (var s in ClientResources.Values)
try
2022-09-06 21:46:35 +08:00
{
2022-10-23 19:02:39 +08:00
s.Close();
s.Dispose();
}
catch (Exception ex)
{
Logger?.Error("[Resources.CloseStream]", ex);
}
foreach (var s in ResourceStreams.Values)
try
{
s.Close();
s.Dispose();
2022-09-06 21:46:35 +08:00
}
2022-10-23 19:02:39 +08:00
catch (Exception ex)
2022-10-15 17:06:19 +08:00
{
2022-10-23 19:02:39 +08:00
Logger?.Error("[Resources.CloseStream]", ex);
2022-10-15 17:06:19 +08:00
}
2022-10-23 19:02:39 +08:00
foreach (var r in Packages)
{
r.Key.Dispose();
r.Value.Dispose();
2022-09-06 21:46:35 +08:00
}
2022-10-23 19:02:39 +08:00
}
public void SendTo(Client client)
{
Task.Run(() =>
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
try
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
if (ClientResources.Count != 0)
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
Logger?.Info($"Sending resources to client:{client.Username}");
foreach (var rs in ClientResources)
{
2022-10-23 19:02:39 +08:00
Logger?.Debug(rs.Key);
Server.SendFile(rs.Value, rs.Key + ".res", client);
}
2022-10-23 19:02:39 +08:00
Logger?.Info($"Resources sent to:{client.Username}");
}
2022-10-23 19:02:39 +08:00
if (Server.GetResponse<Packets.FileTransferResponse>(client, new Packets.AllResourcesSent(),
2023-02-27 11:54:02 +08:00
ConnectionChannel.File, 30000)?.Response == FileResponse.Loaded)
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
client.IsReady = true;
Server.API.Events.InvokePlayerReady(client);
2022-09-08 12:41:56 -07:00
}
2022-10-23 19:02:39 +08:00
else
{
Logger?.Warning($"Client {client.Username} failed to load resource.");
}
}
catch (Exception ex)
{
Logger.Error("Failed to send resource to client: " + client.Username, ex);
client.Kick("Resource error!");
}
});
2022-09-08 12:41:56 -07:00
}
2022-10-23 19:02:39 +08:00
}