using System; using RR.Game2D.Core.Managers; using UnityEngine; using UnityEngine.Events; namespace RR.Common.Controls { /// /// Совместимый фасад над мульти-устройственной COM-системой. /// Старый API сохранен для текущего проекта. /// public class ComWrapper : MonoBehaviour { [Header("Основные настройки")] [SerializeField] private bool saveMoneyBetweenSessions; [SerializeField] private bool enablePrizeChecking; [SerializeField] private bool keepAlive = true; [Header("Авторизация")] [SerializeField] private bool enableEncryptedHandshake = true; [SerializeField] private int handshakeTimeoutMs = 5000; [Header("Роль контроллера (после handshake)")] [SerializeField] private string roleRequestCommand = "97"; [SerializeField] private string roleResponsePrefix = "ROLE"; [SerializeField] private int roleRequestTimeoutMs = 1500; [SerializeField] private string mainControllerRole = "main_controller"; [Header("Мульти-устройства")] [SerializeField] private bool useAllDetectedPorts = true; [SerializeField] private string[] explicitPorts = Array.Empty(); [SerializeField] private string defaultDevicePort = ""; public static UnityEvent OnCreditAdded; public static UnityEvent OnCreditRemoved; public static UnityEvent OnInputReceived; public static Action OnInitialize; public static UnityEvent OnDeviceInputReceived; public static UnityEvent OnDeviceAuthorized; private static ComWrapper _instance; private static int _creditsCount; private ComMultiManager _manager; private LightController _light; private bool _initializeInvoked; public LightController Light => _light; public void Initialize() { _instance = this; OnCreditAdded = new UnityEvent(); OnCreditRemoved = new UnityEvent(); OnInputReceived = new UnityEvent(); OnDeviceInputReceived = new UnityEvent(); OnDeviceAuthorized = new UnityEvent(); if (!saveMoneyBetweenSessions) PlayerPrefs.SetInt("CoinsCount", 0); _creditsCount = PlayerPrefs.GetInt("CoinsCount", 0); _light = GetComponent() ?? gameObject.AddComponent(); _manager = new ComMultiManager( useAllDetectedPorts, explicitPorts, defaultDevicePort, enableEncryptedHandshake, handshakeTimeoutMs, keepAlive || enablePrizeChecking, roleRequestCommand, roleResponsePrefix, roleRequestTimeoutMs, mainControllerRole); _manager.InitializeDevices(); } public static void AddCredit() { _creditsCount++; PlayerPrefs.SetInt("CoinsCount", _creditsCount); OnCreditAdded?.Invoke(_creditsCount); } public static bool Pay(int amount = 1) { if (_creditsCount < amount) { return false; } _creditsCount -= amount; PlayerPrefs.SetInt("CoinsCount", _creditsCount); PlayerPrefs.SetInt(PrizeSystem.key_starts, PlayerPrefs.GetInt(PrizeSystem.key_starts) + 1); PlayerPrefs.SetInt(PrizeSystem.key_startsNul, PlayerPrefs.GetInt(PrizeSystem.key_startsNul) + 1); OnCreditRemoved?.Invoke(_creditsCount); return true; } public static int GetCredits() => _creditsCount; public static void SetCredits(int amount) { int oldCredits = _creditsCount; _creditsCount = Mathf.Max(0, amount); PlayerPrefs.SetInt("CoinsCount", _creditsCount); if (_creditsCount > oldCredits) { OnCreditAdded?.Invoke(_creditsCount); } else if (_creditsCount < oldCredits) { OnCreditRemoved?.Invoke(_creditsCount); } } public static void Send(string message) { if (_instance == null || string.IsNullOrWhiteSpace(message)) return; _instance._manager?.SendToDefault(message); } public static void SendToDevice(string deviceId, string message) { if (_instance == null || string.IsNullOrWhiteSpace(message)) return; _instance._manager?.SendToDevice(deviceId, message); } public static void SendToAll(string message) { if (_instance == null || string.IsNullOrWhiteSpace(message)) return; _instance._manager?.SendToAll(message); } public static string GetLastInputState() { if (_instance?._manager == null) return "11111111111111111111111111"; string defaultId = _instance._manager.DefaultDeviceId; return string.IsNullOrWhiteSpace(defaultId) ? "11111111111111111111111111" : _instance._manager.GetLastInputState(defaultId); } public static string GetLastInputState(string deviceId) { return _instance?._manager?.GetLastInputState(deviceId) ?? "11111111111111111111111111"; } public static string[] GetConnectedDeviceIds() { return _instance?._manager?.ConnectedDeviceIds ?? Array.Empty(); } public static string GetDefaultDeviceId() { return _instance?._manager?.DefaultDeviceId ?? string.Empty; } public static string GetDeviceRole(string deviceId) { return _instance?._manager?.GetDeviceRole(deviceId) ?? string.Empty; } public void Blink() => _light.Blink(); public void StopBlink(bool enableHat = true) => _light.StopBlink(enableHat); private void Update() { if (_manager == null) return; int coinsProcessed = 0; while (_manager.TryDequeueCoin(out _)) { AddCredit(); coinsProcessed++; } while (_manager.TryDequeueInput(out DeviceInputMessage msg)) { OnDeviceInputReceived?.Invoke(msg.DeviceId, msg.InputBits); if (msg.DeviceId == _manager.DefaultDeviceId) { OnInputReceived?.Invoke(msg.InputBits); } } while (_manager.TryDequeueAuthorized(out string deviceId)) { OnDeviceAuthorized?.Invoke(deviceId); if (!_initializeInvoked) { _initializeInvoked = true; OnInitialize?.Invoke(); } if (deviceId == _manager.DefaultDeviceId) { _light.Blink(); } } if (coinsProcessed > 0) { GameManager.Logger?.Log("ComWrapper", $"Обработано монет: {coinsProcessed}"); } } private void OnDisable() { _manager?.ShutdownAll(false); _manager = null; _initializeInvoked = false; } private void OnApplicationQuit() { _manager?.ShutdownAll(true); _manager = null; _initializeInvoked = false; } } }