1
0
forked from 0ad/0ad

Improve rejoin messages. Patch by elexis. Fixes #1949.

This was SVN commit r16614.
This commit is contained in:
leper 2015-05-03 02:06:17 +00:00
parent ecf229046a
commit 7a70c475df
11 changed files with 129 additions and 56 deletions

View File

@ -111,6 +111,7 @@ function pollAndHandleNetworkClient()
Engine.SwitchGuiPage("page_loading.xml", {
"attribs": g_GameAttributes,
"isNetworked" : true,
"isRejoining" : g_IsRejoining,
"playerAssignments": g_PlayerAssignments
});
break;

View File

@ -33,13 +33,11 @@ function init(data)
Engine.GetGUIObjectByName("tipImage").sprite = sprite? sprite : "";
}
else
{
error("Failed to find any matching tips for the loading screen.")
}
// janwas: main loop now sets progress / description, but that won't
// happen until the first timeslice completes, so set initial values.
var loadingMapName = Engine.GetGUIObjectByName ("loadingMapName");
var loadingMapName = Engine.GetGUIObjectByName("loadingMapName");
if (data)
{
@ -48,15 +46,15 @@ function init(data)
{
case "skirmish":
case "scenario":
loadingMapName.caption = sprintf(translate("Loading “%(map)s”"), {map: mapName});
loadingMapName.caption = sprintf(translate("Loading “%(map)s”"), { "map": mapName });
break;
case "random":
loadingMapName.caption = sprintf(translate("Generating “%(map)s”"), {map: mapName});
loadingMapName.caption = sprintf(translate("Generating “%(map)s”"), { "map": mapName });
break;
default:
error(sprintf("Unknown map type: %(mapType)s", { mapType: data.attribs.mapType }));
error("Unknown map type: " + data.attribs.mapType);
}
}
@ -68,49 +66,47 @@ function init(data)
Engine.GetGUIObjectByName("quoteText").caption = translate(quoteArray[getRandom(0, quoteArray.length-1)]);
}
// ====================================================================
function displayProgress()
{
// Make the progessbar finish a little early so that the user can actually see it finish
if (g_Progress < 100)
{
// Show 100 when it is really 99
var progress = g_Progress + 1;
if (g_Progress >= 100)
return;
Engine.GetGUIObjectByName("progressbar").caption = progress; // display current progress
Engine.GetGUIObjectByName("progressText").caption = progress + "%";
// Show 100 when it is really 99
var progress = g_Progress + 1;
// Displays detailed loading info rather than a percent
// Engine.GetGUIObjectByName("progressText").caption = g_LoadDescription; // display current progess details
Engine.GetGUIObjectByName("progressbar").caption = progress; // display current progress
Engine.GetGUIObjectByName("progressText").caption = progress + "%";
// Keep curved right edge of progress bar in sync with the rest of the progress bar
var middle = Engine.GetGUIObjectByName("progressbar");
var rightSide = Engine.GetGUIObjectByName("progressbar_right");
// Displays detailed loading info rather than a percent
// Engine.GetGUIObjectByName("progressText").caption = g_LoadDescription; // display current progess details
var middleLength = (middle.size.right - middle.size.left) - (END_PIECE_WIDTH / 2);
var increment = Math.round(progress * middleLength / 100);
// Keep curved right edge of progress bar in sync with the rest of the progress bar
var middle = Engine.GetGUIObjectByName("progressbar");
var rightSide = Engine.GetGUIObjectByName("progressbar_right");
var size = rightSide.size;
size.left = increment;
size.right = increment + END_PIECE_WIDTH;
rightSide.size = size;
}
var middleLength = (middle.size.right - middle.size.left) - (END_PIECE_WIDTH / 2);
var increment = Math.round(progress * middleLength / 100);
var size = rightSide.size;
size.left = increment;
size.right = increment + END_PIECE_WIDTH;
rightSide.size = size;
}
// ====================================================================
/**
* This is a reserved function name that is executed by the engine when it is ready
* to start the game (i.e. loading progress has reached 100%).
*/
function reallyStartGame()
{
// Stop the music
// if (global.curr_music)
// global.curr_music.fade(-1, 0.0, 5.0); // fade to 0 over 5 seconds
// This is a reserved function name that is executed by the engine when it is ready
// to start the game (i.e. loading progress has reached 100%).
// Switch GUI from loading screen to game session.
Engine.SwitchGuiPage("page_session.xml", g_Data);
// Restore default cursor.
Engine.SetCursor("arrow-default");
// Notify the other clients that we have finished the loading screen
if (g_Data.isNetworked && g_Data.isRejoining)
Engine.SendNetworkRejoined();
}

