diff --git a/source/online/GameClient.hx b/source/online/GameClient.hx index e62dbc73..f81ebff6 100644 --- a/source/online/GameClient.hx +++ b/source/online/GameClient.hx @@ -44,6 +44,7 @@ class GameClient { FlxG.autoPause = false; GameClient.room = room; + clearOnMessage(); GameClient.isOwner = true; GameClient.room.onError += (id:Int, e:String) -> { @@ -78,6 +79,7 @@ class GameClient { FlxG.autoPause = false; GameClient.room = room; + clearOnMessage(); GameClient.isOwner = false; GameClient.room.onError += (id:Int, e:String) -> { @@ -127,6 +129,7 @@ class GameClient { Sys.println("reconnected!"); GameClient.room = room; + clearOnMessage(); GameClient.room.onError += (id:Int, e:String) -> { Sys.println("Room.onError: " + id + " - " + e); @@ -175,12 +178,19 @@ class GameClient { } public static function isConnected() { - return client != null || reconnectTries > 0; + return client != null; } + @:access(io.colyseus.Room.onMessageHandlers) public static function clearOnMessage() { - if (GameClient.isConnected()) - @:privateAccess GameClient.room.onMessageHandlers.clear(); + if (GameClient.isConnected() && GameClient.room?.onMessageHandlers != null) + GameClient.room.onMessageHandlers.clear(); + + GameClient.room.onMessage("ping", function(message) { + Waiter.put(() -> { + GameClient.send("pong"); + }); + }); } public static function send(type:Dynamic, ?message:Null) { diff --git a/source/online/schema/Player.hx b/source/online/schema/Player.hx index 7b2702dc..d5745038 100644 --- a/source/online/schema/Player.hx +++ b/source/online/schema/Player.hx @@ -40,4 +40,7 @@ class Player extends Schema { @:type("boolean") public var hasEnded:Bool = false; + + @:type("number") + public var ping:Dynamic = 0; } diff --git a/source/online/states/FindRoom.hx b/source/online/states/FindRoom.hx index b6d431dc..134b9b91 100644 --- a/source/online/states/FindRoom.hx +++ b/source/online/states/FindRoom.hx @@ -106,7 +106,7 @@ class RoomText extends FlxText { public function new(room:RoomAvailable) { code = room.roomId; - daText = "Code: " + code + " | Player: " + room.metadata.name; + daText = "Code: " + code + " | Player: " + room.metadata.name + " | " + room.metadata.ping + "ms"; super(0, 0, FlxG.width, daText); setFormat("VCR OSD Mono", 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); diff --git a/source/online/states/Lobby.hx b/source/online/states/Lobby.hx index ff288b52..e14b8708 100644 --- a/source/online/states/Lobby.hx +++ b/source/online/states/Lobby.hx @@ -1,5 +1,6 @@ package online.states; +import lime.system.Clipboard; import haxe.Json; import states.MainMenuState; import openfl.events.KeyboardEvent; @@ -66,6 +67,8 @@ class Lobby extends MusicBeatState { override function create() { super.create(); + DiscordClient.changePresence("In online lobby.", null, null, true); + daName = ClientPrefs.data.nickname; var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat')); @@ -224,6 +227,10 @@ class Lobby extends MusicBeatState { newText = newText.toLowerCase(); } + if (key == 86 && e.ctrlKey) { + newText = Clipboard.text; + } + if (newText.length > 0) { inputString += newText; } diff --git a/source/online/states/Room.hx b/source/online/states/Room.hx index 6b880fa2..a357d3ee 100644 --- a/source/online/states/Room.hx +++ b/source/online/states/Room.hx @@ -1,5 +1,6 @@ package online.states; +import lime.system.Clipboard; import online.schema.Player; import backend.Rating; import backend.WeekData; @@ -28,6 +29,13 @@ class Room extends MusicBeatState { public function new() { super(); + if (GameClient.room.state.isPrivate) { + DiscordClient.changePresence("In a online room.", "Private room.", null, true); + } + else { + DiscordClient.changePresence("In a online room.", "Public room: " + GameClient.room.roomId, null, true); + } + WeekData.reloadWeekFiles(false); for (i in 0...WeekData.weeksList.length) { WeekData.setDirectoryFromWeek(WeekData.weeksLoaded.get(WeekData.weeksList[i])); @@ -43,11 +51,11 @@ class Room extends MusicBeatState { add(bg); player1Text = new FlxText(0, 50, 0, "PLAYER 1"); - player1Text.setFormat("VCR OSD Mono", 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + player1Text.setFormat("VCR OSD Mono", 25, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); add(player1Text); player2Text = new FlxText(0, 50, 0, "PLAYER 2"); - player2Text.setFormat("VCR OSD Mono", 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + player2Text.setFormat("VCR OSD Mono", 25, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); add(player2Text); roomCode = new FlxText(0, 0, FlxG.width, "????"); @@ -56,7 +64,7 @@ class Room extends MusicBeatState { roomCode.screenCenter(X); add(roomCode); - roomCodeTip = new FlxText(0, roomCode.y + roomCode.height + 5, FlxG.width, "(Press S to show your room code)"); + roomCodeTip = new FlxText(0, roomCode.y + roomCode.height + 5, FlxG.width, "(Press S to show your room code, CTRL+C to copy)"); roomCodeTip.setFormat("VCR OSD Mono", 18, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); roomCodeTip.screenCenter(X); add(roomCodeTip); @@ -154,7 +162,18 @@ class Room extends MusicBeatState { }); }); + GameClient.room.state.listen("isPrivate", (value, prev) -> { + if (value) { + DiscordClient.changePresence("In a online room.", "Private room.", null, true); + } + else { + DiscordClient.changePresence("In a online room.", "Public room: " + GameClient.room.roomId, null, true); + } + }); + updateTexts(); + + new FlxTimer().start(); } override function update(elapsed) { @@ -204,6 +223,10 @@ class Room extends MusicBeatState { GameClient.send("anarchyMode"); } } + + if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.C) { + Clipboard.text = GameClient.room.roomId; + } } player1Text.x = FlxG.width / 2 - 200 - player1Text.width; @@ -259,7 +282,8 @@ class Room extends MusicBeatState { "Goods: " + GameClient.room.state.player1.goods + "\n" + "Bads: " + GameClient.room.state.player1.bads + "\n" + "Shits: " + GameClient.room.state.player1.shits + "\n" + - "Misses: " + GameClient.room.state.player1.misses; + "Misses: " + GameClient.room.state.player1.misses + "\n" + + "Ping: " + GameClient.room.state.player1.ping + "ms"; if (GameClient.room.state.player2 != null) { player2Text.text = "PLAYER 2\n" + @@ -271,7 +295,8 @@ class Room extends MusicBeatState { "Goods: " + GameClient.room.state.player2.goods + "\n" + "Bads: " + GameClient.room.state.player2.bads + "\n" + "Shits: " + GameClient.room.state.player2.shits + "\n" + - "Misses: " + GameClient.room.state.player2.misses; + "Misses: " + GameClient.room.state.player2.misses + "\n" + + "Ping: " + GameClient.room.state.player2.ping + "ms"; } else { player2Text.text = "WAITING FOR OPPONENT..."; diff --git a/source/states/FreeplayState.hx b/source/states/FreeplayState.hx index fcd957f7..ca431d1e 100644 --- a/source/states/FreeplayState.hx +++ b/source/states/FreeplayState.hx @@ -1,5 +1,6 @@ package states; +import online.Alert; import online.Waiter; import haxe.crypto.Md5; import online.states.Room; @@ -179,6 +180,15 @@ class FreeplayState extends MusicBeatState add(text); updateTexts(); + + if (GameClient.isConnected()) { + GameClient.room.onMessage("log", function(message) { + Waiter.put(() -> { + Alert.alert("New message", message); + }); + }); + } + super.create(); } diff --git a/source/states/MainMenuState.hx b/source/states/MainMenuState.hx index b25d2bbe..8d40992c 100644 --- a/source/states/MainMenuState.hx +++ b/source/states/MainMenuState.hx @@ -17,7 +17,7 @@ import options.OptionsState; class MainMenuState extends MusicBeatState { - public static var psychOnlineVersion:String = "0.2.5"; + public static var psychOnlineVersion:String = "0.2.1"; public static var psychEngineVersion:String = '0.7.1h* (online)'; //This is also used for Discord RPC public static var curSelected:Int = 0; diff --git a/source/states/PlayState.hx b/source/states/PlayState.hx index 20ca5e5f..80c3645d 100644 --- a/source/states/PlayState.hx +++ b/source/states/PlayState.hx @@ -10,6 +10,7 @@ package states; // "function eventEarlyTrigger" - Used for making your event start a few MILLISECONDS earlier // "function triggerEvent" - Called when the song hits your event's timestamp, this is probably what you were looking for +import online.Alert; import online.Waiter; import online.states.Room; import online.GameClient; @@ -291,6 +292,14 @@ class PlayState extends MusicBeatState }; } + if (GameClient.isConnected()) { + GameClient.room.onMessage("log", function(message) { + Waiter.put(() -> { + Alert.alert("New message", message); + }); + }); + } + // for lua instance = this; @@ -590,8 +599,8 @@ class PlayState extends MusicBeatState scoreTxtP2.visible = !ClientPrefs.data.hideHud; add(scoreTxtP2); - scoreTxtP1.y -= scoreTxtP1.height * 2; - scoreTxtP2.y -= scoreTxtP2.height * 2; + scoreTxtP1.y -= scoreTxtP1.height * 3; + scoreTxtP2.y -= scoreTxtP2.height * 3; scoreTxtP1.offset.x -= 30; scoreTxtP2.offset.x += 30; @@ -1189,7 +1198,11 @@ class PlayState extends MusicBeatState } if (GameClient.isConnected()) { - scoreTextObject.text = (GameClient.isOwner ? GameClient.room.state.player1 : GameClient.room.state.player2).name + '\nScore: ' + songScore + '\nMisses: ' + songMisses + '\nRating: ' + str; + scoreTextObject.text = (GameClient.isOwner ? GameClient.room.state.player1 : GameClient.room.state.player2).name + + '\nScore: ' + songScore + + '\nMisses: ' + songMisses + + '\nRating: ' + str + + "\nPing: " + (GameClient.isOwner ? GameClient.room.state.player1 : GameClient.room.state.player2).ping; } else { scoreTextObject.text = 'Score: ' + songScore + ' | Misses: ' + songMisses + ' | Rating: ' + str; @@ -1676,9 +1689,15 @@ class PlayState extends MusicBeatState } #end - //if player 2 left then go back to lobby - if (GameClient.isConnected() && GameClient.room.state.player2.name == "") { - endSong(); + if (GameClient.isConnected()) { + if (controls.BACK) { + GameClient.send("requestEndSong"); + } + + //if player 2 left then go back to lobby + if (GameClient.room.state.player2.name == "") { + endSong(); + } } /*if (FlxG.keys.justPressed.NINE) @@ -1687,6 +1706,9 @@ class PlayState extends MusicBeatState }*/ callOnScripts('onUpdate', [elapsed]); + if (playbackRate != 1.) + playbackRate = 1; + if (cpuControlled && GameClient.isConnected()) { cpuControlled = false; } @@ -2522,6 +2544,7 @@ class PlayState extends MusicBeatState // stores the last judgement object var lastRating:FlxSprite; + var lastRatingOP:FlxSprite; // stores the last combo sprite object var lastCombo:FlxSprite; // stores the last combo score objects in an array @@ -2543,12 +2566,119 @@ class PlayState extends MusicBeatState Paths.image(uiPrefix + 'num' + i + uiSuffix); } + private function popUpScoreOP(ratingImage:String) { + var placement:Float = FlxG.width * 0.35; + if (GameClient.isConnected()) { + placement = FlxG.width * (0.30 + (playerSide() ? 0.1 : -0.1)); + } + + var uiPrefix:String = ""; + var uiSuffix:String = ''; + var antialias:Bool = ClientPrefs.data.antialiasing; + + if (stageUI != "normal") { + uiPrefix = '${stageUI}UI/'; + if (PlayState.isPixelStage) + uiSuffix = '-pixel'; + antialias = !isPixelStage; + } + + var rating:FlxSprite = new FlxSprite(); + rating.loadGraphic(Paths.image(uiPrefix + ratingImage + uiSuffix)); + rating.cameras = [camHUD]; + rating.screenCenter(); + rating.x = placement - 40; + rating.y -= 60; + rating.acceleration.y = 550 * playbackRate * playbackRate; + rating.velocity.y -= FlxG.random.int(140, 175) * playbackRate; + rating.velocity.x -= FlxG.random.int(0, 10) * playbackRate; + rating.visible = (!ClientPrefs.data.hideHud && showRating); + rating.x += ClientPrefs.data.comboOffset[0]; + rating.y -= ClientPrefs.data.comboOffset[1]; + rating.antialiasing = antialias; + + if (!ClientPrefs.data.comboStacking) { + if (lastRatingOP != null) + lastRatingOP.kill(); + lastRatingOP = rating; + } + + insert(members.indexOf(strumLineNotes), rating); + + if (!PlayState.isPixelStage) { + rating.setGraphicSize(Std.int(rating.width * 0.7)); + } + else { + rating.setGraphicSize(Std.int(rating.width * daPixelZoom * 0.85)); + } + + rating.updateHitbox(); + + var seperatedScore:Array = []; + + if (opCumboo >= 1000) { + seperatedScore.push(Math.floor(opCumboo / 1000) % 10); + } + seperatedScore.push(Math.floor(opCumboo / 100) % 10); + seperatedScore.push(Math.floor(opCumboo / 10) % 10); + seperatedScore.push(opCumboo % 10); + + var daLoop:Int = 0; + var xThing:Float = 0; + for (i in seperatedScore) { + var numScore:FlxSprite = new FlxSprite().loadGraphic(Paths.image(uiPrefix + 'num' + Std.int(i) + uiSuffix)); + numScore.cameras = [camHUD]; + numScore.screenCenter(); + numScore.x = placement + (43 * daLoop) - 90 + ClientPrefs.data.comboOffset[2]; + numScore.y += 80 - ClientPrefs.data.comboOffset[3]; + + if (!ClientPrefs.data.comboStacking) + lastScore.push(numScore); + + if (!PlayState.isPixelStage) + numScore.setGraphicSize(Std.int(numScore.width * 0.5)); + else + numScore.setGraphicSize(Std.int(numScore.width * daPixelZoom)); + numScore.updateHitbox(); + + numScore.acceleration.y = FlxG.random.int(200, 300) * playbackRate * playbackRate; + numScore.velocity.y -= FlxG.random.int(140, 160) * playbackRate; + numScore.velocity.x = FlxG.random.float(-5, 5) * playbackRate; + numScore.visible = !ClientPrefs.data.hideHud; + numScore.antialiasing = antialias; + + if (showComboNum) + insert(members.indexOf(strumLineNotes), numScore); + + FlxTween.tween(numScore, {alpha: 0}, 0.2 / playbackRate, { + onComplete: function(tween:FlxTween) { + numScore.destroy(); + }, + startDelay: Conductor.crochet * 0.002 / playbackRate + }); + + daLoop++; + if (numScore.x > xThing) + xThing = numScore.x; + } + + FlxTween.tween(rating, {alpha: 0}, 0.2 / playbackRate, { + startDelay: Conductor.crochet * 0.001 / playbackRate, + onComplete: function(tween:FlxTween) { + rating.destroy(); + } + }); + } + private function popUpScore(note:Note = null):Void { var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition + ClientPrefs.data.ratingOffset); vocals.volume = 1; - var placement:Float = FlxG.width * 0.35; + var placement:Float = FlxG.width * 0.35; + if (GameClient.isConnected()) { + placement = FlxG.width * (0.30 + (!playerSide() ? 0.1 : -0.1)); + } var rating:FlxSprite = new FlxSprite(); var score:Int = 350; @@ -2561,6 +2691,8 @@ class PlayState extends MusicBeatState note.rating = daRating.name; score = daRating.score; + GameClient.send("noteHit", [note.strumTime, note.noteData, note.isSustainNote, daRating.image]); + if(daRating.noteSplash && !note.noteSplashData.disabled) spawnNoteSplashOnNote(note); @@ -3069,8 +3201,6 @@ class PlayState extends MusicBeatState return; } - GameClient.send("noteHit", [note.strumTime, note.noteData, note.isSustainNote]); - if (!note.isSustainNote) { combo++; @@ -3808,6 +3938,11 @@ class PlayState extends MusicBeatState } }); + if (!message[2]) { + opCumboo++; + popUpScoreOP(message[3] ?? null); + } + updateOpAccuracy(); updateScoreOpponent(); vocals.volume = 1; @@ -3835,6 +3970,7 @@ class PlayState extends MusicBeatState updateOpAccuracy(); updateScoreOpponent(); vocals.volume = 0; + opCumboo = 0; }); }); @@ -3854,6 +3990,7 @@ class PlayState extends MusicBeatState var opRatingPercent = 0.; var opRatingName = "?"; var opRatingFC:String = "SFC"; + var opCumboo:Int = 0; function updateOpAccuracy() { var op = (GameClient.isOwner ? GameClient.room.state.player2 : GameClient.room.state.player1); @@ -3905,7 +4042,7 @@ class PlayState extends MusicBeatState (playerSide() ? scoreTxtP2 : scoreTxtP1).text = //op.sicks + " " + op.goods + " " + op.bads + " " + op.shits + " " + op.misses - op.name + '\nScore: ' + op.score + '\nMisses: ' + op.misses + '\nRating: ' + str + op.name + '\nScore: ' + op.score + '\nMisses: ' + op.misses + '\nRating: ' + str + "\nPing: " + op.ping ; } } \ No newline at end of file