mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-07-15 15:19:57 +00:00
Vendored
+30
-2
@@ -5,13 +5,41 @@
|
|||||||
"name": "Debug Daybreak.Linux",
|
"name": "Debug Daybreak.Linux",
|
||||||
"type": "dotnet",
|
"type": "dotnet",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"projectPath": "${workspaceFolder}/Daybreak.Linux/Daybreak.Linux.csproj"
|
"projectPath": "${workspaceFolder}/Daybreak.Linux/Daybreak.Linux.csproj",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"justMyCode": true,
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"suppressJITOptimizations": false,
|
||||||
|
"symbolOptions": {
|
||||||
|
"searchMicrosoftSymbolServer": false,
|
||||||
|
"searchNuGetOrgSymbolServer": false
|
||||||
|
},
|
||||||
|
"logging": {
|
||||||
|
"engineLogging": false,
|
||||||
|
"moduleLoad": false,
|
||||||
|
"exceptions": false,
|
||||||
|
"browserStdOut": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Debug Daybreak.Windows",
|
"name": "Debug Daybreak.Windows",
|
||||||
"type": "dotnet",
|
"type": "dotnet",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"projectPath": "${workspaceFolder}/Daybreak.Windows/Daybreak.Windows.csproj"
|
"projectPath": "${workspaceFolder}/Daybreak.Windows/Daybreak.Windows.csproj",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"justMyCode": true,
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"suppressJITOptimizations": false,
|
||||||
|
"symbolOptions": {
|
||||||
|
"searchMicrosoftSymbolServer": false,
|
||||||
|
"searchNuGetOrgSymbolServer": false
|
||||||
|
},
|
||||||
|
"logging": {
|
||||||
|
"engineLogging": false,
|
||||||
|
"moduleLoad": false,
|
||||||
|
"exceptions": false,
|
||||||
|
"browserStdOut": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-14
@@ -182,24 +182,43 @@ public class EntryPoint
|
|||||||
|
|
||||||
private static void PreloadNativeDependencies(ScopedLogger<EntryPoint> logger)
|
private static void PreloadNativeDependencies(ScopedLogger<EntryPoint> logger)
|
||||||
{
|
{
|
||||||
|
// First, check if gwca.dll is already loaded in the process (e.g. by GWToolbox).
|
||||||
|
// If so, reuse it via a ref-count bump on the existing path rather than loading
|
||||||
|
// a second copy from the Daybreak.API directory. Loading a second instance of
|
||||||
|
// gwca.dll would result in duplicate native modules in the process, which can
|
||||||
|
// lead to inconsistent state across mods that depend on it.
|
||||||
|
string? daybreakApiDir = default;
|
||||||
foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
|
foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
|
||||||
{
|
{
|
||||||
if (module.ModuleName?.Contains("Daybreak.API", StringComparison.OrdinalIgnoreCase) is true)
|
if (module.ModuleName?.Equals("gwca.dll", StringComparison.OrdinalIgnoreCase) is true)
|
||||||
{
|
{
|
||||||
var moduleDir = Path.GetDirectoryName(module.FileName)!;
|
NativeLibrary.Load(module.FileName);
|
||||||
var gwcaPath = Path.Combine(moduleDir, "gwca.dll");
|
logger.LogDebug($"Reused already-loaded gwca.dll from {module.FileName}");
|
||||||
if (File.Exists(gwcaPath))
|
return;
|
||||||
{
|
|
||||||
NativeLibrary.Load(gwcaPath);
|
|
||||||
logger.LogDebug($"Preloaded gwca.dll from {gwcaPath}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogError($"gwca.dll not found at {gwcaPath}");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (daybreakApiDir is null &&
|
||||||
|
module.ModuleName?.Contains("Daybreak.API", StringComparison.OrdinalIgnoreCase) is true)
|
||||||
|
{
|
||||||
|
daybreakApiDir = Path.GetDirectoryName(module.FileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daybreakApiDir is null)
|
||||||
|
{
|
||||||
|
logger.LogError("Could not locate Daybreak.API module directory to preload gwca.dll");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var gwcaPath = Path.Combine(daybreakApiDir, "gwca.dll");
|
||||||
|
if (File.Exists(gwcaPath))
|
||||||
|
{
|
||||||
|
NativeLibrary.Load(gwcaPath);
|
||||||
|
logger.LogDebug($"Preloaded gwca.dll from {gwcaPath}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogError($"gwca.dll not found at {gwcaPath}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Daybreak.API.Interop
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// P/Invoke bindings for 527 C++ exports from gwca.dll (0 skipped).
|
/// P/Invoke bindings for 528 C++ exports from gwca.dll (0 skipped).
|
||||||
/// Nested classes mirror the C++ namespace hierarchy (e.g. GW::Agents → GWCA.GW.Agents).
|
/// Nested classes mirror the C++ namespace hierarchy (e.g. GW::Agents → GWCA.GW.Agents).
|
||||||
/// Types annotated with [GWCAEquivalent] are used in signatures where available.
|
/// Types annotated with [GWCAEquivalent] are used in signatures where available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -59,7 +59,7 @@ public static unsafe partial class GWCA
|
|||||||
// [NAMESPACE] GWCA.GW.StoC popped at line 50
|
// [NAMESPACE] GWCA.GW.StoC popped at line 50
|
||||||
// [NAMESPACE] GWCA.GW.TargetFilter popped at line 112
|
// [NAMESPACE] GWCA.GW.TargetFilter popped at line 112
|
||||||
// [NAMESPACE] GWCA.GW.Trade popped at line 22
|
// [NAMESPACE] GWCA.GW.Trade popped at line 22
|
||||||
// [NAMESPACE] GWCA.GW.UI popped at line 774
|
// [NAMESPACE] GWCA.GW.UI popped at line 31
|
||||||
// [NAMESPACE] GWCA.GW.UI.UIPacket popped at line 30
|
// [NAMESPACE] GWCA.GW.UI.UIPacket popped at line 30
|
||||||
// [NAMESPACE] GWCA.GWCA popped at line 15
|
// [NAMESPACE] GWCA.GWCA popped at line 15
|
||||||
// GWCA.GW.AccountContext: 9 fields [OK]
|
// GWCA.GW.AccountContext: 9 fields [OK]
|
||||||
@@ -1759,6 +1759,11 @@ public static unsafe partial class GWCA
|
|||||||
[return: MarshalAs(UnmanagedType.U1)]
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
public static partial bool SetHeroBehavior(uint value1, global::Daybreak.API.Interop.GWCA.GW.HeroBehavior heroBehavior2);
|
public static partial bool SetHeroBehavior(uint value1, global::Daybreak.API.Interop.GWCA.GW.HeroBehavior heroBehavior2);
|
||||||
|
|
||||||
|
// GW::PartyMgr::SetHeroSkillDisabled
|
||||||
|
[LibraryImport(DllName, EntryPoint = "?SetHeroSkillDisabled@PartyMgr@GW@@YA_NII_N@Z")]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
public static partial bool SetHeroSkillDisabled(uint value1, uint value2, [MarshalAs(UnmanagedType.U1)] bool flag3);
|
||||||
|
|
||||||
// GW::PartyMgr::SetHeroTarget
|
// GW::PartyMgr::SetHeroTarget
|
||||||
[LibraryImport(DllName, EntryPoint = "?SetHeroTarget@PartyMgr@GW@@YA_NII@Z")]
|
[LibraryImport(DllName, EntryPoint = "?SetHeroTarget@PartyMgr@GW@@YA_NII@Z")]
|
||||||
[return: MarshalAs(UnmanagedType.U1)]
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
@@ -8121,7 +8126,7 @@ public static unsafe partial class GWCA
|
|||||||
public static partial class Urgoz
|
public static partial class Urgoz
|
||||||
{
|
{
|
||||||
internal const int HoppingVampire = 3796;
|
internal const int HoppingVampire = 3796;
|
||||||
internal const int Urgoz_ = 3805;
|
internal const int Urgoz = 3805;
|
||||||
|
|
||||||
public static partial class Deep
|
public static partial class Deep
|
||||||
{
|
{
|
||||||
@@ -8255,7 +8260,7 @@ public static unsafe partial class GWCA
|
|||||||
internal const int LockedChest = 8192; // this is actually ->ExtraType
|
internal const int LockedChest = 8192; // this is actually ->ExtraType
|
||||||
internal const int MiniatureLegionnaire = 8035;
|
internal const int MiniatureLegionnaire = 8035;
|
||||||
|
|
||||||
public static partial class Minipet_
|
public static partial class Minipet
|
||||||
{
|
{
|
||||||
internal const int MiniatureConfessorDorian = 8344;
|
internal const int MiniatureConfessorDorian = 8344;
|
||||||
internal const int MiniatureConfessorIsaiah = 8352;
|
internal const int MiniatureConfessorIsaiah = 8352;
|
||||||
|
|||||||
@@ -383,8 +383,11 @@ public class ProjectConfiguration : PluginConfigurationBase
|
|||||||
public override void RegisterMods(IModsProducer modsManager)
|
public override void RegisterMods(IModsProducer modsManager)
|
||||||
{
|
{
|
||||||
modsManager.RegisterMod<IGuildWarsVersionChecker, GuildWarsVersionChecker>();
|
modsManager.RegisterMod<IGuildWarsVersionChecker, GuildWarsVersionChecker>();
|
||||||
modsManager.RegisterMod<IDaybreakApiService, DaybreakApiService>();
|
// Toolbox must be registered before Daybreak API so that Toolbox injects first
|
||||||
|
// and loads its gwca.dll. Daybreak API will then reuse the already-loaded gwca.dll
|
||||||
|
// instead of loading a second copy, avoiding duplicate native module loads.
|
||||||
modsManager.RegisterMod<IToolboxService, ToolboxService>();
|
modsManager.RegisterMod<IToolboxService, ToolboxService>();
|
||||||
|
modsManager.RegisterMod<IDaybreakApiService, DaybreakApiService>();
|
||||||
modsManager.RegisterMod<IUModService, UModService>();
|
modsManager.RegisterMod<IUModService, UModService>();
|
||||||
modsManager.RegisterMod<IDirectSongService, DirectSongService>(singleton: true);
|
modsManager.RegisterMod<IDirectSongService, DirectSongService>(singleton: true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,6 +366,10 @@ internal sealed class ToolboxService(
|
|||||||
if (await this.processInjector.Inject(process, dll, cancellationToken))
|
if (await this.processInjector.Inject(process, dll, cancellationToken))
|
||||||
{
|
{
|
||||||
scopedLogger.LogDebug("Injected toolbox dll");
|
scopedLogger.LogDebug("Injected toolbox dll");
|
||||||
|
// Give Toolbox a moment to load its bundled gwca.dll into the target process
|
||||||
|
// before any subsequent mod (e.g. Daybreak.API) tries to load its own copy.
|
||||||
|
// This ensures Daybreak.API's existing-module check sees gwca.dll and reuses it.
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
|
||||||
this.notificationService.NotifyInformation(
|
this.notificationService.NotifyInformation(
|
||||||
title: "GWToolbox started",
|
title: "GWToolbox started",
|
||||||
description: "GWToolbox has been injected");
|
description: "GWToolbox has been injected");
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Reference in New Issue
Block a user