Opened 8 years ago

Last modified 6 weeks ago

#1088 new enhancement

Multiplayer saved games

Reported by: historic_bruno Owned by:
Priority: Must Have Milestone: Backlog
Component: Core engine Keywords: beta
Cc: Quentin Patch:

Description

We have single player saved games and multiplayer rejoin, we also need multiplayer saved games. This means having a main menu option like Multiplayer > Load Game that allows the users to host a game from the saved games list, then displays a new yet-to-be-designed UI. We could use elements of the current multiplayer setup screen for consistency, except that most of the settings would be defined in the saved game data and only displayed for confirmation.

Change History (23)

comment:1 Changed 6 years ago by Petr

Hello, any updates on this?

comment:2 Changed 6 years ago by Jia Henry

Wouldn't this just be scenarios?

comment:3 in reply to:  2 Changed 4 years ago by elexis

Replying to HenryJia:

Wouldn't this just be scenarios?

No, this includes all maptypes (since rejoining and savegames also work for all maptypes).

Replying to historic_bruno: It should also work for the lobby. So it's likely better to add a button to the gamesetup instead of the main menu to load a savegame.

Details on the implementation:

When the game is started, the server should send the savegame to all clients, which load that after receive. The rejoin mechanism might not be needed and would be slower (since the server downloads the state from a client, which needs to serialize the current state, zip it and send it over the network [which might be the internet in case of a dedicated server #3556]).

Playing rated games with this feature should not be possible to prevent cheating the score. A new match-ID must be generated to keep it unique.

comment:4 Changed 4 years ago by elexis

The mechanism to continue a replay from a serialized state in #3261 would be needed to make those replays work (which can be done in another ticket after implementing this ticket and 3261).

comment:5 Changed 4 years ago by elexis

Basic:

  • New gamesetup button for controllers to select a savegame (load.xml)
    • returns the savegame filename and metadata
    • The game attributes are loaded from the metadata and broadcasted
    • By matching playernames, the players can receive their old player slot again, otherwise will become assigned to an empty slot (might prefer assigning previously assigned players over previous observers).
    • All gamesetup options besides game speed and player assignments become disabled
    • A cancel button undos the selection.
  • When the controller sends the game-start message, the clients start downloading the serialized state from the server.
    • The controller doesn't serialize the gamestate but just sends the savegame.

Advanced:

  • The savegame also contains the entire replayfile, so that the replay can be seen from the beginning to the savepoint and onwards from there.

Alternatively the replay menu shows the replays of these matches with the actual time spent after the savepoint and shows a link (identified via matchID) to the first part of the replay. The replay would load the saved state and continue replaying from there.

comment:7 Changed 3 years ago by scythetwirler

Keywords: beta added

comment:8 Changed 3 years ago by scythetwirler

Priority: Should HaveMust Have

comment:9 in reply to:  5 ; Changed 3 years ago by avi448

Replying to elexis:

Basic:

  • New gamesetup button for controllers to select a savegame (load.xml)
    • returns the savegame filename and metadata
    • The game attributes are loaded from the metadata and broadcasted
    • By matching playernames, the players can receive their old player slot again, otherwise will become assigned to an empty slot (might prefer assigning previously assigned players over previous observers).
    • All gamesetup options besides game speed and player assignments become disabled
    • A cancel button undos the selection.
  • When the controller sends the game-start message, the clients start downloading the serialized state from the server.
    • The controller doesn't serialize the gamestate but just sends the savegame.

Advanced:

  • The savegame also contains the entire replayfile, so that the replay can be seen from the beginning to the savepoint and onwards from there.

Alternatively the replay menu shows the replays of these matches with the actual time spent after the savepoint and shows a link (identified via matchID) to the first part of the replay. The replay would load the saved state and continue replaying from there.

Done:

  • New gamesetup button for controllers to select a savegame (load.xml)
  • returns the savegame filename and metadata

TODO:

  • The game attributes are loaded from the metadata and broadcasted
  • By matching playernames, the players can receive their old player slot again, otherwise will become assigned to an empty slot (might prefer assigning previously assigned players over previous observers).
  • All gamesetup options besides game speed and player assignments become disabled
  • The controller doesn't serialize the gamestate but just sends the savegame.

The button works as intended, some re-writing was needed to parse info from load.js to gamesetup.xml (The game attributes, still to be done). The button only show ups to the player hosting the match (g_IsController), pressing "Load" button still does nothing, but next step would be to have the "Load" button returning the game attributes and parsing it to gamesetup.xml.

By the way, the "Load Game" button on the Singleplayer Submenu doesn't longer work since some re-writing had to be done, and crashes the game. Not really a problem since that won't be necessary once we get this working.

TODO Now:

function loadGame()
{
	let gameSelection = Engine.GetGUIObjectByName("gameSelection");
	let gameId = gameSelection.list_data[gameSelection.selected];
	let metadata = g_SavedGamesMetadata[gameSelection.selected];

	// Check compatibility before really loading it
	let engineInfo = Engine.GetEngineInfo();
	let sameMods = hasSameMods(metadata, engineInfo);
	let sameEngineVersion = hasSameEngineVersion(metadata, engineInfo);
	let sameSavegameVersion = hasSameSavegameVersion(metadata, engineInfo);

	if (sameEngineVersion && sameSavegameVersion && sameMods)
	{
		[init, function(){ parseGameData(); }]
		return;
	}

	// Version not compatible ... ask for confirmation
	let message = translate("This saved game may not be compatible:");

	if (!sameEngineVersion)
	{
		if (metadata.engine_version)
			message += "\n" + sprintf(translate("It needs 0 A.D. version %(requiredVersion)s, while you are running version %(currentVersion)s."), {
				"requiredVersion": metadata.engine_version,
				"currentVersion": engineInfo.engine_version
			});
		else
			message += "\n" + translate("It needs an older version of 0 A.D.");
	}

	if (!sameSavegameVersion)
		message += "\n" + sprintf(translate("It needs 0 A.D. savegame version %(requiredVersion)s, while you have savegame version %(currentVersion)s."), {
			"requiredVersion": metadata.version_major,
			"currentVersion": engineInfo.version_major
		});

	if (!sameMods)
	{
		if (!metadata.mods)
			metadata.mods = [];

		message += translate("The savegame needs a different set of mods:") + "\n" +
			sprintf(translate("Required: %(mods)s"), {
				"mods": metadata.mods.join(translate(", "))
			}) + "\n" +
			sprintf(translate("Active: %(mods)s"), {
				"mods": engineInfo.mods.join(translate(", "))
			});
	}

	message += "\n" + translate("Do you still want to proceed?");

	messageBox(
		500, 250,
		message,
		translate("Warning"),
		[translate("No"), translate("Yes")],
		[init, function(){ parseGameData(); }]
		
	);
}

function parseGameData()
{   


}

Have "function parseGameData()" printing the game attributes to gamesetup.xml

To be noted: gamesetup.xml already includes "load.js" in its script list, some re-writing had to be done because of that but it's all done now.

Last edited 3 years ago by avi448 (previous) (diff)

comment:10 Changed 2 years ago by miirpat

edit: pls delete this mods

Last edited 2 years ago by miirpat (previous) (diff)

comment:11 Changed 2 years ago by miirpat

edit: sorry, pls delete

Last edited 2 years ago by miirpat (previous) (diff)

comment:12 in reply to:  9 Changed 2 years ago by miirpat

Replying to avi448
any news on that topic?

comment:13 Changed 20 months ago by Quentin

This is a very important feature, can this be included in the next release?

comment:14 Changed 20 months ago by Quentin

Cc: Quentin added

comment:15 Changed 20 months ago by stanislas69

It would indeed be a nice feature however there is no one working on it at the moment. If you know people who can or if yourself wants to work on it please go ahead.

comment:16 Changed 20 months ago by elexis

I know someone

comment:17 Changed 20 months ago by Quentin

I have been looking through the code, my thoughts:

Engine.StartSavedGame? is missing the capability to take attributes and/or a player ID.

A simple implementation with minimal engine changes (adding a playerID argument) could be that the game is always saved on all players machines (with the same filename), then in gamesetup, check if the joined player has the same saved game file as the host, then start.

A way to send the save to the other players would be a bonus.

avi448 seems to have made progress though, is there a branch/repo/patch for this?

Last edited 20 months ago by Quentin (previous) (diff)

comment:18 Changed 20 months ago by elexis

With increasing number of players, it's becoming more unlikely that the same players of the same match all meet again. So it'd more supportive it would allow to replace individual players.

The server sends a savegame to clients when they rejoin, it should work the same way here, just that the binary state is sent at gamestart. There are also gamesetup changes needed (easy following Phab:D322 however), because most if not all of the settings cannot be changed anymore.

comment:19 Changed 20 months ago by avi448

I'm glad this is being picked up again, i honestly barely knew programming, i was just learning and brainstorming through the code. I only accomplished some UI work which i probably still have here but it wasn't anything that advanced.

Throughout my way the main problem i encountered was that the NetClient? worked in the same thread as the Map Generation, so it wasn't just as simple as loading a save game as a host. There was a lot of code that had to be rewritten.

Naturally i would have loved to keep working at it but i had personal problems which i had to attend to and i ended up dropping it because of that. Now i don't know all that much about coding SO i could be wrong, but i think doing https://trac.wildfiregames.com/ticket/3700 first would make it a lot easier to implement this, since then we could do what Quentin suggested more easily.

At least that's how i believe it would work, i would love to keep working at this but i probably would slow you down with my inexperience, still i would love to help anyway i can. So i'll be watching :)

Last edited 20 months ago by avi448 (previous) (diff)

comment:20 Changed 19 months ago by Quentin

Just letting everyone know, there is a bounty for this issue on BountySource?.

This can be tracked here: https://www.bountysource.com/issues/5689352-multiplayer-saved-games

comment:21 Changed 11 months ago by Quentin

How difficult would it be to implement a 'Engine.StartNetworkSavedGame?' function?

comment:22 Changed 11 months ago by elexis

In case your question is technical and whether this can be implemented without a full GUI implementation, it's still some effort, since the player assignments are not trivial (playernames would have to be stored along the savegame and match perfectly when loading), the gamesetup stage would have to be skipped (players won't see what game they join), and at least little networking code would have to be changed.

