From 02acadacc1e47f8a30cf6651e609ba879cbfd9e0 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 13:17:41 -0700
Subject: [PATCH 01/26] Added WebSocketUtil (and intenet folder)
Planning on adding more stuff to it.
---
libs.xml | 3 +
project.xml | 2 +
.../funkin/backend/internet/WebSocketUtil.hx | 106 ++++++++++++++++++
source/funkin/backend/system/macros/Macros.hx | 3 +-
4 files changed, 113 insertions(+), 1 deletion(-)
create mode 100644 source/funkin/backend/internet/WebSocketUtil.hx
diff --git a/libs.xml b/libs.xml
index f932da098..a443dfa3a 100644
--- a/libs.xml
+++ b/libs.xml
@@ -4,6 +4,9 @@
+
+
+
diff --git a/project.xml b/project.xml
index 6f01bc102..51a5ab17f 100644
--- a/project.xml
+++ b/project.xml
@@ -170,6 +170,8 @@
+
+
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/internet/WebSocketUtil.hx
new file mode 100644
index 000000000..4368f93b2
--- /dev/null
+++ b/source/funkin/backend/internet/WebSocketUtil.hx
@@ -0,0 +1,106 @@
+package funkin.backend.internet;
+
+import haxe.io.Bytes;
+import hx.ws.Log;
+import hx.ws.WebSocket;
+
+import funkin.backend.system.Logs;
+
+class WebSocketUtil implements IFlxDestroyable {
+
+ static var loggingEnabled:Bool = false;
+ static function toggleLogging(?INFO:Bool = true, ?DEBUG:Bool = true, ?DATA:Bool = true) {
+ loggingEnabled = !loggingEnabled;
+ if (!loggingEnabled) return Log.mask = 0;
+
+ var _mask = Log.mask;
+ if (INFO) _mask = _mask | Log.INFO;
+ if (DEBUG) _mask = _mask | Log.DEBUG;
+ if (DATA) _mask = _mask | Log.DATA;
+ Log.mask = _mask;
+
+ return Log.mask;
+ }
+
+ public var onOpen:WebSocket->Void = (webSocket)->{};
+ public var onMessage:Void->Void = ()->{};
+ public var onClose:Void->Void = ()->{};
+ public var onError:Dynamic->Void = (error)->{};
+
+ private var url:String;
+ private var webSocket:WebSocket;
+ public function new(url:String, ?onOpen:WebSocket->Void, ?immediateOpen:Bool = false) {
+ this.onOpen = (onOpen == null) ? this.onOpen : onOpen;
+
+ this.url = url;
+ this.webSocket = new WebSocket(this.url, false);
+
+ // TODO: make trace print colors with `Logs.hx`
+ this.webSocket.onopen = function() {
+ try {
+ this.onOpen(webSocket);
+ } catch(e) {
+ trace('Error: ${e}');
+ }
+ };
+
+ this.webSocket.onmessage = function(message) {
+ try {
+ this.onMessage();
+ } catch(e) {
+ trace('Error: ${e}');
+ }
+ };
+
+ this.webSocket.onclose = function() {
+ try {
+ this.onClose();
+ } catch(e) {
+ trace('Error: ${e}');
+ }
+ };
+
+ this.webSocket.onerror = function(error) {
+ trace('Websocket error: ${error}');
+ try {
+ this.onError(error);
+ } catch(e) {
+ trace('Error: ${e}');
+ }
+ };
+
+ if (immediateOpen) this.open();
+ }
+
+ public function open() {
+ trace('[Connection Status] Connecting to ${this.url}');
+ try {
+ this.webSocket.open();
+ } catch(e) {
+ trace("Failed to open websocket: " + e);
+ this.onError(e);
+ }
+ }
+
+ public function close() {
+ trace('[Connection Status] Closing connection to ${this.url}');
+ try {
+ this.webSocket.close();
+ } catch(e) {
+ trace("Failed to close websocket: " + e);
+ }
+ }
+
+ public function send(data:String) {
+ try {
+ this.webSocket.send(data);
+ } catch(e) {
+ trace("Failed to send data to websocket: " + e);
+ }
+ }
+
+ public function destroy() {
+ this.webSocket.close();
+ }
+}
+
diff --git a/source/funkin/backend/system/macros/Macros.hx b/source/funkin/backend/system/macros/Macros.hx
index 9183e4a4e..dc56c359c 100644
--- a/source/funkin/backend/system/macros/Macros.hx
+++ b/source/funkin/backend/system/macros/Macros.hx
@@ -21,8 +21,9 @@ class Macros {
// OTHER LIBRARIES & STUFF
#if THREE_D_SUPPORT "away3d", "flx3d", #end
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
+
// BASE HAXE
- "DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting"
+ "DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting",
])
Compiler.include(inc);
From b8d313272c0a3ce5a0961b0ed8fd202571a66f6c Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 14:28:36 -0700
Subject: [PATCH 02/26] WebSocketUtil document
---
.../funkin/backend/internet/WebSocketUtil.hx | 66 ++++++++++++++++---
1 file changed, 58 insertions(+), 8 deletions(-)
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/internet/WebSocketUtil.hx
index 4368f93b2..b92fc8cd0 100644
--- a/source/funkin/backend/internet/WebSocketUtil.hx
+++ b/source/funkin/backend/internet/WebSocketUtil.hx
@@ -1,14 +1,20 @@
package funkin.backend.internet;
import haxe.io.Bytes;
-import hx.ws.Log;
-import hx.ws.WebSocket;
+
+import hx.ws.*;
import funkin.backend.system.Logs;
class WebSocketUtil implements IFlxDestroyable {
-
+ /**
+ * Used for the `toggleLogging` function. this is more of a data handler for the function.
+ **/
static var loggingEnabled:Bool = false;
+
+ /**
+ * Call this function to toggle debugging for the WebSocket.
+ **/
static function toggleLogging(?INFO:Bool = true, ?DEBUG:Bool = true, ?DATA:Bool = true) {
loggingEnabled = !loggingEnabled;
if (!loggingEnabled) return Log.mask = 0;
@@ -22,13 +28,36 @@ class WebSocketUtil implements IFlxDestroyable {
return Log.mask;
}
+ /**
+ * Function calls after the WebSocket has been opened.
+ * @param webSocket Returns the instance of the WebSocket.
+ **/
public var onOpen:WebSocket->Void = (webSocket)->{};
- public var onMessage:Void->Void = ()->{};
+
+ /**
+ * Whenever the WebSocket receives a message sent from the server.
+ * @param message Returns the message sent from the server.
+ **/
+ public var onMessage:Dynamic->Void = (message)->{};
+
+ /**
+ * Runs whenever the WebSocket closes.
+ **/
public var onClose:Void->Void = ()->{};
+
+ /**
+ * Runs whenever the WebSocket encounters an error.
+ **/
public var onError:Dynamic->Void = (error)->{};
- private var url:String;
- private var webSocket:WebSocket;
+ @:dox(hide) private var url:String;
+ @:dox(hide) private var webSocket:WebSocket;
+
+ /**
+ * @param url The URL of the WebSocket. Usually `ws://localhost:port`.
+ * @param onOpen sets the `onOpen` function directly to the class.
+ * @param immediateOpen If true, the WebSocket will open immediately. Hence why `onOpen` is a function in the parameters.
+ **/
public function new(url:String, ?onOpen:WebSocket->Void, ?immediateOpen:Bool = false) {
this.onOpen = (onOpen == null) ? this.onOpen : onOpen;
@@ -45,8 +74,15 @@ class WebSocketUtil implements IFlxDestroyable {
};
this.webSocket.onmessage = function(message) {
+ var data:Dynamic = null;
try {
- this.onMessage();
+ switch(message) {
+ case StrMessage(str):
+ data = str;
+ case BytesMessage(bytes):
+ data = bytes;
+ }
+ this.onMessage(data);
} catch(e) {
trace('Error: ${e}');
}
@@ -70,8 +106,12 @@ class WebSocketUtil implements IFlxDestroyable {
};
if (immediateOpen) this.open();
+ return this;
}
+ /**
+ * Opens the WebSocket.
+ **/
public function open() {
trace('[Connection Status] Connecting to ${this.url}');
try {
@@ -82,6 +122,9 @@ class WebSocketUtil implements IFlxDestroyable {
}
}
+ /**
+ * Closes the WebSocket.
+ **/
public function close() {
trace('[Connection Status] Closing connection to ${this.url}');
try {
@@ -91,14 +134,21 @@ class WebSocketUtil implements IFlxDestroyable {
}
}
- public function send(data:String) {
+ /**
+ * Sends data to the server
+ **/
+ public function send(data) {
try {
this.webSocket.send(data);
} catch(e) {
trace("Failed to send data to websocket: " + e);
+ this.onError(e);
}
}
+ /**
+ * Closes the WebSocket and destroys the class instance.
+ **/
public function destroy() {
this.webSocket.close();
}
From 4a8af03d15e36300f4eb8e8cc96077310a5def62 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 15:42:57 -0700
Subject: [PATCH 03/26] Added the WebSockets and made `internet` lib
Hi you Auto Action Download users!
I can make your text red
pretty cool right?
Human... I remember your Commit History
---
.../funkin/backend/internet/WebSocketUtil.hx | 48 ++++++++++---------
1 file changed, 26 insertions(+), 22 deletions(-)
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/internet/WebSocketUtil.hx
index b92fc8cd0..bcb054c5d 100644
--- a/source/funkin/backend/internet/WebSocketUtil.hx
+++ b/source/funkin/backend/internet/WebSocketUtil.hx
@@ -1,7 +1,5 @@
package funkin.backend.internet;
-import haxe.io.Bytes;
-
import hx.ws.*;
import funkin.backend.system.Logs;
@@ -48,7 +46,17 @@ class WebSocketUtil implements IFlxDestroyable {
/**
* Runs whenever the WebSocket encounters an error.
**/
- public var onError:Dynamic->Void = (error)->{};
+ public var onError(default, set):Dynamic->Void = (error)->{};
+ private function set_onError(_errorFunc):Dynamic->Void {
+ var func = (error)->{
+ Logs.traceColored([
+ Logs.logText("[WebSocket Error] ", RED),
+ Logs.logText('${error}'),
+ ], ERROR);
+ if (_errorFunc != null) _errorFunc(error);
+ };
+ return this.onError = func;
+ }
@:dox(hide) private var url:String;
@:dox(hide) private var webSocket:WebSocket;
@@ -60,16 +68,16 @@ class WebSocketUtil implements IFlxDestroyable {
**/
public function new(url:String, ?onOpen:WebSocket->Void, ?immediateOpen:Bool = false) {
this.onOpen = (onOpen == null) ? this.onOpen : onOpen;
+ this.onError = this.onError;
this.url = url;
this.webSocket = new WebSocket(this.url, false);
- // TODO: make trace print colors with `Logs.hx`
this.webSocket.onopen = function() {
try {
this.onOpen(webSocket);
- } catch(e) {
- trace('Error: ${e}');
+ } catch(error) {
+ this.onError(error);
}
};
@@ -84,7 +92,7 @@ class WebSocketUtil implements IFlxDestroyable {
}
this.onMessage(data);
} catch(e) {
- trace('Error: ${e}');
+ this.onError(e);
}
};
@@ -92,32 +100,26 @@ class WebSocketUtil implements IFlxDestroyable {
try {
this.onClose();
} catch(e) {
- trace('Error: ${e}');
+ this.onError(e);
}
};
- this.webSocket.onerror = function(error) {
- trace('Websocket error: ${error}');
- try {
- this.onError(error);
- } catch(e) {
- trace('Error: ${e}');
- }
- };
+ this.webSocket.onerror = this.onError;
if (immediateOpen) this.open();
- return this;
}
/**
* Opens the WebSocket.
**/
public function open() {
- trace('[Connection Status] Connecting to ${this.url}');
+ Logs.traceColored([
+ Logs.logText("[WebSocket Connection] ", BLUE),
+ Logs.logText('Connecting to ${this.url}'),
+ ], INFO);
try {
this.webSocket.open();
} catch(e) {
- trace("Failed to open websocket: " + e);
this.onError(e);
}
}
@@ -126,11 +128,14 @@ class WebSocketUtil implements IFlxDestroyable {
* Closes the WebSocket.
**/
public function close() {
- trace('[Connection Status] Closing connection to ${this.url}');
+ Logs.traceColored([
+ Logs.logText("[WebSocket Connection] ", BLUE),
+ Logs.logText('Closing connection to ${this.url}'),
+ ], INFO);
try {
this.webSocket.close();
} catch(e) {
- trace("Failed to close websocket: " + e);
+ this.onError(e);
}
}
@@ -141,7 +146,6 @@ class WebSocketUtil implements IFlxDestroyable {
try {
this.webSocket.send(data);
} catch(e) {
- trace("Failed to send data to websocket: " + e);
this.onError(e);
}
}
From ddf1a48c2d04e98cb7746ad428dd9d4ed0666c37 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 15:49:25 -0700
Subject: [PATCH 04/26] added "hx.ws" as an import (wont work neo but ok)
---
source/funkin/backend/system/macros/Macros.hx | 3 +++
1 file changed, 3 insertions(+)
diff --git a/source/funkin/backend/system/macros/Macros.hx b/source/funkin/backend/system/macros/Macros.hx
index dc56c359c..73beaeb3d 100644
--- a/source/funkin/backend/system/macros/Macros.hx
+++ b/source/funkin/backend/system/macros/Macros.hx
@@ -22,6 +22,9 @@ class Macros {
#if THREE_D_SUPPORT "away3d", "flx3d", #end
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
+ // hxWebSocket
+ "hx.ws",
+
// BASE HAXE
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting",
])
From 294fe6bb4ea42c39ef873fa366501e5a7d4e878f Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 15:50:51 -0700
Subject: [PATCH 05/26] fixed indentation
---
.../funkin/backend/internet/WebSocketUtil.hx | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/internet/WebSocketUtil.hx
index bcb054c5d..29aefc83a 100644
--- a/source/funkin/backend/internet/WebSocketUtil.hx
+++ b/source/funkin/backend/internet/WebSocketUtil.hx
@@ -66,22 +66,22 @@ class WebSocketUtil implements IFlxDestroyable {
* @param onOpen sets the `onOpen` function directly to the class.
* @param immediateOpen If true, the WebSocket will open immediately. Hence why `onOpen` is a function in the parameters.
**/
- public function new(url:String, ?onOpen:WebSocket->Void, ?immediateOpen:Bool = false) {
+ public function new(url:String, ?onOpen:WebSocket->Void, ?immediateOpen:Bool = false) {
this.onOpen = (onOpen == null) ? this.onOpen : onOpen;
this.onError = this.onError;
this.url = url;
this.webSocket = new WebSocket(this.url, false);
- this.webSocket.onopen = function() {
+ this.webSocket.onopen = function() {
try {
this.onOpen(webSocket);
} catch(error) {
this.onError(error);
}
- };
+ };
- this.webSocket.onmessage = function(message) {
+ this.webSocket.onmessage = function(message) {
var data:Dynamic = null;
try {
switch(message) {
@@ -94,20 +94,20 @@ class WebSocketUtil implements IFlxDestroyable {
} catch(e) {
this.onError(e);
}
- };
+ };
- this.webSocket.onclose = function() {
+ this.webSocket.onclose = function() {
try {
this.onClose();
} catch(e) {
this.onError(e);
}
- };
+ };
- this.webSocket.onerror = this.onError;
+ this.webSocket.onerror = this.onError;
if (immediateOpen) this.open();
- }
+ }
/**
* Opens the WebSocket.
@@ -156,5 +156,4 @@ class WebSocketUtil implements IFlxDestroyable {
public function destroy() {
this.webSocket.close();
}
-}
-
+}
\ No newline at end of file
From f1e8d9754494bdb7ad416c13581e6bc1e31459e3 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 16:42:23 -0700
Subject: [PATCH 06/26] Fixed some issues
---
source/funkin/backend/internet/WebSocketUtil.hx | 7 +++++++
source/funkin/backend/system/macros/Macros.hx | 4 +---
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/internet/WebSocketUtil.hx
index 29aefc83a..f6a889335 100644
--- a/source/funkin/backend/internet/WebSocketUtil.hx
+++ b/source/funkin/backend/internet/WebSocketUtil.hx
@@ -4,6 +4,13 @@ import hx.ws.*;
import funkin.backend.system.Logs;
+/**
+* Basically a Utility for HScript to use WebSockets. Adds safeguards, error handling, and logging to debug your WebSockets.
+* ItsLJcool wanted to make CodenameEngine Online / Multiplayer. This will make it easier to do so.
+*
+* This does NOT support making a Server Side WebSocket. Its only for Client Side WebSockets. If you want to make a Server you need to that yourself.
+* I'd suggest using JavaScript for it. Though any program will do.
+**/
class WebSocketUtil implements IFlxDestroyable {
/**
* Used for the `toggleLogging` function. this is more of a data handler for the function.
diff --git a/source/funkin/backend/system/macros/Macros.hx b/source/funkin/backend/system/macros/Macros.hx
index 73beaeb3d..b8e6fc6c2 100644
--- a/source/funkin/backend/system/macros/Macros.hx
+++ b/source/funkin/backend/system/macros/Macros.hx
@@ -22,9 +22,6 @@ class Macros {
#if THREE_D_SUPPORT "away3d", "flx3d", #end
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
- // hxWebSocket
- "hx.ws",
-
// BASE HAXE
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting",
])
@@ -44,6 +41,7 @@ class Macros {
}
Compiler.include("funkin", [#if !UPDATE_CHECKING 'funkin.backend.system.updating' #end]);
+ // Compiler.include("hx.ws", [#if !UPDATE_CHECKING 'cs.system.net.sockets' #end]); // idk what im doing neo
}
public static function initMacros() {
From 62f1569caf79d53f6128b901259f8850e2d58bc7 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 19:49:26 -0700
Subject: [PATCH 07/26] Added `WebSocketPacket` to be used with
`WebSocketUtil`.
Srt was the person behind hanlding the data when we did Codename Engine Multiplayer Test.
---
.../backend/internet/WebSocketPacket.hx | 107 ++++++++++++++++++
.../funkin/backend/internet/WebSocketUtil.hx | 7 +-
2 files changed, 111 insertions(+), 3 deletions(-)
create mode 100644 source/funkin/backend/internet/WebSocketPacket.hx
diff --git a/source/funkin/backend/internet/WebSocketPacket.hx b/source/funkin/backend/internet/WebSocketPacket.hx
new file mode 100644
index 000000000..52dade846
--- /dev/null
+++ b/source/funkin/backend/internet/WebSocketPacket.hx
@@ -0,0 +1,107 @@
+package funkin.backend.internet;
+
+import String;
+import StringBuf;
+import Reflect;
+
+/**
+* A data object that can be customized for `WebSocketUtil` to send data to the server.
+* Srt was the person that made the data idea with first version of Codename Engine Multiplayer Test.
+*
+* Here is an example of how the default packet looks like:
+* `value::ENDPACKET>`
+*
+* On the server side its considered as a string so you can use splits to get the data.
+**/
+class WebSocketPacket {
+
+ /**
+ * The starting prefix of the packet.
+ **/
+ static var startPrefix(default, set):String = "";
+ private static function set_endPrefix(value:String):String { return value.trim(); }
+
+ /**
+ * The pointer to the value.
+ * Default example:
+ * `key=>value`
+ **/
+ static var dataPointer(default, set):String = "=>";
+ private static function set_dataPointer(value:String):String { return value.trim(); }
+
+ /**
+ * Splits the packet from key / values.
+ * Default example:
+ * `key=>value::key2=>value2`
+ **/
+ static var dataSplit(default, set):String = "::";
+ private static function set_dataSplit(value:String):String { return value.trim(); }
+
+ /**
+ * Just normal json data that is being held for the packet to stringify.
+ **/
+ private var packetData:Dynamic = {};
+
+ /**
+ * The name of the event the server handles.
+ * If null it won't be added in the packet.
+ **/
+ public var packetEventName:String;
+
+ /**
+ * @param packetName The name of the event the server handles.
+ * @param packetData The data that is being sent to the server. Can also be a stringified JSON.
+ **/
+ public function new(packetName:Null, packetData:Dynamic) {
+ this.packetEventName = (packetName == null) ? "" : packetName;
+
+ if (packetData is String) packetData = haxe.Json.parse(packetData);
+ this.packetData = packetData;
+ }
+
+ /**
+ * Checks if the packet has the field.
+ * @param field The field to check for
+ * @return If the packet has the field.
+ **/
+ public function exists(field:String):Bool {
+ return Reflect.hasField(this.packetData, field);
+ }
+
+ /**
+ * Gets the packet field.
+ * @param field The field to get the value.
+ * @return the value of the field.
+ **/
+ public function get(field:String):Dynamic {
+ return Reflect.field(this.packetData, field);
+ }
+
+ /**
+ * Sets a value to the packet.
+ * @param field The field to get the value.
+ * @param value The value to set.
+ * @return the packet data as a JSON structure.
+ **/
+ public function set(field:String, value:Dynamic) {
+ Reflect.setField(this.packetData, field, value);
+ return this.packetData;
+ }
+
+ /**
+ * Converts the packet to a string.
+ * @return The packet as a string.
+ **/
+ public function toString():String {
+ var data:StringBuf = new StringBuf();
+ if (WebSocketPacket.startPrefix != "" && this.packetEventName != "") data.add('${WebSocketPacket.startPrefix}${WebSocketPacket.dataSplit}${this.packetEventName}');
+ for (field in Reflect.fields(this.packetData)) data.add('${WebSocketPacket.dataSplit}${field}${WebSocketPacket.dataPointer}${Reflect.getProperty(this.packetData, field)}');
+ if (WebSocketPacket.endPrefix != "") data.add('${WebSocketPacket.dataSplit}${WebSocketPacket.endPrefix}');
+ return data.toString();
+ }
+}
\ No newline at end of file
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/internet/WebSocketUtil.hx
index f6a889335..abe905910 100644
--- a/source/funkin/backend/internet/WebSocketUtil.hx
+++ b/source/funkin/backend/internet/WebSocketUtil.hx
@@ -37,7 +37,7 @@ class WebSocketUtil implements IFlxDestroyable {
* Function calls after the WebSocket has been opened.
* @param webSocket Returns the instance of the WebSocket.
**/
- public var onOpen:WebSocket->Void = (webSocket)->{};
+ public var onOpen:WebSocketUtil->Void = (webSocket)->{};
/**
* Whenever the WebSocket receives a message sent from the server.
@@ -73,7 +73,7 @@ class WebSocketUtil implements IFlxDestroyable {
* @param onOpen sets the `onOpen` function directly to the class.
* @param immediateOpen If true, the WebSocket will open immediately. Hence why `onOpen` is a function in the parameters.
**/
- public function new(url:String, ?onOpen:WebSocket->Void, ?immediateOpen:Bool = false) {
+ public function new(url:String, ?onOpen:WebSocketUtil->Void, ?immediateOpen:Bool = false) {
this.onOpen = (onOpen == null) ? this.onOpen : onOpen;
this.onError = this.onError;
@@ -82,7 +82,7 @@ class WebSocketUtil implements IFlxDestroyable {
this.webSocket.onopen = function() {
try {
- this.onOpen(webSocket);
+ this.onOpen(this);
} catch(error) {
this.onError(error);
}
@@ -150,6 +150,7 @@ class WebSocketUtil implements IFlxDestroyable {
* Sends data to the server
**/
public function send(data) {
+ if (data is WebSocketPacket) data = data.toString();
try {
this.webSocket.send(data);
} catch(e) {
From 50aeecd7d8e0521fb27484bd243521ad42158bd6 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 4 Jan 2025 21:39:18 -0700
Subject: [PATCH 08/26] clarification
---
source/funkin/backend/internet/WebSocketUtil.hx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/internet/WebSocketUtil.hx
index abe905910..5bcb4d2c6 100644
--- a/source/funkin/backend/internet/WebSocketUtil.hx
+++ b/source/funkin/backend/internet/WebSocketUtil.hx
@@ -6,6 +6,7 @@ import funkin.backend.system.Logs;
/**
* Basically a Utility for HScript to use WebSockets. Adds safeguards, error handling, and logging to debug your WebSockets.
+* YOU WILL NEED TO HANDLE HOW THE WEBSOCKETS ARE CLOSED!!! calling `destroy` will close the WebSocket.
* ItsLJcool wanted to make CodenameEngine Online / Multiplayer. This will make it easier to do so.
*
* This does NOT support making a Server Side WebSocket. Its only for Client Side WebSockets. If you want to make a Server you need to that yourself.
@@ -162,6 +163,6 @@ class WebSocketUtil implements IFlxDestroyable {
* Closes the WebSocket and destroys the class instance.
**/
public function destroy() {
- this.webSocket.close();
+ this.close();
}
}
\ No newline at end of file
From 23b4f595d061f08685d80a93ae6ec9e2afbce94f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=8D=9A=7ENex?=
<87421482+NexIsDumb@users.noreply.github.com>
Date: Sun, 5 Jan 2025 20:44:46 +0100
Subject: [PATCH 09/26] allow scripting the entire raw websocket api
---
libs.xml | 4 +---
source/funkin/backend/system/macros/Macros.hx | 2 +-
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/libs.xml b/libs.xml
index a443dfa3a..673982bca 100644
--- a/libs.xml
+++ b/libs.xml
@@ -4,9 +4,6 @@
-
-
-
@@ -16,6 +13,7 @@
+
diff --git a/source/funkin/backend/system/macros/Macros.hx b/source/funkin/backend/system/macros/Macros.hx
index b8e6fc6c2..6d95a5c48 100644
--- a/source/funkin/backend/system/macros/Macros.hx
+++ b/source/funkin/backend/system/macros/Macros.hx
@@ -40,8 +40,8 @@ class Macros {
}
}
+ Compiler.include("hx.ws", ["hx.ws.cs", "hx.ws.java", "hx.ws.nodejs"]);
Compiler.include("funkin", [#if !UPDATE_CHECKING 'funkin.backend.system.updating' #end]);
- // Compiler.include("hx.ws", [#if !UPDATE_CHECKING 'cs.system.net.sockets' #end]); // idk what im doing neo
}
public static function initMacros() {
From 4714cbf509af155e8f044eed8c92cc334b391baa Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sun, 5 Jan 2025 12:52:27 -0700
Subject: [PATCH 10/26] reformatted the `WebSocketPacket` to use `Serializer`
instead of a long string.
Also added Meta Data to the packet (can be disabled as a 3rd param)
---
.../backend/internet/WebSocketPacket.hx | 101 ++++++++++--------
1 file changed, 57 insertions(+), 44 deletions(-)
diff --git a/source/funkin/backend/internet/WebSocketPacket.hx b/source/funkin/backend/internet/WebSocketPacket.hx
index 52dade846..3c3884f13 100644
--- a/source/funkin/backend/internet/WebSocketPacket.hx
+++ b/source/funkin/backend/internet/WebSocketPacket.hx
@@ -1,49 +1,27 @@
package funkin.backend.internet;
-import String;
+import funkin.backend.assets.ModsFolder;
+import funkin.backend.system.macros.GitCommitMacro;
+
+import haxe.Serializer;
+
+import Date;
import StringBuf;
+import String;
import Reflect;
/**
* A data object that can be customized for `WebSocketUtil` to send data to the server.
-* Srt was the person that made the data idea with first version of Codename Engine Multiplayer Test.
+* You will need to handle the custom packet on your server yourself.
*
-* Here is an example of how the default packet looks like:
-* `value::ENDPACKET>`
+* GENERAL WEBSOCKET WARNING: Sending data to the server on `update` SHOULD NEVER BE DONE!!
+* It will be slow and generally not a good idea. It might overload the server and cause unforseen issues.
*
-* On the server side its considered as a string so you can use splits to get the data.
+* Why use a packet class instead of sending your own data? Well this Serializes the data and handles it for you, so all you do is just send the class in the `WebSocketUtil.send` and thats it.
**/
class WebSocketPacket {
-
- /**
- * The starting prefix of the packet.
- **/
- static var startPrefix(default, set):String = "";
- private static function set_endPrefix(value:String):String { return value.trim(); }
-
- /**
- * The pointer to the value.
- * Default example:
- * `key=>value`
- **/
- static var dataPointer(default, set):String = "=>";
- private static function set_dataPointer(value:String):String { return value.trim(); }
-
- /**
- * Splits the packet from key / values.
- * Default example:
- * `key=>value::key2=>value2`
- **/
- static var dataSplit(default, set):String = "::";
- private static function set_dataSplit(value:String):String { return value.trim(); }
-
/**
- * Just normal json data that is being held for the packet to stringify.
+ * Just normal data that is being held for the packet to get stringified.
**/
private var packetData:Dynamic = {};
@@ -51,17 +29,41 @@ class WebSocketPacket {
* The name of the event the server handles.
* If null it won't be added in the packet.
**/
- public var packetEventName:String;
+ public var packetEventName(default, set):String;
+ private function set_packetEventName(value:String):String {
+ if (value == null) return "";
+ return this.packetEventName = value;
+ }
+
+ @:dox(hide) private var add_meta_data:Bool = true;
/**
* @param packetName The name of the event the server handles.
* @param packetData The data that is being sent to the server. Can also be a stringified JSON.
+ * @param add_meta_data If true, adds metadata to the packet. This is useful for data like the time it was sent,
**/
- public function new(packetName:Null, packetData:Dynamic) {
- this.packetEventName = (packetName == null) ? "" : packetName;
+ public function new(packetName:Null, packetData:Dynamic, ?_add_meta_data:Bool = true) {
+ this.packetEventName = packetName;
+ this.add_meta_data = _add_meta_data;
- if (packetData is String) packetData = haxe.Json.parse(packetData);
+ // in case ig
+ try {
+ if (packetData is String) packetData = haxe.Json.parse(packetData);
+ } catch (e:Dynamic) {
+ trace("Error parsing string data to packet: " + e);
+ }
+
this.packetData = packetData;
+
+ if (this.add_meta_data) {
+ try {
+ if (ModsFolder.currentModFolder != null) this.packetData.__mod = ModsFolder.currentModFolder;
+ this.packetData.__commitHash = GitCommitMacro.commitHash; // for checking outdated action builds on the server. its gonna be peak trust.
+ } catch (e:Dynamic) {
+ trace("Error adding metadata to packet: " + e);
+ }
+ }
+
}
/**
@@ -94,14 +96,25 @@ class WebSocketPacket {
}
/**
- * Converts the packet to a string.
+ * Converts the packet to a string. Uses `Serializer` to convert the packet to a data string
* @return The packet as a string.
**/
public function toString():String {
- var data:StringBuf = new StringBuf();
- if (WebSocketPacket.startPrefix != "" && this.packetEventName != "") data.add('${WebSocketPacket.startPrefix}${WebSocketPacket.dataSplit}${this.packetEventName}');
- for (field in Reflect.fields(this.packetData)) data.add('${WebSocketPacket.dataSplit}${field}${WebSocketPacket.dataPointer}${Reflect.getProperty(this.packetData, field)}');
- if (WebSocketPacket.endPrefix != "") data.add('${WebSocketPacket.dataSplit}${WebSocketPacket.endPrefix}');
- return data.toString();
+ var cerial = new Serializer();
+ var buffer = new StringBuf();
+
+ // if no name is associated with packet, just serialize the data
+ if (packetEventName != "") {
+ buffer.add('!HXP');
+ buffer.add(this.packetEventName);
+ } else {
+ buffer.add('!HXp');
+ }
+ buffer.add('=>');
+
+ if (add_meta_data) this.packetData.__timestamp = Date.now().getTime();
+
+ cerial.serialize(this.packetData);
+ return '${buffer.toString()}${cerial.toString()}';
}
}
\ No newline at end of file
From 8c8f5320d77228ff63c9dac7d5287af756885291 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=8D=9A=7ENex?=
<87421482+NexIsDumb@users.noreply.github.com>
Date: Sun, 5 Jan 2025 20:56:26 +0100
Subject: [PATCH 11/26] moving to .system.net instead of .internet
so its all together with also yosh's socket
(important to remember that socket and websocket are two different things though)
---
.../{internet => system/net}/WebSocketPacket.hx | 8 ++++----
.../{internet => system/net}/WebSocketUtil.hx | 14 +++++++-------
2 files changed, 11 insertions(+), 11 deletions(-)
rename source/funkin/backend/{internet => system/net}/WebSocketPacket.hx (98%)
rename source/funkin/backend/{internet => system/net}/WebSocketUtil.hx (98%)
diff --git a/source/funkin/backend/internet/WebSocketPacket.hx b/source/funkin/backend/system/net/WebSocketPacket.hx
similarity index 98%
rename from source/funkin/backend/internet/WebSocketPacket.hx
rename to source/funkin/backend/system/net/WebSocketPacket.hx
index 3c3884f13..923d8ece8 100644
--- a/source/funkin/backend/internet/WebSocketPacket.hx
+++ b/source/funkin/backend/system/net/WebSocketPacket.hx
@@ -1,4 +1,4 @@
-package funkin.backend.internet;
+package funkin.backend.system.net;
import funkin.backend.assets.ModsFolder;
import funkin.backend.system.macros.GitCommitMacro;
@@ -24,7 +24,7 @@ class WebSocketPacket {
* Just normal data that is being held for the packet to get stringified.
**/
private var packetData:Dynamic = {};
-
+
/**
* The name of the event the server handles.
* If null it won't be added in the packet.
@@ -52,9 +52,9 @@ class WebSocketPacket {
} catch (e:Dynamic) {
trace("Error parsing string data to packet: " + e);
}
-
+
this.packetData = packetData;
-
+
if (this.add_meta_data) {
try {
if (ModsFolder.currentModFolder != null) this.packetData.__mod = ModsFolder.currentModFolder;
diff --git a/source/funkin/backend/internet/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
similarity index 98%
rename from source/funkin/backend/internet/WebSocketUtil.hx
rename to source/funkin/backend/system/net/WebSocketUtil.hx
index 5bcb4d2c6..d45d4ce7e 100644
--- a/source/funkin/backend/internet/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -1,4 +1,4 @@
-package funkin.backend.internet;
+package funkin.backend.system.net;
import hx.ws.*;
@@ -17,7 +17,7 @@ class WebSocketUtil implements IFlxDestroyable {
* Used for the `toggleLogging` function. this is more of a data handler for the function.
**/
static var loggingEnabled:Bool = false;
-
+
/**
* Call this function to toggle debugging for the WebSocket.
**/
@@ -39,18 +39,18 @@ class WebSocketUtil implements IFlxDestroyable {
* @param webSocket Returns the instance of the WebSocket.
**/
public var onOpen:WebSocketUtil->Void = (webSocket)->{};
-
+
/**
* Whenever the WebSocket receives a message sent from the server.
* @param message Returns the message sent from the server.
**/
public var onMessage:Dynamic->Void = (message)->{};
-
+
/**
* Runs whenever the WebSocket closes.
**/
public var onClose:Void->Void = ()->{};
-
+
/**
* Runs whenever the WebSocket encounters an error.
**/
@@ -68,7 +68,7 @@ class WebSocketUtil implements IFlxDestroyable {
@:dox(hide) private var url:String;
@:dox(hide) private var webSocket:WebSocket;
-
+
/**
* @param url The URL of the WebSocket. Usually `ws://localhost:port`.
* @param onOpen sets the `onOpen` function directly to the class.
@@ -113,7 +113,7 @@ class WebSocketUtil implements IFlxDestroyable {
};
this.webSocket.onerror = this.onError;
-
+
if (immediateOpen) this.open();
}
From bc44bbe8a6b0065381538310b1eddb96d4f14436 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sun, 5 Jan 2025 13:08:00 -0700
Subject: [PATCH 12/26] "The => should only be in the not empty part" - Neo
2025
---
source/funkin/backend/system/net/WebSocketPacket.hx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/funkin/backend/system/net/WebSocketPacket.hx b/source/funkin/backend/system/net/WebSocketPacket.hx
index 923d8ece8..07910a5db 100644
--- a/source/funkin/backend/system/net/WebSocketPacket.hx
+++ b/source/funkin/backend/system/net/WebSocketPacket.hx
@@ -107,10 +107,10 @@ class WebSocketPacket {
if (packetEventName != "") {
buffer.add('!HXP');
buffer.add(this.packetEventName);
+ buffer.add('=>');
} else {
buffer.add('!HXp');
}
- buffer.add('=>');
if (add_meta_data) this.packetData.__timestamp = Date.now().getTime();
From 13d5ab77e8a21dde28bcf10c650dea143a86bc87 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sun, 5 Jan 2025 19:48:20 -0700
Subject: [PATCH 13/26] Added Discord Meta Data (Username, Global name and
Premium Type only)
---
source/funkin/backend/system/net/WebSocketPacket.hx | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/source/funkin/backend/system/net/WebSocketPacket.hx b/source/funkin/backend/system/net/WebSocketPacket.hx
index 07910a5db..8eb91117a 100644
--- a/source/funkin/backend/system/net/WebSocketPacket.hx
+++ b/source/funkin/backend/system/net/WebSocketPacket.hx
@@ -2,6 +2,7 @@ package funkin.backend.system.net;
import funkin.backend.assets.ModsFolder;
import funkin.backend.system.macros.GitCommitMacro;
+import funkin.backend.utils.DiscordUtil;
import haxe.Serializer;
@@ -59,6 +60,11 @@ class WebSocketPacket {
try {
if (ModsFolder.currentModFolder != null) this.packetData.__mod = ModsFolder.currentModFolder;
this.packetData.__commitHash = GitCommitMacro.commitHash; // for checking outdated action builds on the server. its gonna be peak trust.
+ this.packetData.__discord = {
+ username: DiscordUtil.user.username,
+ globalName: DiscordUtil.user.globalName,
+ premiumType: DiscordUtil.user.premiumType,
+ };
} catch (e:Dynamic) {
trace("Error adding metadata to packet: " + e);
}
@@ -112,7 +118,7 @@ class WebSocketPacket {
buffer.add('!HXp');
}
- if (add_meta_data) this.packetData.__timestamp = Date.now().getTime();
+ if (add_meta_data) this.packetData.__timestamp = Date.now();
cerial.serialize(this.packetData);
return '${buffer.toString()}${cerial.toString()}';
From a6fad0abc5b5d40af561cace99c06fc9c80e1d54 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sun, 5 Jan 2025 21:54:46 -0700
Subject: [PATCH 14/26] updated `WebSocketPacket` to actually you know do its
job and not crash under cases
---
.../backend/system/net/WebSocketPacket.hx | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketPacket.hx b/source/funkin/backend/system/net/WebSocketPacket.hx
index 8eb91117a..f4b4fdb16 100644
--- a/source/funkin/backend/system/net/WebSocketPacket.hx
+++ b/source/funkin/backend/system/net/WebSocketPacket.hx
@@ -9,7 +9,7 @@ import haxe.Serializer;
import Date;
import StringBuf;
import String;
-import Reflect;
+import Type;
/**
* A data object that can be customized for `WebSocketUtil` to send data to the server.
@@ -24,15 +24,20 @@ class WebSocketPacket {
/**
* Just normal data that is being held for the packet to get stringified.
**/
- private var packetData:Dynamic = {};
+ private var packetData(default, set):Dynamic = {};
+ private function set_packetData(value:Dynamic):Dynamic {
+ if (value == null) return {};
+ if (value is String) value = haxe.Json.parse(value);
+ return this.packetData = value;
+ }
/**
* The name of the event the server handles.
* If null it won't be added in the packet.
**/
public var packetEventName(default, set):String;
- private function set_packetEventName(value:String):String {
- if (value == null) return "";
+ private function set_packetEventName(value:Null):String {
+ if (value == null) return this.packetEventName = "";
return this.packetEventName = value;
}
@@ -43,17 +48,10 @@ class WebSocketPacket {
* @param packetData The data that is being sent to the server. Can also be a stringified JSON.
* @param add_meta_data If true, adds metadata to the packet. This is useful for data like the time it was sent,
**/
- public function new(packetName:Null, packetData:Dynamic, ?_add_meta_data:Bool = true) {
+ public function new(packetName:Null, ?packetData:Null, ?_add_meta_data:Bool = true) {
this.packetEventName = packetName;
this.add_meta_data = _add_meta_data;
- // in case ig
- try {
- if (packetData is String) packetData = haxe.Json.parse(packetData);
- } catch (e:Dynamic) {
- trace("Error parsing string data to packet: " + e);
- }
-
this.packetData = packetData;
if (this.add_meta_data) {
@@ -106,11 +104,11 @@ class WebSocketPacket {
* @return The packet as a string.
**/
public function toString():String {
- var cerial = new Serializer();
var buffer = new StringBuf();
// if no name is associated with packet, just serialize the data
- if (packetEventName != "") {
+ trace("this.packetEventName.trim(): " + this.packetEventName.trim());
+ if (this.packetEventName.trim() != "") {
buffer.add('!HXP');
buffer.add(this.packetEventName);
buffer.add('=>');
@@ -120,7 +118,8 @@ class WebSocketPacket {
if (add_meta_data) this.packetData.__timestamp = Date.now();
- cerial.serialize(this.packetData);
+ var cerial = new Serializer();
+ if (this.packetData != {}) cerial.serialize(this.packetData);
return '${buffer.toString()}${cerial.toString()}';
}
}
\ No newline at end of file
From 6237a6d27c5459b4d43b87928d969d691b0d1574 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sun, 5 Jan 2025 21:58:39 -0700
Subject: [PATCH 15/26] erm i forgor about a trace line
---
source/funkin/backend/system/net/WebSocketPacket.hx | 1 -
1 file changed, 1 deletion(-)
diff --git a/source/funkin/backend/system/net/WebSocketPacket.hx b/source/funkin/backend/system/net/WebSocketPacket.hx
index f4b4fdb16..da4fe71f2 100644
--- a/source/funkin/backend/system/net/WebSocketPacket.hx
+++ b/source/funkin/backend/system/net/WebSocketPacket.hx
@@ -107,7 +107,6 @@ class WebSocketPacket {
var buffer = new StringBuf();
// if no name is associated with packet, just serialize the data
- trace("this.packetEventName.trim(): " + this.packetEventName.trim());
if (this.packetEventName.trim() != "") {
buffer.add('!HXP');
buffer.add(this.packetEventName);
From 254e59e052d940d25b246ce7386fc9231f316e02 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Mon, 6 Jan 2025 18:39:35 -0700
Subject: [PATCH 16/26] No longer sends Discord Metadata if your not connected.
---
source/funkin/backend/system/net/WebSocketPacket.hx | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketPacket.hx b/source/funkin/backend/system/net/WebSocketPacket.hx
index da4fe71f2..e61c5b79c 100644
--- a/source/funkin/backend/system/net/WebSocketPacket.hx
+++ b/source/funkin/backend/system/net/WebSocketPacket.hx
@@ -58,11 +58,8 @@ class WebSocketPacket {
try {
if (ModsFolder.currentModFolder != null) this.packetData.__mod = ModsFolder.currentModFolder;
this.packetData.__commitHash = GitCommitMacro.commitHash; // for checking outdated action builds on the server. its gonna be peak trust.
- this.packetData.__discord = {
- username: DiscordUtil.user.username,
- globalName: DiscordUtil.user.globalName,
- premiumType: DiscordUtil.user.premiumType,
- };
+ // if Discord isn't active, dont send the metadata
+ if (DiscordUtil.ready) this.packetData.__discord = { username: DiscordUtil.user.username, globalName: DiscordUtil.user.globalName, premiumType: DiscordUtil.user.premiumType };
} catch (e:Dynamic) {
trace("Error adding metadata to packet: " + e);
}
From d52a350859546ab0f13122ae8f6974a21c9a218d Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Tue, 7 Jan 2025 20:31:39 -0700
Subject: [PATCH 17/26] Added `ServerPacketData`. Messages recieved by the
WebSocket will either parse it as a `ServerPacketData` if it can, if not it
will be a string.
Thanks to Neo for helping with that.
---
source/funkin/backend/system/MainState.hx | 4 ++
.../backend/system/net/WebSocketPacket.hx | 29 ++++++++
.../backend/system/net/WebSocketUtil.hx | 72 +++++++++++++++++++
3 files changed, 105 insertions(+)
diff --git a/source/funkin/backend/system/MainState.hx b/source/funkin/backend/system/MainState.hx
index a5011d6d6..1e787754e 100644
--- a/source/funkin/backend/system/MainState.hx
+++ b/source/funkin/backend/system/MainState.hx
@@ -8,6 +8,7 @@ import funkin.menus.TitleState;
import funkin.menus.BetaWarningState;
import funkin.backend.chart.EventsData;
import flixel.FlxState;
+import funkin.backend.system.net.WebSocketPacket;
/**
* Simple state used for loading the game
@@ -21,6 +22,9 @@ class MainState extends FlxState {
Main.loadGameSettings();
initiated = true;
+ // Resetting to default because I doubt any modding the engine will reset it lmao
+ WebSocketPacket.packetTypes = WebSocketPacket.default_packetTypes;
+
#if sys
CoolUtil.deleteFolder('./.temp/'); // delete temp folder
#end
diff --git a/source/funkin/backend/system/net/WebSocketPacket.hx b/source/funkin/backend/system/net/WebSocketPacket.hx
index e61c5b79c..f5d89da4a 100644
--- a/source/funkin/backend/system/net/WebSocketPacket.hx
+++ b/source/funkin/backend/system/net/WebSocketPacket.hx
@@ -21,6 +21,24 @@ import Type;
* Why use a packet class instead of sending your own data? Well this Serializes the data and handles it for you, so all you do is just send the class in the `WebSocketUtil.send` and thats it.
**/
class WebSocketPacket {
+
+ /**
+ * Packet Types that can be gathered from the server. Used by `WebSocketUtil`
+ * If your server doesn't use the Template ItsLJcool made, then you add your own here.
+ **/
+ public static var packetTypes:Map = [
+ "haxe" => {params: "!HXP", none: "!HXp"},
+ "javascript" => {params: "!JSP", none: "!JSp"},
+ "js" => {params: "!JSP", none: "!JSp"},
+ ];
+
+ @:dox(hide)
+ public static var default_packetTypes(default, never):Map = [
+ "haxe" => {params: "!HXP", none: "!HXp"},
+ "javascript" => {params: "!JSP", none: "!JSp"},
+ "js" => {params: "!JSP", none: "!JSp"},
+ ];
+
/**
* Just normal data that is being held for the packet to get stringified.
**/
@@ -118,4 +136,15 @@ class WebSocketPacket {
if (this.packetData != {}) cerial.serialize(this.packetData);
return '${buffer.toString()}${cerial.toString()}';
}
+
+ public static function isServerPacket(data:Dynamic):Bool {
+ if ((data is ServerPacketData)) return true;
+ return false;
+ }
+}
+
+@:structInit
+class ServerPacketData {
+ public var name:String;
+ public var data:Dynamic;
}
\ No newline at end of file
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index d45d4ce7e..ab2ff7fb4 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -2,7 +2,10 @@ package funkin.backend.system.net;
import hx.ws.*;
+import funkin.backend.system.net.WebSocketPacket.ServerPacketData;
import funkin.backend.system.Logs;
+import haxe.Unserializer;
+import Type;
/**
* Basically a Utility for HScript to use WebSockets. Adds safeguards, error handling, and logging to debug your WebSockets.
@@ -62,10 +65,16 @@ class WebSocketUtil implements IFlxDestroyable {
Logs.logText('${error}'),
], ERROR);
if (_errorFunc != null) _errorFunc(error);
+ if (this.closeOnError) this.close();
};
return this.onError = func;
}
+ /**
+ * If true, the WebSocket will close when an error occurs.
+ **/
+ public var closeOnError:Bool = true;
+
@:dox(hide) private var url:String;
@:dox(hide) private var webSocket:WebSocket;
@@ -95,6 +104,8 @@ class WebSocketUtil implements IFlxDestroyable {
switch(message) {
case StrMessage(str):
data = str;
+ var _data = this.attemptDeserialize(data);
+ if (WebSocketPacket.isServerPacket(_data)) data = _data;
case BytesMessage(bytes):
data = bytes;
}
@@ -117,6 +128,61 @@ class WebSocketUtil implements IFlxDestroyable {
if (immediateOpen) this.open();
}
+
+ /*
+ / javascript code for reference
+
+ toString() {
+ if (this.add_meta_data) this.data.__timestamp = Date.now();
+ var hasName = (this.name != null && this.name.trim() != "");
+ var start = (hasName) ? "!JSP"+this.name : "!JSp";
+ start += "=>";
+
+ var cerial = new Serializer();
+ cerial.serialize(this.data);
+
+ return start+cerial.toString();
+ }
+ */
+
+ /**
+ * @param rawData The raw data from the server
+ * @return The packet data if it was found, otherwise null and WebSocketUtil will handle it.
+ */
+ private function attemptDeserialize(rawData:String):Null {
+ if (!rawData.startsWith("!")) return null;
+
+ for (key=>value in WebSocketPacket.packetTypes) {
+ var hasPacketData = rawData.startsWith(value.params); // PREFIXname=>DATA
+ var hasPacketNone = rawData.startsWith(value.none); // PREFIX=>DATA
+
+ if (hasPacketNone) {
+ var data = rawData.substr(rawData.indexOf("=>") + 2);
+ var packetData:Dynamic = Unserializer.run(data);
+ if (packetData == null) packetData = {};
+ var packet:ServerPacketData = { name: null, data: packetData };
+ return packet;
+ }
+
+ if (!hasPacketData) continue;
+
+ try {
+ var data = rawData.substr(rawData.indexOf("=>") + 2);
+ var name = rawData.substring(value.params.length, rawData.indexOf("=>"));
+ var packetData:Dynamic = Unserializer.run(data);
+ if (packetData == null) packetData = {};
+ var packet:ServerPacketData = { name: name, data: packetData };
+ return packet;
+ } catch (e:Dynamic) {
+ trace('Error parsing packet: ${e}');
+ return null;
+ }
+ break;
+ }
+
+ return null;
+ }
+
/**
* Opens the WebSocket.
**/
@@ -140,8 +206,10 @@ class WebSocketUtil implements IFlxDestroyable {
Logs.logText("[WebSocket Connection] ", BLUE),
Logs.logText('Closing connection to ${this.url}'),
], INFO);
+
try {
this.webSocket.close();
+ this._isClosed = true;
} catch(e) {
this.onError(e);
}
@@ -159,10 +227,14 @@ class WebSocketUtil implements IFlxDestroyable {
}
}
+ private var _isClosed:Bool = false;
+
/**
* Closes the WebSocket and destroys the class instance.
**/
public function destroy() {
+ if (this._isClosed) return;
+
this.close();
}
}
\ No newline at end of file
From a5bb1fc5b3111dcbc9258018cab80c6057d43955 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Fri, 10 Jan 2025 01:16:16 -0700
Subject: [PATCH 18/26] `closeOnError` is default since you can handle your
errors by default.
Basically the Server Template is done, and so I think WebSocket's are ready to be put into CNE.
---
source/funkin/backend/system/net/WebSocketUtil.hx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index ab2ff7fb4..fb1f0c733 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -73,7 +73,7 @@ class WebSocketUtil implements IFlxDestroyable {
/**
* If true, the WebSocket will close when an error occurs.
**/
- public var closeOnError:Bool = true;
+ public var closeOnError:Bool = false;
@:dox(hide) private var url:String;
@:dox(hide) private var webSocket:WebSocket;
@@ -206,7 +206,7 @@ class WebSocketUtil implements IFlxDestroyable {
Logs.logText("[WebSocket Connection] ", BLUE),
Logs.logText('Closing connection to ${this.url}'),
], INFO);
-
+
try {
this.webSocket.close();
this._isClosed = true;
From a82d824b61cce6d04f9cbc4433469b3f82998df9 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Fri, 10 Jan 2025 18:37:51 -0700
Subject: [PATCH 19/26] Added Link in comments to Server Template
---
source/funkin/backend/system/net/WebSocketUtil.hx | 3 +++
1 file changed, 3 insertions(+)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index fb1f0c733..be07d34e4 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -14,6 +14,9 @@ import Type;
*
* This does NOT support making a Server Side WebSocket. Its only for Client Side WebSockets. If you want to make a Server you need to that yourself.
* I'd suggest using JavaScript for it. Though any program will do.
+*
+* Check out the WebSocket Server Template for Codename Engine here:
+* https://github.com/ItsLJcool/WebSocket-Server-Template-for-CNE
**/
class WebSocketUtil implements IFlxDestroyable {
/**
From a80578b984763a36f615ad3ca313001721cab7b2 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Fri, 10 Jan 2025 20:33:35 -0700
Subject: [PATCH 20/26] Connecting to WebSocket is now Async. Can be disabled.
---
.../backend/system/net/WebSocketUtil.hx | 26 +++++++++++++++----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index be07d34e4..2fe9d492c 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -80,6 +80,12 @@ class WebSocketUtil implements IFlxDestroyable {
@:dox(hide) private var url:String;
@:dox(hide) private var webSocket:WebSocket;
+
+ /**
+ * If true, when you call `open` the WebSocket will attempt to connect in a new thread.
+ * Usefull for trying to connect to a WebSocket Server whilst the game is running.
+ **/
+ public var _threadedConnection:Bool = true;
/**
* @param url The URL of the WebSocket. Usually `ws://localhost:port`.
@@ -194,11 +200,21 @@ class WebSocketUtil implements IFlxDestroyable {
Logs.logText("[WebSocket Connection] ", BLUE),
Logs.logText('Connecting to ${this.url}'),
], INFO);
- try {
- this.webSocket.open();
- } catch(e) {
- this.onError(e);
- }
+
+ var _func = () -> {
+ try {
+ this.webSocket.open();
+ } catch(e) {
+ this.onError(e);
+ return;
+ }
+ Logs.traceColored([
+ Logs.logText("[WebSocket Connection] ", YELLOW),
+ Logs.logText('Connected to ${this.url}'),
+ ], INFO);
+ };
+ if (_threadedConnection) Main.execAsync(_func);
+ else _func();
}
/**
From 3434bcdcb5d74f8f7d990f4cb5bd5ddce9fd4b88 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 11 Jan 2025 00:42:26 -0700
Subject: [PATCH 21/26] forgor about stuff, also added Threaded Packet Sending
(disabled by default)
---
.../backend/system/net/WebSocketUtil.hx | 40 ++++++++-----------
1 file changed, 17 insertions(+), 23 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index 2fe9d492c..e7f329a56 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -84,9 +84,16 @@ class WebSocketUtil implements IFlxDestroyable {
/**
* If true, when you call `open` the WebSocket will attempt to connect in a new thread.
* Usefull for trying to connect to a WebSocket Server whilst the game is running.
+ * WARNING: CAN CAUSE ERRORS IN HSCRIPT!!
**/
public var _threadedConnection:Bool = true;
+ /**
+ * If true, when you call `send` the WebSocket will attempt to send in a new thread.
+ * WARNING: CAN CAUSE ERRORS IN HSCRIPT!!
+ **/
+ public var _threadedSend:Bool = false;
+
/**
* @param url The URL of the WebSocket. Usually `ws://localhost:port`.
* @param onOpen sets the `onOpen` function directly to the class.
@@ -137,23 +144,6 @@ class WebSocketUtil implements IFlxDestroyable {
if (immediateOpen) this.open();
}
-
- /*
- / javascript code for reference
-
- toString() {
- if (this.add_meta_data) this.data.__timestamp = Date.now();
- var hasName = (this.name != null && this.name.trim() != "");
- var start = (hasName) ? "!JSP"+this.name : "!JSp";
- start += "=>";
-
- var cerial = new Serializer();
- cerial.serialize(this.data);
-
- return start+cerial.toString();
- }
- */
-
/**
* @param rawData The raw data from the server
* @return The packet data if it was found, otherwise null and WebSocketUtil will handle it.
@@ -238,12 +228,16 @@ class WebSocketUtil implements IFlxDestroyable {
* Sends data to the server
**/
public function send(data) {
- if (data is WebSocketPacket) data = data.toString();
- try {
- this.webSocket.send(data);
- } catch(e) {
- this.onError(e);
- }
+ var _func = () -> {
+ if (data is WebSocketPacket) data = data.toString();
+ try {
+ this.webSocket.send(data);
+ } catch(e) {
+ this.onError(e);
+ }
+ };
+ if (_threadedSend) Main.execAsync(_func);
+ else _func();
}
private var _isClosed:Bool = false;
From 7c480d2b4b7d8cdd4b88f8ca1a19482b2a2f1ab6 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 11 Jan 2025 00:43:29 -0700
Subject: [PATCH 22/26] oop
---
source/funkin/backend/system/net/WebSocketUtil.hx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index e7f329a56..715286b1f 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -203,7 +203,7 @@ class WebSocketUtil implements IFlxDestroyable {
Logs.logText('Connected to ${this.url}'),
], INFO);
};
- if (_threadedConnection) Main.execAsync(_func);
+ if (this._threadedConnection) Main.execAsync(_func);
else _func();
}
@@ -236,7 +236,7 @@ class WebSocketUtil implements IFlxDestroyable {
this.onError(e);
}
};
- if (_threadedSend) Main.execAsync(_func);
+ if (this._threadedSend) Main.execAsync(_func);
else _func();
}
From 13afcd1c4c185688216adc7da111e72cbfd04428 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 11 Jan 2025 04:56:50 -0700
Subject: [PATCH 23/26] I forgot the `onmessage` is being sent from a thread,
so updated the `_threadedSend`
---
source/funkin/backend/system/net/WebSocketUtil.hx | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index 715286b1f..a7fd7664d 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -5,7 +5,8 @@ import hx.ws.*;
import funkin.backend.system.net.WebSocketPacket.ServerPacketData;
import funkin.backend.system.Logs;
import haxe.Unserializer;
-import Type;
+
+import flixel.util.FlxTimer;
/**
* Basically a Utility for HScript to use WebSockets. Adds safeguards, error handling, and logging to debug your WebSockets.
@@ -236,8 +237,11 @@ class WebSocketUtil implements IFlxDestroyable {
this.onError(e);
}
};
- if (this._threadedSend) Main.execAsync(_func);
- else _func();
+ // because its already threaded.
+ if (this._threadedSend) _func();
+ else new FlxTimer().start(0.0001, (tmr:FlxTimer) -> {
+ _func();
+ });
}
private var _isClosed:Bool = false;
From ab0e1c96c5680966fbb614134730788a637acb34 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 11 Jan 2025 05:02:51 -0700
Subject: [PATCH 24/26] MORE!!!
---
source/funkin/backend/system/net/WebSocketUtil.hx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index a7fd7664d..62d021ecb 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -239,7 +239,7 @@ class WebSocketUtil implements IFlxDestroyable {
};
// because its already threaded.
if (this._threadedSend) _func();
- else new FlxTimer().start(0.0001, (tmr:FlxTimer) -> {
+ else new FlxTimer().start(0.01, (tmr:FlxTimer) -> {
_func();
});
}
From eecf1f39b8b3a5529a5e5cde67e7ad04df5c7036 Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sat, 11 Jan 2025 05:30:23 -0700
Subject: [PATCH 25/26] testing packet storing
---
.../backend/system/net/WebSocketUtil.hx | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index 62d021ecb..09ef27ee9 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -87,13 +87,15 @@ class WebSocketUtil implements IFlxDestroyable {
* Usefull for trying to connect to a WebSocket Server whilst the game is running.
* WARNING: CAN CAUSE ERRORS IN HSCRIPT!!
**/
- public var _threadedConnection:Bool = true;
+ public var _threadedConnection:Bool = false;
/**
* If true, when you call `send` the WebSocket will attempt to send in a new thread.
* WARNING: CAN CAUSE ERRORS IN HSCRIPT!!
**/
public var _threadedSend:Bool = false;
+
+ @:dox(hide) public var __packets:Array = [];
/**
* @param url The URL of the WebSocket. Usually `ws://localhost:port`.
@@ -130,6 +132,7 @@ class WebSocketUtil implements IFlxDestroyable {
} catch(e) {
this.onError(e);
}
+ __packets.push(data);
};
this.webSocket.onclose = function() {
@@ -145,6 +148,10 @@ class WebSocketUtil implements IFlxDestroyable {
if (immediateOpen) this.open();
}
+ public function getRecentPacket():Dynamic {
+ return __packets.shift();
+ }
+
/**
* @param rawData The raw data from the server
* @return The packet data if it was found, otherwise null and WebSocketUtil will handle it.
@@ -229,19 +236,12 @@ class WebSocketUtil implements IFlxDestroyable {
* Sends data to the server
**/
public function send(data) {
- var _func = () -> {
- if (data is WebSocketPacket) data = data.toString();
- try {
- this.webSocket.send(data);
- } catch(e) {
- this.onError(e);
- }
- };
- // because its already threaded.
- if (this._threadedSend) _func();
- else new FlxTimer().start(0.01, (tmr:FlxTimer) -> {
- _func();
- });
+ if (data is WebSocketPacket) data = data.toString();
+ try {
+ this.webSocket.send(data);
+ } catch(e) {
+ this.onError(e);
+ }
}
private var _isClosed:Bool = false;
From ce99c1c5fedc1849e81e78caaa11700fa268702b Mon Sep 17 00:00:00 2001
From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com>
Date: Sun, 12 Jan 2025 03:35:07 -0700
Subject: [PATCH 26/26] might fix compiling issue?
---
source/funkin/backend/system/net/WebSocketUtil.hx | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/source/funkin/backend/system/net/WebSocketUtil.hx b/source/funkin/backend/system/net/WebSocketUtil.hx
index 09ef27ee9..a9e564d7e 100644
--- a/source/funkin/backend/system/net/WebSocketUtil.hx
+++ b/source/funkin/backend/system/net/WebSocketUtil.hx
@@ -235,10 +235,12 @@ class WebSocketUtil implements IFlxDestroyable {
/**
* Sends data to the server
**/
- public function send(data) {
- if (data is WebSocketPacket) data = data.toString();
+ public function send(data) {
+ var _data = null;
+ if (data is WebSocketPacket) _data = data.toString();
+ else _data = data;
try {
- this.webSocket.send(data);
+ this.webSocket.send(_data);
} catch(e) {
this.onError(e);
}