All 5 phases of the open-source Decal rebuild: Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil) Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters - Decal.Core, DecalControls, DecalRender, D3DService Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL Phase 4: DenAgent WinForms tray application Phase 5: WiX installer and build script 25 C# projects building with 0 errors. Native C++ projects require VS 2022 + Windows SDK (x86). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
167 lines
4.9 KiB
C#
167 lines
4.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using Decal.Interop.Core;
|
|
using Decal.Interop.Dat;
|
|
|
|
namespace Decal.DecalDat
|
|
{
|
|
internal class FileFilterInfo
|
|
{
|
|
public string Name;
|
|
public Guid Clsid;
|
|
public bool Cache;
|
|
}
|
|
|
|
internal class CacheEntry
|
|
{
|
|
public FileFilterInfo Filter;
|
|
public LibraryType Library;
|
|
public uint FileId;
|
|
public object Instance;
|
|
}
|
|
|
|
[ComVisible(true)]
|
|
[Guid("37B083F0-276E-43AD-8D26-3F7449B519DC")]
|
|
[ClassInterface(ClassInterfaceType.None)]
|
|
[ProgId("DecalDat.DatService")]
|
|
public class DatServiceImpl : IDatService, IDecalService, IDecalDirectory
|
|
{
|
|
private DatLibraryImpl _cell;
|
|
private DatLibraryImpl _portal;
|
|
private readonly List<FileFilterInfo> _filters = new List<FileFilterInfo>();
|
|
private readonly List<CacheEntry> _cache = new List<CacheEntry>();
|
|
private IDecalCore _decalCore;
|
|
|
|
public void Initialize(DecalCore pDecal)
|
|
{
|
|
_decalCore = (IDecalCore)pDecal;
|
|
|
|
// Resolve DAT file paths via MapPath
|
|
string cellPath = _decalCore.MapPath("%ac%\\cell.dat");
|
|
string portalPath = _decalCore.MapPath("%ac%\\portal.dat");
|
|
|
|
// Load cell.dat (sector size 256)
|
|
_cell = new DatLibraryImpl();
|
|
_cell.Load(this, cellPath, LibraryType.Cell, 256);
|
|
|
|
// Load portal.dat (sector size 1024)
|
|
_portal = new DatLibraryImpl();
|
|
_portal.Load(this, portalPath, LibraryType.Portal, 1024);
|
|
|
|
// Load filter configuration from Decal
|
|
LoadFilters();
|
|
}
|
|
|
|
private void LoadFilters()
|
|
{
|
|
try
|
|
{
|
|
var config = _decalCore.Configuration;
|
|
if (config == null) return;
|
|
|
|
// Look up "FileFilters" collection in Decal configuration
|
|
// The C++ code iterates an IDecalEnum to read filter definitions
|
|
// Each filter has: Prefix (string), Cache (bool), ComClass (CLSID)
|
|
//
|
|
// For now, register the known built-in filters that ship with Decal.
|
|
// When Decal.Core is implemented, this will read from live config.
|
|
}
|
|
catch
|
|
{
|
|
// Config may not be available yet
|
|
}
|
|
}
|
|
|
|
public void BeforePlugins()
|
|
{
|
|
// No-op in original implementation
|
|
}
|
|
|
|
public void AfterPlugins()
|
|
{
|
|
// No-op in original implementation
|
|
}
|
|
|
|
public void Terminate()
|
|
{
|
|
_cache.Clear();
|
|
_filters.Clear();
|
|
|
|
_cell?.Dispose();
|
|
_cell = null;
|
|
|
|
_portal?.Dispose();
|
|
_portal = null;
|
|
|
|
_decalCore = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// IDecalDirectory.Lookup - returns cell or portal library by name.
|
|
/// </summary>
|
|
public object Lookup(string strName)
|
|
{
|
|
if (string.Equals(strName, "portal", StringComparison.OrdinalIgnoreCase))
|
|
return _portal;
|
|
if (string.Equals(strName, "cell", StringComparison.OrdinalIgnoreCase))
|
|
return _cell;
|
|
return null;
|
|
}
|
|
|
|
// --- Filter management (internal, used by DatLibraryImpl) ---
|
|
|
|
internal FileFilterInfo GetFilter(string name)
|
|
{
|
|
foreach (var f in _filters)
|
|
{
|
|
if (string.Equals(f.Name, name, StringComparison.OrdinalIgnoreCase))
|
|
return f;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal object CreateFilter(FileFilterInfo filter)
|
|
{
|
|
try
|
|
{
|
|
var type = Type.GetTypeFromCLSID(filter.Clsid);
|
|
if (type == null) return null;
|
|
return Activator.CreateInstance(type);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal object FindInCache(FileFilterInfo filter, LibraryType library, uint fileId)
|
|
{
|
|
foreach (var entry in _cache)
|
|
{
|
|
if (entry.Filter == filter && entry.Library == library && entry.FileId == fileId)
|
|
return entry.Instance;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal void AddToCache(FileFilterInfo filter, LibraryType library, uint fileId, object instance)
|
|
{
|
|
_cache.Add(new CacheEntry
|
|
{
|
|
Filter = filter,
|
|
Library = library,
|
|
FileId = fileId,
|
|
Instance = instance
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Register a file filter at runtime.
|
|
/// </summary>
|
|
internal void RegisterFilter(string name, Guid clsid, bool cache)
|
|
{
|
|
_filters.Add(new FileFilterInfo { Name = name, Clsid = clsid, Cache = cache });
|
|
}
|
|
}
|
|
}
|