When the bounty was added, I started reworking the gamesetup so that it can display the immutable settings from the savegame and to allow the host to assing joining players to the existing playerslots. After several hundred lines of changes I had suspended the work on that. I'm currently working to replace bountysource with a non-profit tax-exempt solution where no middleman takes a cut, then will continue to work on this feature, unless someone else comes along before me.

comment:23 Changed 6 weeks ago by elexis

In 23374:

Gamesetup class rewrite, fixes #5322, refs #5387.

  • Decouples settings logically which in turn allows fixing many problems arising from previous coupling.
  • Fixes the persist-match-settings feature, refs #2963, refs #3049.
  • Improves performance of the matchsetup by rebuilding GUI objects only when necessary.

Provides groundwork for:

Refs https://wildfiregames.com/forum/index.php?/topic/20787-paid-development-2016/ https://wildfiregames.com/forum/index.php?/topic/20789-paid-development-2016/

Enable maps to restrict setting values:

  • If a map specifies an AI or Civs for a playerslot, the controller can't assign a player/other AI or Civ to that slot, refs #3049, #3013.

Fix per player StartingResources?, PopulationCap?, StartingTechnologies?, DisabledTechnologies?, DisabledTemplates? following rP12756, refs #812, fixes #4504. Use this for DisabledTechnologies? on Polar Sea.

