mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-12-23 16:32:49 +00:00
work on better lobby and gravity impl start
This commit is contained in:
parent
d0f69e88d3
commit
ecaa938f95
18 changed files with 407 additions and 241 deletions
|
|
@ -1732,6 +1732,7 @@ class Marble extends GameObject {
|
|||
marbleUpdate.oob = this.outOfBounds;
|
||||
marbleUpdate.powerUpId = this.heldPowerup != null ? this.heldPowerup.netIndex : 0x1FF;
|
||||
marbleUpdate.netFlags = this.netFlags;
|
||||
marbleUpdate.gravityDirection = this.currentUp;
|
||||
this.netFlags = 0;
|
||||
marbleUpdate.serialize(b);
|
||||
return b.getBytes();
|
||||
|
|
@ -1756,6 +1757,8 @@ class Marble extends GameObject {
|
|||
this.blastUseTick = p.blastTick;
|
||||
this.helicopterUseTick = p.heliTick;
|
||||
this.megaMarbleUseTick = p.megaTick;
|
||||
this.currentUp = p.gravityDirection;
|
||||
this.level.setUp(cast this, this.currentUp, this.level.timeState, true);
|
||||
this.outOfBounds = p.oob;
|
||||
this.camera.oob = p.oob;
|
||||
if (p.powerUpId == 0x1FF) {
|
||||
|
|
@ -2306,7 +2309,7 @@ class Marble extends GameObject {
|
|||
this.blastTicks = 0;
|
||||
this.helicopterUseTick = 0;
|
||||
this.megaMarbleUseTick = 0;
|
||||
this.netFlags = MarbleNetFlags.DoBlast | MarbleNetFlags.DoMega | MarbleNetFlags.DoHelicopter | MarbleNetFlags.PickupPowerup;
|
||||
this.netFlags = MarbleNetFlags.DoBlast | MarbleNetFlags.DoMega | MarbleNetFlags.DoHelicopter | MarbleNetFlags.PickupPowerup | MarbleNetFlags.GravityChange;
|
||||
this.lastContactNormal = new Vector(0, 0, 1);
|
||||
this.contactEntities = [];
|
||||
this._firstTick = true;
|
||||
|
|
|
|||
|
|
@ -342,12 +342,12 @@ class MarbleWorld extends Scheduler {
|
|||
if (this.isMultiplayer) {
|
||||
// Add us
|
||||
if (Net.isHost) {
|
||||
this.playGui.addPlayer(0, 'Player 0', true);
|
||||
this.playGui.addPlayer(0, Settings.highscoreName.substr(0, 15), true);
|
||||
} else {
|
||||
this.playGui.addPlayer(Net.clientId, 'Player ${Net.clientId}', true);
|
||||
this.playGui.addPlayer(Net.clientId, Settings.highscoreName.substr(0, 15), true);
|
||||
}
|
||||
for (client in Net.clientIdMap) {
|
||||
this.playGui.addPlayer(client.id, 'Player ${client.id}', false);
|
||||
this.playGui.addPlayer(client.id, client.name.substr(0, 15), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -651,6 +651,7 @@ class MarbleWorld extends Scheduler {
|
|||
if (isMultiplayer) {
|
||||
marble.megaMarbleUseTick = 0;
|
||||
marble.helicopterUseTick = 0;
|
||||
marble.collider.radius = marble._radius = 0.3;
|
||||
} else {
|
||||
@:privateAccess marble.helicopterEnableTime = -1e8;
|
||||
@:privateAccess marble.megaMarbleEnableTime = -1e8;
|
||||
|
|
@ -1204,8 +1205,8 @@ class MarbleWorld extends Scheduler {
|
|||
// Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||
|
||||
var distFromUs = @:privateAccess marbleToUpdate.newPos.distance(this.marble.newPos);
|
||||
if (distFromUs < 5) // {
|
||||
m.calculationTicks = ourQueuedMoves.length;
|
||||
// if (distFromUs < 5) // {
|
||||
m.calculationTicks = ourQueuedMoves.length;
|
||||
// } else {
|
||||
// m.calculationTicks = Std.int(Math.max(1, ourQueuedMoves.length - (distFromUs - 5) / 3));
|
||||
// }
|
||||
|
|
@ -2058,7 +2059,12 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
|
||||
public function setUp(marble:Marble, vec:Vector, timeState:TimeState, instant:Bool = false) {
|
||||
if (vec == marble.currentUp)
|
||||
return;
|
||||
marble.currentUp = vec;
|
||||
if (isMultiplayer && Net.isHost) {
|
||||
@:privateAccess marble.netFlags |= MarbleNetFlags.GravityChange;
|
||||
}
|
||||
if (marble == this.marble) {
|
||||
var currentQuat = this.getOrientationQuat(timeState.currentAttemptTime);
|
||||
var oldUp = new Vector(0, 0, 1);
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ class Settings {
|
|||
|
||||
public static var achievementProgression:Int;
|
||||
|
||||
public static var highscoreName = "";
|
||||
public static var highscoreName = "Player";
|
||||
|
||||
public static var uiScale = 1.0;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import gui.GuiControl.MouseState;
|
|||
class Canvas extends GuiControl {
|
||||
var scene2d:Scene;
|
||||
var marbleGame:MarbleGame;
|
||||
var content:GuiControl;
|
||||
|
||||
public function new(scene, marbleGame:MarbleGame) {
|
||||
super();
|
||||
|
|
@ -30,6 +31,7 @@ class Canvas extends GuiControl {
|
|||
|
||||
public function setContent(content:GuiControl) {
|
||||
this.dispose();
|
||||
this.content = content;
|
||||
this.addChild(content);
|
||||
this.render(scene2d);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ class CreateMatchGui extends GuiImage {
|
|||
nextButton.gamepadAccelerator = ["A"];
|
||||
nextButton.accelerators = [hxd.Key.ENTER];
|
||||
nextButton.pressedAction = (e) -> {
|
||||
Net.hostServer('${Settings.highscoreName}\'s Server', maxPlayers, privateSlots, privateGame);
|
||||
MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(true));
|
||||
Net.hostServer("My Server", maxPlayers, privateSlots, privateGame);
|
||||
};
|
||||
bottomBar.addChild(nextButton);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,62 +9,53 @@ import h3d.Vector;
|
|||
import src.ResourceLoader;
|
||||
import src.MarbleGame;
|
||||
|
||||
class EnterNameDlg extends GuiControl {
|
||||
public function new(place:Int, okFunc:String->Void) {
|
||||
super();
|
||||
this.position = new Vector();
|
||||
this.extent = new Vector(640, 480);
|
||||
class EnterNameDlg extends GuiImage {
|
||||
public function new() {
|
||||
var res = ResourceLoader.getImage("data/ui/xbox/roundedBG.png").resource.toTile();
|
||||
super(res);
|
||||
this.horizSizing = Width;
|
||||
this.vertSizing = Height;
|
||||
this.position = new Vector();
|
||||
this.extent = new Vector(640, 480);
|
||||
|
||||
function loadButtonImages(path:String) {
|
||||
var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile();
|
||||
var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile();
|
||||
var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile();
|
||||
return [normal, hover, pressed];
|
||||
}
|
||||
|
||||
var arial14fontdata = ResourceLoader.getFileEntry("data/font/arial.fnt");
|
||||
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 12 * Settings.uiScale, MultiChannel);
|
||||
var arial14 = arial14b.toSdfFont(cast 21 * Settings.uiScale, h2d.Font.SDFChannel.MultiChannel);
|
||||
|
||||
var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt");
|
||||
var domcasual32b = new BitmapFont(domcasual32fontdata.entry);
|
||||
@:privateAccess domcasual32b.loader = ResourceLoader.loader;
|
||||
var domcasual32 = domcasual32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel);
|
||||
var domcasual48 = domcasual32b.toSdfFont(cast 42 * Settings.uiScale, MultiChannel);
|
||||
var yesNoFrame = new GuiImage(ResourceLoader.getResource("data/ui/xbox/popupGUI.png", ResourceLoader.getImage, this.imageResources).toTile());
|
||||
yesNoFrame.horizSizing = Center;
|
||||
yesNoFrame.vertSizing = Center;
|
||||
yesNoFrame.position = new Vector(70, 30);
|
||||
yesNoFrame.extent = new Vector(512, 400);
|
||||
this.addChild(yesNoFrame);
|
||||
|
||||
function mlFontLoader(text:String) {
|
||||
switch (text) {
|
||||
case "DomCasual32":
|
||||
return domcasual32;
|
||||
case "DomCasual48":
|
||||
return domcasual48;
|
||||
case "Arial14":
|
||||
return arial14;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
var text = "Enter your name";
|
||||
|
||||
var dlg = new GuiImage(ResourceLoader.getResource("data/ui/endgame/enternamebox.png", ResourceLoader.getImage, this.imageResources).toTile());
|
||||
dlg.horizSizing = Center;
|
||||
dlg.vertSizing = Center;
|
||||
dlg.position = new Vector(110, 112);
|
||||
dlg.extent = new Vector(420, 256);
|
||||
this.addChild(dlg);
|
||||
var yesNoText = new GuiMLText(arial14, null);
|
||||
yesNoText.position = new Vector(103, 85);
|
||||
yesNoText.extent = new Vector(313, 186);
|
||||
yesNoText.text.text = text;
|
||||
yesNoText.text.textColor = 0xEBEBEB;
|
||||
yesNoFrame.addChild(yesNoText);
|
||||
|
||||
var enterNameEdit = new GuiTextInput(domcasual32);
|
||||
enterNameEdit.text.textColor = 0;
|
||||
enterNameEdit.text.selectionColor.setColor(0xFFFFFFFF);
|
||||
enterNameEdit.text.selectionTile = h2d.Tile.fromColor(0x808080, 0, hxd.Math.ceil(enterNameEdit.text.font.lineHeight));
|
||||
enterNameEdit.position = new Vector(28, 130);
|
||||
enterNameEdit.extent = new Vector(363, 38);
|
||||
enterNameEdit.text.text = Settings.highscoreName;
|
||||
haxe.Timer.delay(() -> {
|
||||
enterNameEdit.text.focus();
|
||||
}, 5);
|
||||
var textFrame = new GuiControl();
|
||||
textFrame.position = new Vector(33, 107);
|
||||
textFrame.extent = new Vector(232, 40);
|
||||
textFrame.horizSizing = Center;
|
||||
yesNoFrame.addChild(textFrame);
|
||||
|
||||
var textInput = new GuiTextInput(arial14);
|
||||
textInput.position = new Vector(6, 5);
|
||||
textInput.extent = new Vector(216, 40);
|
||||
textInput.horizSizing = Width;
|
||||
textInput.vertSizing = Height;
|
||||
textInput.text.textColor = 0xEBEBEB;
|
||||
textInput.text.selectionColor.setColor(0x8DFF8D);
|
||||
textInput.text.selectionTile = h2d.Tile.fromColor(0x88BCEE, 0, hxd.Math.ceil(textInput.text.font.lineHeight));
|
||||
textFrame.addChild(textInput);
|
||||
|
||||
textInput.text.text = Settings.highscoreName;
|
||||
enterNameEdit.text.onFocus = (e) -> {
|
||||
dlg.vertSizing = Bottom;
|
||||
dlg.position = new Vector(110, 56);
|
||||
|
|
@ -76,34 +67,28 @@ class EnterNameDlg extends GuiControl {
|
|||
dlg.render(MarbleGame.canvas.scene2d);
|
||||
}
|
||||
|
||||
var okbutton = new GuiButton(loadButtonImages("data/ui/endgame/ok"));
|
||||
okbutton.position = new Vector(151, 184);
|
||||
okbutton.extent = new Vector(110, 55);
|
||||
okbutton.accelerator = hxd.Key.ENTER;
|
||||
okbutton.gamepadAccelerator = ["A"];
|
||||
okbutton.pressedAction = (sender) -> {
|
||||
MarbleGame.canvas.popDialog(this);
|
||||
Settings.highscoreName = enterNameEdit.text.text;
|
||||
okFunc(enterNameEdit.text.text);
|
||||
var okButton = new GuiXboxButton("Ok", 120);
|
||||
okButton.position = new Vector(211, 248);
|
||||
okButton.extent = new Vector(120, 94);
|
||||
okButton.vertSizing = Top;
|
||||
okButton.accelerators = [hxd.Key.ENTER];
|
||||
okButton.gamepadAccelerator = ["A"];
|
||||
okButton.pressedAction = (sender) -> {
|
||||
Settings.highscoreName = textInput.text.text.substr(0, 15); // Max 15 pls
|
||||
Settings.save();
|
||||
MarbleGame.canvas.setContent(new MultiplayerGui());
|
||||
}
|
||||
dlg.addChild(okbutton);
|
||||
yesNoFrame.addChild(okButton);
|
||||
|
||||
var wnd = new GuiImage(ResourceLoader.getResource("data/ui/endgame/window.png", ResourceLoader.getImage, this.imageResources).toTile());
|
||||
wnd.horizSizing = Width;
|
||||
wnd.vertSizing = Height;
|
||||
wnd.position = new Vector(16, 119);
|
||||
wnd.extent = new Vector(388, 56);
|
||||
dlg.addChild(wnd);
|
||||
|
||||
var enterNameText = new GuiMLText(domcasual32, mlFontLoader);
|
||||
enterNameText.text.textColor = 0xFFFFFF;
|
||||
enterNameText.text.filter = new DropShadow(1.414, 0.785, 0x7777777F, 1, 0, 0.4, 1, true);
|
||||
enterNameText.position = new Vector(37, 23);
|
||||
enterNameText.extent = new Vector(345, 85);
|
||||
// enterNameText.justify = Center;
|
||||
enterNameText.text.text = '<font face="Arial14"><br/></font><p align="center"><font face="DomCasual48">Well Done!<br/></font><font face="DomCasual32">You have the${["", " second", " third", " fourth", " fifth"][place]} top time!</font></p>';
|
||||
dlg.addChild(enterNameText);
|
||||
|
||||
dlg.addChild(enterNameEdit);
|
||||
var cancelButton = new GuiXboxButton("Cancel", 120);
|
||||
cancelButton.position = new Vector(321, 248);
|
||||
cancelButton.extent = new Vector(120, 94);
|
||||
cancelButton.vertSizing = Top;
|
||||
cancelButton.accelerators = [hxd.Key.ENTER];
|
||||
cancelButton.gamepadAccelerator = ["A"];
|
||||
cancelButton.pressedAction = (sender) -> {
|
||||
MarbleGame.canvas.setContent(new MultiplayerGui());
|
||||
}
|
||||
yesNoFrame.addChild(cancelButton);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,8 +120,10 @@ class MPServerListGui extends GuiImage {
|
|||
nextButton.accelerators = [hxd.Key.ENTER];
|
||||
nextButton.gamepadAccelerator = ["X"];
|
||||
nextButton.pressedAction = (e) -> {
|
||||
MarbleGame.canvas.setContent(new MultiplayerLoadingGui("Connecting"));
|
||||
Net.joinServer(ourServerList[curSelection].name, () -> {
|
||||
MarbleGame.canvas.setContent(new MultiplayerLevelSelectGui(false));
|
||||
Net.remoteServerInfo = ourServerList[curSelection];
|
||||
});
|
||||
};
|
||||
bottomBar.addChild(nextButton);
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ class MultiplayerGui extends GuiImage {
|
|||
// });
|
||||
});
|
||||
|
||||
btnList.addButton(5, 'Change Display Name', (e) -> {
|
||||
MarbleGame.canvas.setContent(new EnterNameDlg());
|
||||
});
|
||||
|
||||
var bottomBar = new GuiControl();
|
||||
bottomBar.position = new Vector(0, 590);
|
||||
bottomBar.extent = new Vector(640, 200);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package gui;
|
||||
|
||||
import net.Net;
|
||||
import net.NetCommands;
|
||||
import modes.GameMode.ScoreType;
|
||||
import src.Util;
|
||||
|
|
@ -19,6 +20,8 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
static var setLevelFn:Int->Void;
|
||||
static var playSelectedLevel:Void->Void;
|
||||
|
||||
var playerList:GuiMLTextListCtrl;
|
||||
var updatePlayerCountFn:(Int, Int, Int, Int) -> Void;
|
||||
var innerCtrl:GuiControl;
|
||||
|
||||
public function new(isHost:Bool) {
|
||||
|
|
@ -29,8 +32,15 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
var arial14b = new BitmapFont(arial14fontdata.entry);
|
||||
@:privateAccess arial14b.loader = ResourceLoader.loader;
|
||||
var arial14 = arial14b.toSdfFont(cast 21 * Settings.uiScale, h2d.Font.SDFChannel.MultiChannel);
|
||||
var arial12 = arial14b.toSdfFont(cast 16 * Settings.uiScale, h2d.Font.SDFChannel.MultiChannel);
|
||||
function mlFontLoader(text:String) {
|
||||
return arial14;
|
||||
switch (text) {
|
||||
case "arial14":
|
||||
return arial14;
|
||||
case "arial12":
|
||||
return arial12;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
MarbleGame.instance.toRecord = false;
|
||||
|
|
@ -127,11 +137,34 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
rootTitle.position = new Vector(100, 30);
|
||||
rootTitle.extent = new Vector(1120, 80);
|
||||
rootTitle.text.textColor = 0xFFFFFF;
|
||||
rootTitle.text.text = "SELECT LEVEL";
|
||||
rootTitle.text.text = "LOBBY";
|
||||
rootTitle.text.alpha = 0.5;
|
||||
innerCtrl.addChild(rootTitle);
|
||||
var bottomBar = new GuiControl();
|
||||
|
||||
var playerWnd = new GuiImage(ResourceLoader.getResource("data/ui/xbox/achievementWindow.png", ResourceLoader.getImage, this.imageResources).toTile());
|
||||
playerWnd.horizSizing = Right;
|
||||
playerWnd.vertSizing = Bottom;
|
||||
playerWnd.position = new Vector(330, 58);
|
||||
playerWnd.extent = new Vector(640, 480);
|
||||
innerCtrl.addChild(playerWnd);
|
||||
|
||||
var playerListArr = [Settings.highscoreName];
|
||||
if (Net.isClient) {
|
||||
for (c => v in Net.clientIdMap) {
|
||||
playerListArr.push(v.getName());
|
||||
}
|
||||
}
|
||||
|
||||
playerList = new GuiMLTextListCtrl(arial14, playerListArr, null);
|
||||
playerList.selectedColor = 0xF29515;
|
||||
playerList.selectedFillColor = 0xEBEBEB;
|
||||
playerList.position = new Vector(25, 22);
|
||||
playerList.extent = new Vector(550, 480);
|
||||
playerList.scrollable = true;
|
||||
playerList.onSelectedFunc = (sel) -> {}
|
||||
playerWnd.addChild(playerList);
|
||||
|
||||
var bottomBar = new GuiControl();
|
||||
bottomBar.position = new Vector(0, 590);
|
||||
bottomBar.extent = new Vector(640, 200);
|
||||
bottomBar.horizSizing = Width;
|
||||
|
|
@ -144,7 +177,10 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
backButton.horizSizing = Right;
|
||||
backButton.gamepadAccelerator = ["B"];
|
||||
backButton.accelerators = [hxd.Key.ESCAPE, hxd.Key.BACKSPACE];
|
||||
backButton.pressedAction = (e) -> MarbleGame.canvas.setContent(new DifficultySelectGui());
|
||||
backButton.pressedAction = (e) -> {
|
||||
Net.disconnect();
|
||||
MarbleGame.canvas.setContent(new CreateMatchGui());
|
||||
}
|
||||
bottomBar.addChild(backButton);
|
||||
|
||||
// var lbButton = new GuiXboxButton("Leaderboard", 220);
|
||||
|
|
@ -153,18 +189,17 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
// lbButton.horizSizing = Right;
|
||||
// bottomBar.addChild(lbButton);
|
||||
|
||||
if (isHost) {
|
||||
var nextButton = new GuiXboxButton("Play", 160);
|
||||
nextButton.position = new Vector(960, 0);
|
||||
nextButton.vertSizing = Bottom;
|
||||
nextButton.horizSizing = Right;
|
||||
nextButton.gamepadAccelerator = ["A"];
|
||||
nextButton.accelerators = [hxd.Key.ENTER];
|
||||
nextButton.pressedAction = (e) -> {
|
||||
NetCommands.playLevel();
|
||||
};
|
||||
bottomBar.addChild(nextButton);
|
||||
}
|
||||
var nextButton = new GuiXboxButton("Ready", 160);
|
||||
nextButton.position = new Vector(960, 0);
|
||||
nextButton.vertSizing = Bottom;
|
||||
nextButton.horizSizing = Right;
|
||||
nextButton.gamepadAccelerator = ["A"];
|
||||
nextButton.accelerators = [hxd.Key.ENTER];
|
||||
nextButton.pressedAction = (e) -> {
|
||||
NetCommands.toggleReadiness(Net.isClient ? Net.clientId : 0);
|
||||
};
|
||||
bottomBar.addChild(nextButton);
|
||||
|
||||
playSelectedLevel = () -> {
|
||||
MarbleGame.instance.playMission(curMission, true);
|
||||
}
|
||||
|
|
@ -176,42 +211,19 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
levelWnd.horizSizing = Right;
|
||||
innerCtrl.addChild(levelWnd);
|
||||
|
||||
var statIcon = new GuiImage(ResourceLoader.getResource("data/ui/xbox/statIcon.png", ResourceLoader.getImage, this.imageResources).toTile());
|
||||
statIcon.position = new Vector(29, 54);
|
||||
statIcon.extent = new Vector(20, 20);
|
||||
levelWnd.addChild(statIcon);
|
||||
|
||||
var eggIcon = new GuiImage(ResourceLoader.getResource("data/ui/xbox/eggIcon.png", ResourceLoader.getImage, this.imageResources).toTile());
|
||||
eggIcon.position = new Vector(29, 79);
|
||||
eggIcon.extent = new Vector(20, 20);
|
||||
levelWnd.addChild(eggIcon);
|
||||
|
||||
var c0 = 0xEBEBEB;
|
||||
var c1 = 0x8DFF8D;
|
||||
var c2 = 0x88BCEE;
|
||||
var c3 = 0xFF7575;
|
||||
|
||||
var levelInfoLeft = new GuiMLText(arial14, mlFontLoader);
|
||||
levelInfoLeft.position = new Vector(69, 54);
|
||||
levelInfoLeft.extent = new Vector(180, 100);
|
||||
levelInfoLeft.text.text = '<p align="right"><font color="#EBEBEB">My Best Time:</font><br/><font color="#EBEBEB">Par Time:</font></p>';
|
||||
levelInfoLeft.text.lineSpacing = 6;
|
||||
levelInfoLeft.position = new Vector(33, 40);
|
||||
levelInfoLeft.extent = new Vector(480, 100);
|
||||
levelInfoLeft.text.text = '';
|
||||
levelInfoLeft.text.lineSpacing = 0;
|
||||
levelInfoLeft.text.filter = new h2d.filter.DropShadow(2, 0.785, 0x000000, 1, 0, 0.4, 1, true);
|
||||
levelWnd.addChild(levelInfoLeft);
|
||||
|
||||
var levelInfoMid = new GuiMLText(arial14, mlFontLoader);
|
||||
levelInfoMid.position = new Vector(269, 54);
|
||||
levelInfoMid.extent = new Vector(180, 100);
|
||||
levelInfoMid.text.text = '<p align="left"><font color="#EBEBEB">None</font><br/><font color="#88BCEE">99:59:99</font></p>';
|
||||
levelInfoMid.text.lineSpacing = 6;
|
||||
levelWnd.addChild(levelInfoMid);
|
||||
|
||||
var levelInfoRight = new GuiMLText(arial14, mlFontLoader);
|
||||
levelInfoRight.position = new Vector(379, 54);
|
||||
levelInfoRight.extent = new Vector(180, 100);
|
||||
levelInfoRight.text.text = '<p align="left"><font color="#EBEBEB">Level 1<br/>Difficulty 1</font></p>';
|
||||
levelInfoRight.text.lineSpacing = 6;
|
||||
levelWnd.addChild(levelInfoRight);
|
||||
|
||||
var levelNames = difficultyMissions.map(x -> x.title);
|
||||
var levelSelectOpts = new GuiXboxOptionsList(6, "Level", levelNames);
|
||||
|
||||
|
|
@ -230,10 +242,6 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
var misFile = Path.withoutExtension(Path.withoutDirectory(curMission.path));
|
||||
var mis = difficultyMissions[idx];
|
||||
var requestToken = currentToken;
|
||||
if (Settings.easterEggs.exists(mis.path))
|
||||
eggIcon.bmp.visible = true;
|
||||
else
|
||||
eggIcon.bmp.visible = false;
|
||||
MarbleGame.instance.setPreviewMission(misFile, () -> {
|
||||
lock = false;
|
||||
if (requestToken != currentToken)
|
||||
|
|
@ -243,34 +251,31 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
loadText.text.visible = false;
|
||||
loadTextBg.text.visible = false;
|
||||
});
|
||||
|
||||
var scoreType = mis.missionInfo.gamemode != null
|
||||
&& mis.missionInfo.gamemode.toLowerCase() == 'scrum' ? ScoreType.Score : ScoreType.Time;
|
||||
|
||||
var myScore = Settings.getScores(mis.path);
|
||||
var scoreDisp = "None";
|
||||
if (myScore.length != 0)
|
||||
scoreDisp = scoreType == Time ? Util.formatTime(myScore[0].time) : Util.formatScore(myScore[0].time);
|
||||
var isPar = myScore.length != 0 && myScore[0].time < mis.qualifyTime;
|
||||
var scoreColor = "#EBEBEB";
|
||||
if (isPar)
|
||||
scoreColor = "#8DFF8D";
|
||||
if (scoreType == Score && myScore.length == 0)
|
||||
scoreColor = "#EBEBEB";
|
||||
if (scoreType == Time) {
|
||||
levelInfoLeft.text.text = '<p align="right"><font color="#EBEBEB">My Best Time:</font><br/><font color="#EBEBEB">Par Time:</font></p>';
|
||||
levelInfoMid.text.text = '<p align="left"><font color="${scoreColor}">${scoreDisp}</font><br/><font color="#88BCEE">${Util.formatTime(mis.qualifyTime)}</font></p>';
|
||||
var hostName = Settings.highscoreName;
|
||||
if (!Net.isHost) {
|
||||
hostName = Net.clientIdMap[0].getName();
|
||||
}
|
||||
if (scoreType == Score) {
|
||||
levelInfoLeft.text.text = '<p align="right"><font color="#EBEBEB">My Best Score:</font></p>';
|
||||
levelInfoMid.text.text = '<p align="left"><font color="${scoreColor}">${scoreDisp}</font></p>';
|
||||
|
||||
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>';
|
||||
}
|
||||
|
||||
updatePlayerCountFn(0, 0, Net.serverInfo.maxPlayers - Net.serverInfo.privateSlots, Net.serverInfo.privateSlots);
|
||||
}
|
||||
if (Net.isClient) {
|
||||
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>';
|
||||
}
|
||||
updatePlayerCountFn(0, 0, 0, 0);
|
||||
}
|
||||
levelInfoRight.text.text = '<p align="left"><font color="#EBEBEB">Level ${mis.missionInfo.level}<br/>Difficulty ${mis.missionInfo.difficulty == null ? "" : mis.missionInfo.difficulty}</font></p>';
|
||||
return true;
|
||||
}
|
||||
setLevelFn = setLevel;
|
||||
|
||||
levelSelectOpts.position = new Vector(380, 435);
|
||||
levelSelectOpts.position = new Vector(380, 430);
|
||||
levelSelectOpts.extent = new Vector(815, 94);
|
||||
levelSelectOpts.vertSizing = Bottom;
|
||||
levelSelectOpts.horizSizing = Right;
|
||||
|
|
@ -295,4 +300,16 @@ class MultiplayerLevelSelectGui extends GuiImage {
|
|||
|
||||
super.onResize(width, height);
|
||||
}
|
||||
|
||||
public function updateLobbyNames() {
|
||||
var names = [Settings.highscoreName];
|
||||
for (id => c in Net.clientIdMap) {
|
||||
names.push(c.getName());
|
||||
}
|
||||
playerList.setTexts(names);
|
||||
}
|
||||
|
||||
public function updatePlayerCount(pub:Int, priv:Int, publicTotal:Int, privateTotal:Int) {
|
||||
updatePlayerCountFn(pub, priv, publicTotal, privateTotal);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ import src.Util;
|
|||
class MultiplayerLoadingGui extends GuiImage {
|
||||
var loadText:GuiText;
|
||||
var loadTextBg:GuiText;
|
||||
var loadAnim:GuiLoadAnim;
|
||||
var bottomBar:GuiControl;
|
||||
var innerCtrl:GuiControl;
|
||||
|
||||
public function new(missionName:String) {
|
||||
public function new(initialStatus:String) {
|
||||
var res = ResourceLoader.getImage("data/ui/game/CloudBG.jpg").resource.toTile();
|
||||
super(res);
|
||||
this.position = new Vector();
|
||||
|
|
@ -31,7 +34,7 @@ class MultiplayerLoadingGui extends GuiImage {
|
|||
@:privateAccess arial14b.loader = ResourceLoader.loader;
|
||||
var arial14 = arial14b.toSdfFont(cast 21 * Settings.uiScale, h2d.Font.SDFChannel.MultiChannel);
|
||||
|
||||
var loadAnim = new GuiLoadAnim();
|
||||
loadAnim = new GuiLoadAnim();
|
||||
loadAnim.position = new Vector(610, 253);
|
||||
loadAnim.extent = new Vector(63, 63);
|
||||
loadAnim.horizSizing = Center;
|
||||
|
|
@ -44,7 +47,7 @@ class MultiplayerLoadingGui extends GuiImage {
|
|||
loadTextBg.horizSizing = Center;
|
||||
loadTextBg.vertSizing = Bottom;
|
||||
loadTextBg.justify = Center;
|
||||
loadTextBg.text.text = "Loading";
|
||||
loadTextBg.text.text = initialStatus;
|
||||
loadTextBg.text.textColor = 0;
|
||||
this.addChild(loadTextBg);
|
||||
|
||||
|
|
@ -54,12 +57,69 @@ class MultiplayerLoadingGui extends GuiImage {
|
|||
loadText.horizSizing = Center;
|
||||
loadText.vertSizing = Bottom;
|
||||
loadText.justify = Center;
|
||||
loadText.text.text = "Loading";
|
||||
loadText.text.text = initialStatus;
|
||||
this.addChild(loadText);
|
||||
|
||||
#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);
|
||||
|
||||
bottomBar = new GuiControl();
|
||||
bottomBar.position = new Vector(0, 590);
|
||||
bottomBar.extent = new Vector(640, 200);
|
||||
bottomBar.horizSizing = Width;
|
||||
bottomBar.vertSizing = Bottom;
|
||||
innerCtrl.addChild(bottomBar);
|
||||
}
|
||||
|
||||
public function setLoadingStatus(str:String) {
|
||||
loadText.text.text = str;
|
||||
loadTextBg.text.text = str;
|
||||
}
|
||||
|
||||
public function setErrorStatus(str:String) {
|
||||
loadText.text.text = str;
|
||||
loadTextBg.text.text = str;
|
||||
loadAnim.anim.visible = false;
|
||||
|
||||
var backButton = new GuiXboxButton("Ok", 160);
|
||||
backButton.position = new Vector(960, 0);
|
||||
backButton.vertSizing = Bottom;
|
||||
backButton.horizSizing = Right;
|
||||
backButton.gamepadAccelerator = ["A"];
|
||||
backButton.accelerators = [hxd.Key.ENTER];
|
||||
backButton.pressedAction = (e) -> {
|
||||
MarbleGame.canvas.setContent(new MultiplayerGui());
|
||||
};
|
||||
bottomBar.addChild(backButton);
|
||||
MarbleGame.canvas.render(MarbleGame.canvas.scene2d);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,15 @@ class InputBitStream {
|
|||
public function readFloat() {
|
||||
return FPHelper.i32ToFloat(readInt32());
|
||||
}
|
||||
|
||||
public function readString() {
|
||||
var length = readByte();
|
||||
var str = "";
|
||||
for (i in 0...length) {
|
||||
str += String.fromCharCode(readByte());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
class OutputBitStream {
|
||||
|
|
@ -135,4 +144,11 @@ class OutputBitStream {
|
|||
public function writeFloat(value:Float) {
|
||||
writeInt(FPHelper.floatToI32(value), 32);
|
||||
}
|
||||
|
||||
public function writeString(value:String) {
|
||||
writeByte(value.length);
|
||||
for (i in 0...value.length) {
|
||||
writeByte(StringTools.fastCodeAt(value, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class ClientConnection extends GameConnection {
|
|||
this.datachannel = datachannel;
|
||||
this.state = GameplayState.LOBBY;
|
||||
this.rtt = 0;
|
||||
this.name = "Unknown";
|
||||
}
|
||||
|
||||
override function sendBytes(b:Bytes) {
|
||||
|
|
@ -38,6 +39,7 @@ class DummyConnection extends GameConnection {
|
|||
public function new(id:Int) {
|
||||
super(id);
|
||||
this.state = GameplayState.GAME;
|
||||
this.lobbyReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,16 +48,23 @@ abstract class GameConnection {
|
|||
var id:Int;
|
||||
var state:GameplayState;
|
||||
var moveManager:MoveManager;
|
||||
var name:String;
|
||||
var lobbyReady:Bool;
|
||||
|
||||
public function new(id:Int) {
|
||||
this.id = id;
|
||||
this.moveManager = new MoveManager(this);
|
||||
this.lobbyReady = false;
|
||||
}
|
||||
|
||||
public function ready() {
|
||||
state = GameplayState.GAME;
|
||||
}
|
||||
|
||||
public function toggleLobbyReady() {
|
||||
lobbyReady = !lobbyReady;
|
||||
}
|
||||
|
||||
public function queueMove(m:NetMove) {
|
||||
moveManager.queueMove(m);
|
||||
}
|
||||
|
|
@ -81,4 +90,12 @@ abstract class GameConnection {
|
|||
}
|
||||
|
||||
public function sendBytes(b:haxe.io.Bytes) {}
|
||||
|
||||
public inline function getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public inline function setName(value:String) {
|
||||
name = value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package net;
|
||||
|
||||
import h3d.Vector;
|
||||
import net.NetPacket.MarbleNetFlags;
|
||||
import net.NetPacket.MarbleUpdatePacket;
|
||||
import net.Net;
|
||||
|
|
@ -11,6 +12,7 @@ class OtherMarbleUpdate {
|
|||
var lastHeliTick:Int;
|
||||
var lastMegaTick:Int;
|
||||
var lastPowerUpId:Int;
|
||||
var lastGravityUp:Vector;
|
||||
|
||||
public function new() {}
|
||||
}
|
||||
|
|
@ -48,6 +50,10 @@ class MarbleUpdateQueue {
|
|||
update.powerUpId = otherUpdate.lastPowerUpId;
|
||||
else
|
||||
otherUpdate.lastPowerUpId = update.powerUpId;
|
||||
if (update.netFlags & MarbleNetFlags.GravityChange == 0)
|
||||
update.gravityDirection = otherUpdate.lastGravityUp;
|
||||
else
|
||||
otherUpdate.lastGravityUp = update.gravityDirection;
|
||||
ourList.push(update);
|
||||
} else {
|
||||
var otherUpdate = new OtherMarbleUpdate();
|
||||
|
|
@ -61,6 +67,8 @@ class MarbleUpdateQueue {
|
|||
otherUpdate.lastMegaTick = update.megaTick;
|
||||
if (update.netFlags & MarbleNetFlags.PickupPowerup != 0)
|
||||
otherUpdate.lastPowerUpId = update.powerUpId;
|
||||
if (update.netFlags & MarbleNetFlags.GravityChange != 0)
|
||||
otherUpdate.lastGravityUp = update.gravityDirection;
|
||||
otherMarbleUpdates[cc] = otherUpdate;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -75,6 +83,8 @@ class MarbleUpdateQueue {
|
|||
update.megaTick = myMarbleUpdate.megaTick;
|
||||
if (update.netFlags & MarbleNetFlags.PickupPowerup == 0)
|
||||
update.powerUpId = myMarbleUpdate.powerUpId;
|
||||
if (update.netFlags & MarbleNetFlags.GravityChange == 0)
|
||||
update.gravityDirection = myMarbleUpdate.gravityDirection;
|
||||
}
|
||||
myMarbleUpdate = update;
|
||||
ourMoveApplied = false;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import net.Net.ServerInfo;
|
|||
import hx.ws.WebSocket;
|
||||
import src.Console;
|
||||
import hx.ws.Types.MessageType;
|
||||
import gui.MultiplayerLoadingGui;
|
||||
|
||||
typedef RemoteServerInfo = {
|
||||
name:String,
|
||||
|
|
@ -93,7 +94,7 @@ class MasterServerClient {
|
|||
if (conts.type == "connect") {
|
||||
if (!Net.isHost) {
|
||||
ws.send(Json.stringify({
|
||||
type: "connectResponse",
|
||||
type: "connectFailed",
|
||||
success: false,
|
||||
reason: "The server has shut down"
|
||||
}));
|
||||
|
|
@ -101,7 +102,7 @@ class MasterServerClient {
|
|||
}
|
||||
if (Net.serverInfo.players >= Net.serverInfo.maxPlayers) {
|
||||
ws.send(Json.stringify({
|
||||
type: "connectResponse",
|
||||
type: "connectFailed",
|
||||
success: false,
|
||||
reason: "The server is full"
|
||||
}));
|
||||
|
|
@ -122,7 +123,10 @@ class MasterServerClient {
|
|||
@:privateAccess Net.client.setRemoteDescription(sdpObj.sdp, sdpObj.type);
|
||||
}
|
||||
if (conts.type == "connectFailed") {
|
||||
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg(conts.reason));
|
||||
var loadGui:MultiplayerLoadingGui = cast MarbleGame.canvas.content;
|
||||
if (loadGui != null) {
|
||||
loadGui.setErrorStatus(conts.reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
142
src/net/Net.hx
142
src/net/Net.hx
|
|
@ -1,5 +1,9 @@
|
|||
package net;
|
||||
|
||||
import gui.MultiplayerLevelSelectGui;
|
||||
import gui.Canvas;
|
||||
import net.MasterServerClient.RemoteServerInfo;
|
||||
import gui.MultiplayerLoadingGui;
|
||||
import src.ResourceLoader;
|
||||
import src.AudioManager;
|
||||
import net.NetPacket.GemPickupPacket;
|
||||
|
|
@ -18,6 +22,7 @@ import src.Console;
|
|||
import net.NetCommands;
|
||||
import src.MarbleGame;
|
||||
import hx.ws.Types.MessageType;
|
||||
import src.Settings;
|
||||
|
||||
enum abstract NetPacketType(Int) from Int to Int {
|
||||
var NullPacket;
|
||||
|
|
@ -60,13 +65,11 @@ class Net {
|
|||
static var client:RTCPeerConnection;
|
||||
static var clientDatachannel:RTCDataChannel;
|
||||
|
||||
static var masterWs:WebSocket;
|
||||
|
||||
public static var isMP:Bool;
|
||||
public static var isHost:Bool;
|
||||
public static var isClient:Bool;
|
||||
|
||||
public static var startMP:Bool;
|
||||
public static var lobbyHostReady:Bool;
|
||||
|
||||
public static var clientId:Int;
|
||||
public static var networkRNG:Float;
|
||||
|
|
@ -74,6 +77,7 @@ class Net {
|
|||
public static var clientIdMap:Map<Int, GameConnection> = [];
|
||||
public static var clientConnection:ClientConnection;
|
||||
public static var serverInfo:ServerInfo;
|
||||
public static var remoteServerInfo:RemoteServerInfo;
|
||||
|
||||
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());
|
||||
|
|
@ -84,30 +88,6 @@ class Net {
|
|||
isMP = true;
|
||||
MasterServerClient.instance.sendServerInfo(serverInfo);
|
||||
});
|
||||
|
||||
// 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");
|
||||
|
||||
// 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): {}
|
||||
// }
|
||||
// }
|
||||
|
||||
// isMP = true;
|
||||
}
|
||||
|
||||
public static function addClientFromSdp(sdpString:String, onFinishSdp:String->Void) {
|
||||
|
|
@ -167,6 +147,10 @@ class Net {
|
|||
|
||||
clientDatachannel = client.createDatachannel("mp");
|
||||
clientDatachannel.onOpen = (n) -> {
|
||||
var loadGui:MultiplayerLoadingGui = cast MarbleGame.canvas.content;
|
||||
if (loadGui != null) {
|
||||
loadGui.setLoadingStatus("Handshaking");
|
||||
}
|
||||
Console.log("Successfully connected!");
|
||||
clients.set(client, new ClientConnection(0, client, clientDatachannel)); // host is always 0
|
||||
clientIdMap[0] = clients[client];
|
||||
|
|
@ -182,6 +166,11 @@ class Net {
|
|||
if (MarbleGame.instance.world != null) {
|
||||
MarbleGame.instance.quitMission();
|
||||
}
|
||||
if (!(MarbleGame.canvas.content is MultiplayerLoadingGui)) {
|
||||
var loadGui = new MultiplayerLoadingGui("Server closed");
|
||||
MarbleGame.canvas.setContent(loadGui);
|
||||
loadGui.setErrorStatus("Server closed");
|
||||
}
|
||||
}
|
||||
clientDatachannel.onError = (msg) -> {
|
||||
Console.log('Errored out due to ${msg}');
|
||||
|
|
@ -189,63 +178,15 @@ class Net {
|
|||
if (MarbleGame.instance.world != null) {
|
||||
MarbleGame.instance.quitMission();
|
||||
}
|
||||
var loadGui = new MultiplayerLoadingGui("Connection error");
|
||||
MarbleGame.canvas.setContent(loadGui);
|
||||
loadGui.setErrorStatus("Connection error");
|
||||
}
|
||||
|
||||
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;
|
||||
// }
|
||||
}
|
||||
|
||||
public static function disconnect() {
|
||||
|
|
@ -259,6 +200,9 @@ class Net {
|
|||
Net.clientId = 0;
|
||||
Net.clientIdMap.clear();
|
||||
Net.clientConnection = null;
|
||||
Net.serverInfo = null;
|
||||
Net.remoteServerInfo = null;
|
||||
Net.lobbyHostReady = false;
|
||||
}
|
||||
if (Net.isHost) {
|
||||
NetCommands.serverClosed();
|
||||
|
|
@ -271,6 +215,9 @@ class Net {
|
|||
Net.clients.clear();
|
||||
Net.clientIdMap.clear();
|
||||
MasterServerClient.disconnectFromMasterServer();
|
||||
Net.serverInfo = null;
|
||||
Net.remoteServerInfo = null;
|
||||
Net.lobbyHostReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +255,10 @@ class Net {
|
|||
|
||||
serverInfo.players++;
|
||||
MasterServerClient.instance.sendServerInfo(serverInfo); // notify the server of the new player
|
||||
|
||||
if (MarbleGame.canvas.content is MultiplayerLevelSelectGui) {
|
||||
cast(MarbleGame.canvas.content, MultiplayerLevelSelectGui).updateLobbyNames();
|
||||
}
|
||||
}
|
||||
|
||||
static function onConnectedToServer() {
|
||||
|
|
@ -327,6 +278,12 @@ class Net {
|
|||
serverInfo.players--;
|
||||
MasterServerClient.instance.sendServerInfo(serverInfo); // notify the server of the player leave
|
||||
NetCommands.clientDisconnected(cc.id);
|
||||
|
||||
AudioManager.playSound(ResourceLoader.getAudio("data/sound/infotutorial.wav").resource);
|
||||
|
||||
if (MarbleGame.canvas.content is MultiplayerLevelSelectGui) {
|
||||
cast(MarbleGame.canvas.content, MultiplayerLevelSelectGui).updateLobbyNames();
|
||||
}
|
||||
}
|
||||
|
||||
static function sendPlayerInfosBytes() {
|
||||
|
|
@ -335,9 +292,22 @@ class Net {
|
|||
var cnt = 0;
|
||||
for (c in clientIdMap)
|
||||
cnt++;
|
||||
b.writeByte(cnt);
|
||||
for (c => v in clientIdMap)
|
||||
b.writeByte(cnt + 1); // all + host
|
||||
for (c => v in clientIdMap) {
|
||||
b.writeByte(c);
|
||||
var name = v.getName();
|
||||
b.writeByte(name.length);
|
||||
for (i in 0...name.length) {
|
||||
b.writeByte(StringTools.fastCodeAt(name, i));
|
||||
}
|
||||
}
|
||||
// Write host data
|
||||
b.writeByte(0);
|
||||
var name = Settings.highscoreName;
|
||||
b.writeByte(name.length);
|
||||
for (i in 0...name.length) {
|
||||
b.writeByte(StringTools.fastCodeAt(name, i));
|
||||
}
|
||||
return b.getBytes();
|
||||
}
|
||||
|
||||
|
|
@ -352,6 +322,7 @@ class Net {
|
|||
case ClientIdAssign:
|
||||
clientId = input.readByte(); // 8 bit client id, hopefully we don't exceed this
|
||||
Console.log('Client ID set to ${clientId}');
|
||||
NetCommands.setPlayerName(clientId, Settings.highscoreName); // Send our player name to the server
|
||||
|
||||
case Ping:
|
||||
var pingLeft = input.readByte();
|
||||
|
|
@ -435,10 +406,21 @@ class Net {
|
|||
addGhost(id);
|
||||
newP = true;
|
||||
}
|
||||
var nameLength = input.readByte();
|
||||
var name = "";
|
||||
for (j in 0...nameLength) {
|
||||
name += String.fromCharCode(input.readByte());
|
||||
}
|
||||
if (clientIdMap.exists(id)) {
|
||||
clientIdMap[id].setName(name);
|
||||
}
|
||||
}
|
||||
if (newP) {
|
||||
AudioManager.playSound(ResourceLoader.getAudio("sounds/spawn_alternate.wav").resource);
|
||||
}
|
||||
if (MarbleGame.canvas.content is MultiplayerLevelSelectGui) {
|
||||
cast(MarbleGame.canvas.content, MultiplayerLevelSelectGui).updateLobbyNames();
|
||||
}
|
||||
|
||||
case _:
|
||||
Console.log("unknown command: " + packetType);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import net.ClientConnection.GameplayState;
|
|||
import net.Net.NetPacketType;
|
||||
import gui.MultiplayerLevelSelectGui;
|
||||
import src.MarbleGame;
|
||||
import gui.MultiplayerLoadingGui;
|
||||
|
||||
@:build(net.RPCMacro.build())
|
||||
class NetCommands {
|
||||
|
|
@ -28,13 +29,34 @@ class NetCommands {
|
|||
}
|
||||
}
|
||||
|
||||
@:rpc(client) public static function toggleReadiness(clientId:Int) {
|
||||
if (Net.isHost) {
|
||||
if (clientId == 0)
|
||||
Net.lobbyHostReady = !Net.lobbyHostReady;
|
||||
else
|
||||
Net.clientIdMap[clientId].toggleLobbyReady();
|
||||
var allReady = true;
|
||||
for (id => client in Net.clientIdMap) {
|
||||
if (!client.lobbyReady) {
|
||||
allReady = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allReady && Net.lobbyHostReady) {
|
||||
NetCommands.playLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@:rpc(client) public static function clientIsReady(clientId:Int) {
|
||||
if (Net.isHost) {
|
||||
Net.clientIdMap[clientId].ready();
|
||||
var allReady = true;
|
||||
for (id => client in Net.clientIdMap) {
|
||||
if (client.state != GameplayState.GAME)
|
||||
if (client.state != GameplayState.GAME) {
|
||||
allReady = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allReady) {
|
||||
if (MarbleGame.instance.world != null) {
|
||||
|
|
@ -66,6 +88,9 @@ class NetCommands {
|
|||
MarbleGame.instance.world.removePlayer(conn);
|
||||
}
|
||||
Net.clientIdMap.remove(clientId);
|
||||
if (MarbleGame.canvas.content is MultiplayerLevelSelectGui) {
|
||||
cast(MarbleGame.canvas.content, MultiplayerLevelSelectGui).updateLobbyNames();
|
||||
}
|
||||
}
|
||||
|
||||
@:rpc(server) public static function clientJoin(clientId:Int) {}
|
||||
|
|
@ -81,6 +106,18 @@ class NetCommands {
|
|||
if (MarbleGame.instance.world != null) {
|
||||
MarbleGame.instance.quitMission();
|
||||
}
|
||||
var loadGui = new MultiplayerLoadingGui("Server closed");
|
||||
MarbleGame.canvas.setContent(loadGui);
|
||||
loadGui.setErrorStatus("Server closed");
|
||||
}
|
||||
}
|
||||
|
||||
@:rpc(client) public static function setPlayerName(clientId:Int, name:String) {
|
||||
if (Net.isHost) {
|
||||
Net.clientIdMap[clientId].setName(name);
|
||||
if (MarbleGame.canvas.content is MultiplayerLevelSelectGui) {
|
||||
cast(MarbleGame.canvas.content, MultiplayerLevelSelectGui).updateLobbyNames();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ enum abstract MarbleNetFlags(Int) from Int to Int {
|
|||
var DoHelicopter = 1 << 1;
|
||||
var DoMega = 1 << 2;
|
||||
var PickupPowerup = 1 << 3;
|
||||
var GravityChange = 1 << 4;
|
||||
}
|
||||
|
||||
@:publicFields
|
||||
|
|
@ -52,6 +53,7 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
var blastTick:Int;
|
||||
var megaTick:Int;
|
||||
var heliTick:Int;
|
||||
var gravityDirection:Vector;
|
||||
var oob:Bool;
|
||||
var powerUpId:Int;
|
||||
var moveQueueSize:Int;
|
||||
|
|
@ -99,6 +101,14 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
} else {
|
||||
b.writeFlag(false);
|
||||
}
|
||||
if (netFlags & MarbleNetFlags.GravityChange > 0) {
|
||||
b.writeFlag(true);
|
||||
b.writeFloat(gravityDirection.x);
|
||||
b.writeFloat(gravityDirection.y);
|
||||
b.writeFloat(gravityDirection.z);
|
||||
} else {
|
||||
b.writeFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
public inline function deserialize(b:InputBitStream) {
|
||||
|
|
@ -126,9 +136,12 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
oob = b.readFlag();
|
||||
if (b.readFlag()) {
|
||||
powerUpId = b.readInt(9);
|
||||
trace('pickup: ${powerUpId}');
|
||||
this.netFlags |= MarbleNetFlags.PickupPowerup;
|
||||
}
|
||||
if (b.readFlag()) {
|
||||
gravityDirection = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
||||
this.netFlags |= MarbleNetFlags.GravityChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,14 @@ class RPCMacro {
|
|||
serializeFns.push(macro stream.writeFloat($i{argName}));
|
||||
}
|
||||
|
||||
case TPath({
|
||||
name: 'String'
|
||||
}): {
|
||||
deserializeFns.push(macro var $argName = stream.readString());
|
||||
callExprs.push(macro $i{argName});
|
||||
serializeFns.push(macro stream.writeString($i{argName}));
|
||||
}
|
||||
|
||||
case _: {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue