server browser and joining logifwfdqd

This commit is contained in:
RandomityGuy 2024-03-02 01:33:50 +05:30
parent 251f4a6577
commit c3962091cd
7 changed files with 734 additions and 51 deletions

194
server/MasterServer.hx Normal file
View file

@ -0,0 +1,194 @@
import hx.ws.WebSocket;
import haxe.Json;
import hx.ws.SocketImpl;
import hx.ws.WebSocketHandler;
import hx.ws.WebSocketServer;
import hx.ws.State;
import hx.ws.Log;
import hx.ws.HttpHeader;
import hx.ws.HttpResponse;
import hx.ws.HttpRequest;
using Lambda;
@:publicFields
class ServerInfo {
var socket:SignallingHandler;
var name:String;
var players:Int;
var maxPlayers:Int;
var privateSlots:Int;
var privateServer:Bool;
var inviteCode:Int;
var state:String;
var platform:String;
public function new(socket:SignallingHandler, name:String, players:Int, maxPlayers:Int, privateSlots:Int, privateServer:Bool, inviteCode:Int,
state:String, platform:String) {
this.socket = socket;
this.name = name;
this.players = players;
this.maxPlayers = maxPlayers;
this.privateSlots = privateSlots;
this.privateServer = privateServer;
this.inviteCode = inviteCode;
this.state = state;
this.platform = platform;
}
}
class SignallingHandler extends WebSocketHandler {
static var clients:Array<SignallingHandler> = [];
static var servers:Array<ServerInfo> = [];
static var joiningClients:Map<Int, SignallingHandler> = [];
static var clientId = 0;
public override function handshake(httpRequest:HttpRequest) {
var httpResponse = new HttpResponse();
httpResponse.headers.set(HttpHeader.SEC_WEBSOSCKET_VERSION, "13");
httpResponse.headers.set("Access-Control-Allow-Origin", "*"); // Enable CORS pls, why do i have to override this entire function for a single line
if (httpRequest.method != "GET" || httpRequest.httpVersion != "HTTP/1.1") {
httpResponse.code = 400;
httpResponse.text = "Bad";
httpResponse.headers.set(HttpHeader.CONNECTION, "close");
httpResponse.headers.set(HttpHeader.X_WEBSOCKET_REJECT_REASON, 'Bad request');
} else if (httpRequest.headers.get(HttpHeader.SEC_WEBSOSCKET_VERSION) != "13") {
httpResponse.code = 426;
httpResponse.text = "Upgrade";
httpResponse.headers.set(HttpHeader.CONNECTION, "close");
httpResponse.headers.set(HttpHeader.X_WEBSOCKET_REJECT_REASON,
'Unsupported websocket client version: ${httpRequest.headers.get(HttpHeader.SEC_WEBSOSCKET_VERSION)}, Only version 13 is supported.');
} else if (httpRequest.headers.get(HttpHeader.UPGRADE) != "websocket") {
httpResponse.code = 426;
httpResponse.text = "Upgrade";
httpResponse.headers.set(HttpHeader.CONNECTION, "close");
httpResponse.headers.set(HttpHeader.X_WEBSOCKET_REJECT_REASON, 'Unsupported upgrade header: ${httpRequest.headers.get(HttpHeader.UPGRADE)}.');
} else if (httpRequest.headers.get(HttpHeader.CONNECTION).indexOf("Upgrade") == -1) {
httpResponse.code = 426;
httpResponse.text = "Upgrade";
httpResponse.headers.set(HttpHeader.CONNECTION, "close");
httpResponse.headers.set(HttpHeader.X_WEBSOCKET_REJECT_REASON, 'Unsupported connection header: ${httpRequest.headers.get(HttpHeader.CONNECTION)}.');
} else {
Log.debug('Handshaking', id);
var key = httpRequest.headers.get(HttpHeader.SEC_WEBSOCKET_KEY);
var result = makeWSKeyResponse(key);
Log.debug('Handshaking key - ${result}', id);
httpResponse.code = 101;
httpResponse.text = "Switching Protocols";
httpResponse.headers.set(HttpHeader.UPGRADE, "websocket");
httpResponse.headers.set(HttpHeader.CONNECTION, "Upgrade");
httpResponse.headers.set(HttpHeader.SEC_WEBSOSCKET_ACCEPT, result);
}
sendHttpResponse(httpResponse);
if (httpResponse.code == 101) {
_onopenCalled = false;
state = State.Head;
Log.debug('Connected', id);
} else {
close();
}
}
public function new(s:SocketImpl) {
super(s);
onopen = () -> {
clients.push(this);
}
onclose = () -> {
servers = servers.filter(x -> x.socket != this); // remove server
for (key => val in joiningClients) {
if (val == this) {
joiningClients.remove(key);
break;
}
}
clients.remove(this);
}
onmessage = (m) -> {
switch (m) {
case StrMessage(content):
var conts = Json.parse(content);
trace('Received ${conts.type}');
if (conts.type == "serverInfo") {
var serverInfo = new ServerInfo(this, conts.name, conts.players, conts.maxPlayers, conts.privateSlots, conts.privateServer,
conts.inviteCode, conts.state, conts.platform);
if (servers.find(x -> x.name == serverInfo.name) == null) {
servers.push(serverInfo);
} else {
servers = servers.filter(x -> x.socket != this);
servers.push(serverInfo); // update server
}
}
if (conts.type == "connect") {
var serverInfo = servers.find(x -> x.name == conts.serverName);
if (serverInfo != null) {
if (serverInfo.players >= serverInfo.maxPlayers) {
this.send(Json.stringify({
type: "connectFailed",
reason: "The server is full"
}));
} else {
var cid = clientId++;
joiningClients.set(cid, this);
serverInfo.socket.send(Json.stringify({
type: "connect",
sdp: conts.sdp,
clientId: cid
}));
}
} else {
this.send(Json.stringify({
type: "connectFailed",
reason: "Server not found"
}));
}
}
if (conts.type == "connectResponse") {
var client = joiningClients.get(conts.clientId);
if (client != null) {
var success = conts.success;
if (!success) {
client.send(Json.stringify({
type: "connectFailed",
reason: conts.reason
}));
} else {
client.send(Json.stringify({
type: "connectResponse",
sdp: conts.sdp
}));
}
}
}
if (conts.type == "serverList") {
this.send(Json.stringify({
type: "serverList",
servers: servers.filter(x -> !x.privateServer && x.state == "Lobby").map(x -> {
return {
name: x.name,
players: x.players,
maxPlayers: x.maxPlayers,
platform: x.platform
}
})
}));
}
case _: {}
}
}
}
}
class MasterServer {
static function main() {
var ws = new WebSocketServer<SignallingHandler>("0.0.0.0", 8080, 2);
ws.start();
}
}

