diff --git a/data/ui/mp/kickban/window.png b/data/ui/mp/kickban/window.png index e2a3301d..d06a1732 100644 Binary files a/data/ui/mp/kickban/window.png and b/data/ui/mp/kickban/window.png differ diff --git a/src/Marble.hx b/src/Marble.hx index eecdcf04..e16025dd 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -392,7 +392,7 @@ class Marble extends GameObject { marbleDts.dtsPath = Settings.optionsSettings.marbleModel; marbleDts.matNameOverride.set("base.marble", Settings.optionsSettings.marbleSkin + ".marble"); } else { - var marbleData = MarbleSelectGui.marbleData[0][connection.getMarbleId()]; // FIXME category support + var marbleData = MarbleSelectGui.marbleData[connection.getMarbleCatId()][connection.getMarbleId()]; // FIXME category support Console.log("Marble: " + marbleData.dts + " (" + marbleData.skin + ")"); marbleDts.dtsPath = marbleData.dts; marbleDts.matNameOverride.set("base.marble", marbleData.skin + ".marble"); @@ -557,7 +557,7 @@ class Marble extends GameObject { this.megaHelicopter = new DtsObject(); this.megaHelicopter.dtsPath = "data/shapes/items/megahelicopter.dts"; - this.megaHelicopter.useInstancing = true; + this.megaHelicopter.useInstancing = false; this.megaHelicopter.identifier = "MegaHelicopter"; this.megaHelicopter.showSequences = true; this.megaHelicopter.isBoundingBoxCollideable = false; diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 857ed409..79bd849e 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -1290,10 +1290,11 @@ class MarbleWorld extends Scheduler { restart(marble, true); } - startTime = this.timeState.timeSinceLoad + 3.5; + startTime = this.timeState.timeSinceLoad + 4; if (Net.isHost) { haxe.Timer.delay(() -> { + this.gameMode.onRestart(); NetCommands.setStartTicks(this.timeState.ticks); }, 500); } diff --git a/src/gui/JoinServerGui.hx b/src/gui/JoinServerGui.hx index 3d67d6fa..3cfadcf7 100644 --- a/src/gui/JoinServerGui.hx +++ b/src/gui/JoinServerGui.hx @@ -121,13 +121,9 @@ class JoinServerGui extends GuiImage { var failed = true; haxe.Timer.delay(() -> { if (failed) { - // if (MarbleGame.canvas.content is MultiplayerLoadingGui) { - // var loadGui:MultiplayerLoadingGui = cast MarbleGame.canvas.content; - // if (loadGui != null) { - // loadGui.setErrorStatus("Failed to connect to server. Please try again."); + MarbleGame.canvas.setContent(new JoinServerGui()); + MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Failed to connect to server. Please try again.")); Net.disconnect(); - // } - // } } }, 15000); Net.joinServer(ourServerList[curSelection].name, "", () -> { diff --git a/src/gui/MPKickBanDlg.hx b/src/gui/MPKickBanDlg.hx new file mode 100644 index 00000000..4e10955e --- /dev/null +++ b/src/gui/MPKickBanDlg.hx @@ -0,0 +1,112 @@ +package gui; + +import net.NetCommands; +import net.Net; +import h2d.filter.DropShadow; +import hxd.res.BitmapFont; +import h3d.prim.Polygon; +import h3d.scene.Mesh; +import h3d.shader.AlphaChannel; +import src.MarbleGame; +import h3d.Vector; +import src.ResourceLoader; +import src.DtsObject; +import src.Settings; +import src.ResourceLoaderWorker; + +class MPKickBanDlg extends GuiImage { + public function new() { + var img = ResourceLoader.getImage("data/ui/mp/kickban/window.png"); + super(img.resource.toTile()); + this.horizSizing = Center; + this.vertSizing = Center; + this.position = new Vector(226, 137); + this.extent = new Vector(409, 316); + + 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]; + } + + function loadButtonImagesExt(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(); + var disabled = ResourceLoader.getResource('${path}_i.png', ResourceLoader.getImage, this.imageResources).toTile(); + return [normal, hover, pressed, disabled]; + } + + var markerFelt32fontdata = ResourceLoader.getFileEntry("data/font/MarkerFelt.fnt"); + var markerFelt32b = new BitmapFont(markerFelt32fontdata.entry); + @:privateAccess markerFelt32b.loader = ResourceLoader.loader; + var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); + var markerFelt24 = markerFelt32b.toSdfFont(cast 20 * Settings.uiScale, MultiChannel); + var markerFelt20 = markerFelt32b.toSdfFont(cast 18.5 * Settings.uiScale, MultiChannel); + var markerFelt18 = markerFelt32b.toSdfFont(cast 17 * Settings.uiScale, MultiChannel); + var markerFelt26 = markerFelt32b.toSdfFont(cast 22 * Settings.uiScale, MultiChannel); + + var closeBtn = new GuiButton(loadButtonImages("data/ui/mp/team/close")); + closeBtn.position = new Vector(247, 254); + closeBtn.extent = new Vector(94, 45); + closeBtn.vertSizing = Bottom; + closeBtn.horizSizing = Right; + closeBtn.pressedAction = (e) -> { + MarbleGame.canvas.popDialog(this); + } + this.addChild(closeBtn); + + var kickBtn = new GuiButton(loadButtonImagesExt("data/ui/mp/kickban/kick")); + kickBtn.position = new Vector(77, 254); + kickBtn.extent = new Vector(94, 45); + kickBtn.vertSizing = Bottom; + kickBtn.horizSizing = Right; + kickBtn.disabled = true; + this.addChild(kickBtn); + + var kickTitle = new GuiText(markerFelt32); + kickTitle.text.textColor = 0xFFFFFF; + kickTitle.text.text = "Kick Players"; + kickTitle.text.dropShadow = { + dx: 1, + dy: 1, + alpha: 0.5, + color: 0 + }; + kickTitle.justify = Center; + kickTitle.position = new Vector(11, 17); + kickTitle.extent = new Vector(388, 14); + this.addChild(kickTitle); + + var playerNames = []; + var playerIds = []; + for (c in Net.clients) { + playerNames.push(c.getName()); + playerIds.push(c.id); + } + + var kickPlayerId = -1; + + var playerList = new GuiTextListCtrl(markerFelt18, playerNames, 0); + playerList.position = new Vector(120, 60); + playerList.extent = new Vector(188, 180); + playerList.textYOffset = -6; + playerList.onSelectedFunc = (sel) -> { + kickBtn.disabled = false; + kickPlayerId = playerIds[sel]; + } + this.addChild(playerList); + + kickBtn.pressedAction = (e) -> { + if (Net.clientIdMap.exists(kickPlayerId)) { + var playerToKick = kickPlayerId; + playerNames.remove(Net.clientIdMap.get(playerToKick).getName()); + playerIds.remove(playerToKick); + playerList.setTexts(playerNames); + kickBtn.disabled = true; + NetCommands.getKickedClient(Net.clientIdMap.get(playerToKick)); + } + } + } +} diff --git a/src/gui/MPMarbleSelectGui.hx b/src/gui/MPMarbleSelectGui.hx index 59929bae..e15ca503 100644 --- a/src/gui/MPMarbleSelectGui.hx +++ b/src/gui/MPMarbleSelectGui.hx @@ -1,5 +1,7 @@ package gui; +import net.Net; +import net.NetCommands; import h2d.filter.DropShadow; import hxd.res.BitmapFont; import h3d.prim.Polygon; @@ -54,6 +56,18 @@ class MPMarbleSelectGui extends GuiImage { Settings.optionsSettings.marbleShader = MarbleSelectGui.marbleData[curCategorySelection][curSelection].shader; Settings.save(); MarbleGame.canvas.popDialog(this); + + // Transmit changes to the server/clients + if (Net.isClient) { + NetCommands.setPlayerData(Net.clientId, Settings.highscoreName, Settings.optionsSettings.marbleIndex, + Settings.optionsSettings.marbleCategoryIndex, true); + } + if (Net.isHost) { + var b = Net.sendPlayerInfosBytes(); + for (cc in Net.clients) { + cc.sendBytes(b); + } + } } this.addChild(selectBtn); diff --git a/src/gui/MPPlayMissionGui.hx b/src/gui/MPPlayMissionGui.hx index dc104f8d..04202d46 100644 --- a/src/gui/MPPlayMissionGui.hx +++ b/src/gui/MPPlayMissionGui.hx @@ -163,6 +163,9 @@ class MPPlayMissionGui extends GuiImage { var kickBtn = new GuiButton(loadButtonImages("data/ui/mp/play/kick")); kickBtn.position = new Vector(304, 514); kickBtn.extent = new Vector(44, 44); + kickBtn.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new MPKickBanDlg()); + } if (Net.isHost) window.addChild(kickBtn); diff --git a/src/gui/MPPreGameDlg.hx b/src/gui/MPPreGameDlg.hx index fe48d35c..28af5676 100644 --- a/src/gui/MPPreGameDlg.hx +++ b/src/gui/MPPreGameDlg.hx @@ -96,6 +96,9 @@ class MPPreGameDlg extends GuiControl { kickBtn.vertSizing = Bottom; kickBtn.position = new Vector(360, 388); kickBtn.extent = new Vector(45, 45); + kickBtn.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new MPKickBanDlg()); + } if (Net.isHost) dialogImg.addChild(kickBtn); diff --git a/src/net/MasterServerClient.hx b/src/net/MasterServerClient.hx index cab214ad..5a606213 100644 --- a/src/net/MasterServerClient.hx +++ b/src/net/MasterServerClient.hx @@ -1,5 +1,6 @@ package net; +import gui.JoinServerGui; import gui.MessageBoxOkDlg; import src.MarbleGame; import haxe.Json; @@ -294,10 +295,8 @@ class MasterServerClient { @: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); - // } + MarbleGame.canvas.setContent(new JoinServerGui()); + MarbleGame.canvas.pushDialog(new MessageBoxOkDlg(conts.reason)); } if (conts.type == "turnserver") { Net.turnServer = conts.server; // Turn server! diff --git a/src/net/Net.hx b/src/net/Net.hx index cea059e3..5433e7e4 100644 --- a/src/net/Net.hx +++ b/src/net/Net.hx @@ -1,5 +1,7 @@ package net; +import gui.MessageBoxOkDlg; +import gui.JoinServerGui; import gui.MPPreGameDlg; import net.NetPacket.ScoreboardPacket; import gui.MPPlayMissionGui; @@ -212,14 +214,8 @@ class Net { MarbleGame.instance.quitMission(); } if (!weLeftOurselves || forceShow) { - // if (!(MarbleGame.canvas.content is MultiplayerLoadingGui)) { - // var loadGui = new MultiplayerLoadingGui(msg); - // MarbleGame.canvas.setContent(loadGui); - // loadGui.setErrorStatus(msg); - // } else { - // var loadGui = cast(MarbleGame.canvas.content, MultiplayerLoadingGui); - // loadGui.setErrorStatus(msg); - // } + MarbleGame.canvas.setContent(new JoinServerGui()); + MarbleGame.canvas.pushDialog(new MessageBoxOkDlg(msg)); } } @@ -232,7 +228,7 @@ class Net { switch (s) { case RTC_CLOSED: Console.log("RTC State change: Connection closed!"); - closeFunc("Connection closed", true); + closeFunc("Connection closed", false); case RTC_CONNECTED: Console.log("RTC State change: Connected!"); case RTC_CONNECTING: @@ -312,12 +308,12 @@ class Net { } var onDatachannelClose = (dc:RTCDataChannel) -> { - closeFunc("Disconnected", true); + closeFunc("Disconnected", false); } var onDatachannelError = (msg:String) -> { Console.log('Errored out due to ${msg}'); - closeFunc("Connection error", true); + closeFunc("Connection error", false); } clientDatachannel.onOpen = (n) -> { @@ -424,11 +420,8 @@ class Net { if (MarbleGame.instance.world != null) { MarbleGame.instance.quitMission(); } - // if (!(MarbleGame.canvas.content is MultiplayerLoadingGui)) { - // var loadGui = new MultiplayerLoadingGui("Timed out"); - // MarbleGame.canvas.setContent(loadGui); - // loadGui.setErrorStatus("Timed out"); - // } + MarbleGame.canvas.setContent(new JoinServerGui()); + MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Timed out")); } } } @@ -660,7 +653,7 @@ class Net { clientId = input.readByte(); // 8 bit client id, hopefully we don't exceed this Console.log('Client ID set to ${clientId}'); NetCommands.setPlayerData(clientId, Settings.highscoreName, Settings.optionsSettings.marbleIndex, - Settings.optionsSettings.marbleCategoryIndex); // Send our player name to the server + Settings.optionsSettings.marbleCategoryIndex, false); // Send our player name to the server NetCommands.transmitPlatform(clientId, getPlatform()); // send our platform too case Ping: diff --git a/src/net/NetCommands.hx b/src/net/NetCommands.hx index 2967961d..9d868c00 100644 --- a/src/net/NetCommands.hx +++ b/src/net/NetCommands.hx @@ -1,5 +1,7 @@ package net; +import gui.MessageBoxOkDlg; +import gui.JoinServerGui; import gui.MPExitGameDlg; import gui.MPEndGameGui; import gui.MPPreGameDlg; @@ -262,19 +264,32 @@ class NetCommands { if (MarbleGame.instance.world != null) { MarbleGame.instance.quitMission(); } - // var loadGui = new MultiplayerLoadingGui("Server closed"); - // MarbleGame.canvas.setContent(loadGui); - // loadGui.setErrorStatus("Server closed"); + MarbleGame.canvas.setContent(new JoinServerGui()); + MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Server closed")); } } - @:rpc(client) public static function setPlayerData(clientId:Int, name:String, marble:Int, marbleCat:Int) { + @:rpc(server) public static function getKicked() { + if (Net.isClient) { + Net.disconnect(); + MarbleGame.canvas.setContent(new JoinServerGui()); + MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Kicked from server")); + } + } + + @:rpc(client) public static function setPlayerData(clientId:Int, name:String, marble:Int, marbleCat:Int, needRetransmit:Bool) { if (Net.isHost) { Net.clientIdMap[clientId].setName(name); Net.clientIdMap[clientId].setMarbleId(marble, marbleCat); if (MarbleGame.canvas.content is MPPlayMissionGui) { cast(MarbleGame.canvas.content, MPPlayMissionGui).updateLobbyNames(); } + if (needRetransmit) { + var b = Net.sendPlayerInfosBytes(); + for (cc in Net.clients) { + cc.sendBytes(b); + } + } } }