server join via invite impl, and pub priv slots

This commit is contained in:
RandomityGuy 2024-05-06 14:20:37 +05:30
parent a9149730d5
commit 6a5fd8aeba
7 changed files with 329 additions and 25 deletions

225
src/gui/JoinServerGui.hx Normal file
View file

@ -0,0 +1,225 @@
package gui;
import net.Net;
import hxd.res.BitmapFont;
import h3d.Vector;
import src.ResourceLoader;
import src.MarbleGame;
import src.Settings;
import src.Util;
class JoinServerGui extends GuiImage {
var innerCtrl:GuiControl;
public function new() {
var res = ResourceLoader.getImage("data/ui/xbox/BG_fadeOutSoftEdge.png").resource.toTile();
super(res);
this.position = new Vector();
this.extent = new Vector(640, 480);
this.horizSizing = Width;
this.vertSizing = Height;
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);
#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 = "JOIN GAME";
rootTitle.text.alpha = 0.5;
innerCtrl.addChild(rootTitle);
var inviteCodeBg = new GuiXboxOptionsList(1, "Invite Code: ", [""], 0.3, 155.5, false);
inviteCodeBg.position = new Vector(360, 211);
inviteCodeBg.horizSizing = Right;
inviteCodeBg.vertSizing = Center;
inviteCodeBg.extent = new Vector(835, 400);
inviteCodeBg.selected = true;
innerCtrl.addChild(inviteCodeBg);
var inviteCodeInput = new GuiText(arial14);
inviteCodeInput.position = new Vector(640, 36);
inviteCodeInput.extent = new Vector(235, 18);
inviteCodeInput.vertSizing = Top;
inviteCodeInput.text.text = "";
inviteCodeInput.text.textColor = 0;
inviteCodeBg.addChild(inviteCodeInput);
// Numpad
var numpadCtrl = new GuiControl();
numpadCtrl.position = new Vector(0, 60);
numpadCtrl.extent = new Vector(800, 300);
numpadCtrl.vertSizing = Top;
inviteCodeBg.addChild(numpadCtrl);
var addNum = (str:String) -> {
if (inviteCodeInput.text.text.length < 6) {
inviteCodeInput.text.text += str;
}
}
var delNum = () -> {
if (inviteCodeInput.text.text.length > 0) {
inviteCodeInput.text.text = inviteCodeInput.text.text.substring(0, inviteCodeInput.text.text.length - 1);
}
}
var one = new GuiXboxButton("1", 110);
one.position = new Vector(240, 150);
one.accelerators = [hxd.Key.NUMBER_1, hxd.Key.NUMPAD_1];
one.pressedAction = (e) -> addNum("1");
numpadCtrl.addChild(one);
var two = new GuiXboxButton("2", 110);
two.position = new Vector(320, 150);
two.accelerators = [hxd.Key.NUMBER_2, hxd.Key.NUMPAD_2];
two.pressedAction = (e) -> addNum("2");
numpadCtrl.addChild(two);
var three = new GuiXboxButton("3", 110);
three.position = new Vector(400, 150);
three.accelerators = [hxd.Key.NUMBER_3, hxd.Key.NUMPAD_3];
three.pressedAction = (e) -> addNum("3");
numpadCtrl.addChild(three);
var four = new GuiXboxButton("4", 110);
four.position = new Vector(240, 80);
four.accelerators = [hxd.Key.NUMBER_4, hxd.Key.NUMPAD_4];
four.pressedAction = (e) -> addNum("4");
numpadCtrl.addChild(four);
var five = new GuiXboxButton("5", 110);
five.position = new Vector(320, 80);
five.accelerators = [hxd.Key.NUMBER_5, hxd.Key.NUMPAD_5];
five.pressedAction = (e) -> addNum("5");
numpadCtrl.addChild(five);
var six = new GuiXboxButton("6", 110);
six.position = new Vector(400, 80);
six.accelerators = [hxd.Key.NUMBER_6, hxd.Key.NUMPAD_6];
six.pressedAction = (e) -> addNum("6");
numpadCtrl.addChild(six);
var seven = new GuiXboxButton("7", 110);
seven.position = new Vector(240, 10);
seven.accelerators = [hxd.Key.NUMBER_7, hxd.Key.NUMPAD_7];
seven.pressedAction = (e) -> addNum("7");
numpadCtrl.addChild(seven);
var eight = new GuiXboxButton("8", 110);
eight.position = new Vector(320, 10);
eight.accelerators = [hxd.Key.NUMBER_8, hxd.Key.NUMPAD_8];
eight.pressedAction = (e) -> addNum("8");
numpadCtrl.addChild(eight);
var nine = new GuiXboxButton("9", 110);
nine.position = new Vector(400, 10);
nine.accelerators = [hxd.Key.NUMBER_9, hxd.Key.NUMPAD_9];
nine.pressedAction = (e) -> addNum("9");
numpadCtrl.addChild(nine);
var zero = new GuiXboxButton("0", 110);
zero.position = new Vector(240, 220);
zero.accelerators = [hxd.Key.NUMBER_0, hxd.Key.NUMPAD_0];
zero.pressedAction = (e) -> addNum("0");
numpadCtrl.addChild(zero);
var del = new GuiXboxButton("Del", 110);
del.position = new Vector(400, 220);
del.accelerators = [hxd.Key.DELETE, hxd.Key.BACKSPACE];
del.pressedAction = (e) -> delNum();
numpadCtrl.addChild(del);
var joinFunc = () -> {
MarbleGame.canvas.setContent(new MultiplayerLoadingGui("Connecting"));
var failed = true;
haxe.Timer.delay(() -> {
if (failed) {
var loadGui:MultiplayerLoadingGui = cast MarbleGame.canvas.content;
if (loadGui != null) {
loadGui.setErrorStatus("Failed to connect to server");
Net.disconnect();
}
}
}, 15000);
Net.joinServer(inviteCodeInput.text.text, true, () -> {
failed = false;
// Net.remoteServerInfo = ourServerList[curSelection];
});
}
var ok = new GuiXboxButton("OK", 110);
ok.position = new Vector(320, 220);
ok.accelerators = [hxd.Key.ENTER];
ok.pressedAction = (e) -> joinFunc();
numpadCtrl.addChild(ok);
// Bottom bar
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 goButton = new GuiXboxButton("Go", 160);
goButton.position = new Vector(960, 0);
goButton.vertSizing = Bottom;
goButton.horizSizing = Right;
goButton.gamepadAccelerator = ["A"];
goButton.accelerators = [hxd.Key.ENTER];
goButton.pressedAction = (e) -> joinFunc();
bottomBar.addChild(goButton);
}
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