4
server/build_master.hxml Normal file
View file

@ -0,0 +1,4 @@
--library hxWebSockets
--main MasterServer
-cp .
--hl bin/master.hl

121
src/gui/CreateMatchGui.hx Normal file
View file

@ -0,0 +1,121 @@
package gui;
import net.Net;
import src.MarbleGame;
import hxd.res.BitmapFont;
import h3d.Vector;
import src.ResourceLoader;
import src.Settings;
import src.Util;
class CreateMatchGui extends GuiImage {
var innerCtrl:GuiControl;
public function new() {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
var domcasual32b = new BitmapFont(domcasual32fontdata.entry);
@:privateAccess domcasual32b.loader = ResourceLoader.loader;
var domcasual32 = domcasual32b.toSdfFont(cast 42 * Settings.uiScale, MultiChannel);
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
this.extent = new Vector(640, 480);
#if hl
var scene2d = hxd.Window.getInstance();
#end
#if js
var scene2d = MarbleGame.instance.scene2d;
#end
var offsetX = (scene2d.width - 1280) / 2;
var offsetY = (scene2d.height - 720) / 2;
var subX = 640 - (scene2d.width - offsetX) * 640 / scene2d.width;
var subY = 480 - (scene2d.height - offsetY) * 480 / scene2d.height;
innerCtrl = new GuiControl();
innerCtrl.position = new Vector(offsetX, offsetY);
innerCtrl.extent = new Vector(640 - subX, 480 - subY);
innerCtrl.horizSizing = Width;
innerCtrl.vertSizing = Height;
this.addChild(innerCtrl);
var coliseumfontdata = ResourceLoader.getFileEntry("data/font/ColiseumRR.fnt");
var coliseumb = new BitmapFont(coliseumfontdata.entry);
@:privateAccess coliseumb.loader = ResourceLoader.loader;
var coliseum = coliseumb.toSdfFont(cast 44 * Settings.uiScale, MultiChannel);
var rootTitle = new GuiText(coliseum);
rootTitle.position = new Vector(100, 30);
rootTitle.extent = new Vector(1120, 80);
rootTitle.text.textColor = 0xFFFFFF;
rootTitle.text.text = "CREATE MATCH";
rootTitle.text.alpha = 0.5;
innerCtrl.addChild(rootTitle);
function numberRange(start:Int, stop:Int, step:Int) {
var range = [];
while (start <= stop) {
range.push('${start}');
start += step;
}
return range;
}
var optionCollection = new GuiXboxOptionsListCollection();
optionCollection.position = new Vector(380, 373);
optionCollection.extent = new Vector(815, 500);
innerCtrl.addChild(optionCollection);
var maxPlayers = 2;
var privateSlots = 0;
var privateGame = false;
var playerOpt = optionCollection.addOption(1, "Max Players", ["2", "3", "4", "5", "6", "7", "8"], (idx) -> {
maxPlayers = idx + 2;
return true;
}, 0.5, 118);
var privateOpt = optionCollection.addOption(1, "Max Players", ["None", "1", "2", "3", "4", "5", "6", "7"], (idx) -> {
privateSlots = idx;
return true;
}, 0.5, 118);
var privateGameOpt = optionCollection.addOption(1, "Private Game", ["No", "Yes"], (idx) -> {
privateGame = idx == 1;
return true;
}, 0.5, 118);
var bottomBar = new GuiControl();
bottomBar.position = new Vector(0, 590);
bottomBar.extent = new Vector(640, 200);
bottomBar.horizSizing = Width;
bottomBar.vertSizing = Bottom;
innerCtrl.addChild(bottomBar);
var backButton = new GuiXboxButton("Back", 160);
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MultiplayerGui());
bottomBar.addChild(backButton);
var nextButton = new GuiXboxButton("Go", 160);
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.gamepadAccelerator = ["A"];
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.pressedAction = (e) -> {
MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(true));
Net.hostServer("My Server", maxPlayers, privateSlots, privateGame);
};
bottomBar.addChild(nextButton);
}
}

