Skip to content

Commit

Permalink
Improve multiplayer sync (#6672)
Browse files Browse the repository at this point in the history
* Fix a rare case where the lobby was joined but did not appear as such in the interface
* Text inputs are now synced properly
* Add 2 new expressions for current player ping & username
* Fix Physics2 behavior being properly synced
  • Loading branch information
ClementPasteau committed Jun 18, 2024
1 parent 063bf51 commit 0eb7b85
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 34 deletions.
46 changes: 46 additions & 0 deletions Extensions/Multiplayer/JsExtension.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,29 @@ module.exports = {
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
.setFunctionName('gdjs.multiplayer.getPlayerUsername');

extension
.addStrExpression(
'CurrentPlayerUsername',
_('Current player username in lobby'),
_('Get the username of the current player in the lobby.'),
_('Lobbies'),
'JsPlatform/Extensions/multiplayer.svg'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/P2P/A_peer.js')
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
.addIncludeFile(
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
)
.addIncludeFile(
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
)
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
.setFunctionName('gdjs.multiplayer.getCurrentPlayerUsername');

extension
.addExpression(
'PlayerPing',
Expand Down Expand Up @@ -485,6 +508,29 @@ module.exports = {
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
.setFunctionName('gdjs.multiplayerMessageManager.getPlayerPing');

extension
.addExpression(
'CurrentPlayerPing',
_('Current player ping in lobby'),
_('Get the ping of the current player in the lobby.'),
_('Lobbies'),
'JsPlatform/Extensions/multiplayer.svg'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/P2P/A_peer.js')
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
.addIncludeFile(
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
)
.addIncludeFile(
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
)
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
.setFunctionName('gdjs.multiplayerMessageManager.getCurrentPlayerPing');

extension
.addExpressionAndConditionAndAction(
'number',
Expand Down
6 changes: 6 additions & 0 deletions Extensions/Multiplayer/messageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1943,6 +1943,11 @@ namespace gdjs {
return _playersPings[playerNumber] || 0;
};

const getCurrentPlayerPing = () => {
const currentPlayerNumber = gdjs.multiplayer.getCurrentPlayerNumber();
return getPlayerPing(currentPlayerNumber);
};

const markPlayerAsDisconnected = (playerNumber: number) => {
logger.info(`Marking player ${playerNumber} as disconnected.`);
_playerNumbersWhoJustLeft.push(playerNumber);
Expand Down Expand Up @@ -2130,6 +2135,7 @@ namespace gdjs {
handleHeartbeatsReceived,
// Connection/Disonnection.
getPlayerPing,
getCurrentPlayerPing,
updatePlayersPingsForTests,
handleDisconnectedPeers,
clearDisconnectedPeers,
Expand Down
13 changes: 13 additions & 0 deletions Extensions/Multiplayer/multiplayertools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,14 @@ namespace gdjs {
: `Player ${playerNumber}`;
};

/**
* Returns the player username of the current player in the lobby.
*/
export const getCurrentPlayerUsername = () => {
const currentPlayerNumber = getCurrentPlayerNumber();
return getPlayerUsername(currentPlayerNumber);
};

const handleLeavingPlayer = (runtimeScene: gdjs.RuntimeScene) => {
const disconnectedPlayers = gdjs.multiplayerMessageManager.getDisconnectedPlayers();
if (disconnectedPlayers.length > 0) {
Expand Down Expand Up @@ -418,6 +426,11 @@ namespace gdjs {

if (!connectionId || !positionInLobby) {
logger.error('No connectionId or position received');
gdjs.multiplayerComponents.displayErrorNotification(
runtimeScene
);
// Close the websocket as something wrong happened.
if (_websocket) _websocket.close();
return;
}

Expand Down
84 changes: 66 additions & 18 deletions Extensions/Physics2Behavior/physics2runtimebehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ namespace gdjs {
export interface RuntimeScene {
physics2SharedData: gdjs.Physics2SharedData | null;
}
interface Physics2NetworkSyncDataType {
tpx: number | undefined;
tpy: number | undefined;
tqa: number | undefined;
lvx: number | undefined;
lvy: number | undefined;
av: number | undefined;
aw: boolean | undefined;
}

export interface Physics2NetworkSyncData extends BehaviorNetworkSyncData {
props: Physics2NetworkSyncDataType;
}
export class Physics2SharedData {
gravityX: float;
gravityY: float;
Expand Down Expand Up @@ -476,37 +489,72 @@ namespace gdjs {
return true;
}

getNetworkSyncData() {
getNetworkSyncData(): Physics2NetworkSyncData {
const bodyProps = this._body
? {
tpx: this._body.GetTransform().get_p().get_x(),
tpy: this._body.GetTransform().get_p().get_y(),
tqa: this._body.GetTransform().get_q().GetAngle(),
lvx: this._body.GetLinearVelocity().get_x(),
lvy: this._body.GetLinearVelocity().get_y(),
av: this._body.GetAngularVelocity(),
aw: this._body.IsAwake(),
}
: {
tpx: undefined,
tpy: undefined,
tqa: undefined,
lvx: undefined,
lvy: undefined,
av: undefined,
aw: undefined,
};
return {
...super.getNetworkSyncData(),
props: {
oox: this._objectOldX,
ooy: this._objectOldY,
ooa: this._objectOldAngle,
oow: this._objectOldWidth,
ooh: this._objectOldHeight,
...bodyProps,
},
};
}

updateFromNetworkSyncData(networkSyncData: any) {
updateFromNetworkSyncData(networkSyncData: Physics2NetworkSyncData) {
super.updateFromNetworkSyncData(networkSyncData);

const behaviorSpecificProps = networkSyncData.props;
if (behaviorSpecificProps.oox !== undefined) {
this._objectOldX = behaviorSpecificProps.oox;
}
if (behaviorSpecificProps.ooy !== undefined) {
this._objectOldY = behaviorSpecificProps.ooy;
if (
behaviorSpecificProps.tpx !== undefined &&
behaviorSpecificProps.tpy !== undefined &&
behaviorSpecificProps.tqa !== undefined
) {
if (this._body) {
this._body.SetTransform(
this.b2Vec2(behaviorSpecificProps.tpx, behaviorSpecificProps.tpy),
behaviorSpecificProps.tqa
);
}
}
if (behaviorSpecificProps.ooa !== undefined) {
this._objectOldAngle = behaviorSpecificProps.ooa;

if (
behaviorSpecificProps.lvx !== undefined &&
behaviorSpecificProps.lvy !== undefined
) {
if (this._body) {
this._body.SetLinearVelocity(
this.b2Vec2(behaviorSpecificProps.lvx, behaviorSpecificProps.lvy)
);
}
}
if (behaviorSpecificProps.oow !== undefined) {
this._objectOldWidth = behaviorSpecificProps.oow;

if (behaviorSpecificProps.av !== undefined) {
if (this._body) {
this._body.SetAngularVelocity(behaviorSpecificProps.av);
}
}
if (behaviorSpecificProps.ooh !== undefined) {
this._objectOldHeight = behaviorSpecificProps.ooh;

if (behaviorSpecificProps.aw !== undefined) {
if (this._body) {
this._body.SetAwake(behaviorSpecificProps.aw);
}
}
}

Expand Down
84 changes: 70 additions & 14 deletions Extensions/PlatformBehavior/platformerobjectruntimebehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,60 @@ namespace gdjs {
isCollidingAnyPlatform: boolean;
};

interface OnFloorStateNetworkSyncData {
flx: number;
fly: number;
oh: number;
}

interface FallingStateNetworkSyncData {}

interface JumpingStateNetworkSyncData {
cjs: number;
tscjs: number;
jkhsjs: boolean;
jfd: boolean;
}

interface GrabbingPlatformStateNetworkSyncData {
gplx: float;
gply: float;
}

interface OnLadderStateNetworkSyncData {}

type StateNetworkSyncData =
| OnFloorStateNetworkSyncData
| FallingStateNetworkSyncData
| JumpingStateNetworkSyncData
| GrabbingPlatformStateNetworkSyncData
| OnLadderStateNetworkSyncData;

interface PlatformerObjectNetworkSyncDataType {
cs: float;
rdx: float;
rdy: float;
ldy: float;
cfs: float;
cj: boolean;
ldl: boolean;
lek: boolean;
rik: boolean;
lak: boolean;
upk: boolean;
dok: boolean;
juk: boolean;
rpk: boolean;
rlk: boolean;
sn: string;
ssd: StateNetworkSyncData;
}

export interface PlatformerObjectNetworkSyncData
extends BehaviorNetworkSyncData {
props: PlatformerObjectNetworkSyncDataType;
}

/**
* PlatformerObjectRuntimeBehavior represents a behavior allowing objects to be
* considered as a platform by objects having PlatformerObject Behavior.
Expand Down Expand Up @@ -161,7 +215,7 @@ namespace gdjs {
this._state = this._falling;
}

getNetworkSyncData() {
getNetworkSyncData(): PlatformerObjectNetworkSyncData {
// This method is called, so we are synchronizing this object.
// Let's clear the inputs between frames as we control it.
this._dontClearInputsBetweenFrames = false;
Expand Down Expand Up @@ -190,7 +244,9 @@ namespace gdjs {
};
}

updateFromNetworkSyncData(networkSyncData) {
updateFromNetworkSyncData(
networkSyncData: PlatformerObjectNetworkSyncData
) {
super.updateFromNetworkSyncData(networkSyncData);

const behaviorSpecificProps = networkSyncData.props;
Expand Down Expand Up @@ -1776,9 +1832,9 @@ namespace gdjs {
*/
beforeMovingY(timeDelta: float, oldX: float): void;

getNetworkSyncData(): any;
getNetworkSyncData(): StateNetworkSyncData;

updateFromNetworkSyncData(syncData: any): void;
updateFromNetworkSyncData(syncData: StateNetworkSyncData): void;
}

/**
Expand Down Expand Up @@ -2059,15 +2115,15 @@ namespace gdjs {
}
}

getNetworkSyncData(): any {
getNetworkSyncData(): OnFloorStateNetworkSyncData {
return {
flx: this._floorLastX,
fly: this._floorLastY,
oh: this._oldHeight,
};
}

updateFromNetworkSyncData(data: any) {
updateFromNetworkSyncData(data: OnFloorStateNetworkSyncData) {
this._floorLastX = data.flx;
this._floorLastY = data.fly;
this._oldHeight = data.oh;
Expand Down Expand Up @@ -2130,11 +2186,11 @@ namespace gdjs {
this._behavior._fall(timeDelta);
}

getNetworkSyncData(): any {
getNetworkSyncData(): FallingStateNetworkSyncData {
return {};
}

updateFromNetworkSyncData(data: any) {}
updateFromNetworkSyncData(data: FallingStateNetworkSyncData) {}

toString(): String {
return 'Falling';
Expand Down Expand Up @@ -2249,7 +2305,7 @@ namespace gdjs {
}
}

getNetworkSyncData(): any {
getNetworkSyncData(): JumpingStateNetworkSyncData {
return {
cjs: this._currentJumpSpeed,
tscjs: this._timeSinceCurrentJumpStart,
Expand All @@ -2258,7 +2314,7 @@ namespace gdjs {
};
}

updateFromNetworkSyncData(data: any) {
updateFromNetworkSyncData(data: JumpingStateNetworkSyncData) {
this._currentJumpSpeed = data.cjs;
this._timeSinceCurrentJumpStart = data.tscjs;
this._jumpKeyHeldSinceJumpStart = data.jkhsjs;
Expand Down Expand Up @@ -2337,14 +2393,14 @@ namespace gdjs {
this._grabbedPlatformLastY = this._grabbedPlatform.owner.getY();
}

getNetworkSyncData(): any {
getNetworkSyncData(): GrabbingPlatformStateNetworkSyncData {
return {
gplx: this._grabbedPlatformLastX,
gply: this._grabbedPlatformLastY,
};
}

updateFromNetworkSyncData(data: any) {
updateFromNetworkSyncData(data: GrabbingPlatformStateNetworkSyncData) {
this._grabbedPlatformLastX = data.gplx;
this._grabbedPlatformLastY = data.gply;
}
Expand Down Expand Up @@ -2405,11 +2461,11 @@ namespace gdjs {
}
}

getNetworkSyncData(): any {
getNetworkSyncData(): OnLadderStateNetworkSyncData {
return {};
}

updateFromNetworkSyncData(data: any) {}
updateFromNetworkSyncData(data: OnLadderStateNetworkSyncData) {}

toString(): String {
return 'OnLadder';
Expand Down
Loading

0 comments on commit 0eb7b85

Please sign in to comment.