Skip to content

Commit

Permalink
Ensure the animation frame is called for the sprite when receiving ne…
Browse files Browse the repository at this point in the history
…w animation
  • Loading branch information
ClementPasteau committed Jun 17, 2024
1 parent 9cbc421 commit ad08c61
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 61 deletions.
107 changes: 52 additions & 55 deletions Extensions/Multiplayer/multiplayerobjectruntimebehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,7 @@ namespace gdjs {
}

// private _logToConsoleWithThrottle(message: string) {
// if (
// getTimeNow() - this._lastLogTimestamp >
// 1000 / this._logTickRate
// ) {
// if (getTimeNow() - this._lastLogTimestamp > 1000 / this._logTickRate) {
// logger.info(message);
// this._lastLogTimestamp = getTimeNow();
// }
Expand Down Expand Up @@ -272,16 +269,18 @@ namespace gdjs {
return;
}

const instanceNetworkId = this._getOrCreateInstanceNetworkId();
const objectName = this.owner.getName();
const objectNetworkSyncData = this.owner.getObjectNetworkSyncData();

// this._logToConsoleWithThrottle(
// `Synchronizing object ${this.owner.getName()} (instance ${
// this.owner.networkId
// }) with player ${this.playerNumber}`
// }) with player ${this.playerNumber} and data ${JSON.stringify(
// objectNetworkSyncData
// )}`
// );

const instanceNetworkId = this._getOrCreateInstanceNetworkId();
const objectName = this.owner.getName();
const objectNetworkSyncData = this.owner.getObjectNetworkSyncData();

