diff --git a/ConfigApp/MainWindow.xaml b/ConfigApp/MainWindow.xaml
index 41b1251e7..e3f3b9de8 100644
--- a/ConfigApp/MainWindow.xaml
+++ b/ConfigApp/MainWindow.xaml
@@ -285,10 +285,17 @@
-
+
-
+
+
+
+ /// Universal container for voting overlay message data
+ ///
+ class OverlayBaseMessage
+ {
+ ///
+ /// The type of the message request. This is read by the overlay to properly parse the correct request message.
+ ///
+ public string type { get; set; }
+ ///
+ /// The json data (serialized) of the actual request
+ ///
+ public string messageData { get; set; }
+ }
+
///
- /// Message which is being sent
+ /// Message containing voting data
///
- class OverlayMessage
+ class OverlayVotingMessage
{
public bool retainInitialVotes { get; set; }
///
@@ -23,4 +47,23 @@ class OverlayMessage
///
public OverlayVoteOption[] voteOptions { get; set; }
}
+
+ ///
+ /// Message to tell the voting overlay to update the style color for the bar progression
+ ///
+ class OverlayColorMessage
+ {
+ ///
+ /// Red value of the style color
+ ///
+ public int colorR;
+ ///
+ /// Green value of the style color
+ ///
+ public int colorG;
+ ///
+ /// Blue value of the style color
+ ///
+ public int colorB;
+ }
}
diff --git a/TwitchChatVotingProxy/OverlayServer/OverlayServer.cs b/TwitchChatVotingProxy/OverlayServer/OverlayServer.cs
index dba893ee3..9158d6c6a 100644
--- a/TwitchChatVotingProxy/OverlayServer/OverlayServer.cs
+++ b/TwitchChatVotingProxy/OverlayServer/OverlayServer.cs
@@ -3,6 +3,7 @@
using Serilog;
using System;
using System.Collections.Generic;
+using System.Windows.Media;
// TODO: fix voting mode
namespace TwitchChatVotingProxy.OverlayServer
@@ -10,7 +11,7 @@ namespace TwitchChatVotingProxy.OverlayServer
class OverlayServer : IOverlayServer
{
private OverlayServerConfig config;
- private List connections = new List();
+ private List connections = new List();
private ILogger logger = Log.Logger.ForContext();
public OverlayServer(OverlayServerConfig config)
@@ -19,16 +20,32 @@ public OverlayServer(OverlayServerConfig config)
try
{
- var WSS = new Fleck.WebSocketServer($"ws://0.0.0.0:{config.Port}");
+ var WSS = new WebSocketServer($"ws://0.0.0.0:{config.Port}");
// Set the websocket listeners
WSS.Start(connection =>
{
connection.OnOpen += () => OnWsConnectionOpen(connection);
connection.OnClose += () => OnWSConnectionClose(connection);
});
+
+ //Set voting bar color
+ SendSetBarColorMessage();
} catch (Exception e)
{
- logger.Fatal(e, "failed so start websocket server");
+ logger.Fatal(e, "failed to start websocket server");
+ }
+ }
+
+ public void SendSetBarColorMessage()
+ {
+ if (config.OverlayVotingBarColor.HasValue)
+ {
+ var clrMsg = new OverlayColorMessage();
+ clrMsg.colorR = ((Color)config.OverlayVotingBarColor).R;
+ clrMsg.colorG = ((Color)config.OverlayVotingBarColor).G;
+ clrMsg.colorB = ((Color)config.OverlayVotingBarColor).B;
+
+ Broadcast(eMessageType.SET_COLOR, JsonConvert.SerializeObject(clrMsg));
}
}
@@ -52,14 +69,20 @@ public void UpdateVoting(List voteOptions)
///
/// Broadcasts a message to all socket clients
///
+ /// Type of message which should be broadcast
/// Message which should be broadcast
- private void Broadcast(string message)
+ private void Broadcast(eMessageType messageType, string message)
{
+ OverlayBaseMessage baseMsg = new OverlayBaseMessage();
+ baseMsg.type = Enum.GetName(typeof(eMessageType), messageType);
+ baseMsg.messageData = message;
+ string msg = JsonConvert.SerializeObject(baseMsg);
+
connections.ForEach(connection =>
{
// If the connection is not available for some reason, we just close it
if (!connection.IsAvailable) connection.Close();
- else connection.Send(message);
+ else connection.Send(msg);
});
}
///
@@ -99,7 +122,7 @@ private void OnWsConnectionOpen(IWebSocketConnection connection)
/// Vote options that should be sent
private void Request(string request, List voteOptions)
{
- var msg = new OverlayMessage();
+ var msg = new OverlayVotingMessage();
msg.request = request;
msg.voteOptions = voteOptions.ConvertAll(_ => new OverlayVoteOption(_)).ToArray();
msg.retainInitialVotes = config.RetainInitialVotes;
@@ -116,9 +139,7 @@ private void Request(string request, List voteOptions)
msg.totalVotes = 0;
voteOptions.ForEach(_ => msg.totalVotes += _.Votes);
// Send the message to all clients
- Broadcast(JsonConvert.SerializeObject(msg));
+ Broadcast(eMessageType.SET_VOTES, JsonConvert.SerializeObject(msg));
}
}
-}
-
-
+}
\ No newline at end of file
diff --git a/TwitchChatVotingProxy/OverlayServer/OverlayServerConfig.cs b/TwitchChatVotingProxy/OverlayServer/OverlayServerConfig.cs
index e6c11cc46..61d0d040b 100644
--- a/TwitchChatVotingProxy/OverlayServer/OverlayServerConfig.cs
+++ b/TwitchChatVotingProxy/OverlayServer/OverlayServerConfig.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Windows.Media;
namespace TwitchChatVotingProxy.OverlayServer
{
@@ -14,12 +10,14 @@ class OverlayServerConfig
public bool RetainInitialVotes { get; set; }
public EVotingMode VotingMode { get; set; }
public int Port { get; set; }
+ public Color? OverlayVotingBarColor { get; set; }
- public OverlayServerConfig(EVotingMode votingMode, bool retainInitialVotes, int? port)
+ public OverlayServerConfig(EVotingMode votingMode, bool retainInitialVotes, int? port, Color? overlayVotingBarColor)
{
RetainInitialVotes = retainInitialVotes;
VotingMode = votingMode;
Port = port == null ? 9091 : (int)port;
+ OverlayVotingBarColor = overlayVotingBarColor;
}
}
}
diff --git a/TwitchChatVotingProxy/TwitchChatVotingProxy.cs b/TwitchChatVotingProxy/TwitchChatVotingProxy.cs
index b40b69685..0f6282c07 100644
--- a/TwitchChatVotingProxy/TwitchChatVotingProxy.cs
+++ b/TwitchChatVotingProxy/TwitchChatVotingProxy.cs
@@ -67,10 +67,12 @@ private static void Main(string[] args)
if (config.OverlayMode == EOverlayMode.OVERLAY_OBS)
{
// Create overlay server config
- OverlayServerConfig overlayServerConfig = new OverlayServerConfig(votingMode, config.RetainInitalVotes, config.OverlayServerPort);
+ OverlayServerConfig overlayServerConfig = new OverlayServerConfig(votingMode, config.RetainInitalVotes, config.OverlayServerPort, config.OverlayVotingBarColor);
// Create component
overlayServer = new OverlayServer.OverlayServer(overlayServerConfig);
+
+ logger.Information("succesfully setup OBS voting overlay");
}
// Create components
@@ -80,9 +82,14 @@ private static void Main(string[] args)
// Start the chaos mod controller
new ChaosModController(chaosPipe, overlayServer, votingReceiver, config);
- while (chaosPipe.IsConnected())
+ if (chaosPipe.IsConnected())
{
- Thread.Sleep(100);
+ logger.Information("successfully set up twitch chat voting proxy");
+
+ while (chaosPipe.IsConnected())
+ {
+ Thread.Sleep(100);
+ }
}
}
finally
diff --git a/TwitchChatVotingProxy/TwitchChatVotingProxy.csproj b/TwitchChatVotingProxy/TwitchChatVotingProxy.csproj
index 0e093ddfc..ebcedeea4 100644
--- a/TwitchChatVotingProxy/TwitchChatVotingProxy.csproj
+++ b/TwitchChatVotingProxy/TwitchChatVotingProxy.csproj
@@ -56,6 +56,7 @@
..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
+
..\packages\Serilog.2.10.0\lib\net46\Serilog.dll
diff --git a/twitchVotingOverlay/src/barOverlay.ts b/twitchVotingOverlay/src/barOverlay.ts
index 126e7c997..bd8c6f0a9 100644
--- a/twitchVotingOverlay/src/barOverlay.ts
+++ b/twitchVotingOverlay/src/barOverlay.ts
@@ -1,5 +1,5 @@
import { IChaosOverlayClient } from './chaosOverlayClient/iClient';
-import { IChaosOverlayClientMessage } from './chaosOverlayClient/iMessage';
+import { IChaosOverlayVotingClientMessage } from './chaosOverlayClient/iMessage';
const ANIMATION_DELAY_DELTA = 100;
const ANIMATION_LENGTH = 600;
@@ -115,7 +115,7 @@ export class BarOverlay {
private onEndVote(): void {
this.bars.forEach(bar => (bar.isDisabled = true));
}
- private onUpdateVote(message: IChaosOverlayClientMessage): void {
+ private onUpdateVote(message: IChaosOverlayVotingClientMessage): void {
const { retainInitialVotes, voteOptions, votingMode } = message;
let { totalVotes } = message;
diff --git a/twitchVotingOverlay/src/chaosOverlayClient/client.ts b/twitchVotingOverlay/src/chaosOverlayClient/client.ts
index a3fa6a563..cb09438ec 100644
--- a/twitchVotingOverlay/src/chaosOverlayClient/client.ts
+++ b/twitchVotingOverlay/src/chaosOverlayClient/client.ts
@@ -1,8 +1,9 @@
import { IChaosOverlayClient } from './iClient';
import { LiteEvent } from '../lightEvent';
import { IChaosOverlayVoteOption } from './iVoteOption';
-import { IChaosOverlayClientMessage } from './iMessage';
+import { IChaosOverlayBaseClientMessage, IChaosOverlayVotingClientMessage, IChaosOverlayColorClientMessage } from './iMessage';
import { TChaosOverlayClientEvent } from './tEvent';
+import { SetBarProgressColor } from '../style';
export class ChaosOverlayClient implements IChaosOverlayClient {
/**
@@ -13,12 +14,12 @@ export class ChaosOverlayClient implements IChaosOverlayClient {
private URL: string;
private WS: WebSocket | null = null;
- private createEvent = new LiteEvent();
+ private createEvent = new LiteEvent();
private connectEvent = new LiteEvent();
private disconnectEvent = new LiteEvent();
- private endEvent = new LiteEvent();
- private noVoteRoundEvent = new LiteEvent();
- private updateEvent = new LiteEvent();
+ private endEvent = new LiteEvent();
+ private noVoteRoundEvent = new LiteEvent();
+ private updateEvent = new LiteEvent();
public constructor(URL: string) {
this.URL = URL;
@@ -108,23 +109,39 @@ export class ChaosOverlayClient implements IChaosOverlayClient {
*/
private onSocketMessage(message: MessageEvent): void {
try {
- const MESSAGE: IChaosOverlayClientMessage = JSON.parse(message.data);
+ const BASE_MESSAGE: IChaosOverlayBaseClientMessage = JSON.parse(message.data);
- switch (MESSAGE.request) {
- case 'CREATE':
- this.createEvent.dispatch(MESSAGE);
- break;
- case 'END':
- this.endEvent.dispatch(MESSAGE);
- break;
- case 'NO_VOTING_ROUND':
- this.noVoteRoundEvent.dispatch(MESSAGE);
- break;
- case 'UPDATE':
- this.updateEvent.dispatch(MESSAGE);
- break;
+ switch (BASE_MESSAGE.type) {
+ case 'SET_VOTES': {
+ const MESSAGE: IChaosOverlayVotingClientMessage = JSON.parse(BASE_MESSAGE.messageData);
+ switch (MESSAGE.request) {
+ case 'CREATE':
+ this.createEvent.dispatch(MESSAGE);
+ break;
+ case 'END':
+ this.endEvent.dispatch(MESSAGE);
+ break;
+ case 'NO_VOTING_ROUND':
+ this.noVoteRoundEvent.dispatch(MESSAGE);
+ break;
+ case 'UPDATE':
+ this.updateEvent.dispatch(MESSAGE);
+ break;
+ default:
+ console.warn(`unknown voting message request type: ${MESSAGE.request}`);
+ }
+
+ break;
+ }
+ case 'SET_COLOR': {
+ const MESSAGE : IChaosOverlayColorClientMessage = JSON.parse(BASE_MESSAGE.messageData);
+ SetBarProgressColor(MESSAGE.colorR, MESSAGE.colorG, MESSAGE.colorB);
+
+ break;
+ }
default:
- console.warn(`unknown request type: ${MESSAGE.request}`);
+ console.warn(`unknown message type: ${BASE_MESSAGE.type}`);
+ break;
}
} catch (e) {
console.error(`failed to parse json data: ${e}`);
diff --git a/twitchVotingOverlay/src/chaosOverlayClient/iMessage.ts b/twitchVotingOverlay/src/chaosOverlayClient/iMessage.ts
index 9284d704f..c4303006e 100644
--- a/twitchVotingOverlay/src/chaosOverlayClient/iMessage.ts
+++ b/twitchVotingOverlay/src/chaosOverlayClient/iMessage.ts
@@ -1,6 +1,18 @@
import { IChaosOverlayVoteOption } from './iVoteOption';
-export interface IChaosOverlayClientMessage {
+export interface IChaosOverlayBaseClientMessage
+{
+ type : 'SET_VOTES' | 'SET_COLOR';
+ messageData : string;
+}
+
+export interface IChaosOverlayColorClientMessage {
+ colorR : number;
+ colorG : number;
+ colorB : number;
+}
+
+export interface IChaosOverlayVotingClientMessage {
retainInitialVotes: boolean;
request: 'CREATE' | 'END' | 'NO_VOTING_ROUND' | 'UPDATE';
totalVotes: number;
diff --git a/twitchVotingOverlay/src/chaosOverlayClient/index.ts b/twitchVotingOverlay/src/chaosOverlayClient/index.ts
index 973eb2f3d..0984753a1 100644
--- a/twitchVotingOverlay/src/chaosOverlayClient/index.ts
+++ b/twitchVotingOverlay/src/chaosOverlayClient/index.ts
@@ -1,5 +1,5 @@
export { ChaosOverlayClient } from './client';
export { IChaosOverlayClient } from './iClient';
-export { IChaosOverlayClientMessage } from './iMessage';
+export { IChaosOverlayVotingClientMessage } from './iMessage';
export { IChaosOverlayVoteOption } from './iVoteOption';
export { TChaosOverlayClientEvent } from './tEvent';
diff --git a/twitchVotingOverlay/src/chaosOverlayClient/tEvent.ts b/twitchVotingOverlay/src/chaosOverlayClient/tEvent.ts
index 6e01a144b..8f933504b 100644
--- a/twitchVotingOverlay/src/chaosOverlayClient/tEvent.ts
+++ b/twitchVotingOverlay/src/chaosOverlayClient/tEvent.ts
@@ -1,3 +1,3 @@
-import { IChaosOverlayClientMessage } from './iMessage';
+import { IChaosOverlayVotingClientMessage } from './iMessage';
-export type TChaosOverlayClientEvent = (event: IChaosOverlayClientMessage) => void;
+export type TChaosOverlayClientEvent = (event: IChaosOverlayVotingClientMessage) => void;
diff --git a/twitchVotingOverlay/src/style.ts b/twitchVotingOverlay/src/style.ts
new file mode 100644
index 000000000..4b4c36941
--- /dev/null
+++ b/twitchVotingOverlay/src/style.ts
@@ -0,0 +1,11 @@
+/*
+ These are just color utility functions only used by this script
+*/
+function componentToHex(c : number) {
+ var hex = c.toString(16);
+ return hex.length == 1 ? "0" + hex : hex;
+}
+
+export function SetBarProgressColor(r : number, g : number, b : number) {
+ document.body.style.setProperty("--bar-progression", "#" + componentToHex(r) + componentToHex(g) + componentToHex(b));
+}
\ No newline at end of file