@ -137,7 +137,7 @@ class MPServerListGui extends GuiImage {
}
}
}, 15000);
Net.joinServer(ourServerList[curSelection].name, () -> {
Net.joinServer(ourServerList[curSelection].name, false, () -> {
failed = false;
Net.remoteServerInfo = ourServerList[curSelection];
});

View file

@ -68,6 +68,7 @@ class MultiplayerGui extends GuiImage {
});
btnList.addButton(3, 'Join Match', (e) -> {
MarbleGame.canvas.setContent(new JoinServerGui());
// Net.joinServer(() -> {
// MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(false));
// });

View file

@ -24,6 +24,7 @@ class MultiplayerLevelSelectGui extends GuiImage {
var playerList:GuiMLTextListCtrl;
var updatePlayerCountFn:(Int, Int, Int, Int) -> Void;
var innerCtrl:GuiControl;
var inviteVisibility:Bool = true;
public function new(isHost:Bool) {
var res = ResourceLoader.getImage("data/ui/game/CloudBG.jpg").resource.toTile();
@ -216,15 +217,25 @@ class MultiplayerLevelSelectGui extends GuiImage {
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
backButton.pressedAction = (e) -> {
Net.disconnect();
MarbleGame.canvas.setContent(new CreateMatchGui());
if (Net.isHost) {
MarbleGame.canvas.setContent(new CreateMatchGui());
} else {
MarbleGame.canvas.setContent(new MultiplayerGui());
}
}
bottomBar.addChild(backButton);
// var lbButton = new GuiXboxButton("Leaderboard", 220);
// lbButton.position = new Vector(750, 0);
// lbButton.vertSizing = Bottom;
// lbButton.horizSizing = Right;
// bottomBar.addChild(lbButton);
if (Net.isHost) {
var inviteButton = new GuiXboxButton("Invite Visibility", 220);
inviteButton.position = new Vector(750, 0);
inviteButton.vertSizing = Bottom;
inviteButton.horizSizing = Right;
inviteButton.pressedAction = (e) -> {
inviteVisibility = !inviteVisibility;
updateLobbyNames();
}
bottomBar.addChild(inviteButton);
}
var nextButton = new GuiXboxButton("Ready", 160);
nextButton.position = new Vector(960, 0);
@ -296,12 +307,27 @@ class MultiplayerLevelSelectGui extends GuiImage {
if (Net.isHost) {
updatePlayerCountFn = (pub:Int, priv:Int, publicTotal:Int, privateTotal:Int) -> {
levelInfoLeft.text.text = '<p><font face="arial14">Host: ${hostName}</font></p>'
+ '<p><font face="arial14">Level: ${mis.title}</font></p>'
+ '<p><font face="arial12">Private Slots: ${pub}/${publicTotal}, Public Slots: ${priv}/${privateTotal}</font></p>';
if (inviteVisibility)
levelInfoLeft.text.text = '<p><font face="arial14">Host: ${hostName}</font></p>'
+ '<p><font face="arial14">Level: ${mis.title}</font></p>'
+
'<p><font face="arial12">Public Slots: ${pub}/${publicTotal}, Private Slots: ${priv}/${privateTotal}, Invite Code: ${Net.serverInfo.inviteCode}</font></p>';
else
levelInfoLeft.text.text = '<p><font face="arial14">Host: ${hostName}</font></p>'
+ '<p><font face="arial14">Level: ${mis.title}</font></p>'
+ '<p><font face="arial12">Public Slots: ${pub}/${publicTotal}, Private Slots: ${priv}/${privateTotal}</font></p>';
}
var pubCount = 1; // 1 for host
var privCount = 0;
for (cid => cc in Net.clientIdMap) {
if (cc.isPrivate) {
privCount++;
} else {
pubCount++;
}
}
updatePlayerCountFn(0, 0, Net.serverInfo.maxPlayers - Net.serverInfo.privateSlots, Net.serverInfo.privateSlots);
updatePlayerCountFn(pubCount, privCount, Net.serverInfo.maxPlayers - Net.serverInfo.privateSlots, Net.serverInfo.privateSlots);
}
if (Net.isClient) {
updatePlayerCountFn = (pub:Int, priv:Int, publicTotal:Int, privateTotal:Int) -> {
@ -383,6 +409,20 @@ class MultiplayerLevelSelectGui extends GuiImage {
playerList.setTexts(playerListArr.map(player -> {
return '<img src="${player.state ? "ready" : "notready"}"></img><img src="${platformToString(player.platform)}"></img>${player.name}';
}));
var pubCount = 1; // Self
var privCount = 0;
for (cid => cc in Net.clientIdMap) {
if (cc.isPrivate) {
privCount++;
} else {
pubCount++;
}
}
if (Net.isHost) {
updatePlayerCountFn(pubCount, privCount, Net.serverInfo.maxPlayers - Net.serverInfo.privateSlots, Net.serverInfo.privateSlots);
}
}
public function updatePlayerCount(pub:Int, priv:Int, publicTotal:Int, privateTotal:Int) {

View file

@ -76,6 +76,7 @@ abstract class GameConnection {
var lobbyReady:Bool;
var platform:NetPlatform;
var marbleId:Int;
var isPrivate:Bool;
function new(id:Int) {
this.id = id;

View file

@ -83,12 +83,20 @@ class MasterServerClient {
}));
}
public function sendConnectToServer(serverName:String, sdp:String) {
ws.sendString(Json.stringify({
type: "connect",
serverName: serverName,
sdp: sdp
}));
public function sendConnectToServer(serverName:String, sdp:String, isInvite:Bool = false) {
if (!isInvite) {
ws.sendString(Json.stringify({
type: "connect",
serverName: serverName,
sdp: sdp
}));
} else {
ws.sendString(Json.stringify({
type: "connectInvite",
sdp: sdp,
inviteCode: serverName
}));
}
}
public function getServerList(serverListCb:Array<RemoteServerInfo>->Void) {
@ -115,6 +123,8 @@ class MasterServerClient {
}));
return;
}
var joiningPrivate = conts.isPrivate;
if (Net.serverInfo.players >= Net.serverInfo.maxPlayers) {
ws.sendString(Json.stringify({
type: "connectFailed",
@ -123,7 +133,33 @@ class MasterServerClient {
}));
return;
}
Net.addClientFromSdp(conts.sdp, (sdpReply) -> {
var pubSlotsAvail = Net.serverInfo.maxPlayers - Net.serverInfo.privateSlots;
var privSlotsAvail = Net.serverInfo.privateSlots;
var pubCount = 1; // Self
var privCount = 0;
for (cid => cc in Net.clientIdMap) {
if (cc.isPrivate) {
privCount++;
} else {
pubCount++;
}
}
if (!joiningPrivate && pubCount >= pubSlotsAvail) {
ws.sendString(Json.stringify({
type: "connectFailed",
success: false,
reason: "The server is full"
}));
return;
}
if (joiningPrivate && privCount >= privSlotsAvail) {
joiningPrivate = false; // Join publicly
}
Net.addClientFromSdp(conts.sdp, joiningPrivate, (sdpReply) -> {
ws.sendString(Json.stringify({
success: true,
type: "connectResponse",

View file

@ -91,14 +91,14 @@ class Net {
});
}
public static function addClientFromSdp(sdpString:String, onFinishSdp:String->Void) {
public static function addClientFromSdp(sdpString:String, privateJoin:Bool, 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);
addClient(peer, privateJoin, onFinishSdp);
}
static function addClient(peer:RTCPeerConnection, onFinishSdp:String->Void) {
static function addClient(peer:RTCPeerConnection, privateJoin:Bool, onFinishSdp:String->Void) {
var candidates = [];
peer.onLocalCandidate = (c) -> {
if (c != "")
@ -129,7 +129,7 @@ class Net {
}
}
if (reliable != null && unreliable != null)
onClientConnect(peer, reliable, unreliable);
onClientConnect(peer, reliable, unreliable, privateJoin);
}
}
@ -138,7 +138,7 @@ class Net {
clientIdMap[id] = ghost;
}
public static function joinServer(serverName:String, connectedCb:() -> Void) {
public static function joinServer(serverName:String, isInvite:Bool, connectedCb:() -> Void) {
MasterServerClient.connectToMasterServer(() -> {
client = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
var candidates = [];
@ -156,7 +156,7 @@ class Net {
MasterServerClient.instance.sendConnectToServer(serverName, Json.stringify({
sdp: sdpObj,
type: "offer"
}));
}), isInvite);
}
}
@ -335,10 +335,11 @@ class Net {
}
}
static function onClientConnect(c:RTCPeerConnection, dc:RTCDataChannel, dcu:RTCDataChannel) {
static function onClientConnect(c:RTCPeerConnection, dc:RTCDataChannel, dcu:RTCDataChannel, joiningPrivate:Bool) {
clientId += 1;
var cc = new ClientConnection(clientId, c, dc, dcu);
clients.set(c, cc);
cc.isPrivate = joiningPrivate;
clientIdMap[clientId] = clients[c];
var closing = false;