mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
306 lines
6.4 KiB
Haxe
306 lines
6.4 KiB
Haxe
package net;
|
|
|
|
import gui.MessageBoxOkDlg;
|
|
import src.MarbleGame;
|
|
import haxe.Json;
|
|
import net.Net.ServerInfo;
|
|
import haxe.net.WebSocket;
|
|
import src.Console;
|
|
|
|
typedef RemoteServerInfo = {
|
|
name:String,
|
|
description:String,
|
|
players:Int,
|
|
maxPlayers:Int,
|
|
platform:Int,
|
|
version:String,
|
|
passworded:Bool
|
|
}
|
|
|
|
class MasterServerClient {
|
|
#if js
|
|
static var serverIp = "wss://mbomaster.randomityguy.me:8443";
|
|
#else
|
|
static var serverIp = "ws://89.58.58.191:8084";
|
|
#end
|
|
public static var instance:MasterServerClient;
|
|
|
|
var ws:WebSocket;
|
|
var serverListCb:Array<RemoteServerInfo>->Void;
|
|
|
|
var open = false;
|
|
|
|
static var wsToken:Int = 0;
|
|
|
|
#if hl
|
|
var wsThread:sys.thread.Thread;
|
|
|
|
static var responses:sys.thread.Deque<() -> Void> = new sys.thread.Deque<() -> Void>();
|
|
|
|
var toSend:sys.thread.Deque<String> = new sys.thread.Deque<String>();
|
|
var stopping:Bool = false;
|
|
var stopMutex:sys.thread.Mutex = new sys.thread.Mutex();
|
|
#end
|
|
|
|
public function new(onOpenFunc:() -> Void, onErrorFunc:() -> Void) {
|
|
#if hl
|
|
wsThread = sys.thread.Thread.create(() -> {
|
|
hl.Gc.enable(false);
|
|
hl.Gc.blocking(true); // Wtf is this shit
|
|
#end
|
|
wsToken++;
|
|
|
|
var myToken = wsToken;
|
|
|
|
ws = WebSocket.create(serverIp);
|
|
#if hl
|
|
hl.Gc.enable(true);
|
|
hl.Gc.blocking(false);
|
|
#end
|
|
ws.onopen = () -> {
|
|
open = true;
|
|
#if hl
|
|
responses.add(() -> onOpenFunc());
|
|
#end
|
|
#if js
|
|
onOpenFunc();
|
|
#end
|
|
}
|
|
ws.onmessageString = (m) -> {
|
|
#if hl
|
|
responses.add(() -> handleMessage(m));
|
|
#end
|
|
#if js
|
|
handleMessage(m);
|
|
#end
|
|
}
|
|
ws.onerror = (m) -> {
|
|
#if hl
|
|
responses.add(() -> {
|
|
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Failed to connect to master server: " + m));
|
|
});
|
|
if (onErrorFunc != null)
|
|
responses.add(() -> {
|
|
onErrorFunc();
|
|
});
|
|
#end
|
|
#if js
|
|
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Failed to connect to master server: " + m));
|
|
if (onErrorFunc != null)
|
|
onErrorFunc();
|
|
#end
|
|
#if hl
|
|
stopMutex.acquire();
|
|
#end
|
|
if (myToken == wsToken) {
|
|
open = false;
|
|
ws = null;
|
|
instance = null;
|
|
}
|
|
#if hl
|
|
stopMutex.acquire();
|
|
stopping = true;
|
|
stopMutex.release();
|
|
if (myToken == wsToken) {
|
|
wsThread = null;
|
|
}
|
|
#end
|
|
}
|
|
ws.onclose = (?e) -> {
|
|
#if hl
|
|
stopMutex.acquire();
|
|
#end
|
|
if (myToken == wsToken) {
|
|
open = false;
|
|
ws = null;
|
|
instance = null;
|
|
}
|
|
#if hl
|
|
stopping = true;
|
|
stopMutex.release();
|
|
if (myToken == wsToken) {
|
|
wsThread = null;
|
|
}
|
|
#end
|
|
}
|
|
#if hl
|
|
while (true) {
|
|
stopMutex.acquire();
|
|
if (stopping)
|
|
break;
|
|
while (true) {
|
|
var s = toSend.pop(false);
|
|
if (s == null)
|
|
break;
|
|
#if hl
|
|
hl.Gc.blocking(true);
|
|
#end
|
|
ws.sendString(s);
|
|
#if hl
|
|
hl.Gc.blocking(false);
|
|
#end
|
|
}
|
|
|
|
#if hl
|
|
hl.Gc.blocking(true);
|
|
#end
|
|
ws.process();
|
|
#if hl
|
|
hl.Gc.blocking(false);
|
|
#end
|
|
stopMutex.release();
|
|
Sys.sleep(0.1);
|
|
}
|
|
#end
|
|
#if hl
|
|
});
|
|
#end
|
|
}
|
|
|
|
public static function process() {
|
|
#if sys
|
|
var resp = responses.pop(false);
|
|
if (resp != null) {
|
|
resp();
|
|
}
|
|
#end
|
|
}
|
|
|
|
public static function connectToMasterServer(onConnect:() -> Void, onError:() -> Void = null) {
|
|
if (instance == null)
|
|
instance = new MasterServerClient(onConnect, onError);
|
|
else {
|
|
if (instance.open)
|
|
onConnect();
|
|
else {
|
|
if (instance != null && instance.ws != null)
|
|
instance.ws.close();
|
|
instance = new MasterServerClient(onConnect, onError);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function disconnectFromMasterServer() {
|
|
if (instance != null && instance.ws != null) {
|
|
instance.ws.close();
|
|
if (instance != null) {
|
|
instance.open = false;
|
|
instance.ws = null;
|
|
instance = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
function queueMessage(m:String) {
|
|
#if hl
|
|
toSend.add(m);
|
|
#end
|
|
#if js
|
|
ws.sendString(m);
|
|
#end
|
|
}
|
|
|
|
public function heartBeat() {
|
|
queueMessage(Json.stringify({
|
|
type: "heartbeat"
|
|
}));
|
|
}
|
|
|
|
public function sendServerInfo(serverInfo:ServerInfo) {
|
|
queueMessage(Json.stringify({
|
|
type: "serverInfo",
|
|
name: serverInfo.name,
|
|
description: serverInfo.description,
|
|
players: serverInfo.players,
|
|
maxPlayers: serverInfo.maxPlayers,
|
|
password: serverInfo.password,
|
|
state: serverInfo.state,
|
|
platform: serverInfo.platform,
|
|
version: "MBP" // MarbleGame.currentVersion
|
|
}));
|
|
}
|
|
|
|
public function sendConnectToServer(serverName:String, sdp:String, password:String) {
|
|
queueMessage(Json.stringify({
|
|
type: "connect",
|
|
serverName: serverName,
|
|
sdp: sdp,
|
|
password: password
|
|
}));
|
|
}
|
|
|
|
public function getServerList(serverListCb:Array<RemoteServerInfo>->Void) {
|
|
this.serverListCb = serverListCb;
|
|
queueMessage(Json.stringify({
|
|
type: "serverList"
|
|
}));
|
|
}
|
|
|
|
function handleMessage(message:String) {
|
|
var conts = Json.parse(message);
|
|
Console.log('Received ${conts.type}');
|
|
if (conts.type == "serverList") {
|
|
if (serverListCb != null) {
|
|
serverListCb(conts.servers);
|
|
}
|
|
}
|
|
if (conts.type == "connect") {
|
|
if (!Net.isHost) {
|
|
queueMessage(Json.stringify({
|
|
type: "connectFailed",
|
|
success: false,
|
|
reason: "The server has shut down"
|
|
}));
|
|
return;
|
|
}
|
|
var joiningPrivate = conts.isPrivate;
|
|
|
|
if (Net.serverInfo.players >= Net.serverInfo.maxPlayers) {
|
|
queueMessage(Json.stringify({
|
|
type: "connectFailed",
|
|
success: false,
|
|
reason: "The server is full"
|
|
}));
|
|
return;
|
|
}
|
|
|
|
var pubCount = 1; // Self
|
|
for (cid => cc in Net.clientIdMap) {
|
|
pubCount++;
|
|
}
|
|
|
|
if (!joiningPrivate && pubCount >= Net.serverInfo.maxPlayers) {
|
|
queueMessage(Json.stringify({
|
|
type: "connectFailed",
|
|
success: false,
|
|
reason: "The server is full"
|
|
}));
|
|
return;
|
|
}
|
|
|
|
Net.addClientFromSdp(conts.sdp, (sdpReply) -> {
|
|
queueMessage(Json.stringify({
|
|
success: true,
|
|
type: "connectResponse",
|
|
sdp: sdpReply,
|
|
clientId: conts.clientId
|
|
}));
|
|
});
|
|
}
|
|
if (conts.type == "connectResponse") {
|
|
Console.log("Remote Description Received!");
|
|
var sdpObj = Json.parse(conts.sdp);
|
|
if (@:privateAccess Net.client != null)
|
|
@:privateAccess Net.client.setRemoteDescription(sdpObj.sdp, sdpObj.type);
|
|
}
|
|
if (conts.type == "connectFailed") {
|
|
// var loadGui:MultiplayerLoadingGui = cast MarbleGame.canvas.content;
|
|
// if (loadGui != null) {
|
|
// loadGui.setErrorStatus(conts.reason);
|
|
// }
|
|
}
|
|
if (conts.type == "turnserver") {
|
|
Net.turnServer = conts.server; // Turn server!
|
|
}
|
|
}
|
|
}
|