const areBasicObjectNetworkSyncDataDifferent = this._isBasicObjectNetworkSyncDataDifferentFromLastSync(
{
x: objectNetworkSyncData.x,
Expand Down Expand Up @@ -524,6 +523,12 @@ namespace gdjs {
// Just return and wait to receive an update message to reconcile this object.
return;
}
// If we don't have a networkId, we need to create one now that we are the owner.
// We are probably in a case where we created the object and then changed the ownership.
logger.info(
'We are the new owner, creating a networkId for the object.'
);
instanceNetworkId = this._getOrCreateInstanceNetworkId();
}

const sceneNetworkId = this.owner.getRuntimeScene().networkId;
Expand All @@ -534,58 +539,50 @@ namespace gdjs {

const objectName = this.owner.getName();

if (instanceNetworkId) {
// When changing the ownership of an object with a networkId, we send a message to the host to ensure it is aware of the change,
// and can either accept it and broadcast it to other players, or reject it and do nothing with it.
// We expect an acknowledgment from the host, if not, we will retry and eventually revert the ownership.
const {
messageName,
messageData,
} = gdjs.multiplayerMessageManager.createChangeInstanceOwnerMessage({
objectOwner: previousObjectPlayerNumber,
objectName,
instanceNetworkId,
newObjectOwner: newObjectPlayerNumber,
instanceX: this.owner.getX(),
instanceY: this.owner.getY(),
sceneNetworkId,
// When changing the ownership of an object with a networkId, we send a message to the host to ensure it is aware of the change,
// and can either accept it and broadcast it to other players, or reject it and do nothing with it.
// We expect an acknowledgment from the host, if not, we will retry and eventually revert the ownership.
const {
messageName,
messageData,
} = gdjs.multiplayerMessageManager.createChangeInstanceOwnerMessage({
objectOwner: previousObjectPlayerNumber,
objectName,
instanceNetworkId,
newObjectOwner: newObjectPlayerNumber,
instanceX: this.owner.getX(),
instanceY: this.owner.getY(),
sceneNetworkId,
});
// Before sending the changeOwner message, if we are becoming the new owner,
// we want to ensure this message is acknowledged, by everyone we're connected to.
// If we are player 1, we are connected to everyone, so we expect an acknowledgment from everyone.
// If we are another player, we are only connected to player 1, so we expect an acknowledgment from player 1.
// In both cases, this represents the list of peers the current user is connected to.
if (newObjectPlayerNumber === currentPlayerNumber) {
const otherPeerIds = gdjs.evtTools.p2p.getAllPeers();
const changeOwnerAcknowledgedMessageName = gdjs.multiplayerMessageManager.createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage(
messageName
);
gdjs.multiplayerMessageManager.addExpectedMessageAcknowledgement({
originalMessageName: messageName,
originalData: {
...messageData,
_clock: this._clock + 1, // Will be incremented by the time the message is sent.
},
expectedMessageName: changeOwnerAcknowledgedMessageName,
otherPeerIds,
// If we are not the host, we should revert the ownership if the host does not acknowledge the change.
shouldCancelMessageIfTimesOut: currentPlayerNumber !== 1,
});
// Before sending the changeOwner message, if we are becoming the new owner,
// we want to ensure this message is acknowledged, by everyone we're connected to.
// If we are player 1, we are connected to everyone, so we expect an acknowledgment from everyone.
// If we are another player, we are only connected to player 1, so we expect an acknowledgment from player 1.
// In both cases, this represents the list of peers the current user is connected to.
if (newObjectPlayerNumber === currentPlayerNumber) {
const otherPeerIds = gdjs.evtTools.p2p.getAllPeers();
const changeOwnerAcknowledgedMessageName = gdjs.multiplayerMessageManager.createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage(
messageName
);
gdjs.multiplayerMessageManager.addExpectedMessageAcknowledgement({
originalMessageName: messageName,
originalData: {
...messageData,
_clock: this._clock + 1, // Will be incremented by the time the message is sent.
},
expectedMessageName: changeOwnerAcknowledgedMessageName,
otherPeerIds,
// If we are not the host, we should revert the ownership if the host does not acknowledge the change.
shouldCancelMessageIfTimesOut: currentPlayerNumber !== 1,
});
}

logger.info('Sending change owner message', messageName);
this._sendDataToPeersWithIncreasedClock(messageName, messageData);
}

logger.info('Sending change owner message', messageName);
this._sendDataToPeersWithIncreasedClock(messageName, messageData);

// If we are the new owner, also send directly an update of the position,
// so that the object is immediately moved on the screen and we don't wait for the next tick.
if (newObjectPlayerNumber === currentPlayerNumber) {
if (!instanceNetworkId) {
// If we don't have a networkId, we need to create one now that we are the owner.
// We are probably in a case where we created the object and then changed the ownership.
instanceNetworkId = this._getOrCreateInstanceNetworkId();
}

const objectNetworkSyncData = this.owner.getObjectNetworkSyncData();
const {
messageName: updateMessageName,
Expand Down
24 changes: 18 additions & 6 deletions GDJS/Runtime/SpriteAnimator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,12 +400,24 @@ namespace gdjs {
updateFromObjectNetworkSyncData(
networkSyncData: SpriteAnimatorNetworkSyncData
) {
this._currentAnimation = networkSyncData.an;
this._currentDirection = networkSyncData.di;
this._currentFrameIndex = networkSyncData.fr;
this._animationElapsedTime = networkSyncData.et;
this._animationSpeedScale = networkSyncData.ss;
this._animationPaused = networkSyncData.pa;
if (networkSyncData.an !== undefined) {
this.setAnimationIndex(networkSyncData.an);
}
if (networkSyncData.di !== undefined) {
this._currentDirection = networkSyncData.di;
}
if (networkSyncData.fr !== undefined) {
this.setAnimationFrameIndex(networkSyncData.fr);
}
if (networkSyncData.et !== undefined) {
this.setAnimationElapsedTime(networkSyncData.et);
}
if (networkSyncData.ss !== undefined) {
this.setAnimationSpeedScale(networkSyncData.ss);
}
if (networkSyncData.pa !== undefined) {
networkSyncData.pa ? this.pauseAnimation() : this.resumeAnimation();
}
this.invalidateFrame();
}

Expand Down
2 changes: 2 additions & 0 deletions GDJS/Runtime/spriteruntimeobject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ namespace gdjs {
}
if (newNetworkSyncData.anim) {
this._animator.updateFromObjectNetworkSyncData(newNetworkSyncData.anim);
// TODO: optimize updating the animation frame only if needed.
this._updateAnimationFrame();
}
if (
newNetworkSyncData.ifx !== undefined ||
Expand Down

0 comments on commit ad08c61

Please sign in to comment.