Danil Iarosh 32cfa79578 refactor: Refactor work with COM to ComSystemManager
- Добавлен ComSystemManager как новый публичный компонент COM-системы для поэтапной замены ComWrapper
- Реализовано получение роли контроллера только после успешного handshake в ComDeviceClient
- Добавлено публичное поле ControllerRole в ComDeviceClient
- Добавлен запрос роли по команде 97 и разбор ответа формата ROLE : <value> (с пробелами)
- В ComMultiManager добавлена логика выбора DefaultDeviceId по роли main_controller
- Добавлен доступ к роли устройства через GetDeviceRole(deviceId) в менеджере и фасаде
- В ComWrapper добавлены настройки роли: roleRequestCommand, roleResponsePrefix, roleRequestTimeoutMs, mainControllerRole
- Дефолтная команда запроса роли изменена на 97
- Выполнена кодовая миграция зависимостей с ComWrapper на ComSystemManager в GameManager, GlobalsManager, PaymentManager, BalanceManager, InactivityManager, COMInput, LightController, PrizeSystem
- В GlobalsManager исправлена инициализация ссылки после AddComponent<ComSystemManager>(), чтобы исключить NullReference
2026-02-20 14:59:16 +03:00

232 lines
7.7 KiB
C#

using System;
using RR.Game2D.Core.Managers;
using UnityEngine;
using UnityEngine.Events;
namespace RR.Common.Controls
{
/// <summary>
/// Совместимый фасад над мульти-устройственной COM-системой.
/// Старый API сохранен для текущего проекта.
/// </summary>
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<string>();
[SerializeField] private string defaultDevicePort = "";
public static UnityEvent<int> OnCreditAdded;
public static UnityEvent<int> OnCreditRemoved;
public static UnityEvent<string> OnInputReceived;
public static Action OnInitialize;
public static UnityEvent<string, string> OnDeviceInputReceived;
public static UnityEvent<string> 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<int>();
OnCreditRemoved = new UnityEvent<int>();
OnInputReceived = new UnityEvent<string>();
OnDeviceInputReceived = new UnityEvent<string, string>();
OnDeviceAuthorized = new UnityEvent<string>();
if (!saveMoneyBetweenSessions) PlayerPrefs.SetInt("CoinsCount", 0);
_creditsCount = PlayerPrefs.GetInt("CoinsCount", 0);
_light = GetComponent<LightController>() ?? gameObject.AddComponent<LightController>();
_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<string>();
}
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;
}
}
}