141
src/gui/MPServerListGui.hx Normal file
View file

@ -0,0 +1,141 @@
package gui;
import src.Console;
import net.Net;
import net.Net.ServerInfo;
import net.MasterServerClient;
import hxd.res.BitmapFont;
import h3d.Vector;
import src.ResourceLoader;
import src.MarbleGame;
import src.Settings;
import src.Mission;
import src.MissionList;
class MPServerListGui extends GuiImage {
var innerCtrl:GuiControl;
var serverWnd:GuiImage;
public function new() {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
var arial14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt");
var arial14b = new BitmapFont(arial14fontdata.entry);
@:privateAccess arial14b.loader = ResourceLoader.loader;
var arial14 = arial14b.toSdfFont(cast 21 * Settings.uiScale, h2d.Font.SDFChannel.MultiChannel);
this.horizSizing = Width;
this.vertSizing = Height;
this.position = new Vector();
this.extent = new Vector(640, 480);
#if hl
var scene2d = hxd.Window.getInstance();
#end
#if js
var scene2d = MarbleGame.instance.scene2d;
#end
var offsetX = (scene2d.width - 1280) / 2;
var offsetY = (scene2d.height - 720) / 2;
var subX = 640 - (scene2d.width - offsetX) * 640 / scene2d.width;
var subY = 480 - (scene2d.height - offsetY) * 480 / scene2d.height;
innerCtrl = new GuiControl();
innerCtrl.position = new Vector(offsetX, offsetY);
innerCtrl.extent = new Vector(640 - subX, 480 - subY);
innerCtrl.horizSizing = Width;
innerCtrl.vertSizing = Height;
this.addChild(innerCtrl);
serverWnd = new GuiImage(ResourceLoader.getResource("data/ui/xbox/helpWindow.png", ResourceLoader.getImage, this.imageResources).toTile());
serverWnd.horizSizing = Right;
serverWnd.vertSizing = Bottom;
serverWnd.position = new Vector(260, 107);
serverWnd.extent = new Vector(736, 460);
innerCtrl.addChild(serverWnd);
function imgLoader(path:String) {
switch (path) {
case "locked":
return ResourceLoader.getResource("data/ui/xbox/DemoOutOfTimeIcon.png", ResourceLoader.getImage, this.imageResources).toTile();
case "unlocked":
return ResourceLoader.getResource("data/ui/xbox/Ready.png", ResourceLoader.getImage, this.imageResources).toTile();
}
return null;
}
var curSelection = -1;
var serverDisplays = [];
var serverList = new GuiMLTextListCtrl(arial14, serverDisplays, imgLoader);
serverList.selectedColor = 0xF29515;
serverList.selectedFillColor = 0xEBEBEB;
serverList.position = new Vector(25, 22);
serverList.extent = new Vector(550, 480);
serverList.scrollable = true;
serverList.onSelectedFunc = (sel) -> {
curSelection = sel;
}
serverWnd.addChild(serverList);
var ourServerList:Array<RemoteServerInfo> = [];
function updateServerListDisplay() {
serverDisplays = ourServerList.map(x -> x.name);
serverList.setTexts(serverDisplays);
}
MasterServerClient.connectToMasterServer(() -> {
MasterServerClient.instance.getServerList((servers) -> {
ourServerList = servers;
updateServerListDisplay();
});
});
var bottomBar = new GuiControl();
bottomBar.position = new Vector(0, 590);
bottomBar.extent = new Vector(640, 200);
bottomBar.horizSizing = Width;
bottomBar.vertSizing = Bottom;
innerCtrl.addChild(bottomBar);
var backButton = new GuiXboxButton("Back", 160);
backButton.position = new Vector(400, 0);
backButton.vertSizing = Bottom;
backButton.horizSizing = Right;
backButton.gamepadAccelerator = ["B"];
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new MainMenuGui());
bottomBar.addChild(backButton);
var nextButton = new GuiXboxButton("Join", 160);
nextButton.position = new Vector(960, 0);
nextButton.vertSizing = Bottom;
nextButton.horizSizing = Right;
nextButton.accelerators = [hxd.Key.ENTER];
nextButton.gamepadAccelerator = ["X"];
nextButton.pressedAction = (e) -> {
Net.joinServer(ourServerList[curSelection].name, () -> {
MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(false));
});
};
bottomBar.addChild(nextButton);
}
override function onResize(width:Int, height:Int) {
var offsetX = (width - 1280) / 2;
var offsetY = (height - 720) / 2;
var subX = 640 - (width - offsetX) * 640 / width;
var subY = 480 - (height - offsetY) * 480 / height;
innerCtrl.position = new Vector(offsetX, offsetY);
innerCtrl.extent = new Vector(640 - subX, 480 - subY);
super.onResize(width, height);
}
}

