This repository contains:
- Silent Hunter game file parsers (with extensions
.dat
,.sim
,.zon
,.dsd
,.cam
,.val
,.sdl
,.off
) - Silent Hunter controller templates
- Dynamic code compiler (for controller templates)
SilentHunter.FileFormats |
|
SilentHunter.Controllers |
|
SilentHunter.Controllers.Templates |
|
SilentHunter.Controllers.Compiler |
Over a decade ago, I wrote a popular modding application called S3D (http://s3d.skwas.com) for Silent Hunter game files. Back then, I used some proprietary code to do so (from my own business). Fast forward to today - for posterity sake - I took some time to clean up the old code base and release it for everyone to use.
This repository only covers the parsing logic and controller templates, but time permitted I will try to release S3D source code too in the future.
Important: this is not fully backward compatible with S3D's controller templates that were released in 2009. This is due some refactoring done to make it more usuable in open source context. If you have updated/added/improved controllers, please submit a PR.
There are two ways to configure the parsers:
- Using a dynamically compiled controller assembly
- Using a precompiled controller assembly
S3D specifically uses the dynamic controller assembly. This enabled modders to modify the controller templates, after which S3D would be able to use the new templates.
Which method you choose depends on how you wish to distribute your application. If you do not care much about this, simply use the precompiled package.
The file parsers are developed with dependency injection for IServiceCollection
in mind, allowing you to inject the parsers in your own code base. As such, you need to configure the container before being able to use the parsers.
Install-Package SilentHunter.Controllers.Templates
Install-Package SilentHunter.Controllers.Compiler
Install-Package SilentHunter.FileFormats
By adding the package SilentHunter.Controllers.Templates
, the template source files are added to your application build output directory.
The benefit of using the dynamic compiled assembly is that controllers can be updated without rebuilding/redistributing the whole application, and at the same time allowing modders control over the controller templates (hence why I did this for S3D).
IServiceCollection services = ...
string controllerPath = "path to the controllers";
// Add services
services
.AddSilentHunterParsers(configurer => configurer
.Controllers.CompileFrom(
controllerPath,
assemblyName: "Controllers"
)
);
The benefit of using the precompiled assembly is that you have strong typed access to all controllers and don't have to use reflection.
Install-Package SilentHunter.Controllers
Install-Package SilentHunter.FileFormats
IServiceCollection services = ...
// Add services
services
.AddSilentHunterParsers(configurer => configurer
.Controllers.FromAssembly(typeof(ParticleGenerator).Assembly)
);
IServiceProvider serviceProvider = ... // Or inject into your classes directly.
// Request (transient) instance of DatFile
DatFile datFile = serviceProvider.GetRequiredService<DatFile>();
using (var fsIn = File.OpenRead(...))
using (var fsOut = File.OpenWrite(...))
{
await datFile.LoadAsync(fsIn);
var newChunk = datFile.CreateChunk<LabelChunk>();
newChunk.Text = "My new label";
datFile.Chunks.Add(newChunk);
await datFile.SaveAsync(fsOut);
}
This example uses
IServiceProvider
directly. It is better to design classes and injectDatFile
,SdlFile
orOffFile
instances in there to work with.
For SDL and OFF files, the principle is the same. Simply request a new instance from the service container or inject into a class:
SdlFile sdlFile = serviceProvider.GetRequiredService<SdlFile>();
await sdlFile.LoadAsync(..filename..);
var newSound = new SoundInfo
{
Name = "sound_name",
WaveName = "sound.wav",
Volume = 0.9f,
..
};
sdlFile.Add(newSound);
OffFile offFile = serviceProvider.GetRequiredService<OffFile>();
await offFile.LoadAsync(..filename..);
var newChar = new OffCharacter
{
Character = 'A',
BoundingBox = new Rectangle
{
X = 10,
Y = 20,
Width = 30,
Height = 40
}
}
offFile.Add(newChar);
PR's are welcome. Please rebase before submitting, provide test coverage, and ensure the AppVeyor build passes. I will not consider PR's otherwise.
- skwas (author/maintainer)
- .NET Standard 2.0
- .NET 4.6.1
- Visual Studio 2017/2019
- .NET Core 2.2 SDK
- .NET 4.6.1 targetting pack
Ubisoft, Silent Hunter development team, SubSim.com
Also individuals:
CaptainCox, leovampire, the modders at Submarine Sim Central, tater, Anvart, Bando, WEBSTER, maikarant, Jace11, WilhelmTell, lurbz, Sansal, longam, PepsiCan, UBOAT234, Digital_Trucker, DirtyHarry3033, Kaleun_Endrass, sergbuto, SquareSteelBar, sober, jaketoox, reallydedpoet, swdw, nautilus42, nvdrifter, kapitan_zur_see, DeepIron, panthercules, l3th4l, Laffertytig, alamwuhk2a, privateer, g_BonE, Ducimus, lurker_hlb3, haegemon, wildchild, urfisch, LukeFF, ref, kikn79, WernerSobe, Redwine, GuillermoZS, keltos01, Mikhayl, Kriller2, DrBeast, jimbob, Rubini, M. Sarsfield, miner1436, AVGWarhawk, reallydedpoet, Subject, and those who have been debugging the file formats long before me.