Fixes selection of nation when connecting to a running multiplayer game.

This commit is contained in:
Stian Grenborgen 2022-06-18 10:41:56 +02:00
parent c28b893007
commit a34f43425e
4 changed files with 47 additions and 22 deletions

View File

@ -187,7 +187,8 @@ public final class ConnectController extends FreeColClientHolder {
final String name = player.getName();
try {
if (askServer().reconnect() != null
&& askServer().login(name, FreeCol.getVersion(),
&& askServer().login(name, player.getNationId(),
FreeCol.getVersion(),
fcc.getSinglePlayer(),
fcc.currentPlayerIsMyPlayer())) {
logger.info("Reconnected for client " + name);
@ -212,12 +213,13 @@ public final class ConnectController extends FreeColClientHolder {
* Public for the test suite.
*
* @param user The name of the player to use.
* @param nationId The nationId when the client is selecting a player.
* @param host The name of the machine running the {@code FreeColServer}.
* @param port The port to use when connecting to the host.
* @return True if the player was already logged in, or if the login
* message was sent.
*/
public boolean requestLogin(String user, String host, int port) {
public boolean requestLogin(String user, String nationId, String host, int port) {
final FreeColClient fcc = getFreeColClient();
if (fcc.isLoggedIn()) return true;
fcc.setMapEditor(false);
@ -232,7 +234,7 @@ public final class ConnectController extends FreeColClientHolder {
// name. Control effectively transfers through the server
// back to PGIH.login() and then to login() below.
logger.info("Login request for client " + FreeCol.getName());
if (askServer().login(user, FreeCol.getVersion(),
if (askServer().login(user, nationId, FreeCol.getVersion(),
fcc.getSinglePlayer(),
fcc.currentPlayerIsMyPlayer())) {
return true;
@ -347,7 +349,7 @@ public final class ConnectController extends FreeColClientHolder {
FreeColServer fcs = fcc.startServer(false, true, spec, null, -1);
return (fcs == null) ? false
: requestLogin(FreeCol.getName(),
: requestLogin(FreeCol.getName(), null,
fcs.getHost(), fcs.getPort());
}
@ -450,7 +452,7 @@ public final class ConnectController extends FreeColClientHolder {
fcc.setFreeColServer(fcs);
fcc.setSinglePlayer(true);
return requestLogin(FreeCol.getName(), fcs.getHost(), fcs.getPort());
return requestLogin(FreeCol.getName(), null, fcs.getHost(), fcs.getPort());
}
/**
@ -481,7 +483,7 @@ public final class ConnectController extends FreeColClientHolder {
if (fcs == null) return false;
fcc.setFreeColServer(fcs);
fcc.setSinglePlayer(false);
return requestLogin(FreeCol.getName(), fcs.getHost(), fcs.getPort());
return requestLogin(FreeCol.getName(), null, fcs.getHost(), fcs.getPort());
}
/**
@ -510,6 +512,7 @@ public final class ConnectController extends FreeColClientHolder {
while (fcc.getServerState() == null) Utils.delay(1000, null);
askServer().disconnect();
String nationId = null;
switch (fcc.getServerState()) {
case PRE_GAME: case LOAD_GAME:
// Name is good
@ -529,20 +532,19 @@ public final class ConnectController extends FreeColClientHolder {
if (names.isEmpty()) return false;
if (names.contains(name)) break; // Already there, use it
StringTemplate tmpl = StringTemplate.template("client.choicePlayer");
String choice = getGUI().getChoice(tmpl, "cancel",
nationId = getGUI().getChoice(tmpl, "cancel",
transform(names, alwaysTrue(), n ->
new ChoiceItem<>(Messages.message(StringTemplate
.template("countryName")
.add("%nation%", Messages.nameKey(n))), n)));
if (choice == null) return false; // User cancelled
name = Messages.getRulerName(choice);
if (nationId == null) return false; // User cancelled
break;
case END_GAME: default:
getGUI().showErrorPanel(StringTemplate.template("client.ending"));
return false;
}
return requestLogin(name, host, port);
return requestLogin(name, nationId, host, port);
}
/**

View File

@ -19,6 +19,9 @@
package net.sf.freecol.common.networking;
import static net.sf.freecol.common.util.CollectionUtils.alwaysTrue;
import static net.sf.freecol.common.util.CollectionUtils.transform;
import java.util.stream.Collectors;
import javax.xml.stream.XMLStreamException;
@ -32,7 +35,6 @@ import net.sf.freecol.common.model.Nation;
import net.sf.freecol.common.model.Player;
import net.sf.freecol.common.model.StringTemplate;
import net.sf.freecol.common.networking.ChangeSet.See;
import static net.sf.freecol.common.util.CollectionUtils.*;
import net.sf.freecol.server.FreeColServer;
import net.sf.freecol.server.FreeColServer.ServerState;
import net.sf.freecol.server.model.ServerGame;
@ -49,6 +51,7 @@ public class LoginMessage extends ObjectMessage {
private static final String SINGLE_PLAYER_TAG = "singlePlayer";
private static final String STATE_TAG = "state";
private static final String USER_NAME_TAG = "userName";
private static final String NATION_ID_TAG = "nationId";
private static final String VERSION_TAG = "version";
/** The player in the attached game, if any. */
@ -60,17 +63,21 @@ public class LoginMessage extends ObjectMessage {
*
* @param player The {@code player} to send to.
* @param userName The name of the user logging in.
* @param nationId The nationId when the client is selecting a player.
* @param version The version of FreeCol at the client.
* @param state The server state.
* @param singlePlayer True in single player games.
* @param currentPlayer True if this player is the current player.
* @param game The entire game.
*/
public LoginMessage(Player player, String userName,
public LoginMessage(Player player, String userName, String nationId,
String version, ServerState state,
boolean singlePlayer, boolean currentPlayer,
Game game) {
super(TAG, USER_NAME_TAG, userName, VERSION_TAG, version,
super(TAG,
USER_NAME_TAG, userName,
NATION_ID_TAG, nationId,
VERSION_TAG, version,
SINGLE_PLAYER_TAG, Boolean.toString(singlePlayer),
CURRENT_PLAYER_TAG, Boolean.toString(currentPlayer));
@ -89,7 +96,7 @@ public class LoginMessage extends ObjectMessage {
*/
public LoginMessage(@SuppressWarnings("unused") Game ignoredGame,
FreeColXMLReader xr) throws XMLStreamException {
super(TAG, xr, USER_NAME_TAG, VERSION_TAG, STATE_TAG,
super(TAG, xr, USER_NAME_TAG, NATION_ID_TAG, VERSION_TAG, STATE_TAG,
SINGLE_PLAYER_TAG, CURRENT_PLAYER_TAG);
Game game = null;
@ -110,6 +117,10 @@ public class LoginMessage extends ObjectMessage {
private String getUserName() {
return getStringAttribute(USER_NAME_TAG);
}
private String getNationId() {
return getStringAttribute(NATION_ID_TAG);
}
private String getVersion() {
return getStringAttribute(VERSION_TAG);
@ -139,7 +150,12 @@ public class LoginMessage extends ObjectMessage {
* @return The {@code ServerPlayer} found.
*/
private Player getPlayer(Game game) {
return game.getPlayerByName(getUserName());
final Player playerByUsername = game.getPlayerByName(getUserName());
if (playerByUsername != null) {
return playerByUsername;
}
return game.getPlayerByNationId(getNationId());
}
@ -214,7 +230,7 @@ public class LoginMessage extends ObjectMessage {
serverGame.getLivePlayerList().isEmpty(),
nation);
// ... but override player name.
// ... but override player name
serverPlayer.setName(userName);
// Add the new player and inform all other players
@ -234,7 +250,9 @@ public class LoginMessage extends ObjectMessage {
.toClient(serverPlayer));
ret.add(See.only(serverPlayer),
new LoginMessage(serverPlayer, userName, getVersion(),
new LoginMessage(serverPlayer, userName,
serverPlayer.getNationId(),
getVersion(),
freeColServer.getServerState(),
freeColServer.getSinglePlayer(),
serverGame.getCurrentPlayer() == serverPlayer,
@ -303,7 +321,9 @@ public class LoginMessage extends ObjectMessage {
connection.setWriteScope(FreeColXMLWriter.WriteScope
.toClient(present));
ret = ChangeSet.simpleChange(present,
new LoginMessage(present, userName, getVersion(),
new LoginMessage(present, userName,
present.getNationId(),
getVersion(),
freeColServer.getServerState(),
freeColServer.getSinglePlayer(),
serverGame.getCurrentPlayer() == present,
@ -350,6 +370,7 @@ public class LoginMessage extends ObjectMessage {
// Join allowed, including over an AI
if (present.isAI()) serverGame.changeAI(present, false);
present.setName(userName);
present.setConnection(connection);
// Add the connection, send back the game
@ -357,7 +378,8 @@ public class LoginMessage extends ObjectMessage {
connection.setWriteScope(FreeColXMLWriter.WriteScope
.toClient(present));
ret = ChangeSet.simpleChange(present,
new LoginMessage(present, userName, getVersion(),
new LoginMessage(present, userName, present.getNationId(),
getVersion(),
freeColServer.getServerState(),
freeColServer.getSinglePlayer(),
serverGame.getCurrentPlayer() == present,

View File

@ -635,15 +635,16 @@ public abstract class ServerAPI {
* Server query-response for logging in a player (pre-game).
*
* @param userName The user name.
* @param nationId The nationId when the client is selecting a player.
* @param version The client version.
* @param single True if this is a single player login.
* @param current True if the requesting player should become the
* current player.
* @return True if the server interaction succeeded.
*/
public boolean login(String userName, String version,
public boolean login(String userName, String nationId, String version,
boolean single, boolean current) {
return ask(new LoginMessage(null, userName, version, null,
return ask(new LoginMessage(null, userName, nationId, version, null,
single, current, null));
}

View File

@ -60,7 +60,7 @@ public class ClientTestHelper {
client.setFreeColServer(freeColServer);
client.setSinglePlayer(true);
boolean ok = connectController.requestLogin("test",
boolean ok = connectController.requestLogin("test", null,
freeColServer.getHost(), freeColServer.getPort());
assertTrue("test login", ok);
connectController.startSinglePlayerGame(specification);