Additional logging around initialisation
This commit is contained in:
parent
0136dc1141
commit
9bf80b1b5f
|
@ -1,5 +1,6 @@
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using KeepersCompound.LGS.Database.Chunks;
|
using KeepersCompound.LGS.Database.Chunks;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace KeepersCompound.LGS.Database;
|
namespace KeepersCompound.LGS.Database;
|
||||||
|
|
||||||
|
@ -84,8 +85,13 @@ public class DbFile
|
||||||
|
|
||||||
public DbFile(string filename)
|
public DbFile(string filename)
|
||||||
{
|
{
|
||||||
// TODO: Throw rather than return
|
Log.Information("Loading DbFile: {Path}", filename);
|
||||||
if (!File.Exists(filename)) return;
|
|
||||||
|
if (!File.Exists(filename))
|
||||||
|
{
|
||||||
|
Log.Error("Failed to load DbFile. File does not exist.");
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
using MemoryStream stream = new(File.ReadAllBytes(filename));
|
using MemoryStream stream = new(File.ReadAllBytes(filename));
|
||||||
using BinaryReader reader = new(stream, Encoding.UTF8, false);
|
using BinaryReader reader = new(stream, Encoding.UTF8, false);
|
||||||
|
@ -105,6 +111,8 @@ public class DbFile
|
||||||
|
|
||||||
public void Save(string filename)
|
public void Save(string filename)
|
||||||
{
|
{
|
||||||
|
Log.Information("Saving DbFile: {Path}", filename);
|
||||||
|
|
||||||
using var stream = File.Open(filename, FileMode.Create);
|
using var stream = File.Open(filename, FileMode.Create);
|
||||||
using var writer = new BinaryWriter(stream, Encoding.UTF8, false);
|
using var writer = new BinaryWriter(stream, Encoding.UTF8, false);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace KeepersCompound.LGS;
|
namespace KeepersCompound.LGS;
|
||||||
|
|
||||||
|
@ -77,33 +78,41 @@ public class ResourcePathManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (name, path) in GetTexturePaths(resPath))
|
var texPaths = GetTexturePaths(resPath);
|
||||||
|
var objPaths = GetObjectPaths(resPath);
|
||||||
|
var objTexPaths = GetObjectTexturePaths(resPath);
|
||||||
|
Log.Information("Found {TexCount} textures, {ObjCount} objects, {ObjTexCount} object textures for campaign: {CampaignName}",
|
||||||
|
texPaths.Count, objPaths.Count, objTexPaths.Count, name);
|
||||||
|
|
||||||
|
foreach (var (resName, path) in texPaths)
|
||||||
{
|
{
|
||||||
_texturePathMap[name] = path;
|
_texturePathMap[resName] = path;
|
||||||
}
|
}
|
||||||
foreach (var (name, path) in GetObjectPaths(resPath))
|
foreach (var (resName, path) in objPaths)
|
||||||
{
|
{
|
||||||
_objectPathMap[name] = path;
|
_objectPathMap[resName] = path;
|
||||||
}
|
}
|
||||||
foreach (var (name, path) in GetObjectTexturePaths(resPath))
|
foreach (var (resName, path) in objTexPaths)
|
||||||
{
|
{
|
||||||
_objectTexturePathMap[name] = path;
|
_objectTexturePathMap[resName] = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialise(string misPath, string resPath, CampaignResources parent)
|
public void Initialise(string misPath, string resPath, CampaignResources parent)
|
||||||
{
|
{
|
||||||
foreach (var (name, path) in parent._texturePathMap)
|
foreach (var (resName, path) in parent._texturePathMap)
|
||||||
{
|
{
|
||||||
_texturePathMap[name] = path;
|
_texturePathMap[resName] = path;
|
||||||
}
|
}
|
||||||
foreach (var (name, path) in parent._objectPathMap)
|
foreach (var (resName, path) in parent._objectPathMap)
|
||||||
{
|
{
|
||||||
_objectPathMap[name] = path;
|
_objectPathMap[resName] = path;
|
||||||
}
|
}
|
||||||
foreach (var (name, path) in parent._objectTexturePathMap)
|
foreach (var (resName, path) in parent._objectTexturePathMap)
|
||||||
{
|
{
|
||||||
_objectTexturePathMap[name] = path;
|
_objectTexturePathMap[resName] = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Initialise(misPath, resPath);
|
Initialise(misPath, resPath);
|
||||||
|
@ -126,7 +135,7 @@ public class ResourcePathManager
|
||||||
return path.Replace('\\', '/');
|
return path.Replace('\\', '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(string installPath)
|
public bool TryInit(string installPath)
|
||||||
{
|
{
|
||||||
// TODO:
|
// TODO:
|
||||||
// - Determine if folder is a thief install
|
// - Determine if folder is a thief install
|
||||||
|
@ -136,22 +145,25 @@ public class ResourcePathManager
|
||||||
// - Initialise OM campaign resource paths
|
// - Initialise OM campaign resource paths
|
||||||
// - Lazy load FM campaign resource paths (that inherit OM resources)
|
// - Lazy load FM campaign resource paths (that inherit OM resources)
|
||||||
|
|
||||||
|
Log.Information("Initialising path manager");
|
||||||
|
|
||||||
if (!DirContainsThiefExe(installPath))
|
if (!DirContainsThiefExe(installPath))
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"No Thief installation found at {installPath}", nameof(installPath));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Should these paths be stored?
|
// TODO: Should these paths be stored?
|
||||||
if (!TryGetConfigPaths(installPath, out var configPaths))
|
if (!TryGetConfigPaths(installPath, out var configPaths))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failed to find all installation config paths.");
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to know where all the texture and object resources are
|
// We need to know where all the texture and object resources are
|
||||||
var installCfgLines = File.ReadAllLines(configPaths[(int)ConfigFile.Install]);
|
var installCfgLines = File.ReadAllLines(configPaths[(int)ConfigFile.Install]);
|
||||||
if (!FindConfigVar(installCfgLines, "resname_base", out var resPaths))
|
if (!FindConfigVar(installCfgLines, "resname_base", out var resPaths))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failed to find resnames in install config");
|
Log.Error("Failed to find `resname_base` in install config");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var zipPaths = new List<string>();
|
var zipPaths = new List<string>();
|
||||||
|
@ -160,6 +172,7 @@ public class ResourcePathManager
|
||||||
var dir = Path.Join(installPath, ConvertSeparator(resPath));
|
var dir = Path.Join(installPath, ConvertSeparator(resPath));
|
||||||
if (!Directory.Exists(dir))
|
if (!Directory.Exists(dir))
|
||||||
{
|
{
|
||||||
|
Log.Warning("Install config references non-existent `resname_base`: {Path}", dir);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +196,12 @@ public class ResourcePathManager
|
||||||
ZipFile.OpenRead(zipPath).ExtractToDirectory(extractPath, false);
|
ZipFile.OpenRead(zipPath).ExtractToDirectory(extractPath, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FindConfigVar(installCfgLines, "load_path", out var omsPath);
|
if (!FindConfigVar(installCfgLines, "load_path", out var omsPath))
|
||||||
|
{
|
||||||
|
Log.Error("Failed to find `load_path` in install config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
omsPath = Path.Join(installPath, ConvertSeparator(omsPath));
|
omsPath = Path.Join(installPath, ConvertSeparator(omsPath));
|
||||||
_omResources = new CampaignResources();
|
_omResources = new CampaignResources();
|
||||||
_omResources.name = "";
|
_omResources.name = "";
|
||||||
|
@ -192,6 +210,7 @@ public class ResourcePathManager
|
||||||
var camModLines = File.ReadAllLines(configPaths[(int)ConfigFile.CamMod]);
|
var camModLines = File.ReadAllLines(configPaths[(int)ConfigFile.CamMod]);
|
||||||
FindConfigVar(camModLines, "fm_path", out var fmsPath, "FMs");
|
FindConfigVar(camModLines, "fm_path", out var fmsPath, "FMs");
|
||||||
_fmsDir = Path.Join(installPath, fmsPath);
|
_fmsDir = Path.Join(installPath, fmsPath);
|
||||||
|
Log.Information("Searching for FMS at: {FmsPath}", _fmsDir);
|
||||||
|
|
||||||
// Build up the map of FM campaigns. These are uninitialised, we just want
|
// Build up the map of FM campaigns. These are uninitialised, we just want
|
||||||
// to have their name
|
// to have their name
|
||||||
|
@ -205,6 +224,7 @@ public class ResourcePathManager
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialised = true;
|
_initialised = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> GetCampaignNames()
|
public List<string> GetCampaignNames()
|
||||||
|
@ -222,17 +242,19 @@ public class ResourcePathManager
|
||||||
{
|
{
|
||||||
return _omResources;
|
return _omResources;
|
||||||
}
|
}
|
||||||
else if (_fmResources.TryGetValue(campaignName, out var campaign))
|
|
||||||
{
|
|
||||||
if (!campaign.initialised)
|
|
||||||
{
|
|
||||||
var fmPath = Path.Join(_fmsDir, campaignName);
|
|
||||||
campaign.Initialise(fmPath, fmPath, _omResources);
|
|
||||||
}
|
|
||||||
return campaign;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException("No campaign found with given name", nameof(campaignName));
|
if (!_fmResources.TryGetValue(campaignName, out var campaign))
|
||||||
|
{
|
||||||
|
Log.Error("Failed to find campaign: {CampaignName}", campaignName);
|
||||||
|
throw new ArgumentException("No campaign found with given name", nameof(campaignName));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!campaign.initialised)
|
||||||
|
{
|
||||||
|
var fmPath = Path.Join(_fmsDir, campaignName);
|
||||||
|
campaign.Initialise(fmPath, fmPath, _omResources);
|
||||||
|
}
|
||||||
|
return campaign;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<string, string> GetObjectTexturePaths(string root)
|
private static Dictionary<string, string> GetObjectTexturePaths(string root)
|
||||||
|
@ -337,11 +359,12 @@ public class ResourcePathManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.Error("No Thief executable found in {InstallPath}. Is this the right directory?", dir);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get an array of of all the Dark config file paths.
|
/// Get an array of all the Dark config file paths.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="installPath">Root directory of the Thief installation.</param>
|
/// <param name="installPath">Root directory of the Thief installation.</param>
|
||||||
/// <param name="configPaths">Output array of config file paths</param>
|
/// <param name="configPaths">Output array of config file paths</param>
|
||||||
|
@ -362,20 +385,21 @@ public class ResourcePathManager
|
||||||
foreach (var path in Directory.GetFiles(installPath, "cam*", searchOptions))
|
foreach (var path in Directory.GetFiles(installPath, "cam*", searchOptions))
|
||||||
{
|
{
|
||||||
var name = Path.GetFileName(path).ToLower();
|
var name = Path.GetFileName(path).ToLower();
|
||||||
if (name == "cam.cfg")
|
switch (name)
|
||||||
{
|
{
|
||||||
configPaths[(int)ConfigFile.Cam] = path;
|
case "cam.cfg":
|
||||||
}
|
configPaths[(int)ConfigFile.Cam] = path;
|
||||||
else if (name == "cam_ext.cfg")
|
break;
|
||||||
{
|
case "cam_ext.cfg":
|
||||||
configPaths[(int)ConfigFile.CamExt] = path;
|
configPaths[(int)ConfigFile.CamExt] = path;
|
||||||
}
|
break;
|
||||||
else if (name == "cam_mod.ini")
|
case "cam_mod.ini":
|
||||||
{
|
configPaths[(int)ConfigFile.CamMod] = path;
|
||||||
configPaths[(int)ConfigFile.CamMod] = path;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Verify we found cam/cam_ext/cam_mod
|
||||||
var camExtLines = File.ReadAllLines(configPaths[(int)ConfigFile.CamExt]);
|
var camExtLines = File.ReadAllLines(configPaths[(int)ConfigFile.CamExt]);
|
||||||
var camLines = File.ReadAllLines(configPaths[(int)ConfigFile.Cam]);
|
var camLines = File.ReadAllLines(configPaths[(int)ConfigFile.Cam]);
|
||||||
|
|
||||||
|
@ -386,9 +410,24 @@ public class ResourcePathManager
|
||||||
}
|
}
|
||||||
|
|
||||||
FindCamVar("include_path", out var includePath, "./");
|
FindCamVar("include_path", out var includePath, "./");
|
||||||
FindCamVar("game", out var gameName);
|
|
||||||
FindCamVar($"{gameName}_include_install_cfg", out var installCfgName);
|
if (!FindCamVar("game", out var gameName))
|
||||||
FindCamVar("include_user_cfg", out var userCfgName);
|
{
|
||||||
|
Log.Error("`game` not specified in Cam/CamExt");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FindCamVar($"{gameName}_include_install_cfg", out var installCfgName))
|
||||||
|
{
|
||||||
|
Log.Error("Install config file path not specified in Cam/CamExt");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FindCamVar("include_user_cfg", out var userCfgName))
|
||||||
|
{
|
||||||
|
Log.Error("User config file path not specified in Cam/CamExt");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: How to handle case-insensitive absolute paths?
|
// TODO: How to handle case-insensitive absolute paths?
|
||||||
// Fixup the include path to "work" cross-platform
|
// Fixup the include path to "work" cross-platform
|
||||||
|
@ -396,6 +435,7 @@ public class ResourcePathManager
|
||||||
includePath = Path.Join(installPath, includePath);
|
includePath = Path.Join(installPath, includePath);
|
||||||
if (!Directory.Exists(includePath))
|
if (!Directory.Exists(includePath))
|
||||||
{
|
{
|
||||||
|
Log.Error("Include path specified in Cam/CamExt does not exist: {IncludePath}", includePath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,15 +457,25 @@ public class ResourcePathManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check we found everything
|
// Check we found everything
|
||||||
var i = 0;
|
var found = 0;
|
||||||
foreach (var path in configPaths)
|
for (var i = 0; i < (int)ConfigFile.ConfigFileCount; i++)
|
||||||
{
|
{
|
||||||
|
var path = configPaths[i];
|
||||||
if (path == null || path == "")
|
if (path == null || path == "")
|
||||||
{
|
{
|
||||||
return false;
|
Log.Error("Failed to find {ConfigFile} config file", (ConfigFile)i);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
|
found++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found != (int)ConfigFile.ConfigFileCount)
|
||||||
|
{
|
||||||
|
Log.Error("Failed to find all required config files in Thief installation directory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,12 +42,19 @@ public class LightMapper
|
||||||
string campaignName,
|
string campaignName,
|
||||||
string missionName)
|
string missionName)
|
||||||
{
|
{
|
||||||
var pathManager = SetupPathManager(installPath);
|
if (!SetupPathManager(installPath, out var pathManager))
|
||||||
|
{
|
||||||
|
Log.Error("Failed to configure path manager");
|
||||||
|
throw new Exception("Failed to configure path manager");
|
||||||
|
}
|
||||||
|
|
||||||
_campaign = pathManager.GetCampaign(campaignName);
|
_campaign = pathManager.GetCampaign(campaignName);
|
||||||
_misPath = _campaign.GetResourcePath(ResourceType.Mission, missionName);
|
_misPath = _campaign.GetResourcePath(ResourceType.Mission, missionName);
|
||||||
_mission = Timing.TimeStage("Parse DB", () => new DbFile(_misPath));
|
_mission = Timing.TimeStage("Parse DB", () => new DbFile(_misPath));
|
||||||
_hierarchy = Timing.TimeStage("Build Hierarchy", BuildHierarchy);
|
_hierarchy = Timing.TimeStage("Build Hierarchy", BuildHierarchy);
|
||||||
_lights = [];
|
_lights = [];
|
||||||
|
|
||||||
|
VerifyRequiredChunksExist();
|
||||||
|
|
||||||
var mesh = Timing.TimeStage("Build Mesh", BuildMesh);
|
var mesh = Timing.TimeStage("Build Mesh", BuildMesh);
|
||||||
_triangleTypeMap = mesh.TriangleSurfaceMap;
|
_triangleTypeMap = mesh.TriangleSurfaceMap;
|
||||||
|
@ -121,12 +128,36 @@ public class LightMapper
|
||||||
Timing.TimeStage("Save DB", () => _mission.Save(savePath));
|
Timing.TimeStage("Save DB", () => _mission.Save(savePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ResourcePathManager SetupPathManager(string installPath)
|
private bool VerifyRequiredChunksExist()
|
||||||
|
{
|
||||||
|
var requiredChunkNames = new []
|
||||||
|
{
|
||||||
|
"RENDPARAMS",
|
||||||
|
"LM_PARAM",
|
||||||
|
"WREXT",
|
||||||
|
"BRLIST",
|
||||||
|
"P$AnimLight",
|
||||||
|
};
|
||||||
|
|
||||||
|
var allFound = true;
|
||||||
|
foreach (var name in requiredChunkNames)
|
||||||
|
{
|
||||||
|
if (!_mission.Chunks.ContainsKey(name))
|
||||||
|
{
|
||||||
|
Log.Warning("Failed to find required chunk: {ChunkName}", name);
|
||||||
|
allFound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool SetupPathManager(string installPath, out ResourcePathManager pathManager)
|
||||||
{
|
{
|
||||||
var tmpDir = Directory.CreateTempSubdirectory("KCLightmapper");
|
var tmpDir = Directory.CreateTempSubdirectory("KCLightmapper");
|
||||||
var resPathManager = new ResourcePathManager(tmpDir.FullName);
|
|
||||||
resPathManager.Init(installPath);
|
pathManager = new ResourcePathManager(tmpDir.FullName);
|
||||||
return resPathManager;
|
return pathManager.TryInit(installPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectHierarchy BuildHierarchy()
|
private ObjectHierarchy BuildHierarchy()
|
||||||
|
@ -144,6 +175,8 @@ public class LightMapper
|
||||||
{
|
{
|
||||||
return new ObjectHierarchy(_mission, new DbFile(paths[0]));
|
return new ObjectHierarchy(_mission, new DbFile(paths[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.Warning("Failed to find GameSys");
|
||||||
return new ObjectHierarchy(_mission);
|
return new ObjectHierarchy(_mission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System.Numerics;
|
||||||
using KeepersCompound.LGS;
|
using KeepersCompound.LGS;
|
||||||
using KeepersCompound.LGS.Database;
|
using KeepersCompound.LGS.Database;
|
||||||
using KeepersCompound.LGS.Database.Chunks;
|
using KeepersCompound.LGS.Database.Chunks;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace KeepersCompound.Lightmapper;
|
namespace KeepersCompound.Lightmapper;
|
||||||
|
|
||||||
|
@ -117,6 +118,7 @@ public class MeshBuilder
|
||||||
var modelPath = campaignResources.GetResourcePath(ResourceType.Object, modelName);
|
var modelPath = campaignResources.GetResourcePath(ResourceType.Object, modelName);
|
||||||
if (modelPath == null)
|
if (modelPath == null)
|
||||||
{
|
{
|
||||||
|
Log.Warning("Failed to find model file: {Path}", modelPath);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue