sea-battle/Assets/Scripts/BlinkController.cs

260 lines
8.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class BlinkController
{
// Èíòåðâàë ìèãàíèÿ ïî óìîë÷àíèþ (â ñåêóíäàõ)
public static float DefaultInterval = 0.5f;
// Âíóòðåííèé ðàííåð äëÿ çàïóñêà êîðóòèí (äèíàìè÷åñêè ñîçäà¸òñÿ ïðè ïåðâîì èñïîëüçîâàíèè)
private class Runner : MonoBehaviour {
// Ïðè âûõîäå èç ïðèëîæåíèÿ âûêëþ÷àåì âñå ïîäñâåòêè
private void OnApplicationQuit()
{
BlinkController.TurnAllOff();
}
}
private static Runner _runner;
// Õðàíèëèùå çàïóùåííûõ êîðóòèí: êëþ÷ ôîðìèðóåì êàê "A_1" (òèï_èãðîê)
private static readonly Dictionary<string, Coroutine> _coroutines = new Dictionary<string, Coroutine>();
// Óáåäèìñÿ, ÷òî ðàííåð ñóùåñòâóåò è æèâ¸ò íà ñöåíå
private static void EnsureRunner()
{
if (_runner != null) return;
var go = new GameObject("_BlinkControllerRunner");
Object.DontDestroyOnLoad(go);
_runner = go.AddComponent<Runner>();
go.hideFlags = HideFlags.HideAndDontSave;
}
// ---- Àäðåñíûå êîìàíäû äëÿ ïîäñâåòîê A è B (ïî èãðîêó) ----
public static void LightAOn(int playerId) => ComWrapper.Send("2171", playerId);
public static void LightAOff(int playerId) => ComWrapper.Send("2170", playerId);
public static void LightBOn(int playerId) => ComWrapper.Send("2131", playerId);
public static void LightBOff(int playerId) => ComWrapper.Send("2130", playerId);
// ---- Ãëîáàëüíàÿ ïîäñâåòêà C (broadcast) ----
public static void LightCOn() => ComWrapper.Send("401");
public static void LightCOff() => ComWrapper.Send("400");
// ---- Start/Stop ìèãàíèÿ ----
public static void StartBlinkA(int playerId, float interval = -1f)
{
// Îñòàâëÿåì îáðàòíóþ ñîâìåñòèìîñòü: áåñêîíå÷íîå ìèãàíèå
StartBlinkATimes(playerId, -1, interval);
}
// Ìèãàíèå N ðàç (N <= 0 = áåñêîíå÷íî)
public static void StartBlinkATimes(int playerId, int times, float interval = -1f)
{
StopBlinkA(playerId);
EnsureRunner();
string key = KeyFor("A", playerId);
var coro = _runner.StartCoroutine(BlinkRoutinePlayer(key, playerId, "2170", "2171", interval > 0 ? interval : DefaultInterval, times));
_coroutines[key] = coro;
}
public static void StopBlinkA(int playerId)
{
string key = KeyFor("A", playerId);
StopAndRemove(key);
LightAOff(playerId);
}
public static void StartBlinkB(int playerId, float interval = -1f)
{
// Îñòàâëÿåì îáðàòíóþ ñîâìåñòèìîñòü: áåñêîíå÷íîå ìèãàíèå
StartBlinkBTimes(playerId, -1, interval);
}
// Ìèãàíèå N ðàç (N <= 0 = áåñêîíå÷íî)
public static void StartBlinkBTimes(int playerId, int times, float interval = -1f)
{
StopBlinkB(playerId);
EnsureRunner();
string key = KeyFor("B", playerId);
var coro = _runner.StartCoroutine(BlinkRoutinePlayer(key, playerId, "2130", "2131", interval > 0 ? interval : DefaultInterval, times));
_coroutines[key] = coro;
}
public static void StopBlinkB(int playerId)
{
string key = KeyFor("B", playerId);
StopAndRemove(key);
LightBOff(playerId);
}
// Ãëîáàëüíàÿ C
public static void StartBlinkC(float interval = -1f)
{
// Îñòàâëÿåì îáðàòíóþ ñîâìåñòèìîñòü: áåñêîíå÷íîå ìèãàíèå
StartBlinkCTimes(-1, interval);
}
// Ìèãàíèå N ðàç ãëîáàëüíî (N <= 0 = áåñêîíå÷íî)
public static void StartBlinkCTimes(int times, float interval = -1f)
{
StopBlinkC();
EnsureRunner();
string key = KeyFor("C", 0);
var coro = _runner.StartCoroutine(BlinkRoutineGlobal(key, "400", "401", interval > 0 ? interval : DefaultInterval, times));
_coroutines[key] = coro;
}
public static void StopBlinkC()
{
string key = KeyFor("C", 0);
StopAndRemove(key);
LightCOff();
}
private static void StopAndRemove(string key)
{
if (_coroutines.TryGetValue(key, out Coroutine c))
{
if (_runner != null && c != null) _runner.StopCoroutine(c);
_coroutines.Remove(key);
}
}
private static string KeyFor(string type, int playerId) => $"{type}_{playerId}";
private static IEnumerator BlinkRoutinePlayer(string key, int playerId, string onCmd, string offCmd, float interval, int repeatCount)
{
// repeatCount <= 0 => áåñêîíå÷íî
if (repeatCount <= 0)
{
while (true)
{
ComWrapper.Send(onCmd, playerId);
yield return new WaitForSeconds(interval);
ComWrapper.Send(offCmd, playerId);
yield return new WaitForSeconds(interval);
}
}
// Ïîâòîðÿåì çàäàííîå êîëè÷åñòâî ðàç
for (int i = 0; i < repeatCount; i++)
{
ComWrapper.Send(onCmd, playerId);
yield return new WaitForSeconds(interval);
ComWrapper.Send(offCmd, playerId);
// Ìåæäó èòåðàöèÿìè äåëàåì ïàóçó, êàê â îáû÷íîì ìèãàíèè, êðîìå ïîñëåäíåé
if (i < repeatCount - 1) yield return new WaitForSeconds(interval);
}
// Ãàðàíòèðóåì, ÷òî êîìàíäà âûêëþ÷åíèÿ ïîñëàíà
ComWrapper.Send(offCmd, playerId);
// Óäàëÿåì çàïèñü î êîðóòèíå
try { _coroutines.Remove(key); } catch { }
}
private static IEnumerator BlinkRoutineGlobal(string key, string onCmd, string offCmd, float interval, int repeatCount)
{
if (repeatCount <= 0)
{
while (true)
{
ComWrapper.Send(onCmd);
yield return new WaitForSeconds(interval);
ComWrapper.Send(offCmd);
yield return new WaitForSeconds(interval);
}
}
for (int i = 0; i < repeatCount; i++)
{
ComWrapper.Send(onCmd);
yield return new WaitForSeconds(interval);
ComWrapper.Send(offCmd);
if (i < repeatCount - 1) yield return new WaitForSeconds(interval);
}
ComWrapper.Send(offCmd);
try { _coroutines.Remove(key); } catch { }
}
// Âñïîìîãàòåëüíûå: ìãíîâåííûé âêë/âûêë âñåõ
public static void StopAll()
{
var keys = new List<string>(_coroutines.Keys);
foreach (var k in keys) StopAndRemove(k);
}
// Âêëþ÷èòü âñå ïîäñâåòêè (A è B — äëÿ îáîèõ èãðîêîâ, C — ãëîáàëüíî)
public static void TurnAllOn()
{
Debug.Log("BlinkController: TurnAllOn");
// A è B àäðåñíûå — äëÿ èãðîêîâ 1 è 2
LightAOn(1);
LightAOn(2);
LightBOn(1);
LightBOn(2);
// C — ãëîáàëüíî
LightCOn();
}
// Âûêëþ÷èòü âñå ïîäñâåòêè (è îñòàíîâèòü êîðóòèíû)
public static void TurnAllOff()
{
Debug.Log("BlinkController: TurnAllOff");
// Îñòàíîâèì âñå ìèãàíèÿ
StopAll();
// Îòïðàâèì êîìàíäû âûêëþ÷åíèÿ àäðåñíî äëÿ èãðîêîâ 1 è 2
try
{
LightAOff(1);
LightAOff(2);
LightBOff(1);
LightBOff(2);
// C — ãëîáàëüíî
LightCOff();
}
catch (System.Exception e)
{
Debug.LogWarning($"BlinkController: îøèáêà ïðè TurnAllOff: {e.Message}");
}
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
private static void OnRuntimeInitialized()
{
// Ïîäïèñûâàåìñÿ íà ñîáûòèå èíèöèàëèçàöèè ComWrapper — âêëþ÷èì ïîäñâåòêè, êîãäà COM áóäåò ãîòîâ
try
{
ComWrapper.OnInitialize += TurnAllOn;
// Ïîäïèñûâàåìñÿ, ÷òîáû âûêëþ÷èòü ïîäñâåòêè ÄÎ çàêðûòèÿ ïîðòîâ
ComWrapper.OnBeforeClose += TurnAllOff;
}
catch
{
// Åñëè ComWrapper åù¸ íå ñóùåñòâóåò èëè íå îïðåäåë¸í, ïðîèãíîðèðóåì — âûçîâ ïðîèçîéä¸ò ïðè èíèöèàëèçàöèè
}
// Ñîçäà¸ì ðàííåð çàðàíåå, ÷òîáû îí áûë äîñòóïåí è ãàðàíòèðîâàííî ñóùåñòâîâàë
EnsureRunner();
// Ïîäïèøåìñÿ íà ñîáûòèå âûõîäà ïðèëîæåíèÿ — ãàðàíòèðîâàííî âûêëþ÷èò ïîäñâåòêè è ïî÷èñòèò ïîäïèñêè
Application.quitting += OnApplicationQuitting;
}
// Îáðàáîò÷èê âûõîäà ïðèëîæåíèÿ: îòïèñûâàåìñÿ îò ñîáûòèé ComWrapper
private static void OnApplicationQuitting()
{
try { ComWrapper.OnInitialize -= TurnAllOn; } catch { }
try { ComWrapper.OnBeforeClose -= TurnAllOff; } catch { }
try { TurnAllOff(); } catch { }
if (_runner != null)
{
Object.Destroy(_runner.gameObject);
_runner = null;
}
}
}