using System; using System.Collections.Generic; using LiteNetLib; using Microsoft.Xna.Framework.Input; using Syntriax.Engine.Input; using Syntriax.Engine.Network; namespace Pong.Behaviours; public class NetworkedKeyboardInputs : NetworkBehaviour, IButtonInputs { private readonly Dictionary, Keys>?> OnPressed = new(256); private readonly Dictionary, Keys>?> OnReleased = new(256); private int cachePressedCurrentlyCount = 0; private readonly Keys[] cachePressedCurrently = new Keys[256]; private int cachePressedPreviouslyCount = 0; private readonly Keys[] cachePressedPreviously = new Keys[256]; public void RegisterOnPress(Keys key, Action, Keys> callback) { if (OnPressed.TryGetValue(key, out var action)) { action += callback; OnPressed.Remove(key); OnPressed.Add(key, action); return; } OnPressed.Add(key, callback); } public void UnregisterOnPress(Keys key, Action, Keys> callback) { if (OnPressed.TryGetValue(key, out var action)) action -= callback; } public void RegisterOnRelease(Keys key, Action, Keys> callback) { if (OnReleased.TryGetValue(key, out var action)) { action += callback; OnReleased.Remove(key); OnReleased.Add(key, action); return; } OnReleased.Add(key, callback); } public void UnregisterOnRelease(Keys key, Action, Keys> callback) { if (OnReleased.TryGetValue(key, out var action)) action -= callback; } protected override void OnUpdate() { if (!IsServer && !LocalAssigned) return; KeyboardState keyboardState = Keyboard.GetState(); keyboardState.GetPressedKeys(cachePressedCurrently); cachePressedCurrentlyCount = keyboardState.GetPressedKeyCount(); for (int i = 0; i < cachePressedCurrentlyCount; i++) { Keys currentlyPressedKey = cachePressedCurrently[i]; if (!OnPressed.TryGetValue(currentlyPressedKey, out var action)) continue; if (WasPressed(currentlyPressedKey)) continue; action?.Invoke(this, currentlyPressedKey); } for (int i = 0; i < cachePressedPreviouslyCount; i++) { Keys previouslyPressedKey = cachePressedPreviously[i]; if (!OnReleased.TryGetValue(previouslyPressedKey, out var action)) continue; if (IsPressed(previouslyPressedKey)) continue; action?.Invoke(this, previouslyPressedKey); } Array.Copy(cachePressedCurrently, cachePressedPreviously, cachePressedCurrentlyCount); cachePressedPreviouslyCount = cachePressedCurrentlyCount; } public bool IsPressed(Keys key) { for (int i = 0; i < cachePressedCurrentlyCount; i++) if (cachePressedCurrently[i] == key) return true; return false; } public bool WasPressed(Keys key) { for (int i = 0; i < cachePressedPreviouslyCount; i++) if (cachePressedPreviously[i] == key) return true; return false; } protected override void OnInitialize() { base.OnInitialize(); foreach (Keys key in Enum.GetValues(typeof(Keys))) { RegisterOnPress(key, (keys, keyVal) => { if (!LocalAssigned && !IsServer) return; var netDataWriter = NetworkCommunicator.GetMessageWriter(this); netDataWriter.Put(true); netDataWriter.Put((int)key); NetworkCommunicator.Manager.SendToAll(netDataWriter, DeliveryMethod.ReliableOrdered); }); RegisterOnRelease(key, (keys, keyVal) => { if (!LocalAssigned && !IsServer) return; var netDataWriter = NetworkCommunicator.GetMessageWriter(this); netDataWriter.Put(false); netDataWriter.Put((int)key); NetworkCommunicator.Manager.SendToAll(netDataWriter, DeliveryMethod.ReliableOrdered); }); } } protected override void OnMessageReceived(NetPacketReader reader, NetPeer peer) { bool isPressed = reader.GetBool(); Keys key = (Keys)reader.GetInt(); if (isPressed) if (OnPressed.TryGetValue(key, out var action)) action?.Invoke(this, key); if (!isPressed) if (OnReleased.TryGetValue(key, out var action)) action?.Invoke(this, key); } }