Persist user settings for Skirmish maps:

  • All user chosen settings are persisted when changing the selected map or maptype, except where the selected map overwrites the setting value and except for Scenario maps which still use the default value where the map doesn't specify the setting value.
  • Tickets relating to that Skirmish mapchange user setting persistance:
    • Selecting a map doesn't change the selected civilizations, fixes #3120 (together with r23279 removing map specified Civs).
    • Selecting a map type doesn't reset the selected settings, fixes #5372.
    • Selecting a map doesn't change the selected victory conditions, unless the map specifies those, refs #4661, #3209. (Atlas still writes VictoryConditions? to every map.)
    • Consume the player color palette from Skirmish maps, refs rP17040 / #1580. Preserve the selected playercolors when switching the Skirmish/Random? map by chosing the most similar colors if the map comes with a different palette.

Rated games:

  • Hide and disable Rated game setting unless there are exactly two players, fixes #3950, supersedes D2117.
  • Display conspicuous warning if the game is rated, so players are perfectly aware.

Autostarted games:

  • Allow using the gamesetup page to autostart matches with arbitrary maps, not only this one tutorial, as reported in D194 and rP19599, refs D11.

Networking:

  • Keep gamesetup page open after disconnect, allowing players to read chat messages indicating why the host stopped the server, fixes #4114.
  • The message subscription system allows new and mod settings to run custom logic on arbitrary setting changes (most importantly on map change). This removes hardcoded logic restrictions from the gamesetup option unification rewrite in rP19504/D322, refs #3994, such as the hardcoding of setting references in selectMap to biomes from rP20115/D852 and the difficulty from rP20760/D1189, RelicDuration?, WonderDuration?, LastManStanding?, RegicideGarrison?, TriggerScripts?, CircularMap?, Garrison, DisabledTemplates?.

Checkboxes:

  • Display values of disabled checkboxes with Yes/No? labels, fixes D2349, reviewed by nani.

Clean g_GameAttributes of invalid values and gamesetup GUI temporaries, refs #3049, #3883:

MapCache?:

  • Refactor to MapCache? class, store maps of all types and use it in the replaymenu, lobby and session as well.

SettingTabsPanel?:

  • Remove hardcodings and coupling of the SettingTabsPanel? with biomes/difficulties/chat UI from D1027/rP20945.

GamesetupPage?.xml:

  • Restructure the page to use hierarchical object organization (topPanel, centerPanel, centerLeftPanel, bottomPanel, centerCenterPanel, centerRightPanel, bottomLeftPanel, bottomRightPanel), allowing to deduplicate object position margins and size math and ease navigation.

New defaults:

  • Check LockedTeams? default in multiplayer (not only rated games).
  • Persist the rated game setting instead of defaulting to true when restarting a match, which often lead to unintentional rated games when rehosting.
  • 60 FPS in menus since they are animated

Autocomplete sorting fixed (playernames should be completed first).
Refactoring encompasses the one proposed in Polakrity and bb D1651.

Differential Revision: https://code.wildfiregames.com/D2483
Tested by: nani
Discussed with:

Emojis by: asterix, Imarok, fpre, nani, Krinkle, Stan, Angen, Freagarach

Note: See TracTickets for help on using tickets.