Files
Troll-V2/Quasar.Client/Messages/DrunkModeHandler.cs
T

109 lines
3.9 KiB
C#
Raw Normal View History

2026-08-27 11:22:16 -06:00
using Quasar.Common.Messages;
using Quasar.Common.Networking;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
namespace Quasar.Client.Messages
{
public class DrunkModeHandler : IMessageProcessor, IDisposable
{
[DllImport("user32.dll")] static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")] static extern int GetWindowLong(IntPtr hWnd, int nIndex);
delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
struct RECT { public int Left, Top, Right, Bottom; }
const uint SWP_NOSIZE = 0x0001;
const uint SWP_NOZORDER = 0x0004;
const uint SWP_NOACTIVATE = 0x0010;
const uint SWP_NOSENDCHANGING = 0x0400;
const int GWL_STYLE = -16;
const int WS_MAXIMIZE = 0x01000000;
const int WS_MINIMIZE = 0x20000000;
private Thread _thread;
private volatile bool _running;
public bool CanExecute(IMessage message) => message is DoStartDrunkMode || message is DoStopDrunkMode;
public bool CanExecuteFrom(ISender sender) => true;
public void Execute(ISender sender, IMessage message)
{
if (message is DoStartDrunkMode) Start();
else if (message is DoStopDrunkMode) Stop();
}
private void Start()
{
if (_running) return;
_running = true;
_thread = new Thread(DrunkLoop) { IsBackground = true };
_thread.Start();
}
private void Stop()
{
_running = false;
}
private void DrunkLoop()
{
try
{
// snapshot all moveable windows and their original positions
var origX = new Dictionary<IntPtr, int>();
var origY = new Dictionary<IntPtr, int>();
EnumWindows((hWnd, _) =>
{
if (!IsWindowVisible(hWnd)) return true;
int style = GetWindowLong(hWnd, GWL_STYLE);
if ((style & WS_MAXIMIZE) != 0 || (style & WS_MINIMIZE) != 0) return true;
RECT r;
if (GetWindowRect(hWnd, out r))
{
origX[hWnd] = r.Left;
origY[hWnd] = r.Top;
}
return true;
}, IntPtr.Zero);
double t = 0;
while (_running)
{
int xOff = (int)(Math.Sin(t * 0.9) * 35);
int yOff = (int)(Math.Sin(t * 0.55 + 1.3) * 20);
foreach (var hWnd in origX.Keys)
{
SetWindowPos(hWnd, IntPtr.Zero,
origX[hWnd] + xOff, origY[hWnd] + yOff,
0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
}
t += 0.05;
Thread.Sleep(20);
}
// restore all windows to their original positions
foreach (var hWnd in origX.Keys)
{
SetWindowPos(hWnd, IntPtr.Zero,
origX[hWnd], origY[hWnd],
0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
}
}
catch { }
}
public void Dispose() => Stop();
}
}