View file

@ -64,15 +64,18 @@ class MultiplayerGui extends GuiImage {
btnList.extent = new Vector(502, 500);
innerCtrl.addChild(btnList);
btnList.addButton(3, 'Create Game', (e) -> {
MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(true));
Net.hostServer();
btnList.addButton(3, 'Search Matches', (e) -> {
MarbleGame.canvas.setContent(new MPServerListGui());
});
btnList.addButton(3, 'Join Game', (e) -> {
Net.joinServer(() -> {
MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(false));
});
btnList.addButton(3, 'Create Match', (e) -> {
MarbleGame.canvas.setContent(new CreateMatchGui());
});
btnList.addButton(3, 'Join Match', (e) -> {
// Net.joinServer(() -> {
// MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(false));
// });
});
var bottomBar = new GuiControl();

View file

@ -0,0 +1,120 @@
package net;
import gui.MessageBoxOkDlg;
import src.MarbleGame;
import haxe.Json;
import net.Net.ServerInfo;
import hx.ws.WebSocket;
import src.Console;
typedef RemoteServerInfo = {
name:String,
players:Int,
maxPlayers:Int,
platform:String,
}
class MasterServerClient {
static var serverIp = "ws://localhost:8080";
public static var instance:MasterServerClient;
var ws:WebSocket;
var serverListCb:Array<RemoteServerInfo>->Void;
var open = false;
public function new(onOpenFunc:() -> Void) {
ws = new WebSocket(serverIp);
ws.onopen = () -> {
open = true;
onOpenFunc();
}
ws.onmessage = (m) -> {
switch (m) {
case StrMessage(content):
handleMessage(content);
case _:
return;
}
}
}
public static function connectToMasterServer(onConnect:() -> Void) {
if (instance == null)
instance = new MasterServerClient(onConnect);
else
onConnect();
}
public function sendServerInfo(serverInfo:ServerInfo) {
ws.send(Json.stringify({
type: "serverInfo",
name: serverInfo.name,
players: serverInfo.players,
maxPlayers: serverInfo.maxPlayers,
privateSlots: serverInfo.privateSlots,
privateServer: serverInfo.privateServer,
inviteCode: serverInfo.inviteCode,
state: serverInfo.state
}));
}
public function sendConnectToServer(serverName:String, sdp:String) {
ws.send(Json.stringify({
type: "connect",
serverName: serverName,
sdp: sdp
}));
}
public function getServerList(serverListCb:Array<RemoteServerInfo>->Void) {
this.serverListCb = serverListCb;
ws.send(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) {
ws.send(Json.stringify({
type: "connectResponse",
success: false,
reason: "The server has shut down"
}));
return;
}
if (Net.serverInfo.players >= Net.serverInfo.maxPlayers) {
ws.send(Json.stringify({
type: "connectResponse",
success: false,
reason: "The server is full"
}));
return;
}
Net.addClientFromSdp(conts.sdp, (sdpReply) -> {
ws.send(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);
@:privateAccess Net.client.setRemoteDescription(sdpObj.sdp, sdpObj.type);
}
if (conts.type == "connectFailed") {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg(conts.reason));
}
}
}

View file

@ -31,6 +31,29 @@ enum abstract NetPacketType(Int) from Int to Int {
var PlayerInfo;
}
@:publicFields
class ServerInfo {
var name:String;
var players:Int;
var maxPlayers:Int;
var privateSlots:Int;
var privateServer:Bool;
var inviteCode:Int;
var state:String;
var platform:String;
public function new(name:String, players:Int, maxPlayers:Int, privateSlots:Int, privateServer:Bool, inviteCode:Int, state:String, platform:String) {
this.name = name;
this.players = players;
this.maxPlayers = maxPlayers;
this.privateSlots = privateSlots;
this.privateServer = privateServer;
this.inviteCode = inviteCode;
this.state = state;
this.platform = platform;
}
}
class Net {
static var client:RTCPeerConnection;
static var clientDatachannel:RTCDataChannel;
@ -48,34 +71,51 @@ class Net {
public static var clients:Map<RTCPeerConnection, GameConnection> = [];
public static var clientIdMap:Map<Int, GameConnection> = [];
public static var clientConnection:ClientConnection;
public static var serverInfo:ServerInfo;
public static function hostServer(name:String, maxPlayers:Int, privateSlots:Int, privateServer:Bool) {
serverInfo = new ServerInfo(name, 1, maxPlayers, privateSlots, privateServer, Std.int(999999 * Math.random()), "Lobby", getPlatform());
MasterServerClient.connectToMasterServer(() -> {
isHost = true;
isClient = false;
clientId = 0;
isMP = true;
MasterServerClient.instance.sendServerInfo(serverInfo);
});
public static function hostServer() {
// host = new RTCPeerConnection(["stun.l.google.com:19302"], "0.0.0.0");
// host.bind("127.0.0.1", 28000, (c) -> {
// onClientConnect(c);
// isMP = true;
// });
isHost = true;
isClient = false;
clientId = 0;
masterWs = new WebSocket("ws://localhost:8080");
// isHost = true;
// isClient = false;
// clientId = 0;
// masterWs = new WebSocket("ws://localhost:8080");
masterWs.onmessage = (m) -> {
switch (m) {
case StrMessage(content):
var conts = Json.parse(content);
var peer = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
peer.setRemoteDescription(conts.sdp, conts.type);
addClient(peer);
// masterWs.onmessage = (m) -> {
// switch (m) {
// case StrMessage(content):
// var conts = Json.parse(content);
// var peer = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
// peer.setRemoteDescription(conts.sdp, conts.type);
// addClient(peer);
case BytesMessage(content): {}
}
}
// case BytesMessage(content): {}
// }
// }
isMP = true;
// isMP = true;
}
static function addClient(peer:RTCPeerConnection) {
public static function addClientFromSdp(sdpString:String, onFinishSdp:String->Void) {
var peer = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
var sdpObj = Json.parse(sdpString);
peer.setRemoteDescription(sdpObj.sdp, sdpObj.type);
addClient(peer, onFinishSdp);
}
static function addClient(peer:RTCPeerConnection, onFinishSdp:String->Void) {
var candidates = [];
peer.onLocalCandidate = (c) -> {
if (c != "")
@ -85,12 +125,9 @@ class Net {
if (s == RTC_GATHERING_COMPLETE) {
var sdpObj = StringTools.trim(peer.localDescription);
sdpObj = sdpObj + '\r\n' + candidates.join('\r\n') + '\r\n';
masterWs.send(Json.stringify({
type: "connect",
sdpObj: {
sdp: sdpObj,
type: "answer"
}
onFinishSdp(Json.stringify({
sdp: sdpObj,
type: "answer"
}));
}
}
@ -104,9 +141,8 @@ class Net {
clientIdMap[id] = ghost;
}
public static function joinServer(connectedCb:() -> Void) {
masterWs = new WebSocket("ws://localhost:8080");
masterWs.onopen = () -> {
public static function joinServer(serverName:String, connectedCb:() -> Void) {
MasterServerClient.connectToMasterServer(() -> {
client = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
var candidates = [];
@ -114,31 +150,19 @@ class Net {
if (c != "")
candidates.push('a=${c}');
}
client.onGatheringStateChange = (s) -> {
if (s == RTC_GATHERING_COMPLETE) {
Console.log("Local Description Set!");
var sdpObj = StringTools.trim(client.localDescription);
sdpObj = sdpObj + '\r\n' + candidates.join('\r\n') + '\r\n';
masterWs.send(Json.stringify({
type: "connect",
sdpObj: {
sdp: sdpObj,
type: "offer"
}
MasterServerClient.instance.sendConnectToServer(serverName, Json.stringify({
sdp: sdpObj,
type: "offer"
}));
}
}
masterWs.onmessage = (m) -> {
switch (m) {
case StrMessage(content):
Console.log("Remote Description Received!");
var conts = Json.parse(content);
client.setRemoteDescription(conts.sdp, conts.type);
case _: {}
}
}
clientDatachannel = client.createDatachannel("mp");
clientDatachannel.onOpen = (n) -> {
Console.log("Successfully connected!");
@ -155,16 +179,71 @@ class Net {
isMP = true;
isHost = false;
isClient = true;
}
});
// masterWs = new WebSocket("ws://localhost:8080");
// masterWs.onopen = () -> {
// client = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
// var candidates = [];
// client.onLocalCandidate = (c) -> {
// if (c != "")
// candidates.push('a=${c}');
// }
// client.onGatheringStateChange = (s) -> {
// if (s == RTC_GATHERING_COMPLETE) {
// Console.log("Local Description Set!");
// var sdpObj = StringTools.trim(client.localDescription);
// sdpObj = sdpObj + '\r\n' + candidates.join('\r\n') + '\r\n';
// masterWs.send(Json.stringify({
// type: "connect",
// sdpObj: {
// sdp: sdpObj,
// type: "offer"
// }
// }));
// }
// }
// masterWs.onmessage = (m) -> {
// switch (m) {
// case StrMessage(content):
// Console.log("Remote Description Received!");
// var conts = Json.parse(content);
// client.setRemoteDescription(conts.sdp, conts.type);
// case _: {}
// }
// }
// clientDatachannel = client.createDatachannel("mp");
// clientDatachannel.onOpen = (n) -> {
// Console.log("Successfully connected!");
// clients.set(client, new ClientConnection(0, client, clientDatachannel)); // host is always 0
// clientIdMap[0] = clients[client];
// clientConnection = cast clients[client];
// onConnectedToServer();
// haxe.Timer.delay(() -> connectedCb(), 1500); // 1.5 second delay to do the RTT calculation
// }
// clientDatachannel.onMessage = (b) -> {
// onPacketReceived(client, clientDatachannel, new InputBitStream(b));
// }
// isMP = true;
// isHost = false;
// isClient = true;
// }
}
static function onClientConnect(c:RTCPeerConnection, dc:RTCDataChannel) {
clientId += 1;
clients.set(c, new ClientConnection(clientId, c, dc));
var cc = new ClientConnection(clientId, c, dc);
clients.set(c, cc);
clientIdMap[clientId] = clients[c];
dc.onMessage = (msgBytes) -> {
onPacketReceived(c, dc, new InputBitStream(msgBytes));
}
dc.onClosed = () -> {
onClientLeave(cc);
}
var b = haxe.io.Bytes.alloc(2);
b.set(0, ClientIdAssign);
b.set(1, clientId);
@ -177,6 +256,9 @@ class Net {
cast(clients[c], ClientConnection).pingSendTime = Console.time();
dc.sendBytes(b);
Console.log("Sending ping packet!");
serverInfo.players++;
MasterServerClient.instance.sendServerInfo(serverInfo); // notify the server of the new player
}
static function onConnectedToServer() {
@ -190,6 +272,11 @@ class Net {
Console.log("Sending ping packet!");
}
static function onClientLeave(cc:ClientConnection) {
serverInfo.players--;
MasterServerClient.instance.sendServerInfo(serverInfo); // notify the server of the player leave
}
static function sendPlayerInfosBytes() {
var b = new haxe.io.BytesOutput();
b.writeByte(PlayerInfo);
@ -314,4 +401,17 @@ class Net {
addGhost(Net.clientId++);
}
}
public static function getPlatform() {
#if js
return "Browser";
#end
#if hl
#if MACOS_BUNDLE
return "MacOS";
#else
return "Windows";
#end
#end
}
}