diff --git a/GreatGamedevVault/Библиотека/Карантин/AudioManager.cs b/GreatGamedevVault/Библиотека/Карантин/AudioManager.cs deleted file mode 100644 index c84c7ee..0000000 --- a/GreatGamedevVault/Библиотека/Карантин/AudioManager.cs +++ /dev/null @@ -1,345 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Audio; - -namespace Managers -{ - - public class AudioManager : MonoBehaviour - { - // ==== Singleton ==== - public static AudioManager Instance { get; private set; } - - [Header("Music")] - [SerializeField] private AudioSource musicSource; // child: MusicSource - [SerializeField] private AudioSource tempMusicSource; // child: TempMusicSource - - [Tooltip("Группа микшера для музыки (необязательно)")] - [SerializeField] private AudioMixerGroup musicMixerGroup; - - [Tooltip("Целевой громкость музыки (после фейдов)")] - [Range(0f, 1.5f)] public float musicTargetVolume = 1f; - - [Tooltip("Длительность фейда по умолчанию (сек)")] - [SerializeField] private float defaultFadeDuration = 0.8f; - - [Header("SFX Pool")] - [SerializeField] private int sfxPoolSize = 8; - [SerializeField] private Transform sfxPoolParent; // child: SFX Pool - [Tooltip("Группа микшера для SFX (необязательно)")] - [SerializeField] private AudioMixerGroup sfxMixerGroup; - [Range(0f, 1.5f)] public float sfxDefaultVolume = 1f; - - private readonly List sfxPool = new List(64); - private int sfxRoundRobinIndex = 0; - - // Внутреннее - private Coroutine musicFadeCoroutine; - private Coroutine crossfadeCoroutine; - private float storedMusicVolumeBeforePause = 1f; - private bool isPausedFaded = false; - - // ==== Unity Lifetime ==== - public void Initialize() - { - // Singleton init - if (Instance != null && Instance != this) - { - Destroy(gameObject); - return; - } - Instance = this; - DontDestroyOnLoad(gameObject); - - EnsureMusicSources(); - EnsureSfxPool(); - - } - //private void Awake() - //{ - //} - - // Создаёт/находит MusicSource и TempMusicSource - private void EnsureMusicSources() - { - if (musicSource == null) - { - var t = transform.Find("MusicSource"); - if (t != null) musicSource = t.GetComponent(); - } - if (tempMusicSource == null) - { - var t = transform.Find("TempMusicSource"); - if (t != null) tempMusicSource = t.GetComponent(); - } - - if (musicSource == null) musicSource = CreateChildAudioSource("MusicSource", loop: true, output: musicMixerGroup); - if (tempMusicSource == null) tempMusicSource = CreateChildAudioSource("TempMusicSource", loop: true, output: musicMixerGroup); - - PrepareMusicSource(musicSource); - PrepareMusicSource(tempMusicSource); - tempMusicSource.volume = 0f; // запасной источник молчит - musicSource.volume = Mathf.Clamp01(musicTargetVolume); - } - - private void PrepareMusicSource(AudioSource src) - { - src.playOnAwake = false; - src.loop = true; - src.spatialBlend = 0f; // 2D музыка - if (musicMixerGroup != null) src.outputAudioMixerGroup = musicMixerGroup; - } - - private AudioSource CreateChildAudioSource(string name, bool loop, AudioMixerGroup output) - { - var go = new GameObject(name); - go.transform.SetParent(transform, false); - var src = go.AddComponent(); - src.loop = loop; - src.playOnAwake = false; - src.spatialBlend = 0f; - if (output != null) src.outputAudioMixerGroup = output; - return src; - } - - // Создаёт/находит контейнер и пул SFX источников - private void EnsureSfxPool() - { - if (sfxPoolParent == null) - { - var t = transform.Find("SFX Pool"); - if (t != null) sfxPoolParent = t; - } - if (sfxPoolParent == null) - { - var go = new GameObject("SFX Pool"); - sfxPoolParent = go.transform; - sfxPoolParent.SetParent(transform, false); - } - - // Если уже есть дети-аудиоисточники — используем их как пул. - sfxPool.Clear(); - var existing = sfxPoolParent.GetComponentsInChildren(includeInactive: true); - foreach (var src in existing) - { - SetupSfxSource(src); - sfxPool.Add(src); - } - - // Добираем до нужного размера - for (int i = sfxPool.Count; i < sfxPoolSize; i++) - { - var src = CreateSfxSource($"SFX_{i:00}"); - sfxPool.Add(src); - } - } - - private AudioSource CreateSfxSource(string name) - { - var go = new GameObject(name); - go.transform.SetParent(sfxPoolParent, false); - var src = go.AddComponent(); - SetupSfxSource(src); - return src; - } - - private void SetupSfxSource(AudioSource src) - { - src.playOnAwake = false; - src.loop = false; - src.spatialBlend = 0f; // по умолчанию 2D - src.volume = sfxDefaultVolume; - if (sfxMixerGroup != null) src.outputAudioMixerGroup = sfxMixerGroup; - } - - // ==== Public API ==== - - /// - /// Мгновенно запустить музыку (без фейда). - /// - public void PlayMusicImmediate(AudioClip clip, bool loop = true, float targetVolume = -1f) - { - if (clip == null) return; - - StopCrossfadeAndFade(); - musicSource.clip = clip; - musicSource.loop = loop; - musicSource.volume = (targetVolume >= 0f ? targetVolume : musicTargetVolume); - musicSource.Play(); - - tempMusicSource.Stop(); - tempMusicSource.clip = null; - tempMusicSource.volume = 0f; - } - - /// - /// 2) Плавно сменить музыку (кроссфейд A->B). - /// - public void CrossfadeMusic(AudioClip newClip, float duration = -1f, bool loop = true, float newTargetVolume = -1f) - { - if (newClip == null) return; - - float d = (duration > 0f ? duration : defaultFadeDuration); - float toVol = (newTargetVolume >= 0f ? newTargetVolume : musicTargetVolume); - - StopCrossfadeAndFade(); - crossfadeCoroutine = StartCoroutine(CrossfadeRoutine(newClip, d, loop, toVol)); - } - - /// - /// 1) Плавно приостановить музыку (для паузы). - /// pause=true: плавный фейд к 0 и Pause(). pause=false: UnPause() и плавный фейд к musicTargetVolume. - /// - public void SmoothPauseMusic(bool pause, float duration = -1f) - { - float d = (duration > 0f ? duration : defaultFadeDuration); - if (pause) - { - if (isPausedFaded) return; - storedMusicVolumeBeforePause = musicSource.volume; - StopCrossfadeAndFade(); - musicFadeCoroutine = StartCoroutine(FadeOutThenPause(musicSource, d)); - isPausedFaded = true; - } - else - { - if (!isPausedFaded) return; - StopCrossfadeAndFade(); - musicSource.UnPause(); - musicFadeCoroutine = StartCoroutine(Fade(musicSource, from: 0f, to: Mathf.Clamp01(musicTargetVolume), d)); - isPausedFaded = false; - } - } - - /// - /// 3) Воспроизвести SFX из пула (2D). - /// - public void PlaySfx(AudioClip clip, float volume = 1f, float pitch = 1f) - { - if (clip == null) return; - var src = GetFreeSfxSource(); - ConfigureAndPlaySfx(src, clip, volume, pitch, spatialBlend: 0f, position: null); - } - - /// - /// 3) Воспроизвести SFX из пула в мире (3D). - /// - public void PlaySfxAt(AudioClip clip, Vector3 position, float volume = 1f, float pitch = 1f, float spatialBlend = 1f) - { - if (clip == null) return; - var src = GetFreeSfxSource(); - ConfigureAndPlaySfx(src, clip, volume, pitch, Mathf.Clamp01(spatialBlend), position); - } - - // ==== Internal helpers ==== - - private void StopCrossfadeAndFade() - { - if (crossfadeCoroutine != null) { StopCoroutine(crossfadeCoroutine); crossfadeCoroutine = null; } - if (musicFadeCoroutine != null) { StopCoroutine(musicFadeCoroutine); musicFadeCoroutine = null; } - } - - private IEnumerator CrossfadeRoutine(AudioClip newClip, float duration, bool loop, float targetVol) - { - // Готовим второй источник - tempMusicSource.clip = newClip; - tempMusicSource.loop = loop; - tempMusicSource.volume = 0f; - tempMusicSource.Play(); - - float startVolA = musicSource.volume; - float t = 0f; - - while (t < duration) - { - t += Time.unscaledDeltaTime; // не зависим от timescale (музыка при паузе всё равно может фейдиться) - float k = Mathf.Clamp01(t / duration); - - // кроссфейд - musicSource.volume = Mathf.Lerp(startVolA, 0f, k); - tempMusicSource.volume = Mathf.Lerp(0f, targetVol, k); - - yield return null; - } - - // Завершение: стопим A, меняем роли (чтобы основной всегда указывал на текущую музыку) - musicSource.Stop(); - musicSource.clip = null; - musicSource.volume = targetVol; - - // Меняем ссылки местами - var swap = musicSource; - musicSource = tempMusicSource; - tempMusicSource = swap; - - // Убедимся, что запасной источник молчит - tempMusicSource.volume = 0f; - tempMusicSource.Stop(); - tempMusicSource.clip = null; - - crossfadeCoroutine = null; - } - - private IEnumerator FadeOutThenPause(AudioSource src, float duration) - { - float startVol = src.volume; - yield return Fade(src, startVol, 0f, duration); - src.Pause(); - musicFadeCoroutine = null; - } - - private IEnumerator Fade(AudioSource src, float from, float to, float duration) - { - float t = 0f; - src.volume = from; - if (!src.isPlaying) src.Play(); - - while (t < duration) - { - t += Time.unscaledDeltaTime; - float k = Mathf.Clamp01(t / duration); - src.volume = Mathf.Lerp(from, to, k); - yield return null; - } - src.volume = to; - } - - private AudioSource GetFreeSfxSource() - { - // Сначала ищем свободный - for (int i = 0; i < sfxPool.Count; i++) - { - int idx = (sfxRoundRobinIndex + i) % sfxPool.Count; - if (!sfxPool[idx].isPlaying) - { - sfxRoundRobinIndex = (idx + 1) % sfxPool.Count; - return sfxPool[idx]; - } - } - - // Если все заняты — берём по round-robin (steal) - var src = sfxPool[sfxRoundRobinIndex]; - sfxRoundRobinIndex = (sfxRoundRobinIndex + 1) % sfxPool.Count; - return src; - } - - private void ConfigureAndPlaySfx(AudioSource src, AudioClip clip, float volume, float pitch, float spatialBlend, Vector3? position) - { - src.clip = clip; - src.volume = Mathf.Clamp(volume * sfxDefaultVolume, 0f, 1.5f); - src.pitch = Mathf.Clamp(pitch, -3f, 3f); - src.spatialBlend = spatialBlend; - - if (position.HasValue) - { - src.transform.position = position.Value; - src.rolloffMode = AudioRolloffMode.Linear; - src.minDistance = 1f; - src.maxDistance = 20f; - } - - src.Play(); - } - } -} \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Карантин/GameManager.cs b/GreatGamedevVault/Библиотека/Карантин/GameManager.cs deleted file mode 100644 index d344430..0000000 --- a/GreatGamedevVault/Библиотека/Карантин/GameManager.cs +++ /dev/null @@ -1,306 +0,0 @@ -using System; -using System.IO; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace RR.Game2D.Core -{ - [DefaultExecutionOrder(-1000)] - public class GameManager : MonoBehaviour - { - public static GameManager Instance { get; private set; } - - [Header("Пауза")] - public bool IsPaused { get; private set; } - public event Action PauseStateChanged; - - [Header("Информация для игры")] - public int World { get; private set; } = 1; - public int Stage { get; private set; } = 1; - public int StagesByWorld { get; private set; } = 5; - public int Lives { get; private set; } = 3; - public int Coins { get; private set; } = 0; - - [Header("Игрок")] - [SerializeField] private GameObject playerPrefab; - [SerializeField] private string playerPrefabResourcePath = "Prefabs/Player"; - public GameObject PlayerObj { get; private set; } - private bool _shouldSpawnPlayer; - - private void OnEnable() => SceneManager.sceneLoaded += OnSceneLoaded; - private void OnDisable() => SceneManager.sceneLoaded -= OnSceneLoaded; - - public event Action PlayerSpawned; - - public event Action CoinsChanged; - - //--------------------------- - // Singleton - //--------------------------- - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] - private static void Bootstrap() - { - if (Instance == null) - { - var go = new GameObject(nameof(GameManager)); - Instance = go.AddComponent(); - DontDestroyOnLoad(go); - } - } - - private void Awake() - { - if (Instance != null && Instance != this) - { - Destroy(gameObject); - return; - } - - Instance = this; - DontDestroyOnLoad(gameObject); - - if (SceneManager.GetActiveScene().name != "MainMenu") _shouldSpawnPlayer = true; - } - - private void OnDestroy() - { - if (Instance == this) Instance = null; - } - //--------------------------- - // - //--------------------------- - - //private void Start() - //{ - // //Application.targetFrameRate = 60; - // //LoadScene("MainMenu", false); - // //NewGame(); - // if (SceneManager.GetActiveScene().name != "MainMenu") - // { - // TrySpawnPlayerForActiveScene(); - // } - //} - - /// - /// Поиск префаба игрока. - /// Если не найдет префаб из инспектора, ищет в "Resources" - /// - /// Префаб игрока - private GameObject ResolvePlayerPrefab() - { - if (playerPrefab != null) return playerPrefab; - - var loaded = Resources.Load(playerPrefabResourcePath); - if (loaded == null) - { - Debug.LogError( - $"GameManager: playerPrefab is null. Resources.Load('{playerPrefabResourcePath}') вернул null. " + - $"Ожидается файл: Assets/Resources/{playerPrefabResourcePath}.prefab (точное совпадение регистра)."); - } - return loaded; - } - - /// - /// Начало новой игры. - /// Загружает первый уровень. - /// Устанавливает жизни на 3, монеты на 0 - /// - public void NewGame() - { - Lives = 3; - Coins = 0; - CoinsChanged?.Invoke(Coins); - LoadLevel(1, 1); - } - - // Можно заменить на другое поведение - /// - /// Окончание игры. - /// Загружает сцену главного меню - /// - public void GameOver() => LoadScene("MainMenu", false); - // -- - - /// - /// Загрузка уровня по данным. - /// Загружает уровень по номерам мира и уровня - /// - /// Номер мира - /// Номер уровня - public void LoadLevel(int world, int stage) - { - this.World = world; - this.Stage = stage; - - string sceneName = $"{world}-{stage}"; - if (SceneInBuildSettingsExists(sceneName)) - { - LoadScene(sceneName); - } - else - { - //NewGame(); - // Можно заменить на другое поведение - print("WIN"); - LoadScene("MainMenu", false); - // -- - } - } - - /// - /// Загрузка сцены по названию. - /// Вызывает одноименный метод в SceneManager. - /// Может загружать сцены с UI и без. - /// В сценах без UI игрок не спавнится - /// - /// Строковое название сцены - /// Использовать ли UI - public void LoadScene(string sceneName, bool useUI = true) - { - _shouldSpawnPlayer = true; - - SceneManager.LoadScene(sceneName); - - if (useUI) - { - SceneManager.LoadScene("Level UI", LoadSceneMode.Additive); - } - - else _shouldSpawnPlayer = false; - } - - private void OnSceneLoaded(Scene scene, LoadSceneMode mode) - { - string currentSceneName = SceneManager.GetActiveScene().name; - - TrySpawnPlayerForActiveScene(); - - if (currentSceneName != $"{World}-{Stage}" && currentSceneName.Contains("-")) - { - string[] levelInfo = currentSceneName.Split("-"); - World = Convert.ToInt32(levelInfo[0]); - World = Convert.ToInt32(levelInfo[1]); - } - } - - /// - /// Метод для спавна игрока. - /// Ищет первый спавнпоинт, спавнит игрока на его позиции. - /// Если на карте есть объект игрока, удаляет его и спавнит свой - /// - private void TrySpawnPlayerForActiveScene() - { - if (!_shouldSpawnPlayer) return; - PlayerSpawn spawn = FindFirstObjectByType(); - Vector3 pos = spawn ? spawn.transform.position : new Vector3(0, 1.3f, 0); - Quaternion rot = spawn ? spawn.transform.rotation : Quaternion.identity; - - PlayerObj = GameObject.FindGameObjectWithTag("Player"); - if (PlayerObj != null) Destroy(PlayerObj); - - var prefab = ResolvePlayerPrefab(); - if (prefab == null) return; - - PlayerObj = Instantiate(prefab, pos, rot); - SceneManager.MoveGameObjectToScene(PlayerObj, SceneManager.GetActiveScene()); - - PlayerSpawned?.Invoke(PlayerObj); - } - - - /// - /// Метод переход на следующий уровень. - /// Может загружать уровни и миры в прямой зависимости от - /// Количества уровней на мир(StagesByWorld) - /// - public void NextLevel() - { - if (Stage >= StagesByWorld) - { - World++; - Stage = 1; - } - else Stage++; - LoadLevel(World, Stage); - } - - /// - /// Метод сброса уровня. - /// При сбросе также сбрасывает монеты и отнимает жизни - /// - public void ResetLevel() - { - Lives--; - - Coins = 0; - CoinsChanged?.Invoke(Coins); - - //print($"Lives: {lives}"); - if (Lives > 0) LoadLevel(World, Stage); - else GameOver(); - } - - /// - /// Метод добавления монеты - /// - public void AddCoin() - { - Coins++; - // Можно заменить на другое поведение - if (Coins >= 100) - { - Coins = 0; - AddLife(); - } - // -- - CoinsChanged?.Invoke(Coins); - } - - /// - /// Метод паузы игры. - /// Ставит на паузу все SFX и саму игру - /// - /// Ставить ли на паузу - public void SetPause(bool pause) - { - if (IsPaused == pause) return; - IsPaused = pause; - - Time.timeScale = pause ? 0f : 1f; - AudioListener.pause = pause; - - PauseStateChanged?.Invoke(IsPaused); - } - - // Можно заменить на другое поведение - /// - /// Метод переключателя паузы - /// - public void TogglePause() => SetPause(!IsPaused); - // -- - - // Можно заменить на другое поведение - /// - /// Метод для добавления жизни. - /// - public void AddLife() => Lives++; - // -- - - /// - /// Метод проверки сцены на существование в настройках билда - /// - /// Строковое название сцены - /// - private static bool SceneInBuildSettingsExists(string sceneName) - { - int count = SceneManager.sceneCountInBuildSettings; - for (int i = 0; i < count; i++) - { - string path = SceneUtility.GetScenePathByBuildIndex(i); - if (Path.GetFileNameWithoutExtension(path) == sceneName) - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative.sln b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative.sln deleted file mode 100644 index cbb102c..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.14.36603.0 d17.14 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ComNative", "ComNative\ComNative.vcxproj", "{BCC43995-EF98-4066-BB8D-58819B0AFB01}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Debug|x64.ActiveCfg = Release|x64 - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Debug|x64.Build.0 = Release|x64 - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Debug|x86.ActiveCfg = Debug|Win32 - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Debug|x86.Build.0 = Debug|Win32 - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Release|x64.ActiveCfg = Release|x64 - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Release|x64.Build.0 = Release|x64 - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Release|x86.ActiveCfg = Release|Win32 - {BCC43995-EF98-4066-BB8D-58819B0AFB01}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {022B4E09-68D9-43CB-B2A3-E6ABE4525C96} - EndGlobalSection -EndGlobal diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj deleted file mode 100644 index 1e2c5d6..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj +++ /dev/null @@ -1,154 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 17.0 - Win32Proj - {bcc43995-ef98-4066-bb8d-58819b0afb01} - ComNative - 10.0 - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - Level3 - true - WIN32;_DEBUG;COMNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use - pch.h - - - Windows - true - false - - - - - Level3 - true - true - true - WIN32;NDEBUG;COMNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use - pch.h - - - Windows - true - false - - - - - Level3 - true - _DEBUG;COMNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use - pch.h - - - Windows - true - false - - - - - Level3 - true - true - true - NDEBUG;COMNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - NotUsing - pch.h - - - Windows - true - false - - - - - - - - - - - Create - Create - Create - Create - - - - - - \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj.filters b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj.filters deleted file mode 100644 index 6216c47..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Файлы заголовков - - - Файлы заголовков - - - Файлы заголовков - - - - - Исходные файлы - - - Исходные файлы - - - \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj.user b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/ComNative.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/SerialNative.cpp b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/SerialNative.cpp deleted file mode 100644 index 34f0a2c..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/SerialNative.cpp +++ /dev/null @@ -1,261 +0,0 @@ -// SerialNative.cpp -#include "SerialNative.h" -#include -#include -#include -#include -#include - -static std::mutex gMutex; -static std::unordered_map gHandles; -static int gNextId = 1; - -static thread_local std::wstring gLastError; - -static void SetLastErrFromWin32(const wchar_t* where, DWORD err = GetLastError()) { - wchar_t* msg = nullptr; - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR)&msg, 0, nullptr); - if (msg) { gLastError = std::wstring(where) + L": (" + std::to_wstring(err) + L") " + msg; LocalFree(msg); } - else { gLastError = std::wstring(where) + L": error " + std::to_wstring(err); } -} - -static std::wstring BuildDevicePath(const std::wstring& portName) { - if (portName.rfind(L"\\\\.\\", 0) == 0) return portName; // уже с префиксом - return L"\\\\.\\" + portName; -} - -// --- аккуратный enumerator COM-портов --- -static std::wstring EnumerateComPortsJoined() { - std::vector found; - wchar_t target[4096]; - for (int i = 1; i <= 256; ++i) { - std::wstring name = L"COM" + std::to_wstring(i); - DWORD r = QueryDosDeviceW(name.c_str(), target, static_cast(std::size(target))); - if (r != 0) found.push_back(name); - } - std::wstring joined; - for (size_t i = 0; i < found.size(); ++i) { - if (i) joined += L";"; - joined += found[i]; - } - return joined; -} - -// --- безопасная выдача HANDLE по id --- -static HANDLE GetHandle(int handleId) { - std::lock_guard lk(gMutex); - auto it = gHandles.find(handleId); - return (it == gHandles.end()) ? nullptr : it->second; -} - -// --- внутренняя запись байтов (без экспорта) --- -static int WriteBytes(HANDLE h, const uint8_t* data, int length) { - if (!h || !data || length < 0) { gLastError = L"WriteBytes: invalid args"; return -1; } - DWORD written = 0; - if (!WriteFile(h, data, static_cast(length), &written, nullptr)) { - SetLastErrFromWin32(L"WriteFile"); - return -1; - } - return static_cast(written); -} - -// --- гарантированная зачистка при выгрузке процесса (Alt+F4 и т.п.) --- -BOOL APIENTRY DllMain(HINSTANCE, DWORD reason, LPVOID) { - if (reason == DLL_PROCESS_DETACH) { - std::lock_guard lk(gMutex); - for (auto& kv : gHandles) { - HANDLE h = kv.second; - if (h && h != INVALID_HANDLE_VALUE) CloseHandle(h); - } - gHandles.clear(); - } - return TRUE; -} - -// ---------- Перечень портов ---------- -SERIAL_API -int __cdecl Serial_ListPortsLength() { - std::wstring s = EnumerateComPortsJoined(); - return static_cast(s.size() + 1); -} - -SERIAL_API -int __cdecl Serial_ListPorts(wchar_t* buffer, int bufferChars) { - std::wstring s = EnumerateComPortsJoined(); - int need = static_cast(s.size() + 1); - if (!buffer || bufferChars <= 0) return need; - if (bufferChars < need) return -1; - wcsncpy_s(buffer, bufferChars, s.c_str(), _TRUNCATE); - return need; -} - -// ---------- Работа с портом ---------- -SERIAL_API -int __cdecl Serial_Open(const wchar_t* portName, - int baudRate, int dataBits, int parity, int stopBits, - int readTimeoutMs, int writeTimeoutMs) -{ - if (!portName || !*portName) { gLastError = L"Serial_Open: empty portName"; return 0; } - - std::wstring dev = BuildDevicePath(portName); - - // Retry-цикл, лечит ACCESS_DENIED/SHARING_VIOLATION сразу после Alt+F4 - const int kMaxTries = 20; // до ~2 сек - const DWORD kSleepMs = 100; - HANDLE h = INVALID_HANDLE_VALUE; - DWORD lastErr = 0; - - for (int i = 0; i < kMaxTries; ++i) { - h = CreateFileW(dev.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (h != INVALID_HANDLE_VALUE) break; - - lastErr = GetLastError(); - if (lastErr == ERROR_ACCESS_DENIED || lastErr == ERROR_SHARING_VIOLATION) { - Sleep(kSleepMs); - continue; - } - else { - break; - } - } - if (h == INVALID_HANDLE_VALUE) { SetLastErrFromWin32(L"CreateFileW", lastErr); return 0; } - - SetupComm(h, 1 << 15, 1 << 15); // 32KB RX/TX - - // DCB - DCB dcb{}; dcb.DCBlength = sizeof(DCB); - if (!GetCommState(h, &dcb)) { SetLastErrFromWin32(L"GetCommState"); CloseHandle(h); return 0; } - dcb.BaudRate = static_cast(baudRate); - dcb.ByteSize = static_cast(dataBits > 0 ? dataBits : 8); - dcb.fBinary = TRUE; - dcb.fParity = (parity != 0); - - switch (parity) { - case 0: dcb.Parity = NOPARITY; break; - case 1: dcb.Parity = ODDPARITY; break; - case 2: dcb.Parity = EVENPARITY; break; - case 3: dcb.Parity = MARKPARITY; break; - case 4: dcb.Parity = SPACEPARITY;break; - default: dcb.Parity = NOPARITY; break; - } - dcb.StopBits = (stopBits == 2) ? TWOSTOPBITS : ONESTOPBIT; - dcb.fDtrControl = DTR_CONTROL_DISABLE; // как раньше - dcb.fRtsControl = RTS_CONTROL_DISABLE; // как раньше - - if (!SetCommState(h, &dcb)) { SetLastErrFromWin32(L"SetCommState"); CloseHandle(h); return 0; } - - // Таймауты - COMMTIMEOUTS to{}; - to.ReadIntervalTimeout = 50; - to.ReadTotalTimeoutConstant = (readTimeoutMs >= 0) ? static_cast(readTimeoutMs) : 0; - to.ReadTotalTimeoutMultiplier = 0; - to.WriteTotalTimeoutConstant = (writeTimeoutMs >= 0) ? static_cast(writeTimeoutMs) : 0; - to.WriteTotalTimeoutMultiplier = 0; - if (!SetCommTimeouts(h, &to)) { SetLastErrFromWin32(L"SetCommTimeouts"); CloseHandle(h); return 0; } - - // Полная очистка очередей на старте - PurgeComm(h, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); - - // Регистрируем handle - { - std::lock_guard lk(gMutex); - int id = gNextId++; - gHandles[id] = h; - return id; - } -} - -SERIAL_API -int __cdecl Serial_Close(int handleId) { - std::lock_guard lk(gMutex); - auto it = gHandles.find(handleId); - if (it == gHandles.end()) { gLastError = L"Serial_Close: invalid handleId"; return 0; } - HANDLE h = it->second; - gHandles.erase(it); - if (h && h != INVALID_HANDLE_VALUE) { CloseHandle(h); return 1; } - return 0; -} - -SERIAL_API -int __cdecl Serial_CloseAll() { - std::lock_guard lk(gMutex); - int closed = 0; - for (auto& kv : gHandles) { - HANDLE h = kv.second; - if (h && h != INVALID_HANDLE_VALUE) { CloseHandle(h); ++closed; } - } - gHandles.clear(); - return closed; -} - -// ---------- Запись ---------- -SERIAL_API -int __cdecl Serial_WriteStringUTF8(int handleId, const char* utf8, int appendNewline) { - if (!utf8) { gLastError = L"Serial_WriteStringUTF8: utf8 is null"; return -1; } - HANDLE h = GetHandle(handleId); - if (!h) { gLastError = L"Serial_WriteStringUTF8: invalid handleId"; return -1; } - - const uint8_t* bytes = reinterpret_cast(utf8); - int len = static_cast(strlen(utf8)); - - int total = 0; - int w = WriteBytes(h, bytes, len); - if (w < 0) return -1; - total += w; - - if (appendNewline) { - const uint8_t nl = '\n'; - w = WriteBytes(h, &nl, 1); - if (w < 0) return -1; - total += w; - } - return total; -} - -// ---------- Чтение ---------- -SERIAL_API -int __cdecl Serial_ReadLineUTF8(int handleId, char* buffer, int bufferSize) { - HANDLE h = GetHandle(handleId); - if (!h) { gLastError = L"handle incorrect"; return -1; } - if (buffer == nullptr) { gLastError = L"Serial_ReadLineUTF8: buffer is null"; return -1; } - if (bufferSize <= 1) { - gLastError = L"Serial_ReadLineUTF8: bufferSize too small (<=1). Got " + std::to_wstring(bufferSize); - buffer[0] = 0; return -1; - } - - int pos = 0; - DWORD read = 0; - char ch = 0; - - while (pos < bufferSize - 1) { - BOOL ok = ReadFile(h, &ch, 1, &read, nullptr); - if (!ok) { SetLastErrFromWin32(L"ReadFile"); return -1; } - if (read == 0) { // таймаут - if (pos == 0) { buffer[0] = 0; return 0; } - break; - } - if (ch == '\n') break; - if (ch != '\r') buffer[pos++] = ch; - } - - if (pos >= bufferSize - 1) { - buffer[bufferSize - 1] = 0; - return -2; // усечено - } - - buffer[pos] = 0; - return pos; -} - -// ---------- Диагностика ---------- -SERIAL_API -int __cdecl Serial_GetLastErrorW(wchar_t* buffer, int bufferChars) { - int need = static_cast(gLastError.size() + 1); - if (!buffer || bufferChars <= 0) return need; - if (bufferChars < need) return -1; - wcsncpy_s(buffer, bufferChars, gLastError.c_str(), _TRUNCATE); - return need; -} diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/SerialNative.h b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/SerialNative.h deleted file mode 100644 index 8cb17e7..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/SerialNative.h +++ /dev/null @@ -1,29 +0,0 @@ -// SerialNative.h -#pragma once -#include - -#ifdef _WIN32 - #define SERIAL_API extern "C" __declspec(dllexport) -#else - #define SERIAL_API extern "C" -#endif - -// --- Перечень портов --- -SERIAL_API int __cdecl Serial_ListPortsLength(); -SERIAL_API int __cdecl Serial_ListPorts(wchar_t* buffer, int bufferChars); - -// --- Работа с портом --- -SERIAL_API int __cdecl Serial_Open(const wchar_t* portName, - int baudRate, int dataBits, int parity, int stopBits, - int readTimeoutMs, int writeTimeoutMs); -SERIAL_API int __cdecl Serial_Close(int handleId); -SERIAL_API int __cdecl Serial_CloseAll(); // NEW: глобальная зачистка хэндлов - -// --- Запись (оставили только строковую; байтовую убрали из экспорта) --- -SERIAL_API int __cdecl Serial_WriteStringUTF8(int handleId, const char* utf8, int appendNewline); - -// --- Чтение (оставили только построчное) --- -SERIAL_API int __cdecl Serial_ReadLineUTF8(int handleId, char* buffer, int bufferSize); - -// --- Диагностика --- -SERIAL_API int __cdecl Serial_GetLastErrorW(wchar_t* buffer, int bufferChars); diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/dllmain.cpp b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/dllmain.cpp deleted file mode 100644 index f840505..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/dllmain.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// dllmain.cpp : Определяет точку входа для приложения DLL. -#include "pch.h" - -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} - diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/framework.h b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/framework.h deleted file mode 100644 index 61ca0b6..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/framework.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN // Исключите редко используемые компоненты из заголовков Windows -// Файлы заголовков Windows -#include diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/pch.cpp b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/pch.cpp deleted file mode 100644 index 9211a5e..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/pch.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// pch.cpp: файл исходного кода, соответствующий предварительно скомпилированному заголовочному файлу - -#include "pch.h" - -// При использовании предварительно скомпилированных заголовочных файлов необходим следующий файл исходного кода для выполнения сборки. diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/pch.h b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/pch.h deleted file mode 100644 index 42d0757..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/pch.h +++ /dev/null @@ -1,13 +0,0 @@ -// pch.h: это предварительно скомпилированный заголовочный файл. -// Перечисленные ниже файлы компилируются только один раз, что ускоряет последующие сборки. -// Это также влияет на работу IntelliSense, включая многие функции просмотра и завершения кода. -// Однако изменение любого из приведенных здесь файлов между операциями сборки приведет к повторной компиляции всех(!) этих файлов. -// Не добавляйте сюда файлы, которые планируете часто изменять, так как в этом случае выигрыша в производительности не будет. - -#ifndef PCH_H -#define PCH_H - -// Добавьте сюда заголовочные файлы для предварительной компиляции -#include "framework.h" - -#endif //PCH_H diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.dll.recipe b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.dll.recipe deleted file mode 100644 index c4fa5f5..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.dll.recipe +++ /dev/null @@ -1,11 +0,0 @@ - - - - - C:\Users\Programmer\source\repos\ComNative\x64\Release\ComNative.dll - - - - - - \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.iobj b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.iobj deleted file mode 100644 index 0a544c0..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.iobj and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.ipdb b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.ipdb deleted file mode 100644 index 9272437..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.ipdb and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.log b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.log deleted file mode 100644 index 8898563..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.log +++ /dev/null @@ -1,8 +0,0 @@ - SerialNative.cpp - Создается библиотека C:\Users\Programmer\source\repos\ComNative\x64\Release\ComNative.lib и объект C:\Users\Programmer\source\repos\ComNative\x64\Release\ComNative.exp - Создание кода - 1 of 376 functions ( 0.3%) were compiled, the rest were copied from previous compilation. - 0 functions were new in current compilation - 0 functions had inline decision re-evaluated but remain unchanged - Создание кода завершено - ComNative.vcxproj -> C:\Users\Programmer\source\repos\ComNative\x64\Release\ComNative.dll diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.pch b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.pch deleted file mode 100644 index 1beffe4..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.pch and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.command.1.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.command.1.tlog deleted file mode 100644 index 558e29a..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.command.1.tlog and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.read.1.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.read.1.tlog deleted file mode 100644 index 9272a88..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.read.1.tlog and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.write.1.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.write.1.tlog deleted file mode 100644 index 17fb5c0..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/CL.write.1.tlog and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/Cl.items.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/Cl.items.tlog deleted file mode 100644 index 21e6b56..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/Cl.items.tlog +++ /dev/null @@ -1,2 +0,0 @@ -C:\Users\Programmer\source\repos\ComNative\ComNative\SerialNative.cpp;C:\Users\Programmer\source\repos\ComNative\ComNative\x64\Release\SerialNative.obj -C:\Users\Programmer\source\repos\ComNative\ComNative\pch.cpp;C:\Users\Programmer\source\repos\ComNative\ComNative\x64\Release\pch.obj diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/ComNative.lastbuildstate b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/ComNative.lastbuildstate deleted file mode 100644 index 135a445..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/ComNative.lastbuildstate +++ /dev/null @@ -1,2 +0,0 @@ -PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.44.35207:TargetPlatformVersion=10.0.26100.0: -Release|x64|C:\Users\Programmer\source\repos\ComNative\| diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.command.1.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.command.1.tlog deleted file mode 100644 index 23eaf57..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.command.1.tlog and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.read.1.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.read.1.tlog deleted file mode 100644 index e447ff8..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.read.1.tlog and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.secondary.1.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.secondary.1.tlog deleted file mode 100644 index f0e2c69..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.secondary.1.tlog +++ /dev/null @@ -1,5 +0,0 @@ -^C:\USERS\PROGRAMMER\SOURCE\REPOS\COMNATIVE\COMNATIVE\X64\RELEASE\PCH.OBJ|C:\USERS\PROGRAMMER\SOURCE\REPOS\COMNATIVE\COMNATIVE\X64\RELEASE\SERIALNATIVE.OBJ -C:\Users\Programmer\source\repos\ComNative\x64\Release\ComNative.lib -C:\Users\Programmer\source\repos\ComNative\x64\Release\ComNative.EXP -C:\Users\Programmer\source\repos\ComNative\ComNative\x64\Release\ComNative.IPDB -C:\Users\Programmer\source\repos\ComNative\ComNative\x64\Release\ComNative.iobj diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.write.1.tlog b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.write.1.tlog deleted file mode 100644 index 02688e0..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/ComNative.tlog/link.write.1.tlog and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/SerialNative.obj b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/SerialNative.obj deleted file mode 100644 index 32697bc..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/SerialNative.obj and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/dllmain.obj b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/dllmain.obj deleted file mode 100644 index 60b69c1..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/dllmain.obj and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/pch.obj b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/pch.obj deleted file mode 100644 index ae1e334..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/pch.obj and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/vc143.pdb b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/vc143.pdb deleted file mode 100644 index bae206d..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/ComNative/x64/Release/vc143.pdb and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.dll b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.dll deleted file mode 100644 index e0f6d6b..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.dll and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.exp b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.exp deleted file mode 100644 index ccb093f..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.exp and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.lib b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.lib deleted file mode 100644 index ba0439c..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.lib and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.pdb b/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.pdb deleted file mode 100644 index 508efef..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/src/ComNative/x64/Release/ComNative.pdb and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Plugins/x86_64/ComNative.dll b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Plugins/x86_64/ComNative.dll deleted file mode 100644 index e0f6d6b..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Plugins/x86_64/ComNative.dll and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ButtonPinMapping.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ButtonPinMapping.cs deleted file mode 100644 index 9b5e564..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ButtonPinMapping.cs +++ /dev/null @@ -1,43 +0,0 @@ -/// -/// Соответствие между кнопками игрового ввода и цифровыми выходами периферийной платы (пины 0-15). -/// Содержит mapping для управления двух игроков, служебных кнопок и датчиков хопера. -/// -public enum ButtonPinMapping -{ - /// Кнопка движения вверх для первого игрока - up1 = 0, - /// Кнопка движения вправо для первого игрока - right1 = 1, - /// Кнопка движения вниз для первого игрока - down1 = 2, - /// Кнопка движения влево для первого игрока - left1 = 3, - /// Действие/огонь для первого игрока - action1 = 4, - - /// Кнопка движения вверх для второго игрока - up2 = 5, - /// Кнопка движения вправо для второго игрока - right2 = 6, - /// Кнопка движения вниз для второго игрока - down2 = 7, - /// Кнопка движения влево для второго игрока - left2 = 8, - /// Действие/огонь для второго игрока - action2 = 9, - - /// Запуск игры для одного игрока - startOnePlayer = 10, - /// Запуск игры для двух игроков - startTwoPlayers = 11, - /// Секретная/служебная кнопка для захода в настройки - secret = 12, - - /// Дополнительная/резервная кнопка - extra = 13, - - /// Датчик наличия приза в хопере - hasPrize = 14, - /// Датчик выдачи приза из хопера - prizeGiven = 15 -} diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/COMinput.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/COMinput.cs deleted file mode 100644 index d4e3694..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/COMinput.cs +++ /dev/null @@ -1,253 +0,0 @@ -using System; -using UnityEngine; - -public class COMinput : InputSource -{ - //Количество = цифровые + 2 датчика. - //На момент написания количество цифровых входов 7*N. - //Настроить количество пинов под свою настройку платы - private const int PIN_COUNT = 16; - - private const char POSITIVE = '0'; - private const char NEGATIVE = '1'; - - private bool[] buttonState = new bool[PIN_COUNT]; - private bool[] buttonDown = new bool[PIN_COUNT]; - private bool[] buttonUp = new bool[PIN_COUNT]; - - //Свойство для определения текущего игрока - //Должно возвращать 1 или 2 - //Используется для получения состояния кнопок с пометкой ...CurrentPlayer - private int currentPlayer => gm.currentPlayer == CellState.Player1 ? 1 : 2;//ПЕРЕОПРЕДЕЛИТЕ ОПРЕДЕЛЕНИЕ ТЕКУЩЕГО ИГРОКА ПОД СВОЮ СИСТЕМУ. - private GameManager gm;//я получаю кто сейчас ходит через этого менеджера. Если у вас другое, допишите. - - public override bool Initialize() - { - try - { - gm = GameManager.instance; - - //ОБЯЗАТЕЛЬНЫЙ БЛОК - ComWrapper.onInputRecieved.AddListener(UpdateInputState); - - } - catch (Exception e) - { - Debug.Log($"Что то в COMinput {e.ToString()}"); - return false; - } - return true; - } - - #region PUBLIC_API - - //ЭТА ГРУППА МЕТОДОВ ДЛЯ ПОЛУЧЕНИЯ СОСТОЯНИЯ ЛЮБОЙ КНОПКИ ПО ПИНУ (enum ButtonPinMapping) - - /// - /// Получает состояние конкретной кнопки по её физическому пину. - /// Возвращает true если кнопка в данный момент нажата. - /// - /// Пин кнопки на периферийной плате - /// True если кнопка нажата в текущем кадре - public override bool GetButton(ButtonPinMapping button) => buttonState[(int)button]; - - /// - /// Проверяет, была ли кнопка нажата в начале текущего кадра. - /// Удерживает true до тех пор, пока кто то не проверит, затем сбрасывает. - /// - /// Пин кнопки на периферийной плате - /// True если кнопка была нажата в этом кадре - public override bool GetButtonDown(ButtonPinMapping button) => ConsumeButtonEvent(buttonDown, button); - - /// - /// Проверяет, была ли кнопка отпущена в начале текущего кадра. - /// Удерживает true до тех пор, пока кто то не проверит, затем сбрасывает. - /// - /// Пин кнопки на периферийной плате - /// True если кнопка была отпущена в этом кадре - public override bool GetButtonUp(ButtonPinMapping button) => ConsumeButtonEvent(buttonUp, button); - - - /// - /// Получает состояние кнопки по числовому индексу пина напрямую из буфера состояний. - /// Обходит перечисление ButtonPinMapping для прямого доступа к пинам по индексу. - /// - /// Числовой индекс пина (0-15) - /// true если кнопка нажата в текущий момент - /// - /// Используется когда необходим прямой доступ к пинам без приведения к перечислению. - /// Подходит для сценариев где количество пинов может превышать размер перечисления. - /// - public override bool GetButton(int pinIndex) => buttonState[pinIndex]; - - /// - /// Проверяет, была ли кнопка нажата в начале текущего кадра по числовому индексу пина. - /// Возвращает true только в первом кадре после нажатия и сбрасывает флаг события. - /// - /// Числовой индекс пина (0-15) - /// true если кнопка была нажата в этом кадре - /// - /// Метод "потребляет" событие - после чтения флаг сбрасывается. - /// Использует общий механизм ConsumeButtonEvent для обработки одноразовых событий. - /// - public override bool GetButtonDown(int pinIndex) => ConsumeButtonEvent(buttonDown, pinIndex); - - /// - /// Проверяет, была ли кнопка отпущена в начале текущего кадра по числовому индексу пина. - /// Возвращает true только в первом кадре после отпускания и сбрасывает флаг события. - /// - /// Числовой индекс пина (0-15) - /// true если кнопка была отпущена в этом кадре - /// - /// Метод "потребляет" событие - после чтения флаг сбрасывается. - /// Использует общий механизм ConsumeButtonEvent для обработки одноразовых событий. - /// - public override bool GetButtonUp(int pinIndex) => ConsumeButtonEvent(buttonUp, pinIndex); - // ------------------------------------------------------------------------------------ - //ЭТА ГРУППА МЕТОДОВ ПОЗВОЛЯЕТ УЗНАТЬ СОСТОЯНИЯ КНОПОК АКТИВНОГО ИГРОКА (проверка по enum PlayerAction) - //Служебные кнопки типа startOnePlayer, startTwoPlayers, secret, extra, hasPrize, prizeGiven здесь не проверяются - - /// - /// Получает состояние действия для текущего игрока. - /// Возвращает true если действие активно (кнопка нажата) у текущего игрока. - /// - /// Действие игрока (up, down, left, right, action, extra) - /// True если действие активно у текущего игрока - public override bool GetButtonCurrentPlayer(PlayerAction button) - => GetButton(GetButtonForCurrentPlayer(button)); - - /// - /// Проверяет, было ли действие начато текущим игроком в этом кадре. - /// Возвращает true только в первом кадре после начала действия. - /// - /// Действие игрока - /// True если действие было начато в этом кадре - public override bool GetButtonDownCurrentPlayer(PlayerAction button) - => GetButtonDown(GetButtonForCurrentPlayer(button)); - - /// - /// Проверяет, было ли действие завершено текущим игроком в этом кадре. - /// Возвращает true только в первом кадре после завершения действия. - /// - /// Действие игрока - /// True если действие было завершено в этом кадре - public override bool GetButtonUpCurrentPlayer(PlayerAction button) - => GetButtonUp(GetButtonForCurrentPlayer(button)); - - // ------------------------------------------------------------------------------------ - //ЭТА ГРУППА МЕТОДОВ ПОЗВОЛЯЕТ УЗНАТЬ СОСТОЯНИЯ КНОПОК ЛЮБОГО ИГРОКА (проверка по enum PlayerAction) - //Служебные кнопки типа startOnePlayer, startTwoPlayers, secret, extra, hasPrize, prizeGiven здесь не проверяются - - /// - /// Получает состояние действия для любого из игроков. - /// Возвращает true если действие активно у первого ИЛИ второго игрока. - /// - /// Действие игрока - /// True если действие активно у любого игрока - public override bool GetButtonAnyPlayer(PlayerAction button) - => CheckBothPlayers(button, GetButton); - - /// - /// Проверяет, было ли действие начато любым игроком в этом кадре. - /// Возвращает true если первый ИЛИ второй игрок начали действие в этом кадре. - /// - /// Действие игрока - /// True если действие было начато любым игроком в этом кадре - public override bool GetButtonDownAnyPlayer(PlayerAction button) - => CheckBothPlayers(button, GetButtonDown); - - /// - /// Проверяет, было ли действие завершено любым игроком в этом кадре. - /// Возвращает true если первый ИЛИ второй игрок завершили действие в этом кадре. - /// - /// Действие игрока - /// True если действие было завершено любым игроком в этом кадре - public override bool GetButtonUpAnyPlayer(PlayerAction button) - => CheckBothPlayers(button, GetButtonUp); - #endregion - - - //==========ХЕЛПЕРЫ========== - // Проверка нажатия с обоих контроллеров игроков - private bool CheckBothPlayers(PlayerAction action, Func buttonFunc) - { - var buttons = _buttonByAction(action); - return buttonFunc(buttons.player1button) || buttonFunc(buttons.player2button); - } - - // Проверка нажатия с контроллера текущего игрока - private ButtonPinMapping GetButtonForCurrentPlayer(PlayerAction button) - { - var buttons = _buttonByAction(button); - return currentPlayer == 1 ? buttons.player1button : buttons.player2button; - } - - // Маппер из действий игрока => пины платы - private (ButtonPinMapping player1button, ButtonPinMapping player2button) _buttonByAction(PlayerAction playerAction) => - playerAction switch - { - PlayerAction.up => (ButtonPinMapping.up1, ButtonPinMapping.up2), - PlayerAction.down => (ButtonPinMapping.down1, ButtonPinMapping.down2), - PlayerAction.left => (ButtonPinMapping.left1, ButtonPinMapping.left2), - PlayerAction.right => (ButtonPinMapping.right1, ButtonPinMapping.right2), - PlayerAction.action => (ButtonPinMapping.action1, ButtonPinMapping.action2), - PlayerAction.extra => (ButtonPinMapping.extra, ButtonPinMapping.extra), // одинаковая кнопка - _ => throw new ArgumentException($"Unknown player action: {playerAction}") - - }; - - // Обновляет состояния инпута когда приходит новый ввод с платы. Дергается событием. - private void UpdateInputState(string input) - { - // Будем принимать в нативном формате by Pasha. 0 - нажато 1 - не нажато (чтобы преобразовывать циклом) - // В параметрприходит строка вида "1111011111011111" - for (int i = 0; i < input.Length; i++) - { - // Получаем новое состояние пина - bool newState = input[i] == POSITIVE; - - // Состояние пина изменилось => пишем в буферы - if (newState != buttonState[i]) - { - if(newState) // Пин был зажат - { - buttonDown[i] = true; - buttonUp[i] = false; - } - else // Пин был отжат - { - buttonDown[i] = false; - buttonUp[i] = true; - } - } - - buttonState[i] = newState; - - } - if (input[^1] == POSITIVE) PlayerPrefs.SetInt("PrizeGivenBuffer", 1); //пишем в буфер чтобы между кадрами и порядком вызова не проебать - - DebugWindow.Message("Инпуты: " + string.Join("", buttonState));//можно вырезать - } - - // Потребление "Нажатия"/"Отжатия". Возвращает что там было и чистит флаг из буфера - private bool ConsumeButtonEvent(bool[] buffer, ButtonPinMapping button) - { - bool result = buffer[(int)button]; - buffer[(int)button] = false; - return result; - } - - /// - /// Вспомогательный метод для обработки одноразовых событий кнопок по числовому индексу. - /// Возвращает текущее значение флага и сбрасывает его для предотвращения повторной обработки. - /// - /// Буфер событий (buttonDown или buttonUp) - /// Числовой индекс пина - /// Состояние флага события до сброса - private bool ConsumeButtonEvent(bool[] buffer, int pinIndex) - { - bool result = buffer[pinIndex]; - buffer[pinIndex] = false; - return result; - } -} diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/ComNativeWrapper.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/ComNativeWrapper.cs deleted file mode 100644 index eea135e..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/ComNativeWrapper.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Text; - -public static class ComNativeWrapper -{ - private const string Dll = "ComNative"; // имя файла в Plugins/x86_64 без .dll - - // --- Порты (Unicode) --- - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] - public static extern int Serial_ListPortsLength(); - - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] - public static extern int Serial_ListPorts(StringBuilder buffer, int bufferChars); - - // --- Открытие/закрытие --- - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] - public static extern int Serial_Open(string portName, int baud, int dataBits, int parity, int stopBits, - int readTimeoutMs, int writeTimeoutMs); - - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl)] - public static extern int Serial_Close(int handleId); - - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl)] - public static extern int Serial_CloseAll(); // NEW - - // --- Запись/чтение (строкой) --- - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern int Serial_WriteStringUTF8(int handleId, string utf8, int appendNewline); - - // byte[]-вариант к той же native-функции (EntryPoint), чтобы избежать маршаллинга StringBuilder - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Serial_ReadLineUTF8")] - public static extern int Serial_ReadLineUTF8_bytes(int handleId, byte[] buffer, int bufferSize); - - // --- Ошибка (Unicode) --- - [DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] - public static extern int Serial_GetLastErrorW(StringBuilder buffer, int bufferChars); - - public static string GetLastError() - { - int need = Serial_GetLastErrorW(null, 0); - var sb = new StringBuilder(Math.Max(need, 1)); - int r = Serial_GetLastErrorW(sb, sb.Capacity); - return (r < 0) ? $"err({r})" : sb.ToString(); - } - - public static string[] ListPorts() - { - int need = Serial_ListPortsLength(); - if (need <= 1) return Array.Empty(); - var sb = new StringBuilder(need); - int r = Serial_ListPorts(sb, sb.Capacity); - if (r < 0) return Array.Empty(); - string joined = sb.ToString(); - return string.IsNullOrWhiteSpace(joined) ? Array.Empty() : joined.Split(';'); - } -} diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/ComWrapper.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/ComWrapper.cs deleted file mode 100644 index 316df6c..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/ComWrapper.cs +++ /dev/null @@ -1,262 +0,0 @@ -using System.Text; -using UnityEngine; -using UnityEngine.Events; - -/// -/// Основной класс-обертка для работы с COM-портом и периферийной платой. -/// Управляет всей коммуникацией с аппаратным обеспечением: прием монет, чтение кнопок, управление подсветкой, отправка сигналов. -/// -public class ComWrapper : MonoBehaviour -{ - //Настраиваем из инспектора - [SerializeField] bool saveMoneyBetweenSessions; - [SerializeField] bool enablePrizeChecking = false; // Если хопер с проверкой наличия приза ставим true - - - public static UnityEvent onCoinAdded; - public static UnityEvent onCoinRemoved; - public static UnityEvent onInputRecieved; - - #region Приватные поля - private const string REQUEST_INPUT = "91"; - private const string DEFAULT_INPUT = "INPUT1111111111111111"; - private const string LIGHTSIGNAL_PREFIX = "80"; - - private static int h;//идентификатор хэндла - private static byte[] buf = new byte[1024]; //Байт-буфер куда будут приходить данные с порта - - private static int CreditsCount; - private string inputString = DEFAULT_INPUT; - #endregion - - //===========================start: PUBLIC API===========================// - - /// - /// Инициализирует систему работы с COM-портом. - /// Открывает соединение, настраивает события и запускает периодические запросы состояния. - /// - /// - /// Обязателен к вызову при старте приложения. Выполняет: - /// - Создание UnityEvent'ов для уведомлений - /// - Загрузку количества кредитов из PlayerPrefs - /// - Открытие COM-порта - /// - Запуск периодического опроса пинов (если включена проверка призов) - /// - public void Initialize() - { - //Создаем ивенты - onCoinAdded = new UnityEvent(); - onCoinRemoved = new UnityEvent(); - - //Начальная настройка - if (!saveMoneyBetweenSessions) PlayerPrefs.SetInt("CoinsCount", 0); - CreditsCount = PlayerPrefs.GetInt("CoinsCount", 0); - initPort(); //вот это важный метод который собственно порт открывает. - - //Каждые 5 сек запрашиваем инпуты у платы. Надо потому что при заходе в игру с пинов еще не пришла инфа - if (enablePrizeChecking) InvokeRepeating("requestInputs", 0, 5); - } - - /// - /// Добавляет один кредит в систему и сохраняет обновленное количество. - /// Вызывается автоматически событием при получении сигнала "COIN" из COM-порта. - /// - /// - /// Увеличивает счетчик кредитов и вызывает событие onCoinAdded для уведомления подписчиков. - /// Автоматически сохраняет состояние в PlayerPrefs. - /// - public static void AddCredit() - { - CreditsCount++; - PlayerPrefs.SetInt("CoinsCount", CreditsCount); - onCoinAdded?.Invoke(CreditsCount); - } - - /// - /// Отправляет произвольную строковую команду на периферийную плату через COM-порт. - /// - /// Команда для отправки - /// - /// Используется для отправки пользовательских команд на плату. - /// Команда должна быть в формате, ожидаемом прошивкой платы. - /// В случае ошибки отправки выводит предупреждение в DebugWindow. - /// - public static void Send(string message) - { - try - { - int w = ComNativeWrapper.Serial_WriteStringUTF8(h, message, 1); //w-количество записаных символов в порт. можно обработать - //Debug.Log("Wrote: " + w); - - } - catch { DebugWindow.Message("Ошибка отправки строкового сигнала."); } - } - - /// - /// Отправляет команду управления подсветкой на периферийную плату. - /// - /// Режим подсветки из перечисления LightMode - /// - /// Формирует команду вида "80XXX" где XXX - код режима подсветки. - /// Для добавления новых режимов необходимо обновить вложенный метод getLightString + добавить режим в перечисление. - /// - public static void Send(LightMode lightMode) - { - try - { - string signal = LIGHTSIGNAL_PREFIX + getLightString(lightMode); - Send(signal); - - //ВОТЭТОТ МЕТОД ПОД СВОИ ПОДСВЕТКИ НАДО ПОДГОНЯТЬ - string getLightString(LightMode lightMode) => - - lightMode switch - { - LightMode.Idle => "106", - LightMode.Orange => "107", - LightMode.Blue => "108", - LightMode.Win => "109", - LightMode.Lose => "110", - LightMode.Prize => "111", - _ => "106" - }; - - } - catch { DebugWindow.Message("Ошибка отправки светового сигнала."); } - } - - /// - /// Выполняет списание платы за запуск игры. - /// Проверяет наличие доступных кредитов или режим бесплатной игры. - /// При успешном списании увеличивает счетчики запусков. - /// - /// - /// true - если списание прошло успешно (бесплатный режим или есть кредиты), - /// false - если кредитов недостаточно и платный режим - /// - /// - /// В случае успеха: - /// - Увеличивает общие счетчики запусков (key_starts и key_startsNul) - /// - При платном режиме уменьшает количество кредитов на 1 - /// - Вызывает событие onCoinRemoved при списании кредита - /// - public static bool Pay() - { - //блок проверки оплаты - if (SettingsManager.instance.GetSettingValue("Бесплатная игра") == "Вкл") - { - //Счетчики пробега - PlayerPrefs.SetInt(PrizeSystem.key_starts, PlayerPrefs.GetInt(PrizeSystem.key_starts) + 1); - PlayerPrefs.SetInt(PrizeSystem.key_startsNul, PlayerPrefs.GetInt(PrizeSystem.key_startsNul) + 1); - - return true; - } - - if (CreditsCount > 0) - { - CreditsCount--; - 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); - - onCoinRemoved?.Invoke(CreditsCount); - return true; - } - - return false; - } - //===========================end: PUBLIC API===========================// - - - - - private void Update() => pollPort(); - private void OnDisable() => ClosePort(); - private void OnApplicationQuit() => ClosePort(); - - - #region Приватные методы - //Ну тут по дебаг логам все должно быть понятно - //Если интересно, то h - это хэндл. Что то на плюсовом, типа ID соединения или чтото. Если 0 то нету соед. если меньше то ошибка, больше 0 - норм. - private void initPort() - { - Debug.Log("Старт программы"); - ComNativeWrapper.Serial_CloseAll(); - var ports = ComNativeWrapper.ListPorts(); - Debug.Log("Ports: " + string.Join(", ", ports)); - if (ports.Length == 0) { Debug.Log("Нет портов, завершаю"); return; } - - string port = ports[^1]; - Debug.Log("Открываю первый с конца порт: " + port); - - - //вот эти настройки лучше не ковырять, но если очень хочется можно поменять readTimeoutMs и writeTimeoutMs - //Если read поставить слишком маленьким оно проебует кредиты когда они идут большой пачкой например при оплате через вендисту. - //Там в порт спамит "COIN" в больших количествах и процентов 10 из этих строк не успевают прочитаться при таймауте 1мс, соотв. монеты проебуются. - //Слишком большой таймаут будет тормозить игру потому что оно все выполняется синхронно и каждый кадр забирает столько мс сколько в переменной указано. - h = ComNativeWrapper.Serial_Open(port, 115200, 8, 0, 1, 5, 10); - - - Debug.Log($"handle: {h}"); - if (h <= 0) - { - Debug.Log("Open failed: " + ComNativeWrapper.GetLastError()); - return; - } - } - - private static void ClosePort() - { - if (h > 0) - { - ComNativeWrapper.Serial_Close(h); - h = 0; - } - } - - - //Тут чтение, не трогаем(опционально) - private static string ReadBufferLine() - { - - int read = ComNativeWrapper.Serial_ReadLineUTF8_bytes(h, buf, buf.Length); - if (read > 0) - { - var s = Encoding.UTF8.GetString(buf, 0, read); - //Debug.Log($"ReadLine len={read} data=[{s}]"); - return s; - } - else if (read < 0) - { - Debug.Log($"ReadLine err={read} :: {ComNativeWrapper.GetLastError()}"); - } - return ""; - } - //просим прислать состояние цифровых входов. Приходит что то вроде "INPUT111111101" - private void requestInputs() => Send(REQUEST_INPUT); - - private void pollPort() - { - //Тут все просто, читаем что нам приходит с порта и сравниваем. - string comInput = ReadBufferLine(); - if (comInput != "") - { - DebugWindow.Message("COM: " + comInput); - - if (comInput == "COIN") AddCredit(); - if (comInput.StartsWith("INPUT")) onInputRecieved?.Invoke(comInput.Substring(5)); //инвокаю сразу без префикса "INPUT" - } - } - #endregion -} -public enum LightMode -{ - Idle, - Orange, - Blue, - Win, - Lose, - Prize, -} \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/PrizeStandController.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/PrizeStandController.cs deleted file mode 100644 index a1309ad..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/PrizeStandController.cs +++ /dev/null @@ -1,314 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using UnityEngine; - -//Зависит от ComNativeWrapper и одноименного плагина -//рекомендуется соединение с таймаутом не меньше 10мс. Иначе вероятно busy loop и много алокаций. -public static class PrizeStandController -{ - /// - /// По завершении инициализации. - /// bool - успех/неуспех. - /// string - сообщение в случае неуспеха - /// - public static event Action InitializationComplete; - /// - /// По завершении операции открытия. - /// bool - успех/неуспех. - /// string - сообщение в случае неуспеха - /// - public static event Action OpeningFinished; - - private const string REQUEST_STAND_STATUS = "25"; - private const string OPEN_BOX_PREFIX = "2501"; - private const float STATUS_REQUEST_TIMEOUT = 3; - private const float WAIT_OPEN_STATUS_TIMEOUT = 5; - - private static readonly IReadOnlyList READY_TO_OPEN_STATUSES = new[] { BoxStatus.OK, BoxStatus.OKplusCard }; - - private static int handle = -1; - private static int boxesCount; - private static readonly SemaphoreSlim _lock = new(1, 1); - private static bool initialized = false; - - private static ILogger _logger; - - #region PUBLIC API - /// - /// Инициализировать модуль витрины. - /// - /// Id хэндла полученное после ComNativeWrapper.Serial_Open - /// Количество физических коробок витрины - /// (опционально) Логгер - public static void Initialize(int handleId, int countOfBoxes, ILogger logger) - { - bool hasError = false; - StringBuilder sb = new StringBuilder(); - - //Проверка хэндла. h<=0 - ошибка открытия порта - if (handleId <= 0) - { - hasError = true; - sb.AppendLine($"[Модуль витрины] Переданный handle={handleId}. Ожидалось значение>0."); - } - else handle = handleId; - - //Проверка количества коробок - if (countOfBoxes <= 0) - { - hasError = true; - sb.AppendLine($"[Модуль витрины] Попытка задать количество коробок={countOfBoxes}. Ожидалось значение>0."); - } - else boxesCount = countOfBoxes; - - //Установка логгера - _logger = logger; - if (_logger == null) - sb.AppendLine($"[Модуль витрины] Получен логгер NULL. Если нужно логгирование, передайте дествующий логгер."); - - //Завершение - if (hasError) - { - initialized = false; - handle = -1; - boxesCount = 0; - - InitializationComplete?.Invoke(false, sb.ToString()); - } - else - { - initialized = true; - InitializationComplete?.Invoke(true, sb.ToString()); - } - } - - - /// - /// Открыть коробку по номеру - /// - /// Номер коробки (считаем с 1) - public static async Task OpenBoxAsync(int boxNumber) - { - if(!await _lock.WaitAsync(0)) - { - OpeningFinished?.Invoke(false, "Выдача уже в процессе"); - return; - } - - try - { - //Валидация - var validationResult = await CanExecuteOpenAsync(boxNumber); - if (!validationResult.OK) - { - OpeningFinished?.Invoke(false, validationResult.Message); - return; - } - - SendOpenCommand(boxNumber); - - //Обработка результатов - BoxStatus openStatus = await ReadBoxStatus(boxNumber, 1, WAIT_OPEN_STATUS_TIMEOUT); - if (openStatus == BoxStatus.OPENED) - { - OpeningFinished?.Invoke(true, $"Ячейка {boxNumber} успешно открыта"); - } - else - { - _logger?.Log($"[Модуль витрины] Ошибка при открытии ячейки {boxNumber}"); - OpeningFinished?.Invoke(false, $"Ошибка при открытии ячейки номер {boxNumber}"); - } - } - catch (Exception ex) - { - _logger?.Log($"[Модуль витрины] Ошибка при открытии ячейки {boxNumber}: {ex.Message}"); - OpeningFinished?.Invoke(false, ex.Message); - } - finally - { - _lock.Release(); - } - } - #endregion - - #region HELPERS - private static void SendOpenCommand(int boxNumber) - => ComNativeWrapper.Serial_WriteStringUTF8(handleId: handle, - utf8: $"{OPEN_BOX_PREFIX}{boxNumber:D2}", //D2 приводит в формат XX (2 знака, ноль впереди) - appendNewline: 1); - private static void SendRequestStatusCommand() - => ComNativeWrapper.Serial_WriteStringUTF8(handle, REQUEST_STAND_STATUS, 1); - - /// - /// Проверка может ли модуль произвести выдачу - /// - private static async Task<(bool OK, string Message)> CanExecuteOpenAsync(int boxNumber) - { - bool isOk = true; - StringBuilder sb = new StringBuilder(); - sb.AppendLine($"[Модуль витрины. Проверка перед открытием]"); - - //Проверка инициализации - if (!initialized) - { - isOk = false; - sb.AppendLine("- Модуль не инициализирован."); - } - - bool boxNumberIsValid = boxNumber > 0 && boxNumber <= boxesCount; - if (!boxNumberIsValid) - { - isOk = false; - sb.AppendLine($"- Номер коробки={boxNumber} невалидный. Требуется от 1 до {boxesCount}."); - } - - //Не лезем в порт с запросом статуса коробки, если то, что выше дало НеОК - if (isOk) - { - SendRequestStatusCommand(); - BoxStatus boxStatus = await ReadBoxStatus(boxNumber, boxesCount, STATUS_REQUEST_TIMEOUT); - - if (!READY_TO_OPEN_STATUSES.Contains(boxStatus)) - { - isOk = false; - sb.AppendLine($"- Статус коробки {boxNumber}: {boxStatus} не позволяет провести открытие."); - } - } - else - { - sb.AppendLine($"- Невозможно проверить статус коробки {boxNumber} из-за ошибок выше."); - } - - return (isOk, sb.ToString()); - } - - - /// - /// Читать статус заданной ячейки витрины. Выход когда прочитали заданное количество вхождений, или по таймауту. - /// - /// Номер ячейки которую мы ждем - /// Сколько ячеек мы ждем - /// Таймаут операции(сек.) - /// - private static async Task ReadBoxStatus(int expectedBoxNumber, int expectedEntriesCount, float timeout) - { - byte[] buffer = new byte[1024]; - - //Изначально предполагаем что статус нужной коробки не пришел - BoxStatus status = BoxStatus.NotFound; - - int boxesRecieved = 0; - var sw = Stopwatch.StartNew(); - - while (sw.Elapsed.TotalSeconds < timeout && boxesRecieved < expectedEntriesCount) - { - //ждать пока всё не считаем - int entryLength = await Task.Run(() => ComNativeWrapper.Serial_ReadLineUTF8_bytes(handle, buffer, buffer.Length)); - - if (entryLength == 0) //ничего не пришло - { - continue; - } - else if (entryLength < 0) //ошибка - { - _logger?.Log($"Ошибка при считывании статуса ячеек={entryLength} :: {ComNativeWrapper.GetLastError()}"); - continue; - } - - - string entry = Encoding.UTF8.GetString(buffer, 0, entryLength).Trim(); - var ParseResult = ParseBoxStatus(entry); - - if(ParseResult.BoxNumber == -1) - { - _logger?.Log($"[Модуль витрины. Ошибка получения статуса ячейки]\n{ParseResult.Message}"); - } - else - { - boxesRecieved++; - if (ParseResult.BoxNumber == expectedBoxNumber) - status = ParseResult.Status; - } - } - - if (status == BoxStatus.NotFound) - _logger?.Log($"[Модуль витрины. Не дождался ответа по статусу ячейки]\n" + - $"Ожидаемый номер: {expectedBoxNumber}\n" + - $"Получено статусов ячеек: {boxesRecieved}/{expectedEntriesCount}"); - return status; - } - - private static (int BoxNumber, BoxStatus Status, string Message) ParseBoxStatus(string entryString) - { - int number = -1; - BoxStatus status = BoxStatus.ParsingError; - string message = ""; - - - - if (entryString.StartsWith("BOX")) - { - var noPrefixEntry = entryString.Substring(3); //Убираем "BOX" - string[] parts = noPrefixEntry.Split('_'); //ожидаем массив [<номер_коробки>, <статус_коробки>] - if (parts.Length == 2) - { - //Парсим номер коробки - bool boxNumberParsed = (int.TryParse(parts[0], out int parsedNumber)); - - if (boxNumberParsed) - { - number = parsedNumber; - status = MapStatusFromString(parts[1]); - } - else message = $"Не удалось спарсить номер коробки: {entryString}"; - } - else - { - message = $"Ошибка парсинга. Часть строки не пришла: {entryString}"; - } - } - else message = $"Неожиданный префикс при парсинге ячеек: {entryString}"; - - - return (number, status, message); - - } - private static BoxStatus MapStatusFromString(string statusString) => statusString switch - { - "OK" => BoxStatus.OK, - "OK+CARD" => BoxStatus.OKplusCard, - "EMPTY" => BoxStatus.Empty, - "OPEN" => BoxStatus.Open, - - "OPENED" => BoxStatus.OPENED, - "OPEN_ERROR" => BoxStatus.OPEN_ERROR, - - "ERROR" => BoxStatus.Error, - - _ => BoxStatus.ParsingError - }; - #endregion -} - -enum BoxStatus -{ - //Статусы ДО открытия - OK, //Готов к выдаче - OKplusCard, //Готов к выдаче + готов выдать по карте - Empty, //Пусто, уже выдали - Open, //Дверка УЖЕ открыта. Приз предположительно пустой - - //Статусы ПОСЛЕ открытия - OPENED, //Всё хорошо, открылся - OPEN_ERROR, //Ошибка открытия - - //Служебные статусы - ParsingError, //При парсинге что то пошло не так, или пришла непредусмотренная фигня - NotFound, //Коробка с требуемым номером не найдена - Error //Общая ошибка (например дали команду на открытие пустого ящика или сломан замок) -} \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/PrizeSystem.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/PrizeSystem.cs deleted file mode 100644 index d4d3ab4..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/ComSystem/PrizeSystem.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Collections; -using UnityEngine; - -/// -/// Система управления выдачей призов и ведения статистики игры. -/// Отвечает за процесс выдачи призов, подсчет запусков и наград. -/// -public class PrizeSystem : MonoBehaviour -{ - [SerializeField] AudioClip prizeErrorSound; - - public static string key_starts = "STARTS"; - public static string key_startsNul = "STARTSNUL"; - public static string key_prizesgiven = "PRIZESGIVEN"; - public static string key_prizesgivenNul = "PRIZESGIVENNUL"; - - private static PrizeSystem instance; - private static Coroutine prizeCoroutine; - private static bool prizing = false; - - - //===========================start: PUBLIC API===========================// - /// - /// Инициализирует систему призов и счетчики статистики. - /// Должен быть вызван один раз при запуске приложения. - /// - /// - /// Выполняет: - /// - Установку статического экземпляра (singleton) - /// - Инициализацию счетчиков в PlayerPrefs если они отсутствуют - /// - Подготовку системы к работе - /// - public void Initialize() - { - instance = this; - InitCounters(); - } - - /// - /// Запускает процесс выдачи физического приза игроку. - /// Проверяет настройки и текущее состояние перед началом выдачи. - /// - /// - /// Условия для выдачи приза: - /// - В настройках включена выдача призов при игре с ботом - /// - В данный момент не выполняется другая выдача приза - /// - /// Процесс выдачи: - /// - Включает мотор хопера - /// - Ожидает подтверждения выдачи от датчиков (10 сек таймаут) - /// - Выключает мотор по завершению - /// - Обновляет счетчики выданных призов - /// - Воспроизводит звук ошибки при неудаче - /// - public static void GivePrize() - { - bool settingEnabled = SettingsManager.instance.GetSettingValue("Выдача призов при игре с ботом") == "Выдавать"; - - if (!settingEnabled) { DebugWindow.Message("Выдача приза отключена в настройках"); return; } - if (prizing) { DebugWindow.Message("Уже идет выдача приза. Не спамь кнопку."); return; } - - DebugWindow.Message("Выдаю приз"); - if (prizeCoroutine != null) instance.StopCoroutine(prizeCoroutine); - prizeCoroutine = instance.StartCoroutine(instance.Prize()); - } - //===========================end: PUBLIC API===========================// - - #region Приватные методы - private IEnumerator Prize() - { - prizing = true; - DebugWindow.Message("Начинаю выдачу"); - - float timeout = 10; //сек - ComWrapper.Send("301");//включаем мотор - float startTime = Time.time; - bool success = false; - - PlayerPrefs.SetInt("PrizeGivenBuffer", 0);//На всякий случай подготовка буфера - //проверить где он пишется - - while (Time.time - startTime < timeout) - { - if (PlayerPrefs.GetInt("PrizeGivenBuffer", 0) == 1) - { - success = true; - IncreasePrizeCounters(); - break; - } - yield return null; - } - - //Выключаем мотор - ComWrapper.Send("300"); - DebugWindow.Message("Закончил. Успех: " + success); - prizing = false; - - if (!success) SoundManager.instance.playClip(prizeErrorSound); - } - - void IncreasePrizeCounters() - { - PlayerPrefs.SetInt(key_prizesgiven, PlayerPrefs.GetInt(key_prizesgiven) + 1); - PlayerPrefs.SetInt(key_prizesgivenNul, PlayerPrefs.GetInt(key_prizesgivenNul) + 1); - } - void InitCounters() - { - if (!PlayerPrefs.HasKey(key_starts)) PlayerPrefs.SetInt(key_starts, 0); - if (!PlayerPrefs.HasKey(key_startsNul)) PlayerPrefs.SetInt(key_startsNul, 0); - if (!PlayerPrefs.HasKey(key_prizesgiven)) PlayerPrefs.SetInt(key_prizesgiven, 0); - if (!PlayerPrefs.HasKey(key_prizesgivenNul)) PlayerPrefs.SetInt(key_prizesgivenNul, 0); - } - #endregion -} diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/In.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/In.cs deleted file mode 100644 index db3c29a..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/In.cs +++ /dev/null @@ -1,89 +0,0 @@ -using UnityEngine; - -/// -/// Статический фасад для унифицированного доступа к системе ввода. -/// Предоставляет глобальный интерфейс для работы с управлением независимо от выбранного источника. -/// -/// -/// Этот класс является точкой входа для всей игровой логики, работающей с вводом. -/// Автоматически инициализирует выбранный источник управления (клавиатура или COM-порт) -/// и предоставляет статические методы для удобного доступа из любого места кода. -/// -/// Использование: -/// 1. Настройте тип ввода в инспекторе -/// 2. Вызовите Initialize() при старте игры -/// 3. Используйте статические методы для проверки ввода -/// -public class In : MonoBehaviour -{ - [Header("Выбор источника управления")] - [SerializeField] private InputSourceType inputType; - - static InputSource source; - - /// - /// Инициализирует систему ввода на основе выбранного типа. - /// Должен быть вызван один раз при запуске приложения. - /// - /// - /// Создает соответствующий экземпляр InputSource: - /// - KeyboardInput для тестирования на клавиатуре - /// - COMinput для работы с периферийной платой - /// - public void Initialize() - { - source = inputType switch - { - InputSourceType.Keyboard => new KeyboardInput(), - InputSourceType.COM => new COMinput(), - _ => throw new System.NotImplementedException() - }; - - var success = source.Initialize(); - if (!success) Debug.LogWarning("Не удалось проинициалзировать источник управления."); - } - - // ================================================================================ - // СТАТИЧЕСКИЕ МЕТОДЫ ДЛЯ РАБОТЫ С ФИЗИЧЕСКИМИ ПИНАМИ - // ================================================================================ - - /// Проверяет состояние конкретной кнопки по её физическому пину - public static bool GetButton(ButtonPinMapping button) => source.GetButton(button); - - /// Проверяет нажатие кнопки по пину в текущем кадре - public static bool GetButtonDown(ButtonPinMapping button) => source.GetButtonDown(button); - - /// Проверяет отпускание кнопки по пину в текущем кадре - public static bool GetButtonUp(ButtonPinMapping button) => source.GetButtonUp(button); - - /// Проверяет состояние кнопки по числовому индексу пина - public static bool GetButton(int pinindex) => source.GetButton(pinindex); - - /// Проверяет нажатие кнопки по индексу пина в текущем кадре - public static bool GetButtonDown(int pinindex) => source.GetButtonDown(pinindex); - - /// Проверяет отпускание кнопки по индексу пина в текущем кадре - public static bool GetButtonUp(int pinindex) => source.GetButtonUp(pinindex); - - // ================================================================================ - // СТАТИЧЕСКИЕ МЕТОДЫ ДЛЯ РАБОТЫ С АБСТРАКТНЫМИ ДЕЙСТВИЯМИ ИГРОКОВ - // ================================================================================ - - /// Проверяет состояние действия для любого из игроков - public static bool GetButtonAnyPlayer(PlayerAction button) => source.GetButtonAnyPlayer(button); - - /// Проверяет начало действия любым игроком в текущем кадре - public static bool GetButtonDownAnyPlayer(PlayerAction button) => source.GetButtonDownAnyPlayer(button); - - /// Проверяет завершение действия любым игроком в текущем кадре - public static bool GetButtonUpAnyPlayer(PlayerAction button) => source.GetButtonUpAnyPlayer(button); - - /// Проверяет состояние действия для текущего активного игрока - public static bool GetButtonCurrentPlayer(PlayerAction button) => source.GetButtonCurrentPlayer(button); - - /// Проверяет начало действия текущим игроком в текущем кадре - public static bool GetButtonDownCurrentPlayer(PlayerAction button) => source.GetButtonDownCurrentPlayer(button); - - /// Проверяет завершение действия текущим игроком в текущем кадре - public static bool GetButtonUpCurrentPlayer(PlayerAction button) => source.GetButtonUpCurrentPlayer(button); -} \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/InputSource.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/InputSource.cs deleted file mode 100644 index d8d9323..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/InputSource.cs +++ /dev/null @@ -1,117 +0,0 @@ -/// -/// Абстрактный базовый класс для всех источников ввода в системе. -/// Определяет унифицированный интерфейс для работы с аппаратными кнопками и виртуальными действиями игроков. -/// -/// -/// Наследники этого класса реализуют конкретные способы ввода: -/// - COMinput: работа с периферийной платой через COM-порт -/// - KeyboardInput: эмуляция ввода с клавиатуры для тестирования -/// -/// Класс предоставляет три уровня абстракции: -/// 1. Низкоуровневый доступ к физическим пинам -/// 2. Доступ к абстрактным игровым действиям -/// 3. Мультиплеерные методы для работы с несколькими игроками -/// -public abstract class InputSource -{ - /// - /// Инициализирует источник ввода. Должен быть вызван перед использованием других методов. - /// - /// true если инициализация прошла успешно, false в случае ошибки - public abstract bool Initialize(); - - //---------------------------------------------------------------------------------- - - /// - /// Получает текущее состояние конкретной кнопки по её физическому пину. - /// - /// Пин кнопки на периферийной плате - /// true если кнопка нажата в текущий момент - public abstract bool GetButton(ButtonPinMapping button); - - /// - /// Проверяет, была ли кнопка нажата в начале текущего кадра. - /// - /// Пин кнопки на периферийной плате - /// true только в первом кадре после нажатия кнопки - public abstract bool GetButtonDown(ButtonPinMapping button); - - /// - /// Проверяет, была ли кнопка отпущена в начале текущего кадра. - /// - /// Пин кнопки на периферийной плате - /// true только в первом кадре после отпускания кнопки - public abstract bool GetButtonUp(ButtonPinMapping button); - - //---------------------------------------------------------------------------------- - - /// - /// Получает состояние кнопки по числовому индексу пина. - /// Перегрузка для работы с системами, где количество пинов превышает размер перечисления. - /// - /// Числовой индекс пина (0-based) - /// true если кнопка нажата в текущий момент - public abstract bool GetButton(int pinIndex); - - /// - /// Проверяет нажатие кнопки по числовому индексу пина в текущем кадре. - /// - /// Числовой индекс пина (0-based) - /// true только в первом кадре после нажатия - public abstract bool GetButtonDown(int pinIndex); - - /// - /// Проверяет отпускание кнопки по числовому индексу пина в текущем кадре. - /// - /// Числовой индекс пина (0-based) - /// true только в первом кадре после отпускания - public abstract bool GetButtonUp(int pinIndex); - - //---------------------------------------------------------------------------------- - - /// - /// Получает состояние игрового действия для любого из игроков. - /// Используется для мультиплеерных сценариев где важно действие любого игрока. - /// - /// Абстрактное игровое действие - /// true если действие активно у первого ИЛИ второго игрока - public abstract bool GetButtonAnyPlayer(PlayerAction button); - - /// - /// Проверяет начало игрового действия любым игроком в текущем кадре. - /// - /// Абстрактное игровое действие - /// true если действие начато любым игроком в этом кадре - public abstract bool GetButtonDownAnyPlayer(PlayerAction button); - - /// - /// Проверяет завершение игрового действия любым игроком в текущем кадре. - /// - /// Абстрактное игровое действие - /// true если действие завершено любым игроком в этом кадре - public abstract bool GetButtonUpAnyPlayer(PlayerAction button); - - //---------------------------------------------------------------------------------- - - /// - /// Получает состояние игрового действия для текущего активного игрока. - /// Используется для одиночной игры или поочередного управления. - /// - /// Абстрактное игровое действие - /// true если действие активно у текущего игрока - public abstract bool GetButtonCurrentPlayer(PlayerAction button); - - /// - /// Проверяет начало игрового действия текущим игроком в текущем кадре. - /// - /// Абстрактное игровое действие - /// true если действие начато текущим игроком в этом кадре - public abstract bool GetButtonDownCurrentPlayer(PlayerAction button); - - /// - /// Проверяет завершение игрового действия текущим игроком в текущем кадре. - /// - /// Абстрактное игровое действие - /// true если действие завершено текущим игроком в этом кадре - public abstract bool GetButtonUpCurrentPlayer(PlayerAction button); -} \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/InputSourceType.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/InputSourceType.cs deleted file mode 100644 index ad891ed..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/InputSourceType.cs +++ /dev/null @@ -1,5 +0,0 @@ -public enum InputSourceType -{ - COM, - Keyboard -} diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/KeyboardInput.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/KeyboardInput.cs deleted file mode 100644 index 94db5f2..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/KeyboardInput.cs +++ /dev/null @@ -1,175 +0,0 @@ -using UnityEngine; - -/// -/// Реализация системы ввода с клавиатуры для тестирования и разработки. -/// Эмулирует работу периферийной платы через стандартные клавиши клавиатуры. -/// -/// -/// Соответствие клавиш и пинов: -/// - Игрок 1: WASD + Space -/// - Игрок 2: Стрелки + RightControl -/// - Служебные: 1, 2, 3, F5 -/// - Датчики хопера: O, P -/// -public class KeyboardInput : InputSource -{ - private int currentPlayer => gm.currentPlayer == CellState.Player1 ? 1 : 2;//ПЕРЕОПРЕДЕЛИТЕ ОПРЕДЕЛЕНИЕ ТЕКУЩЕГО ИГРОКА ПОД СВОЮ СИСТЕМУ. - private GameManager gm;//я получаю кто сейчас ходит через этого менеджера. Если у вас другое, допишите. - - - - /// Проверяет состояние кнопки по её физическому пину через клавиатуру - public override bool GetButton(ButtonPinMapping button) => Input.GetKey(getKeyCode(button)); - - /// Проверяет нажатие кнопки по пину в текущем кадре через клавиатуру - public override bool GetButtonDown(ButtonPinMapping button) => Input.GetKeyDown(getKeyCode(button)); - - /// Проверяет отпускание кнопки по пину в текущем кадре через клавиатуру - public override bool GetButtonUp(ButtonPinMapping button) => Input.GetKeyUp(getKeyCode(button)); - - //---------------------------------------------------------------------------------- - - /// Проверяет состояние кнопки по числовому индексу пина через клавиатуру - public override bool GetButton(int pinIndex) => Input.GetKey(getKeyCode(pinIndex)); - - /// Проверяет нажатие кнопки по индексу пина в текущем кадре через клавиатуру - public override bool GetButtonDown(int pinIndex) => Input.GetKeyDown(getKeyCode(pinIndex)); - - /// Проверяет отпускание кнопки по индексу пина в текущем кадре через клавиатуру - public override bool GetButtonUp(int pinIndex) => Input.GetKeyUp(getKeyCode(pinIndex)); - - //---------------------------------------------------------------------------------- - - /// Проверяет состояние действия для текущего игрока (всегда игрок 1 для клавиатуры) - public override bool GetButtonCurrentPlayer(PlayerAction button) => GetButton(GetButtonForCurrentPlayer(button)); - - /// Проверяет начало действия текущим игроком в текущем кадре - public override bool GetButtonDownCurrentPlayer(PlayerAction button) => GetButtonDown(GetButtonForCurrentPlayer(button)); - - /// Проверяет завершение действия текущим игроком в текущем кадре - public override bool GetButtonUpCurrentPlayer(PlayerAction button) => GetButtonUp(GetButtonForCurrentPlayer(button)); - - //---------------------------------------------------------------------------------- - - /// Проверяет состояние действия для любого из игроков (игрок 1 ИЛИ игрок 2) - public override bool GetButtonAnyPlayer(PlayerAction button) => CheckBothPlayers(button, GetButton); - - /// Проверяет начало действия любым игроком в текущем кадре - public override bool GetButtonDownAnyPlayer(PlayerAction button) => CheckBothPlayers(button, GetButtonDown); - - /// Проверяет завершение действия любым игроком в текущем кадре - public override bool GetButtonUpAnyPlayer(PlayerAction button) => CheckBothPlayers(button, GetButtonUp); - - //---------------------------------------------------------------------------------- - - /// - /// Инициализирует клавиатурный ввод. Всегда возвращает true так как клавиатура всегда доступна. - /// - /// Всегда true - public override bool Initialize() => gm = GameManager.instance; - - // ================================================================================ - // ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ - // ================================================================================ - - /// - /// Определяет кнопку текущего игрока для указанного действия. - /// Для клавиатуры всегда возвращает кнопку первого игрока. - /// - private ButtonPinMapping GetButtonForCurrentPlayer(PlayerAction button) - { - var buttons = _buttonByAction(button); - return currentPlayer == 1 ? buttons.player1button : buttons.player2button; - } - - /// - /// Проверяет действие для обоих игроков используя указанную функцию проверки. - /// - private bool CheckBothPlayers(PlayerAction action, System.Func buttonFunc) - { - var buttons = _buttonByAction(action); - return buttonFunc(buttons.player1button) || buttonFunc(buttons.player2button); - } - - /// - /// Возвращает соответствие между игровыми действиями и физическими кнопками игроков. - /// - private (ButtonPinMapping player1button, ButtonPinMapping player2button) _buttonByAction(PlayerAction playerAction) => - playerAction switch - { - PlayerAction.up => (ButtonPinMapping.up1, ButtonPinMapping.up2), - PlayerAction.down => (ButtonPinMapping.down1, ButtonPinMapping.down2), - PlayerAction.left => (ButtonPinMapping.left1, ButtonPinMapping.left2), - PlayerAction.right => (ButtonPinMapping.right1, ButtonPinMapping.right2), - PlayerAction.action => (ButtonPinMapping.action1, ButtonPinMapping.action2), - PlayerAction.extra => (ButtonPinMapping.extra, ButtonPinMapping.extra), - _ => throw new System.ArgumentException($"Unknown player action: {playerAction}") - }; - - /// - /// Преобразует физический пин в соответствующую клавишу клавиатуры. - /// - private KeyCode getKeyCode(ButtonPinMapping button) - { - return button switch - { - ButtonPinMapping.up1 => KeyCode.W, - ButtonPinMapping.right1 => KeyCode.D, - ButtonPinMapping.down1 => KeyCode.S, - ButtonPinMapping.left1 => KeyCode.A, - ButtonPinMapping.action1 => KeyCode.Space, - - ButtonPinMapping.up2 => KeyCode.UpArrow, - ButtonPinMapping.right2 => KeyCode.RightArrow, - ButtonPinMapping.down2 => KeyCode.DownArrow, - ButtonPinMapping.left2 => KeyCode.LeftArrow, - ButtonPinMapping.action2 => KeyCode.RightControl, - - ButtonPinMapping.startOnePlayer => KeyCode.Alpha1, - ButtonPinMapping.startTwoPlayers => KeyCode.Alpha2, - - ButtonPinMapping.secret => KeyCode.F5, - - ButtonPinMapping.extra => KeyCode.Alpha3, - - ButtonPinMapping.hasPrize => KeyCode.O, - ButtonPinMapping.prizeGiven => KeyCode.P, - - _ => KeyCode.None, - }; - } - - /// - /// Преобразует числовой индекс пина в соответствующую клавишу клавиатуры. - /// Используется для методов с прямым доступом по индексу. - /// - private KeyCode getKeyCode(int pinIndex) - { - return pinIndex switch - { - 0 => KeyCode.W, // up1 - 1 => KeyCode.D, // right1 - 2 => KeyCode.S, // down1 - 3 => KeyCode.A, // left1 - 4 => KeyCode.Space, // action1 - - 5 => KeyCode.UpArrow, // up2 - 6 => KeyCode.RightArrow, // right2 - 7 => KeyCode.DownArrow, // down2 - 8 => KeyCode.LeftArrow, // left2 - 9 => KeyCode.RightControl, // action2 - - 10 => KeyCode.Alpha1, // startOnePlayer - 11 => KeyCode.Alpha2, // startTwoPlayers - - 12 => KeyCode.F5, // secret - - 13 => KeyCode.Alpha3, // extra - - 14 => KeyCode.O, // hasPrize - 15 => KeyCode.P, // prizeGiven - - _ => KeyCode.None, // невалидный индекс - }; - } -} \ No newline at end of file diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/PlayerAction.cs b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/PlayerAction.cs deleted file mode 100644 index db8f348..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/Scripts/Inputs/PlayerAction.cs +++ /dev/null @@ -1,19 +0,0 @@ -/// -/// Абстрактные игровые действия для управления игроком. -/// Обеспечивает независимость от физического расположения кнопок. -/// -public enum PlayerAction -{ - /// Вверх - up, - /// Вниз - down, - /// Влево - left, - /// Вправо - right, - /// Основное действие - action, - /// Дополнительное действие(ВНИМАНИЕ РАБОТАЕТ У ОБОИХ ИГРОКОВ ОДНОВРЕМЕННО) - extra -} diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/StreamingAssets/RRLauncher.exe b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/StreamingAssets/RRLauncher.exe deleted file mode 100644 index 2e0a6f1..0000000 Binary files a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/StreamingAssets/RRLauncher.exe and /dev/null differ diff --git a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/StreamingAssets/RRLauncher.exe.lic.json b/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/StreamingAssets/RRLauncher.exe.lic.json deleted file mode 100644 index 160b90a..0000000 --- a/GreatGamedevVault/Библиотека/Периферия/Встраиваемые/Assets/StreamingAssets/RRLauncher.exe.lic.json +++ /dev/null @@ -1 +0,0 @@ -{"product":"RRLicensedApp","hwid_sha256":"9f67ba1daae5c0d237588a2f32dbba2a38ca763ce44898c2722e3edaa4a3ae6d","fingerprint":"d675d82f7d58bf105dd381d028ff66f776bdd7881d535e483bd1e80aaf6c3c97","expiry":0,"nonce":"I1onNRUkvn8TybL3h5Q7dAt1KIj/wJ7WSPy3LLgzAvU","issued":"2025-11-05T09:14:02.2416908Z","features":["full"],"sig":"XHEz/NOCSeIErht17gtSoYxPNyF2OeawtLHO3lqkARxf1r4rYOiIALA8tybqE/BE7w4/bB\u002B2AIHDwMyyAXVh6Q=="} \ No newline at end of file