Serialise messages in the GuiInterface to allow players to see them on a saved game or after a rejoin. Fixes #3185

This was SVN commit r16601.
This commit is contained in:
sanderd17 2015-04-30 18:01:38 +00:00
parent 41113f6f9b
commit fe9eeedd66
3 changed files with 30 additions and 43 deletions

View file

@ -179,20 +179,13 @@ function updateTimeNotifications()
var playerID = Engine.GetPlayerID();
for (var n of notifications)
{
if (!n.players)
{
warn("notification has unknown player list. Text:\n"+n.message);
continue;
}
if (n.players.indexOf(playerID) == -1)
continue;
var message = n.message;
if (n.translateMessage)
message = translate(message);
var parameters = n.parameters || {};
if (n.translateParameters)
translateObjectKeys(parameters, n.translateParameters);
parameters.time = timeToString(n.time);
parameters.time = timeToString(n.endTime - g_SimState.timeElapsed);
notificationText += sprintf(message, parameters) + "\n";
}
Engine.GetGUIObjectByName("notificationText").caption = notificationText;

View file

@ -34,17 +34,15 @@ Trigger.prototype.CheckWonderVictory = function(data)
messages.otherMessage = cmpGuiInterface.AddTimeNotification({
"message": markForTranslation("%(player)s will have won in %(time)s"),
"players": players,
"duration": time,
"parameters": {"player": cmpPlayer.GetName()},
"translateMessage": true,
"translateParameters": [],
});
}, time);
messages.ownMessage = cmpGuiInterface.AddTimeNotification({
"message": markForTranslation("You will have won in %(time)s"),
"players": [data.to],
"duration": time,
"translateMessage": true,
});
}, time);
timer = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager, "MarkPlayerAsWon", time, data.to);
this.wonderVictoryTimers[ent] = timer;

View file

@ -5,14 +5,20 @@ GuiInterface.prototype.Schema =
GuiInterface.prototype.Serialize = function()
{
// This component isn't network-synchronised so we mustn't serialise
// its non-deterministic data. Instead just return an empty object.
return {};
// This component isn't network-synchronised for the biggest part
// So most of the attributes shouldn't be serialized
// Return an object with a small selection of deterministic data
return {
"timeNotifications": this.timeNotifications,
"timeNotificationID": this.timeNotificationID
};
};
GuiInterface.prototype.Deserialize = function(obj)
GuiInterface.prototype.Deserialize = function(data)
{
this.Init();
this.timeNotifications = data.timeNotifications;
this.timeNotificationID = data.timeNotificationID;
};
GuiInterface.prototype.Init = function()
@ -695,53 +701,43 @@ GuiInterface.prototype.GetNeededResources = function(player, amounts)
return cmpPlayer.GetNeededResources(amounts);
};
GuiInterface.prototype.AddTimeNotification = function(notification)
/**
* Add a timed notification.
* Warning: timed notifacations are serialised
* (to also display them on saved games or after a rejoin)
* so they should allways be added and deleted in a deterministic way.
*/
GuiInterface.prototype.AddTimeNotification = function(notification, duration = 10000)
{
var time = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime();
notification.endTime = notification.duration + time;
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
notification.endTime = duration + cmpTimer.GetTime();
notification.id = ++this.timeNotificationID;
this.timeNotifications.push(notification);
this.timeNotifications.sort(function (n1, n2){return n2.endTime - n1.endTime});
cmpTimer.SetTimeout(this.entity, IID_GuiInterface, "DeleteTimeNotification", duration, this.timeNotificationID);
return this.timeNotificationID;
};
GuiInterface.prototype.DeleteTimeNotification = function(notificationID)
{
for (var i in this.timeNotifications)
{
if (this.timeNotifications[i].id == notificationID)
{
this.timeNotifications.splice(i);
return;
}
}
this.timeNotifications = this.timeNotifications.filter(n => n.id != notificationID);
};
GuiInterface.prototype.GetTimeNotifications = function(playerID)
{
var time = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime();
var toDelete = [];
for (var n of this.timeNotifications)
{
n.time = n.endTime - time;
if (n.time < 0)
toDelete.push(n.id);
}
for (var id of toDelete)
this.DeleteTimeNotification(id);
return this.timeNotifications;
// filter on players and time, since the delete timer might be executed with a delay
return this.timeNotifications.filter(n => n.players.indexOf(playerID) != -1 && n.endTime > time);
};
GuiInterface.prototype.PushNotification = function(notification)
{
if (!notification.type || notification.type == "text")
{
if (!notification.duration)
notification.duration = 10000;
this.AddTimeNotification(notification);
return;
}
this.notifications.push(notification);
else
this.notifications.push(notification);
};
GuiInterface.prototype.GetNextNotification = function()