View File

@ -252,7 +252,7 @@ function handleNetMessage(message)
// Find and report all leavings
for (var host in g_PlayerAssignments)
{
if (! message.hosts[host])
if (!message.hosts[host])
{
// Tell the user about the disconnection
addChatMessage({ "type": "disconnect", "guid": host });
@ -265,7 +265,7 @@ function handleNetMessage(message)
// Find and report all joinings
for (var host in message.hosts)
{
if (! g_PlayerAssignments[host])
if (!g_PlayerAssignments[host])
{
// Update the cached player data, so we can display the correct name
updatePlayerDataAdd(g_Players, host, message.hosts[host]);
@ -293,6 +293,10 @@ function handleNetMessage(message)
addChatMessage({ "type": "message", "guid": message.guid, "text": message.text, "translate": true });
break;
case "rejoined":
addChatMessage({ "type": "rejoined", "guid": message.guid});
break;
// To prevent errors, ignore these message types that occur during autostart
case "gamesetup":
case "start":
@ -432,11 +436,14 @@ function addChatMessage(msg, playerAssignments)
switch (msg.type)
{
case "connect":
formatted = sprintf(translate("%(player)s has joined the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
formatted = sprintf(translate("%(player)s is starting to rejoin the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
break;
case "disconnect":
formatted = sprintf(translate("%(player)s has left the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
break;
case "rejoined":
formatted = sprintf(translate("%(player)s has rejoined the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
break;
case "defeat":
// In singleplayer, the local player is "You". "You has" is incorrect.
if (!g_IsNetworked && msg.player == Engine.GetPlayerID())
@ -445,29 +452,31 @@ function addChatMessage(msg, playerAssignments)
formatted = sprintf(translate("%(player)s has been defeated."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
break;
case "diplomacy":
var status = (msg.status == "ally" ? "allied" : (msg.status == "enemy" ? "at war" : "neutral"));
var message;
if (msg.player == Engine.GetPlayerID())
{
[username, playerColor] = getUsernameAndColor(msg.player1);
if (msg.status == "ally")
formatted = sprintf(translate("You are now allied with %(player)s."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
message = translate("You are now allied with %(player)s.");
else if (msg.status == "enemy")
formatted = sprintf(translate("You are now at war with %(player)s."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
message = translate("You are now at war with %(player)s.");
else // (msg.status == "neutral")
formatted = sprintf(translate("You are now neutral with %(player)s."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
message = translate("You are now neutral with %(player)s.");
}
else if (msg.player1 == Engine.GetPlayerID())
{
[username, playerColor] = getUsernameAndColor(msg.player);
if (msg.status == "ally")
formatted = sprintf(translate("%(player)s is now allied with you."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
message = translate("%(player)s is now allied with you.");
else if (msg.status == "enemy")
formatted = sprintf(translate("%(player)s is now at war with you."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
message = translate("%(player)s is now at war with you.");
else // (msg.status == "neutral")
formatted = sprintf(translate("%(player)s is now neutral with you."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" });
message = translate("%(player)s is now neutral with you.");
}
else // No need for other players to know of this.
return;
formatted = sprintf(message, { "player": '[color="'+ playerColor + '"]' + username + '[/color]' });
break;
case "tribute":
if (msg.player != Engine.GetPlayerID())

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -395,6 +395,13 @@ void SendNetworkReady(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int messag
g_NetClient->SendReadyMessage(message);
}
void SendNetworkRejoined(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
{
ENSURE(g_NetClient);
g_NetClient->SendRejoinedMessage();
}
JS::Value GetAIs(ScriptInterface::CxPrivate* pCxPrivate)
{
return ICmpAIManager::GetAIs(*(pCxPrivate->pScriptInterface));
@ -956,6 +963,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady");
scriptInterface.RegisterFunction<void, std::wstring, &SendNetworkChat>("SendNetworkChat");
scriptInterface.RegisterFunction<void, int, &SendNetworkReady>("SendNetworkReady");
scriptInterface.RegisterFunction<void, &SendNetworkRejoined>("SendNetworkRejoined");
scriptInterface.RegisterFunction<JS::Value, &GetAIs>("GetAIs");
scriptInterface.RegisterFunction<JS::Value, &GetEngineInfo>("GetEngineInfo");

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -109,6 +109,7 @@ CNetClient::CNetClient(CGame* game) :
AddTransition(NCS_LOADING, (uint)NMT_PLAYER_ASSIGNMENT, NCS_LOADING, (void*)&OnPlayerAssignment, context);
AddTransition(NCS_LOADING, (uint)NMT_LOADED_GAME, NCS_INGAME, (void*)&OnLoadedGame, context);
AddTransition(NCS_INGAME, (uint)NMT_REJOINED, NCS_INGAME, (void*)&OnRejoined, context);
AddTransition(NCS_INGAME, (uint)NMT_CHAT, NCS_INGAME, (void*)&OnChat, context);
AddTransition(NCS_INGAME, (uint)NMT_GAME_SETUP, NCS_INGAME, (void*)&OnGameSetup, context);
AddTransition(NCS_INGAME, (uint)NMT_PLAYER_ASSIGNMENT, NCS_INGAME, (void*)&OnPlayerAssignment, context);
@ -286,6 +287,12 @@ void CNetClient::SendReadyMessage(const int status)
SendMessage(&readyStatus);
}
void CNetClient::SendRejoinedMessage()
{
CRejoinedMessage rejoinedMessage;
SendMessage(&rejoinedMessage);
}
bool CNetClient::HandleMessage(CNetMessage* message)
{
// Handle non-FSM messages first
@ -584,6 +591,22 @@ bool CNetClient::OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event)
return true;
}
bool CNetClient::OnRejoined(void *context, CFsmEvent* event)
{
ENSURE(event->GetType() == (uint)NMT_REJOINED);
CNetClient* client = (CNetClient*)context;
JSContext* cx = client->GetScriptInterface().GetContext();
CRejoinedMessage* message = (CRejoinedMessage*)event->GetParamRef();
JS::RootedValue msg(cx);
client->GetScriptInterface().Eval("({'type':'rejoined'})", &msg);
client->GetScriptInterface().SetProperty(msg, "guid", std::string(message->m_GUID), false);
client->PushGuiMessage(msg);
return true;
}
bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event)
{
ENSURE(event->GetType() == (uint)NMT_LOADED_GAME);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -180,6 +180,12 @@ public:
void SendReadyMessage(const int status);
/**
* Call when the client has rejoined a running match and finished
* the loading screen.
*/
void SendRejoinedMessage();
private:
// Net message / FSM transition handlers
static bool OnConnect(void* context, CFsmEvent* event);
@ -194,6 +200,7 @@ private:
static bool OnGameStart(void* context, CFsmEvent* event);
static bool OnJoinSyncStart(void* context, CFsmEvent* event);
static bool OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event);
static bool OnRejoined(void* context, CFsmEvent* event);
static bool OnLoadedGame(void* context, CFsmEvent* event);
/**

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -131,6 +131,10 @@ CNetMessage* CNetMessageFactory::CreateMessage(const void* pData,
pNewMessage = new CJoinSyncStartMessage;
break;
case NMT_REJOINED:
pNewMessage = new CRejoinedMessage;
break;
case NMT_LOADED_GAME:
pNewMessage = new CLoadedGameMessage;
break;
@ -174,7 +178,7 @@ CNetMessage* CNetMessageFactory::CreateMessage(const void* pData,
case NMT_CHAT:
pNewMessage = new CChatMessage;
break;
case NMT_READY:
pNewMessage = new CReadyMessage;
break;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -28,7 +28,7 @@
#define PS_PROTOCOL_MAGIC 0x5073013f // 'P', 's', 0x01, '?'
#define PS_PROTOCOL_MAGIC_RESPONSE 0x50630121 // 'P', 'c', 0x01, '!'
#define PS_PROTOCOL_VERSION 0x01010005 // Arbitrary protocol
#define PS_PROTOCOL_VERSION 0x01010006 // Arbitrary protocol
#define PS_DEFAULT_PORT 0x5073 // 'P', 's'
// Defines the list of message types. The order of the list must not change.
@ -57,6 +57,8 @@ enum NetMessageType
NMT_JOIN_SYNC_START,
NMT_REJOINED,
NMT_LOADED_GAME,
NMT_GAME_START,
NMT_END_COMMAND_BATCH,
@ -155,6 +157,10 @@ END_NMT_CLASS()
START_NMT_CLASS_(JoinSyncStart, NMT_JOIN_SYNC_START)
END_NMT_CLASS()
START_NMT_CLASS_(Rejoined, NMT_REJOINED)
NMT_FIELD(CStr8, m_GUID)
END_NMT_CLASS()
START_NMT_CLASS_(LoadedGame, NMT_LOADED_GAME)
NMT_FIELD_INT(m_CurrentTurn, u32, 4)
END_NMT_CLASS()

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -593,6 +593,7 @@ void CNetServerWorker::SetupSession(CNetServerSession* session)
session->AddTransition(NSS_JOIN_SYNCING, (uint)NMT_CONNECTION_LOST, NSS_UNCONNECTED, (void*)&OnDisconnect, context);
session->AddTransition(NSS_JOIN_SYNCING, (uint)NMT_LOADED_GAME, NSS_INGAME, (void*)&OnJoinSyncingLoadedGame, context);
session->AddTransition(NSS_INGAME, (uint)NMT_REJOINED, NSS_INGAME, (void*)&OnRejoined, context);
session->AddTransition(NSS_INGAME, (uint)NMT_CONNECTION_LOST, NSS_UNCONNECTED, (void*)&OnDisconnect, context);
session->AddTransition(NSS_INGAME, (uint)NMT_CHAT, NSS_INGAME, (void*)&OnChat, context);
session->AddTransition(NSS_INGAME, (uint)NMT_SIMULATION_COMMAND, NSS_INGAME, (void*)&OnInGame, context);
@ -988,6 +989,23 @@ bool CNetServerWorker::OnJoinSyncingLoadedGame(void* context, CFsmEvent* event)
return true;
}
bool CNetServerWorker::OnRejoined(void* context, CFsmEvent* event)
{
// A client has finished rejoining and the loading screen disappeared.
ENSURE(event->GetType() == (uint)NMT_REJOINED);
CNetServerSession* session = (CNetServerSession*)context;
CNetServerWorker& server = session->GetServer();
CRejoinedMessage* message = (CRejoinedMessage*)event->GetParamRef();
message->m_GUID = session->GetGUID();
server.Broadcast(message);
return true;
}
bool CNetServerWorker::OnDisconnect(void* context, CFsmEvent* event)
{
ENSURE(event->GetType() == (uint)NMT_CONNECTION_LOST);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2013 Wildfire Games.
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -262,6 +262,7 @@ private:
static bool OnReady(void* context, CFsmEvent* event);
static bool OnLoadedGame(void* context, CFsmEvent* event);
static bool OnJoinSyncingLoadedGame(void* context, CFsmEvent* event);
static bool OnRejoined(void* context, CFsmEvent* event);
static bool OnDisconnect(void* context, CFsmEvent* event);
void CheckGameLoadStatus(CNetServerSession* changedSession);

View File

@ -235,6 +235,9 @@ PSRETURN CGame::ReallyStartGame()
if (CRenderer::IsInitialised())
Render();
if (g_NetClient)
g_NetClient->LoadFinished();
// Call the reallyStartGame GUI function, but only if it exists
if (g_GUI && g_GUI->HasPages())
{
@ -243,9 +246,6 @@ PSRETURN CGame::ReallyStartGame()
g_GUI->GetActiveGUI()->GetScriptInterface()->CallFunctionVoid(global, "reallyStartGame");
}
if (g_NetClient)
g_NetClient->LoadFinished();
debug_printf("GAME STARTED, ALL INIT COMPLETE\n");
// The call tree we've built for pregame probably isn't useful in-game.