Skip to content

Instantly share code, notes, and snippets.

@chrisuehlinger
Created July 1, 2021 01:00
Show Gist options
  • Save chrisuehlinger/224fdc479e4cabd461a24aa1ff854140 to your computer and use it in GitHub Desktop.
Save chrisuehlinger/224fdc479e4cabd461a24aa1ff854140 to your computer and use it in GitHub Desktop.
Kumite Socket Listener
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.WebSockets;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;
using Newtonsoft.Json;
public class SocketListener : MonoBehaviour
{
public Matrix4x4 anchor = Matrix4x4.identity;
public Matrix4x4 leftEyeAnchor = Matrix4x4.identity;
public Matrix4x4 rightEyeAnchor = Matrix4x4.identity;
public ArkitBlendShapes blendShapes = null;
float smooth = 5.0f;
Uri u = new Uri("wss://xana.local/unity-app");
ClientWebSocket cws = null;
ArraySegment<byte> buf = new ArraySegment<byte>(new byte[4096]);
ServerMessage currentMessage = null;
String prevHost = null;
String currentHost = null;
public bool isGaladriel = false;
GameObject Partisans;
GameObject Referees;
ControlEffect controlEffect;
GlitchEffect glitchEffect;
VHSPostProcessEffect vhsEffect;
VideoPlayer vhsPlayer;
Material backgroundMaterial;
public String transitionTarget = null;
public float transitionTimeLeft = 0f;
public float TRANSITION_DURATION = 1f;
public float currentInversionAmount = 0f;
public Color currentBackgroundInnerColor = new Color(0,0,0,1);
public Color currentBackgroundOuterColor = new Color(0,0,0,1);
public float currentVHSPlaybackSpeed = 1f;
public Dictionary<string, Color> outerColors = new Dictionary<string, Color>(){
{ "biome", new Color(0,1,0,1)},
{ "creche", new Color(1,0,0,1)},
{ "nav", new Color(1,1,0,1)},
{ "interface", new Color(1,1,1,1)},
{ "control", new Color(0,0,0,1)}
};
public Dictionary<string, Color> innerColors = new Dictionary<string, Color>(){
{ "biome", new Color(0,0,0,1)},
{ "creche", new Color(0,0,0,1)},
{ "nav", new Color(1,1,1,1)},
{ "interface", new Color(0,0,0,1)},
{ "control", new Color(1,1,1,1)}
};
public Dictionary<string, Quaternion> cameraAngles = new Dictionary<string, Quaternion>(){
{ "biome", Quaternion.Euler(0, 0, 0) },
{ "creche", Quaternion.Euler(0, 120, 0) },
{ "nav", Quaternion.Euler(0, -120, 0) },
{ "interface", Quaternion.Euler(0, 180, 0) },
{ "control", Quaternion.Euler(0, 180, 0) }
};
// Start is called before the first frame update
void Start()
{
Debug.Log("GO!");
// QualitySettings.vSyncCount = 0;
// Application.targetFrameRate = 17;
var camera = GameObject.Find("Main Camera");
controlEffect = camera.GetComponent<ControlEffect>();
glitchEffect = camera.GetComponent<GlitchEffect>();
vhsEffect = camera.GetComponent<VHSPostProcessEffect>();
vhsPlayer = camera.GetComponent<VideoPlayer>();
backgroundMaterial = GameObject.Find("Background Plane").GetComponent<MeshRenderer>().materials[0];
backgroundMaterial.SetColor("_OuterColor", new Color(1,0,0,1) );
Partisans = GameObject.Find("Partisans");
Referees = GameObject.Find("Referees");
// Go into "No AI" mode until we get a signal
Partisans.SetActive(false);
Referees.SetActive(false);
glitchEffect.enabled = false;
vhsEffect.enabled = false;
Connect();
}
// Update is called once per frame
void Update()
{
bool immediateSwitch = false;
if(prevHost != currentHost) {
var prevMode = HostMode(prevHost);
var currentMode = HostMode(currentHost);
if(prevMode != currentMode){
Debug.Log("STARTING TRANSITION TO " + currentMode);
transitionTarget = currentMode;
transitionTimeLeft = TRANSITION_DURATION;
glitchEffect.enabled = true;
vhsEffect.enabled = true;
glitchEffect.intensity = 1f;
glitchEffect.flipIntensity = 1f;
glitchEffect.colorIntensity = 1f;
}
prevHost = currentHost;
} else if(!String.IsNullOrEmpty(transitionTarget)) {
transitionTimeLeft -= Time.deltaTime;
Debug.Log("TRANSITIONING " + transitionTimeLeft);
if(transitionTimeLeft < 0f) {
Debug.Log("FINISHING TRANSITION TO " + transitionTarget);
transitionTimeLeft = 0f;
immediateSwitch = true;
glitchEffect.intensity = 0f;
glitchEffect.flipIntensity = 0f;
glitchEffect.colorIntensity = 0f;
if(transitionTarget == "none") {
Partisans.SetActive(false);
Referees.SetActive(false);
glitchEffect.enabled = false;
vhsEffect.enabled = false;
} else if(transitionTarget == "partisan") {
Partisans.SetActive(true);
Referees.SetActive(false);
} else if(transitionTarget == "referees") {
Partisans.SetActive(false);
Referees.SetActive(true);
}
transitionTarget = null;
}
}
Color targetOuterColor = String.IsNullOrEmpty(currentHost) ? new Color(0,0,0,1) : outerColors[currentHost];
Color targetInnerColor = String.IsNullOrEmpty(currentHost) ? new Color(0,0,0,1) : innerColors[currentHost];
Quaternion target = String.IsNullOrEmpty(currentHost) ? Quaternion.Euler(0, 0, 0) : cameraAngles[currentHost];
float targetInversionAmount = (currentHost == "control") ? 1 : 0;
float targetPlaybackSpeed = (currentHost == "control" || isGaladriel) ? 10f : 1f;
if(isGaladriel){
glitchEffect.intensity = 1f;
glitchEffect.flipIntensity = 1f;
glitchEffect.colorIntensity = 1f;
}
if(immediateSwitch){
transform.rotation = target;
currentBackgroundOuterColor = targetOuterColor;
currentBackgroundInnerColor = targetInnerColor;
currentInversionAmount = targetInversionAmount;
currentVHSPlaybackSpeed = targetPlaybackSpeed;
} else if(String.IsNullOrEmpty(transitionTarget)) {
currentBackgroundOuterColor = Color.Lerp(currentBackgroundOuterColor, targetOuterColor, Time.deltaTime * smooth);
currentBackgroundInnerColor = Color.Lerp(currentBackgroundInnerColor, targetInnerColor, Time.deltaTime * smooth);
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * smooth);
currentInversionAmount += Time.deltaTime * smooth * (targetInversionAmount - currentInversionAmount);
currentVHSPlaybackSpeed += Time.deltaTime * smooth * (targetPlaybackSpeed - currentVHSPlaybackSpeed);
}
backgroundMaterial.SetColor("_OuterColor", currentBackgroundOuterColor );
backgroundMaterial.SetColor("_InnerColor", currentBackgroundInnerColor );
controlEffect.intensity = currentInversionAmount;
vhsPlayer.playbackSpeed = currentVHSPlaybackSpeed;
}
String HostMode(String hostName) {
if(hostName == "biome" || hostName == "creche" || hostName == "nav") {
return "partisan";
} else if(hostName == "interface" || hostName == "control") {
return "referees";
} else {
return "none";
}
}
async void Connect() {
Debug.Log("Connecting...");
cws = new ClientWebSocket();
try {
await cws.ConnectAsync(u, CancellationToken.None);
if (cws.State == WebSocketState.Open) {
Debug.Log("connected");
} else {
Task.Delay(1000).ContinueWith(t=> Connect());
}
SayHello();
GetStuff();
}
catch (Exception e) {
Debug.Log("woe " + e.Message);
Task.Delay(1000).ContinueWith(t=> Connect());
}
}
async void SayHello() {
ArraySegment<byte> b = new ArraySegment<byte>(Encoding.UTF8.GetBytes("hello"));
await cws.SendAsync(b, WebSocketMessageType.Text, true, CancellationToken.None);
}
async void GetStuff() {
try {
WebSocketReceiveResult r = await cws.ReceiveAsync(buf, CancellationToken.None);
var rawMessage = Encoding.UTF8.GetString(buf.Array, 0, r.Count);
Debug.Log("Got: " + rawMessage);
currentMessage = JsonConvert.DeserializeObject<ServerMessage>(rawMessage);
switch(currentMessage.messageType) {
case "changeAI":
String newHost = currentMessage.hostName == "mummy" ? null : currentMessage.hostName;
prevHost = currentHost;
currentHost = newHost;
isGaladriel = false;
break;
case "removeAI":
prevHost = currentHost;
currentHost = null;
isGaladriel = false;
break;
case "galadriel":
isGaladriel = true;
break;
case "faceUpdate":
var a = currentMessage.anchor;
Matrix4x4 eyeRotation = Matrix4x4.Rotate(Quaternion.Euler(0, -90, 0));
Matrix4x4 zRotation = Matrix4x4.Rotate(Quaternion.Euler(0, 0, -90));
Matrix4x4 unflip = Matrix4x4.identity;
// unflip.m22 = -1;
var newAnchor = new Matrix4x4();
newAnchor.SetRow(0, new Vector4(a[0], a[1], a[2], a[3]));
newAnchor.SetRow(1, new Vector4(a[4], a[5], a[6], a[7]));
newAnchor.SetRow(2, new Vector4(a[8], a[9], a[10], a[11]));
newAnchor.SetRow(3, new Vector4(a[12], a[13], a[14], a[15]));
anchor = zRotation * newAnchor * unflip;
a = currentMessage.leftEyeAnchor;
newAnchor = new Matrix4x4();
newAnchor.SetRow(0, new Vector4(a[0], a[1], a[2], a[3]));
newAnchor.SetRow(1, new Vector4(a[4], a[5], a[6], a[7]));
newAnchor.SetRow(2, new Vector4(a[8], a[9], a[10], a[11]));
newAnchor.SetRow(3, new Vector4(a[12], a[13], a[14], a[15]));
leftEyeAnchor = eyeRotation * newAnchor;
a = currentMessage.rightEyeAnchor;
newAnchor = new Matrix4x4();
newAnchor.SetRow(0, new Vector4(a[0], a[1], a[2], a[3]));
newAnchor.SetRow(1, new Vector4(a[4], a[5], a[6], a[7]));
newAnchor.SetRow(2, new Vector4(a[8], a[9], a[10], a[11]));
newAnchor.SetRow(3, new Vector4(a[12], a[13], a[14], a[15]));
rightEyeAnchor = eyeRotation * newAnchor;
blendShapes = currentMessage.blendShapes;
var currentTime = DateTime.Now;
var latency = DateTime.Now - new DateTime(currentMessage.timestamp);
Debug.Log("LATENCY: " + latency.Milliseconds);
// Debug.Log("BLENDSHAPES: " + currentMessage.blendShapes.jawOpen);
break;
default:
Debug.Log("No handler for message of type: " + currentMessage.messageType);
break;
}
GetStuff();
} catch (Exception e) {
Debug.Log("woe2 " + e.Message);
Task.Delay(1000).ContinueWith(t=> Connect());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment