Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
mcagabe19 committed Oct 1, 2024
2 parents bbb3101 + c11e424 commit 8468b44
Show file tree
Hide file tree
Showing 6 changed files with 289 additions and 49 deletions.
10 changes: 9 additions & 1 deletion source/backend/Rating.hx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ class Rating
var window:String = name + 'Window';
try
{
this.hitWindow = Reflect.field(ClientPrefs.data, window);
switch (window) {
case "sickWindow":
this.hitWindow = 45;
case "goodWindow":
this.hitWindow = 90;
case "badWindow":
this.hitWindow = 135;
}
//this.hitWindow = Reflect.field(ClientPrefs.data, window);
}
catch(e) FlxG.log.error(e);
}
Expand Down
246 changes: 246 additions & 0 deletions source/io/colyseus/Client.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
package io.colyseus;

import haxe.net.WebSocket.ReadyState;
import haxe.macro.Expr.Binop;
import haxe.Timer;
import haxe.macro.Expr.Catch;
import haxe.Constraints.Function;

using io.colyseus.events.EventHandler;
using io.colyseus.error.MatchMakeError;

import tink.Url;
import haxe.io.Bytes;
import org.msgpack.MsgPack;

interface RoomAvailable {
public var roomId: String;
public var clients: Int;
public var maxClients: Int;
public var metadata: Dynamic;
}

class EndpointSettings {
public var hostname:String;
public var port:Int;
public var useSSL:Bool;

public function new (hostname: String, port: Int, useSSL: Bool) {
this.hostname = hostname;
this.port = port;
this.useSSL = useSSL;
}
}

@:keep
class Client {
// public var endpoint: String;
public var settings: EndpointSettings;

public function new (endpointOrHostname: String, ?port: Int, ?useSSL: Bool) {
if (port == null && useSSL == null) {
var url: Url = Url.parse(Std.string(endpointOrHostname));
var useSSL = (url.scheme == "https" || url.scheme == "wss");
var port = (url.host.port != null)
? url.host.port
: (useSSL)
? 443
: 80;

this.settings = new EndpointSettings(url.host.name, port, useSSL);

} else {
this.settings = new EndpointSettings(endpointOrHostname, port, useSSL);
}
}

@:generic
public function joinOrCreate<T>(roomName: String, options: Map<String, Dynamic>, stateClass: Class<T>, callback: (MatchMakeError, Room<T>)->Void) {
this.createMatchMakeRequest('joinOrCreate', roomName, options, stateClass, callback);
}

@:generic
public function create<T>(roomName: String, options: Map<String, Dynamic>, stateClass: Class<T>, callback: (MatchMakeError, Room<T>)->Void) {
this.createMatchMakeRequest('create', roomName, options, stateClass, callback);
}

@:generic
public function join<T>(roomName: String, options: Map<String, Dynamic>, stateClass: Class<T>, callback: (MatchMakeError, Room<T>)->Void) {
this.createMatchMakeRequest('join', roomName, options, stateClass, callback);
}

@:generic
public function joinById<T>(roomId: String, options: Map<String, Dynamic>, stateClass: Class<T>, callback: (MatchMakeError, Room<T>)->Void) {
this.createMatchMakeRequest('joinById', roomId, options, stateClass, callback);
}

@:generic
public function reconnect<T>(reconnectionToken: String, stateClass: Class<T>, callback: (MatchMakeError, Room<T>)->Void) {
var roomIdAndReconnectionToken = reconnectionToken.split(":");
this.createMatchMakeRequest('reconnect', roomIdAndReconnectionToken[0], [ "reconnectionToken" => roomIdAndReconnectionToken[1] ], stateClass, callback);
}

public function getAvailableRooms(roomName: String, callback: (MatchMakeError, Array<RoomAvailable>)->Void) {
this.request("GET", "matchmake/" + roomName, null, callback);
}

@:generic
public function consumeSeatReservation<T>(response: Dynamic, stateClass: Class<T>, callback: (MatchMakeError, Room<T>)->Void) {

// Prevents crashing upon .room being null. Can be caused if the server itself encounters an error making a room.
if (response.error != null)
{
callback(new MatchMakeError(response.code, response.error), null);
return;
}

var room: Room<T> = new Room<T>(response.room.name, stateClass);

room.roomId = response.room.roomId;
room.sessionId = response.sessionId;

//
// WORKAROUND: declare onError/onJoin first, so we can use its references to remove the listeners
// FIXME: EventHandler must implement a .once() method to remove the listener after the first call
//
var onError:(Int, String) -> Void;
var onJoin:() -> Void;

onError = function(code: Int, message: String) {
// TODO: this may not work on native targets + devMode
room.onError -= onError;
room.onJoin -= onJoin;
callback(new MatchMakeError(code, message), null);
};

onJoin = function() {
// TODO: this may not work on native targets + devMode
room.onError -= onError;
room.onJoin -= onJoin;
callback(null, room);
};

room.onError += onError;
room.onJoin += onJoin;

var options = ["sessionId" => room.sessionId];

if (response.reconnectionToken != null) {
options.set("reconnectionToken", response.reconnectionToken);
}

function reserveSeat() {
function devModeCloseCallBack() {
var retryCount = 0;
var maxRetryCount = 8;

function retryConnection () {
retryCount++;
reserveSeat();

room.connection.onError = function(e) {
if( retryCount <= maxRetryCount) {
trace("[Colyseus devMode]: retrying... (" + retryCount + " out of " + maxRetryCount + ")");
Timer.delay(retryConnection, 2000);
} else {
trace("[Colyseus devMode]: Failed to reconnect. Is your server running? Please check server logs.");
}
}

room.connection.onOpen = function () {
trace("[Colyseus devMode]: Successfully re-established connection with room " + room.roomId);
}
}

Timer.delay(retryConnection, 2000);
}

room.connect(this.createConnection(response.room, options), room, response.devMode? devModeCloseCallBack: null);
}
reserveSeat();
}

@:generic
private function createMatchMakeRequest<T>(
method: String,
roomName: String,
options: Map<String, Dynamic>,
stateClass: Class<T>,
callback: (MatchMakeError, Room<T>)->Void
) {
this.request("POST", "matchmake/" + method + "/" + roomName, haxe.Json.stringify(options), function(err, response) {
if (err != null) {
return callback(err, null);

} else {
if (method == "reconnect") {
response.reconnectionToken = options.get("reconnectionToken");
}
this.consumeSeatReservation(response, stateClass, callback);
}
});
}

private function createConnection(room: Dynamic, options: Map<String, Dynamic>) {
// append colyseusid to connection string.
var params: Array<String> = [];

for (name in options.keys()) {
params.push(name + "=" + options[name]);
}

var endpoint = (this.settings.useSSL) ? "wss://" : "ws://";

if (room.publicAddress != null) {
endpoint += room.publicAddress;
} else {
endpoint += '${this.settings.hostname}${this.getEndpointPort()}';
}
return new Connection('${endpoint}/${room.processId}/${room.roomId}?${params.join('&')}');
}

private function request(method: String, segments: String, body: String, callback: (MatchMakeError,Dynamic)->Void) {
var req = new haxe.Http(this.buildHttpEndpoint(segments));

if (body != null) {
req.setPostData(body);
req.setHeader("Content-Type", "application/json");
}

req.setHeader("Accept", "application/json");

var responseStatus: Int;
req.onStatus = function(status) {
responseStatus = status;
};

req.onData = function(json) {
var response = haxe.Json.parse(json);

if (response.error) {
var code = cast response.code;
var message = cast response.error;
callback(new MatchMakeError(code, message), null);

} else {
callback(null, response);
}
};

req.onError = function(err) {
callback(new MatchMakeError(0, err), null);
};

req.request(method == "POST");
}

private function buildHttpEndpoint(segments: String) {
return '${(this.settings.useSSL) ? "https" : "http"}://${this.settings.hostname}${this.getEndpointPort()}/${segments}';
}

private function getEndpointPort() {
return (this.settings.port != 80 && this.settings.port != 443)
? ':${this.settings.port}'
: '';
}
}
67 changes: 24 additions & 43 deletions source/online/GameClient.hx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class GameClient {
public static var room:Room<GameRoom>;
public static var isOwner:Bool;
public static var address:String;
public static var reconnectTries:Int = 0;
public static var reconnecting:Bool = false;
public static var rpcClientRoomID:String;

/**
Expand Down Expand Up @@ -80,7 +80,9 @@ class GameClient {
}

private static function _onJoin(err:Error, room:Room<GameRoom>, isHost:Bool, address:String, ?onJoin:(err:Dynamic)->Void) {
reconnecting = false;
if (err != null) {
trace(err.code + " - " + err.message);
Alert.alert("Couldn't connect!", "JOIN ERROR: " + err.code + " - " + err.message);
client = null;
_pendingMessages = [];
Expand Down Expand Up @@ -136,51 +138,30 @@ class GameClient {
}

public static function reconnect(?nextTry:Bool = false) {
if (nextTry) {
reconnectTries--;
Sys.println("reconnecting (" + reconnectTries + ")");
}
else {
try {
room.connection.close();
} catch (exc) {}
Sys.println("reconnecting");
Alert.alert("Reconnecting...");
reconnectTries = 15;
}
if (reconnecting)
return;

Thread.run(() -> {
try {
client.reconnect(room.reconnectionToken, GameRoom, (err, room) -> {
if (err != null) {
if (reconnectTries <= 0) {
Waiter.put(() -> {
Alert.alert("Couldn't reconnect!", "RECONNECT ERROR: " + err.code + " - " + err.message);
});
leaveRoom();
}
else {
Waiter.put(() -> {
new FlxTimer().start(0.5, t -> reconnect(true));
});
}
return;
}
reconnecting = true;
Sys.println("reconnecting with token: " + room.reconnectionToken);
Alert.alert("Reconnecting...");

Thread.run(() -> {
client.reconnect(room.reconnectionToken, GameRoom, (err, newRoom) -> {
if (err != null) {
trace(err.code + " - " + err.message);
Waiter.put(() -> {
Alert.alert("Reconnected!");
Alert.alert("Couldn't reconnect!", "RECONNECT ERROR: " + err.code + " - " + err.message);
});
_onJoin(err, room, GameClient.isOwner, GameClient.address);
sendPending();
reconnectTries = 0;
});
}
catch (exc) {
trace(exc);
leaveRoom();
return;
}

_onJoin(err, newRoom, GameClient.isOwner, GameClient.address);
sendPending();
Waiter.put(() -> {
new FlxTimer().start(0.5, t -> reconnect(true));
Alert.alert("Reconnected!");
});
}
});
});
}

Expand Down Expand Up @@ -213,7 +194,7 @@ class GameClient {

public static function leaveRoom(?reason:String = null) {
Waiter.pingServer = null;
reconnectTries = 0;
reconnecting = false;
_pendingMessages = [];

if (!isConnected())
Expand All @@ -233,7 +214,7 @@ class GameClient {
FlxG.sound.playMusic(Paths.music('freakyMenu'));

if (GameClient.room?.connection != null) {
GameClient.room.connection.close();
GameClient.room.leave(true);
GameClient.room.teardown();
}

Expand Down Expand Up @@ -311,7 +292,7 @@ class GameClient {
catch (exc) {
_pendingMessages.push([type, message]);

if (reconnectTries <= 0) {
if (!reconnecting) {
trace(exc + " : FAILED TO SEND: " + type + " -> " + message);
reconnect();
}
Expand Down
Loading

0 comments on commit 8468b44

Please sign in to comment.