Files
hanfuit 645b64fe21 DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go):
- GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面
- GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新
- 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新)
- 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍
- 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0)
- 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算

启动器(Python/JS):
- 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭
- GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐)
- 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
2026-11-04 14:31:55 +08:00

81 lines
2.7 KiB
C#

using System.Runtime.InteropServices;
namespace DNFLoadout;
internal sealed class HotkeyManager : IDisposable
{
private const int AltBit = 0x1;
private const int CtrlBit = 0x2;
private const int ShiftBit = 0x4;
private readonly System.Windows.Forms.Timer _timer = new() { Interval = 50 };
private readonly HashSet<int> _down = new();
private Config _config;
public event Action<Scheme>? Triggered;
public HotkeyManager(Config config)
{
_config = config;
_timer.Tick += (_, _) => Poll();
_timer.Start();
}
public void UpdateConfig(Config config) => _config = config;
private static bool Down(int vk) => (GetAsyncKeyState(vk) & 0x8000) != 0;
private static bool ModCtrl => Down((int)Keys.ControlKey);
private static bool ModAlt => Down((int)Keys.Menu);
private static bool ModShift => Down((int)Keys.ShiftKey);
private void Poll()
{
foreach (var scheme in _config.CurrentPage.Schemes)
{
if (scheme.KeyCode == 0) continue;
bool mods = ((scheme.Modifiers & CtrlBit) == 0 || ModCtrl)
&& ((scheme.Modifiers & AltBit) == 0 || ModAlt)
&& ((scheme.Modifiers & ShiftBit) == 0 || ModShift);
// Reject extra modifiers so Ctrl+F1 cannot fire plain F1.
if ((scheme.Modifiers & CtrlBit) == 0 && ModCtrl) mods = false;
if ((scheme.Modifiers & AltBit) == 0 && ModAlt) mods = false;
if ((scheme.Modifiers & ShiftBit) == 0 && ModShift) mods = false;
bool key = Down(scheme.KeyCode);
int id = scheme.KeyCode | (scheme.Modifiers << 16);
bool was = _down.Contains(id);
if (key && mods && !was)
{
_down.Add(id);
Triggered?.Invoke(scheme);
}
else if (!key || !mods)
{
_down.Remove(id);
}
}
}
public static (int Modifiers, int KeyCode) Capture(Keys keyData)
{
var modifiers = 0;
if ((keyData & Keys.Control) != 0) modifiers |= CtrlBit;
if ((keyData & Keys.Alt) != 0) modifiers |= AltBit;
if ((keyData & Keys.Shift) != 0) modifiers |= ShiftBit;
var keyCode = (int)(keyData & Keys.KeyCode);
if (keyCode is (int)Keys.ControlKey or (int)Keys.Menu or (int)Keys.ShiftKey
or (int)Keys.LControlKey or (int)Keys.RControlKey
or (int)Keys.LMenu or (int)Keys.RMenu
or (int)Keys.LShiftKey or (int)Keys.RShiftKey)
return (modifiers, 0);
return (modifiers, keyCode);
}
public void Dispose()
{
_timer.Stop();
_timer.Dispose();
}
[DllImport("user32.dll")]
private static extern short GetAsyncKeyState(int vKey);
}