Fixed a few indexing errors.

This commit is contained in:
genxium 2022-09-26 10:36:46 +08:00
parent 50273c981b
commit 2dfd6083c5
3 changed files with 71 additions and 97 deletions

View File

@ -977,7 +977,7 @@ func (pR *Room) StopBattleForSettlement() {
for playerId, _ := range pR.Players { for playerId, _ := range pR.Players {
assembledFrame := pb.RoomDownsyncFrame{ assembledFrame := pb.RoomDownsyncFrame{
Id: pR.Tick, Id: pR.Tick,
RefFrameId: 0, // Hardcoded for now. RefFrameId: pR.Tick, // Hardcoded for now.
Players: toPbPlayers(pR.Players), Players: toPbPlayers(pR.Players),
SentAt: utils.UnixtimeMilli(), SentAt: utils.UnixtimeMilli(),
CountdownNanos: -1, // TODO: Replace this magic constant! CountdownNanos: -1, // TODO: Replace this magic constant!

View File

@ -90,23 +90,7 @@ cc.Class({
if (remoteUrl == null || remoteUrl == '') { if (remoteUrl == null || remoteUrl == '') {
cc.log(`No avatar to show for :`); cc.log(`No avatar to show for :`);
cc.log(playerMeta); cc.log(playerMeta);
remoteUrl = 'http://wx.qlogo.cn/mmopen/PiajxSqBRaEJUWib5D85KXWHumaxhU4E9XOn9bUpCNKF3F4ibfOj8JYHCiaoosvoXCkTmOQE1r2AKKs8ObMaz76EdA/0'
} }
cc.loader.load({
url: remoteUrl,
type: 'jpg'
}, function(err, texture) {
if (null != err ) {
console.error(err);
} else {
if (null == texture) {
return;
}
const sf = new cc.SpriteFrame();
sf.setTexture(texture);
playerInfoNode.getChildByName('avatarMask').getChildByName('avatar').getComponent(cc.Sprite).spriteFrame = sf;
}
});
})(); })();
function isEmptyString(str) { function isEmptyString(str) {

View File

@ -137,9 +137,12 @@ cc.Class({
_dumpToRenderCache: function(roomDownsyncFrame) { _dumpToRenderCache: function(roomDownsyncFrame) {
const self = this; const self = this;
const minToKeepRenderFrameId = self.lastAllConfirmedRenderFrameId; const minToKeepRenderFrameId = self.lastAllConfirmedRenderFrameId;
while (self.recentInputCache.stFrameId < minToKeepRenderFrameId) { while (0 < self.recentRenderCache.cnt && self.recentRenderCache.stFrameId < minToKeepRenderFrameId) {
self.recentRenderCache.pop(); self.recentRenderCache.pop();
} }
if (self.recentRenderCache.stFrameId < minToKeepRenderFrameId) {
console.warn("Weird dumping of RENDER frame: self.renderFrame=", self.renderFrame, ", self.recentInputCache=", self._stringifyRecentInputCache(false), ", self.recentRenderCache=", self._stringifyRecentRenderCache(false), ", self.lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", self.lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId);
}
const existing = self.recentRenderCache.getByFrameId(roomDownsyncFrame.id); const existing = self.recentRenderCache.getByFrameId(roomDownsyncFrame.id);
if (null != existing) { if (null != existing) {
existing.players = roomDownsyncFrame.players; existing.players = roomDownsyncFrame.players;
@ -157,10 +160,14 @@ cc.Class({
_dumpToInputCache: function(inputFrameDownsync) { _dumpToInputCache: function(inputFrameDownsync) {
const self = this; const self = this;
const minToKeepInputFrameId = self._convertToInputFrameId(self.lastAllConfirmedRenderFrameId, self.inputDelayFrames); // [WARNING] This could be different from "self.lastAllConfirmedInputFrameId". We'd like to keep the corresponding inputFrame for "self.lastAllConfirmedRenderFrameId" such that a rollback could place "self.chaserRenderFrameId = self.lastAllConfirmedRenderFrameId" for the worst case incorrect prediction. let minToKeepInputFrameId = self._convertToInputFrameId(self.lastAllConfirmedRenderFrameId, self.inputDelayFrames); // [WARNING] This could be different from "self.lastAllConfirmedInputFrameId". We'd like to keep the corresponding inputFrame for "self.lastAllConfirmedRenderFrameId" such that a rollback could place "self.chaserRenderFrameId = self.lastAllConfirmedRenderFrameId" for the worst case incorrect prediction.
while (self.recentInputCache.stFrameId < minToKeepInputFrameId) { if (minToKeepInputFrameId > self.lastAllConfirmedInputFrameId) minToKeepInputFrameId = self.lastAllConfirmedInputFrameId;
while (0 < self.recentInputCache.cnt && self.recentInputCache.stFrameId < minToKeepInputFrameId) {
self.recentInputCache.pop(); self.recentInputCache.pop();
} }
if (self.recentInputCache.stFrameId < minToKeepInputFrameId) {
console.warn("Weird dumping of INPUT frame: self.renderFrame=", self.renderFrame, ", self.recentInputCache=", self._stringifyRecentInputCache(false), ", self.recentRenderCache=", self._stringifyRecentRenderCache(false), ", self.lastAllConfirmedRenderFrameId=", self.lastAllConfirmedRenderFrameId, ", self.lastAllConfirmedInputFrameId=", self.lastAllConfirmedInputFrameId);
}
const existing = self.recentInputCache.getByFrameId(inputFrameDownsync.inputFrameId); const existing = self.recentInputCache.getByFrameId(inputFrameDownsync.inputFrameId);
if (null != existing) { if (null != existing) {
existing.inputList = inputFrameDownsync.inputList; existing.inputList = inputFrameDownsync.inputList;
@ -532,54 +539,38 @@ cc.Class({
self.transitToState(ALL_MAP_STATES.WAITING); self.transitToState(ALL_MAP_STATES.WAITING);
self._inputControlEnabled = false; self._inputControlEnabled = false;
let findingPlayerScriptIns = null; let findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
window.handleRoomDownsyncFrame = function(rdf) { window.handleRoomDownsyncFrame = function(rdf) {
if (ALL_BATTLE_STATES.WAITING != self.battleState if (ALL_BATTLE_STATES.WAITING != self.battleState
&& ALL_BATTLE_STATES.IN_BATTLE != self.battleState && ALL_BATTLE_STATES.IN_BATTLE != self.battleState
&& ALL_BATTLE_STATES.IN_SETTLEMENT != self.battleState) { && ALL_BATTLE_STATES.IN_SETTLEMENT != self.battleState) {
return; return;
} }
const frameId = rdf.id;
// Right upon establishment of the "PersistentSessionClient", we should receive an initial signal "BattleColliderInfo" earlier than any "RoomDownsyncFrame" containing "PlayerMeta" data. // Right upon establishment of the "PersistentSessionClient", we should receive an initial signal "BattleColliderInfo" earlier than any "RoomDownsyncFrame" containing "PlayerMeta" data.
const refFrameId = rdf.refFrameId; const refFrameId = rdf.refFrameId;
switch (refFrameId) { switch (refFrameId) {
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.PLAYER_ADDED_AND_ACKED: case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.PLAYER_ADDED_AND_ACKED:
self._initPlayerRichInfoDict(rdf.players, rdf.playerMetas); // Update the "finding player" GUI and show it if not previously present
// 显示匹配玩家
findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
if (!self.findingPlayerNode.parent) { if (!self.findingPlayerNode.parent) {
self.showPopupInCanvas(self.findingPlayerNode); self.showPopupInCanvas(self.findingPlayerNode);
} }
findingPlayerScriptIns.updatePlayersInfo(rdf.playerMetas); findingPlayerScriptIns.updatePlayersInfo(rdf.playerMetas);
return; return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.PLAYER_READDED_AND_ACKED:
self._initPlayerRichInfoDict(rdf.players, rdf.playerMetas);
// In this case, we're definitely in an active battle, thus the "self.findingPlayerNode" should be hidden if being presented.
if (self.findingPlayerNode && self.findingPlayerNode.parent) {
self.findingPlayerNode.parent.removeChild(self.findingPlayerNode);
self.transitToState(ALL_MAP_STATES.VISUAL);
if (self.playersInfoNode) {
for (let playerId in rdf.playerMetas) {
const playerMeta = rdf.playerMetas[playerId];
const playersInfoScriptIns = self.playersInfoNode.getComponent("PlayersInfo");
playersInfoScriptIns.updateData(playerMeta);
}
}
}
return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_READY_TO_START: case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_READY_TO_START:
// 显示倒计时 self.onBattleReadyToStart(rdf.playerMetas, false);
self.playersMatched(rdf.playerMetas);
// 隐藏返回按钮
findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
findingPlayerScriptIns.hideExitButton();
return; return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START: case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START:
self.onBattleStarted(rdf); self.onBattleStarted(rdf);
return; return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.PLAYER_READDED_AND_ACKED:
self.lastAllConfirmedRenderFrameId = frameId;
self.onBattleReadyToStart(rdf.playerMetas, true);
self.onBattleStarted(rdf);
return;
} }
const frameId = rdf.id;
self.lastAllConfirmedRenderFrameId = frameId;
// TODO: Inject a NetworkDoctor as introduced in https://app.yinxiang.com/shard/s61/nl/13267014/5c575124-01db-419b-9c02-ec81f78c6ddc/. // TODO: Inject a NetworkDoctor as introduced in https://app.yinxiang.com/shard/s61/nl/13267014/5c575124-01db-419b-9c02-ec81f78c6ddc/.
}; };
@ -698,10 +689,19 @@ cc.Class({
onBattleStarted(rdf) { onBattleStarted(rdf) {
// This function is also applicable to "re-joining". // This function is also applicable to "re-joining".
const players = rdf.players;
const playerMetas = rdf.playerMetas;
console.log('On battle started!'); console.log('On battle started!');
const self = window.mapIns; const self = window.mapIns;
const players = rdf.players;
const playerMetas = rdf.playerMetas;
self._initPlayerRichInfoDict(players, playerMetas);
// Show the top status indicators for IN_BATTLE
const playersInfoScriptIns = self.playersInfoNode.getComponent("PlayersInfo");
for (let i in playerMetas) {
const playerMeta = playerMetas[i];
playersInfoScriptIns.updateData(playerMeta);
}
if (null != rdf.countdownNanos) { if (null != rdf.countdownNanos) {
self.countdownNanos = rdf.countdownNanos; self.countdownNanos = rdf.countdownNanos;
} }
@ -715,7 +715,7 @@ cc.Class({
self.countdownToBeginGameNode.parent.removeChild(self.countdownToBeginGameNode); self.countdownToBeginGameNode.parent.removeChild(self.countdownToBeginGameNode);
} }
self.transitToState(ALL_MAP_STATES.VISUAL); self.transitToState(ALL_MAP_STATES.VISUAL);
self.chaserRenderFrameId = MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START; self.chaserRenderFrameId = rdf.id;
self.applyRoomDownsyncFrameDynamics(rdf); self.applyRoomDownsyncFrameDynamics(rdf);
self._dumpToRenderCache(rdf); self._dumpToRenderCache(rdf);
self.battleState = ALL_BATTLE_STATES.IN_BATTLE; // Starts the increment of "self.renderFrameId" in "self.update(dt)" self.battleState = ALL_BATTLE_STATES.IN_BATTLE; // Starts the increment of "self.renderFrameId" in "self.update(dt)"
@ -912,27 +912,29 @@ cc.Class({
setLocalZOrder(toShowNode, 10); setLocalZOrder(toShowNode, 10);
}, },
playersMatched(playerMetas) { onBattleReadyToStart(playerMetas, isSelfRejoining) {
console.log("Calling `playersMatched` with:", playerMetas); console.log("Calling `onBattleReadyToStart` with:", playerMetas);
const self = this; const self = this;
const findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer"); const findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
findingPlayerScriptIns.hideExitButton();
findingPlayerScriptIns.updatePlayersInfo(playerMetas); findingPlayerScriptIns.updatePlayersInfo(playerMetas);
window.setTimeout(() => {
if (null != self.findingPlayerNode.parent) { const hideFindingPlayersGUI = function() {
self.findingPlayerNode.parent.removeChild(self.findingPlayerNode); if (null == self.findingPlayerNode.parent) return;
self.transitToState(ALL_MAP_STATES.VISUAL); self.findingPlayerNode.parent.removeChild(self.findingPlayerNode);
const playersInfoScriptIns = self.playersInfoNode.getComponent("PlayersInfo"); };
for (let i in playerMetas) {
const playerMeta = playerMetas[i]; if (true == isSelfRejoining) {
playersInfoScriptIns.updateData(playerMeta); hideFindingPlayersGUI();
} } else {
} // Delay to hide the "finding player" GUI, then show a countdown clock
const countDownScriptIns = self.countdownToBeginGameNode.getComponent("CountdownToBeginGame"); window.setTimeout(() => {
countDownScriptIns.setData(); hideFindingPlayersGUI();
self.showPopupInCanvas(self.countdownToBeginGameNode); const countDownScriptIns = self.countdownToBeginGameNode.getComponent("CountdownToBeginGame");
return; countDownScriptIns.setData();
}, 2000); self.showPopupInCanvas(self.countdownToBeginGameNode);
}, 1500);
}
}, },
_createRoomDownsyncFrameLocally(renderFrameId, collisionSys, collisionSysMap) { _createRoomDownsyncFrameLocally(renderFrameId, collisionSys, collisionSysMap) {
@ -1019,6 +1021,9 @@ cc.Class({
const self = this; const self = this;
const renderFrameSt = self.recentRenderCache.getByFrameId(renderFrameIdSt); // typed "RoomDownsyncFrame" const renderFrameSt = self.recentRenderCache.getByFrameId(renderFrameIdSt); // typed "RoomDownsyncFrame"
if (null == renderFrameSt) {
console.error("Couldn't find renderFrameId=", renderFrameIdSt, " to rollback, recentRenderCache=", self._stringifyRecentRenderCache(false));
}
/* /*
Reset "position" of players in "collisionSys" according to "renderFrameSt". The easy part is that we don't have path-dependent-integrals to worry about like that of thermal dynamics. Reset "position" of players in "collisionSys" according to "renderFrameSt". The easy part is that we don't have path-dependent-integrals to worry about like that of thermal dynamics.
*/ */
@ -1031,7 +1036,6 @@ cc.Class({
playerCollider.y = player.y; playerCollider.y = player.y;
}); });
const result = collisionSys.createResult(); // Can I reuse a "self.latestCollisionSysResult" object throughout the whole battle?
/* /*
This function eventually calculates a "RoomDownsyncFrame" where "RoomDownsyncFrame.id == renderFrameIdEd". This function eventually calculates a "RoomDownsyncFrame" where "RoomDownsyncFrame.id == renderFrameIdEd".
*/ */
@ -1057,6 +1061,7 @@ cc.Class({
}); });
collisionSys.update(); collisionSys.update();
const result = collisionSys.createResult(); // Can I reuse a "self.latestCollisionSysResult" object throughout the whole battle?
self.playerRichInfoDict.forEach((playerRichInfo, playerId) => { self.playerRichInfoDict.forEach((playerRichInfo, playerId) => {
const joinIndex = playerRichInfo.joinIndex; const joinIndex = playerRichInfo.joinIndex;
@ -1099,44 +1104,29 @@ cc.Class({
}, },
_stringifyRecentInputCache(usefullOutput) { _stringifyRecentInputCache(usefullOutput) {
const self = this;
if (true == usefullOutput) { if (true == usefullOutput) {
let s = []; let s = [];
self.recentInputCache.forEach((inputFrameDownsync, inputFrameId) => { for (let i = self.recentInputCache.stFrameId; i < self.recentInputCache.edFrameId; ++i) {
s.push(JSON.stringify(inputFrameDownsync)); s.push(JSON.stringify(self.recentInputCache.getByFrameId(i)));
}); }
return s.join('\n'); return s.join('\n');
} }
return "[stInputFrameId=" + self.recentInputCacheSt + ", edInputFrameId=" + self.recentInputCacheEd + ")"; return "[stInputFrameId=" + self.recentInputCache.stFrameId + ", edInputFrameId=" + self.recentInputCache.edFrameId + ")";
}, },
_stringifyRollbackResult(renderFrameId, delayedInputFrameDownsync) { _stringifyRecentRenderCache(usefullOutput) {
const self = this; const self = this;
const s = ( if (true == usefullOutput) {
null == delayedInputFrameDownsync let s = [];
? for (let i = self.recentRenderCache.stFrameId; i < self.recentRenderCache.edFrameId; ++i) {
{ s.push(JSON.stringify(self.recentRenderCache.getByFrameId(i)));
renderFrameId: renderFrameId,
players: {}
} }
:
{
renderFrameId: renderFrameId,
players: {},
delayedInputFrameDownsync: delayedInputFrameDownsync,
}
);
self.playerRichInfoDict.forEach((playerRichInfo, playerId) => {
const joinIndex = playerRichInfo.joinIndex;
const playerNode = playerRichInfo.node;
const playerScriptIns = playerRichInfo.scriptIns;
s.players[playerRichInfo.id] = {
id: playerRichInfo.id,
x: playerNode.position.x,
y: playerNode.position.y,
};
});
return JSON.stringify(s); return s.join('\n');
}
return "[stRenderFrameId=" + self.recentRenderCache.stFrameId + ", edRenderFrameId=" + self.recentRenderCache.edFrameId + ")";
}, },
}); });