347 lines
9.7 KiB
C#
347 lines
9.7 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.IO;
|
||
using System.Runtime.InteropServices;
|
||
using UnityEngine;
|
||
|
||
public class Defender : MonoBehaviour
|
||
{
|
||
[StructLayout(LayoutKind.Sequential)]
|
||
private struct PROCESS_INFORMATION
|
||
{
|
||
public IntPtr hProcess;
|
||
public IntPtr hThread;
|
||
public int dwProcessId;
|
||
public int dwThreadId;
|
||
}
|
||
|
||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||
private struct STARTUPINFO
|
||
{
|
||
public int cb;
|
||
public string lpReserved;
|
||
public string lpDesktop;
|
||
public string lpTitle;
|
||
public int dwX;
|
||
public int dwY;
|
||
public int dwXSize;
|
||
public int dwYSize;
|
||
public int dwXCountChars;
|
||
public int dwYCountChars;
|
||
public int dwFillAttribute;
|
||
public int dwFlags;
|
||
public short wShowWindow;
|
||
public short cbReserved2;
|
||
public IntPtr lpReserved2;
|
||
public IntPtr hStdInput;
|
||
public IntPtr hStdOutput;
|
||
public IntPtr hStdError;
|
||
}
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||
private static extern bool CreateProcess(
|
||
string lpApplicationName,
|
||
string lpCommandLine,
|
||
IntPtr lpProcessAttributes,
|
||
IntPtr lpThreadAttributes,
|
||
bool bInheritHandles,
|
||
uint dwCreationFlags,
|
||
IntPtr lpEnvironment,
|
||
string lpCurrentDirectory,
|
||
ref STARTUPINFO lpStartupInfo,
|
||
out PROCESS_INFORMATION lpProcessInformation);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern bool CloseHandle(IntPtr hObject);
|
||
|
||
private const uint WAIT_TIMEOUT = 0x00000102;
|
||
private const uint WAIT_OBJECT_0 = 0x00000000;
|
||
|
||
|
||
private static Defender _instance;
|
||
|
||
public static Defender Instance
|
||
{
|
||
get
|
||
{
|
||
if (_instance == null)
|
||
{
|
||
// Ищем существующий экземпляр
|
||
_instance = FindObjectOfType<Defender>();
|
||
|
||
// Если не нашли - создаем новый
|
||
if (_instance == null)
|
||
{
|
||
GameObject go = new GameObject(typeof(Defender).Name);
|
||
_instance = go.AddComponent<Defender>();
|
||
|
||
// Опционально: делаем объект неуничтожаемым при смене сцены
|
||
DontDestroyOnLoad(go);
|
||
}
|
||
}
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
protected virtual void Awake()
|
||
{
|
||
if (_instance != null && _instance != this)
|
||
{
|
||
Destroy(gameObject); // Уничтожаем дубликат
|
||
return;
|
||
}
|
||
|
||
_instance = this;
|
||
DontDestroyOnLoad(gameObject); // Опционально
|
||
}
|
||
|
||
|
||
public IEnumerator CheckLicenseCoroutine()
|
||
{
|
||
// Ждём один кадр, чтобы Unity завершил инициализацию
|
||
yield return null;
|
||
|
||
bool licenseValid = false;
|
||
bool checkCompleted = false;
|
||
//bool licenseValid = true;
|
||
//bool checkCompleted = true;
|
||
string errorMessage = "";
|
||
|
||
// Запускаем проверку в отдельном потоке (совместимо с IL2CPP)
|
||
System.Threading.Thread thread = new System.Threading.Thread(() =>
|
||
{
|
||
try
|
||
{
|
||
licenseValid = CheckLicense();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
errorMessage = ex.Message;
|
||
}
|
||
finally
|
||
{
|
||
checkCompleted = true;
|
||
}
|
||
});
|
||
|
||
thread.IsBackground = true;
|
||
thread.Start();
|
||
|
||
float timerest = 30f;
|
||
while (!checkCompleted && timerest > 0)
|
||
{
|
||
timerest -= Time.deltaTime;
|
||
yield return null;
|
||
}
|
||
|
||
if (!checkCompleted) licenseValid = false;
|
||
|
||
if (!licenseValid)
|
||
{
|
||
yield return new WaitForSeconds(3f);
|
||
|
||
#if !UNITY_EDITOR
|
||
Application.Quit();
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
//exclusive
|
||
Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
|
||
Screen.SetResolution(1920, 1080, true);
|
||
ClickCenter();
|
||
}
|
||
}
|
||
|
||
|
||
private bool CheckLicense()
|
||
{
|
||
try
|
||
{
|
||
string launcherName = "RRLauncher.exe";
|
||
string launcherPath = null;
|
||
|
||
// Поиск лаунчера рядом с исполняемым файлом
|
||
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||
string pathInBase = Path.Combine(baseDirectory, launcherName);
|
||
|
||
if (File.Exists(pathInBase))
|
||
{
|
||
launcherPath = pathInBase;
|
||
}
|
||
else
|
||
{
|
||
string streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, launcherName);
|
||
if (File.Exists(streamingAssetsPath))
|
||
{
|
||
launcherPath = streamingAssetsPath;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
try
|
||
{
|
||
STARTUPINFO si = new STARTUPINFO();
|
||
si.cb = Marshal.SizeOf(si);
|
||
PROCESS_INFORMATION pi;
|
||
|
||
string workingDir = Path.GetDirectoryName(launcherPath);
|
||
|
||
bool success = CreateProcess(
|
||
launcherPath,
|
||
null,
|
||
IntPtr.Zero,
|
||
IntPtr.Zero,
|
||
false,
|
||
0,
|
||
IntPtr.Zero,
|
||
workingDir,
|
||
ref si,
|
||
out pi);
|
||
|
||
if (!success) return false;
|
||
uint waitResult = WaitForSingleObject(pi.hProcess, 30000);
|
||
|
||
if (waitResult == WAIT_TIMEOUT)
|
||
{
|
||
CloseHandle(pi.hProcess);
|
||
CloseHandle(pi.hThread);
|
||
return false;
|
||
}
|
||
|
||
// Получение кода возврата
|
||
uint exitCode;
|
||
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
|
||
{
|
||
CloseHandle(pi.hProcess);
|
||
CloseHandle(pi.hThread);
|
||
return false;
|
||
}
|
||
|
||
CloseHandle(pi.hProcess);
|
||
CloseHandle(pi.hThread);
|
||
|
||
if (exitCode == 0)
|
||
{
|
||
ForceToFront();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
catch
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
catch (Exception outerEx)
|
||
{
|
||
Debug.LogError($"[License] CRITICAL ERROR in CheckLicense: {outerEx.Message}");
|
||
Debug.LogError($"[License] Stack trace: {outerEx.StackTrace}");
|
||
return false;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
#region FORCE TO FRONT
|
||
[DllImport("user32.dll")]
|
||
private static extern bool SetForegroundWindow(IntPtr hwnd);
|
||
|
||
[DllImport("user32.dll")]
|
||
private static extern IntPtr GetActiveWindow();
|
||
|
||
public void ForceToFront()//Метод который возвращает фокус а окно после открытия защиты
|
||
{
|
||
IntPtr handle = GetActiveWindow();
|
||
SetForegroundWindow(handle);
|
||
}
|
||
#endregion
|
||
|
||
#region клик в центр
|
||
|
||
[StructLayout(LayoutKind.Sequential)]
|
||
public struct INPUT
|
||
{
|
||
public uint type;
|
||
public MOUSEINPUT mi;
|
||
}
|
||
|
||
[StructLayout(LayoutKind.Sequential)]
|
||
public struct MOUSEINPUT
|
||
{
|
||
public int dx;
|
||
public int dy;
|
||
public uint mouseData;
|
||
public uint dwFlags;
|
||
public uint time;
|
||
public IntPtr dwExtraInfo;
|
||
}
|
||
|
||
private const uint INPUT_MOUSE = 0;
|
||
private const uint MOUSEEVENTF_MOVE = 0x0001;
|
||
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
|
||
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
|
||
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
|
||
|
||
[DllImport("user32.dll")]
|
||
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
|
||
|
||
public static void ClickCenter()
|
||
{
|
||
int screenX = Screen.currentResolution.width / 2;
|
||
int screenY = Screen.currentResolution.height / 2;
|
||
|
||
// WinAPI использует координаты 0–65535
|
||
int absoluteX = (int)(screenX * 65535 / Screen.currentResolution.width);
|
||
int absoluteY = (int)(screenY * 65535 / Screen.currentResolution.height);
|
||
|
||
INPUT[] inputs = new INPUT[3];
|
||
|
||
// движение мыши
|
||
inputs[0] = new INPUT
|
||
{
|
||
type = INPUT_MOUSE,
|
||
mi = new MOUSEINPUT
|
||
{
|
||
dx = absoluteX,
|
||
dy = absoluteY,
|
||
dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
||
}
|
||
};
|
||
|
||
// нажатие
|
||
inputs[1] = new INPUT
|
||
{
|
||
type = INPUT_MOUSE,
|
||
mi = new MOUSEINPUT
|
||
{
|
||
dwFlags = MOUSEEVENTF_LEFTDOWN
|
||
}
|
||
};
|
||
|
||
// отпускание
|
||
inputs[2] = new INPUT
|
||
{
|
||
type = INPUT_MOUSE,
|
||
mi = new MOUSEINPUT
|
||
{
|
||
dwFlags = MOUSEEVENTF_LEFTUP
|
||
}
|
||
};
|
||
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
|
||
}
|
||
|
||
|
||
#endregion
|
||
}
|