public void Initialize(ParsecUnityController parsecUnityController) { gameObject.SetActive(true); // Normally you'd likely want a module between Parsec and your Game management code to inject // players without knowing where they came from, but we'll be lazy here. parsecUnityController.OnGuestConnected += ParsecUnityController_OnGuestConnected; parsecUnityController.OnGuestDisconnected += ParsecUnityController_OnGuestDisconnected; parsecUnityController.OnReceiveUserData += ParsecUnityController_OnReceiveUserData; }
// TODO: This should be applied before all updates, or whenever // input normally is applied (based on the InputSystem configuration). // TODO: There's a bug where although a press and release are recorded, // sometimes the InputSystem does not correctly reset state. private void Update() { var keyboardMessages = new Dictionary <uint, List <Parsec.ParsecMessage> >(); var gamepadMessages = new Dictionary <uint, List <Parsec.ParsecMessage> >(); while (parsec.HostPollInput(0u, out Parsec.ParsecGuest guest, out Parsec.ParsecMessage msg)) { switch (msg.type) { case Parsec.ParsecMessageType.MESSAGE_KEYBOARD: if (!keyboardMessages.ContainsKey(guest.id)) { keyboardMessages[guest.id] = new List <Parsec.ParsecMessage>(); } keyboardMessages[guest.id].Add(msg); break; case Parsec.ParsecMessageType.MESSAGE_MOUSE_BUTTON: ParsecUnityController.Log($"Guest {guest.id} {(msg.mouseButton.pressed ? "pressed" : "released")} mouse button {msg.mouseButton} at {Time.time}"); break; case Parsec.ParsecMessageType.MESSAGE_GAMEPAD_BUTTON: if (!gamepadMessages.ContainsKey(guest.id)) { gamepadMessages[guest.id] = new List <Parsec.ParsecMessage>(); } gamepadMessages[guest.id].Add(msg); break; case Parsec.ParsecMessageType.MESSAGE_GAMEPAD_AXIS: if (!gamepadMessages.ContainsKey(guest.id)) { gamepadMessages[guest.id] = new List <Parsec.ParsecMessage>(); } gamepadMessages[guest.id].Add(msg); break; default: break; } } // Unity's low level input event queuing system apparently does not like // multiple events to be queued for a single device each input round, // making it necessary to store all events per device ahead of time. foreach (var kvp in keyboardMessages) { if (!guests[kvp.Key].Get(out Keyboard keyboard)) { keyboard = guests[kvp.Key].Add <Keyboard>(); } using (StateEvent.From(keyboard, out InputEventPtr eventPtr)) { foreach (var msg in kvp.Value) { if (ParsecInputSystemMapping.Keys.TryGetValue(msg.keyboard.code, out Key key)) { if (guests[kvp.Key].Use(keyboard)) { ParsecUnityController.Log($"Guest {kvp.Key} switched current device to keyboard at {Time.time}"); } ParsecUnityController.Log($"Guest {kvp.Key} {(msg.keyboard.pressed ? "pressed" : "released")} key {key} at {Time.time}"); keyboard[key].WriteValueIntoEvent <float>(msg.keyboard.pressed ? 1 : 0, eventPtr); } } InputSystem.QueueEvent(eventPtr); } } foreach (var kvp in gamepadMessages) { if (!guests[kvp.Key].Get(out Gamepad gamepad)) { gamepad = guests[kvp.Key].Add <Gamepad>(); } using (StateEvent.From(gamepad, out InputEventPtr eventPtr)) { foreach (var msg in kvp.Value) { if (msg.type == Parsec.ParsecMessageType.MESSAGE_GAMEPAD_BUTTON) { var button = ParsecInputSystemMapping.ParsecToGamepadButton(gamepad, msg.gamepadButton.button); if (button != null) { if (guests[kvp.Key].Use(gamepad)) { ParsecUnityController.Log($"Guest {kvp.Key} switched current device to gamepad {msg.gamepadButton.id} at {Time.time}"); } ParsecUnityController.Log($"Guest {kvp.Key} {(msg.gamepadButton.pressed ? "pressed" : "released")} {button} on gamepad {msg.gamepadButton.id} at {Time.time}"); button.WriteValueIntoEvent <float>(msg.gamepadButton.pressed ? 1 : 0, eventPtr); } } else if (msg.type == Parsec.ParsecMessageType.MESSAGE_GAMEPAD_AXIS) { var axis = ParsecInputSystemMapping.ParsecToGamepadAxis(gamepad, msg.gamepadAxis.axis); if (axis != null) { float value = (float)msg.gamepadAxis.value / short.MaxValue; // TODO: Set a constant for this value that makes sense to avoid deadzoned values switching devices. if (Mathf.Abs(value) > 0.4f && guests[kvp.Key].Use(gamepad)) { ParsecUnityController.Log($"Guest {kvp.Key} switched current device to gamepad {msg.gamepadButton.id} at {Time.time}"); } axis.WriteValueIntoEvent(value, eventPtr); } } } InputSystem.QueueEvent(eventPtr); } } }
// TODO: This should be applied before all updates, or whenever // input normally is applied (based on the InputSystem configuration). private void Update() { // TODO: Probably don't need to allocate a new set of dictionaries every frame. var keyboardMessages = new Dictionary <uint, List <Parsec.ParsecMessage> >(); var mouseMessages = new Dictionary <uint, List <Parsec.ParsecMessage> >(); var gamepadMessages = new Dictionary <uint, List <Parsec.ParsecMessage> >(); while (parsec.HostPollInput(0u, out Parsec.ParsecGuest guest, out Parsec.ParsecMessage msg)) { switch (msg.type) { case Parsec.ParsecMessageType.MESSAGE_KEYBOARD: if (!keyboardMessages.ContainsKey(guest.id)) { keyboardMessages[guest.id] = new List <Parsec.ParsecMessage>(); } keyboardMessages[guest.id].Add(msg); break; case Parsec.ParsecMessageType.MESSAGE_MOUSE_BUTTON: if (!mouseMessages.ContainsKey(guest.id)) { mouseMessages[guest.id] = new List <Parsec.ParsecMessage>(); } mouseMessages[guest.id].Add(msg); break; case Parsec.ParsecMessageType.MESSAGE_MOUSE_MOTION: if (!mouseMessages.ContainsKey(guest.id)) { mouseMessages[guest.id] = new List <Parsec.ParsecMessage>(); } mouseMessages[guest.id].Add(msg); break; case Parsec.ParsecMessageType.MESSAGE_GAMEPAD_BUTTON: if (!gamepadMessages.ContainsKey(guest.id)) { gamepadMessages[guest.id] = new List <Parsec.ParsecMessage>(); } gamepadMessages[guest.id].Add(msg); break; case Parsec.ParsecMessageType.MESSAGE_GAMEPAD_AXIS: if (!gamepadMessages.ContainsKey(guest.id)) { gamepadMessages[guest.id] = new List <Parsec.ParsecMessage>(); } gamepadMessages[guest.id].Add(msg); break; default: break; } } // Unity's low level input event queuing system apparently does not like // multiple events to be queued for a single device each input round, // making it necessary to store all events per device ahead of time. foreach (var kvp in keyboardMessages) { if (!guests[kvp.Key].Get(out Keyboard keyboard)) { keyboard = guests[kvp.Key].CreateAndAdd <Keyboard>(); } using (StateEvent.From(keyboard, out InputEventPtr eventPtr)) { foreach (var msg in kvp.Value) { if (ParsecInputSystemMapping.Keys.TryGetValue(msg.keyboard.code, out Key key)) { ParsecUnityController.Log($"Guest {kvp.Key} {(msg.keyboard.pressed ? "pressed" : "released")} key {key} at {Time.time}"); keyboard[key].WriteValueIntoEvent <float>(msg.keyboard.pressed ? 1 : 0, eventPtr); } } InputSystem.QueueEvent(eventPtr); } } foreach (var kvp in mouseMessages) { if (!guests[kvp.Key].Get(out Mouse mouse)) { mouse = guests[kvp.Key].CreateAndAdd <Mouse>(); } using (StateEvent.From(mouse, out InputEventPtr eventPtr)) { foreach (var msg in kvp.Value) { if (msg.type == Parsec.ParsecMessageType.MESSAGE_MOUSE_BUTTON) { var button = ParsecInputSystemMapping.ParsecToMouseButton(mouse, msg.mouseButton.button); if (button != null) { ParsecUnityController.Log($"Guest {kvp.Key} {(msg.mouseButton.pressed ? "pressed" : "released")} {button} on mouse at {Time.time}"); button.WriteValueIntoEvent <float>(msg.mouseButton.pressed ? 1 : 0, eventPtr); } } else if (msg.type == Parsec.ParsecMessageType.MESSAGE_MOUSE_MOTION && !msg.mouseMotion.relative) { // TODO: Logging levels for very low priority debugs, like mouse motion or position. // ParsecUnityController.Log($"Guest {kvp.Key} mouse position is at {msg.mouseMotion.x}, {msg.mouseMotion.y} at {Time.time}"); mouse.position.x.WriteValueIntoEvent <float>(msg.mouseMotion.x, eventPtr); mouse.position.y.WriteValueIntoEvent <float>(msg.mouseMotion.y, eventPtr); } else if (msg.type == Parsec.ParsecMessageType.MESSAGE_MOUSE_MOTION && msg.mouseMotion.relative) { // TODO: Logging levels for very low priority debugs, like mouse motion or position. // ParsecUnityController.Log($"Guest {kvp.Key} mouse delta was {msg.mouseMotion.x}, {msg.mouseMotion.y} at {Time.time}"); mouse.delta.x.WriteValueIntoEvent <float>(msg.mouseMotion.x, eventPtr); mouse.delta.y.WriteValueIntoEvent <float>(msg.mouseMotion.y, eventPtr); } } InputSystem.QueueEvent(eventPtr); } } foreach (var kvp in gamepadMessages) { if (!guests[kvp.Key].Get(out Gamepad gamepad)) { gamepad = guests[kvp.Key].CreateAndAdd <Gamepad>(); } using (StateEvent.From(gamepad, out InputEventPtr eventPtr)) { foreach (var msg in kvp.Value) { if (msg.type == Parsec.ParsecMessageType.MESSAGE_GAMEPAD_BUTTON) { var button = ParsecInputSystemMapping.ParsecToGamepadButton(gamepad, msg.gamepadButton.button); if (button != null) { ParsecUnityController.Log($"Guest {kvp.Key} {(msg.gamepadButton.pressed ? "pressed" : "released")} {button} on gamepad {msg.gamepadButton.id} at {Time.time}"); button.WriteValueIntoEvent <float>(msg.gamepadButton.pressed ? 1 : 0, eventPtr); } } else if (msg.type == Parsec.ParsecMessageType.MESSAGE_GAMEPAD_AXIS) { var axis = ParsecInputSystemMapping.ParsecToGamepadAxis(gamepad, msg.gamepadAxis.axis); if (axis != null) { float value = (float)msg.gamepadAxis.value / short.MaxValue; axis.WriteValueIntoEvent(value, eventPtr); } } } InputSystem.QueueEvent(eventPtr); } } }