I have been held up multiple times, but as foreshadowed a while back a big change in the way players see the map has just occurred. The main visibility data structure remains the "canSeeTiles", but the old PlayerExploredTiles are gone (well, going).
PETs used to live in a Map<Player, PET> within Tile. This has been replaced with a Map<Player, Tile> called cachedTiles, where the Tile value is either the actual tile, or a copy made with the newfangled FreeColObject.copy() routine via Tile.getTileToCache(). cachedTiles lives solely on the server, and the tile values it contains are what are used to serialize to the client (European ATM) players. The contents of cachedTiles are set in various ways. It starts empty, but when a player explores a tile (i.e sees it for the first time) an entry will be made for that player. The entry will contain the tile itself. Indeed the rule is that if a player can see a tile, the cachedTile must be the tile itself. Therefore in the routine that constructs the canSeeTiles the cachedTile is set (with Tile.seeTile). This works for exploration as sighting the tile is implicit, and the definition of an explored tile (on the server side) is one where there is a cachedTile entry for the player. So when a player can no longer see an explored tile, what is its value? We could make a copy of the current state of the tile at the point it goes invisible, however this would require an expensive scan through all the map tiles whenever we call makeCanSeeTiles. The latest point at which it is vital to make a copy is whenever a permanent visible change is made to a tile that a player can not see (where "permanent" means any change other than units moving through). We need to capture the old state of the tile then, so that if the game is then saved, on reload the player continues to see the old view of the tile. This is what we do wrong ATM --- reloading can reveal information that players do not know (tile type changes, missionary and settlement changes, these are only partially handled). The other benefit from this lazy caching is that it avoids unnecessary FreeColObject.copy() calls when the visibility changes an arbitrary number of times without a permanent change to the tile. Therefore, prior to making tile changes, there should now be a call to Tile.cacheUnseen(). This reverses an existing pattern, where after making a tile change we called Tile.updatePlayerExploredTiles. All these calls are safely within the server, and no cases have been missed, and I have a flying pig for sale. Alternately a copy of the tile can be taken and cached later if it is unclear whether it will be needed. There are rough patches remaining. - Tile owningSettlements are a bit of a problem because the settlements may not have been seen, or no longer exist, etc. This is a really special case where we are caching a reference to something not within the tile itself. I may have to simplify these to only apply when the settlement is visible or at least still exists in which case there will be an information leak. - Stockade levels seen by clients are not handled correctly yet. The plan here is to serialize stockade-class buildings to the clients. I think this is better than the existing hack where we send a special stockade key to the clients, as this leads to confusing code where we have to work out whether the key is present and whether to use it. If we send the building, the same code works in both client and server. A patch is in testing. - Serialization of Tile is not entirely obvious, but OTOH all the PET code distributed around the other classes is now gone (hooray), so at least the hairiness is all in one place. - Except... the invisible native settlement information (wanted goods, skill) is handled independently (with another Map in Tile), as that should not be updated except when a player unit is in close contact. So there is still some special handling in IndianSettlement for this. - The PlayerExploredTile class is still around, but only used to read old saved files. When a PET is read, a deeply ugly routine therein makes an effort to set up a cached tile with the same effect, but this is somewhat fictional. Fortunately it is a one-off effect. PlayerExploredTile can be removed completely at the next save format break. - Testing is limited. My 7-AI games do not regress, but AIs cheat on map visibility so that is not much comfort. The play-one-turn,save,reload mode works so at least the serialization is getting a workout. I need to pause and play for a bit. What we got out of this: - The hairy error-prone save-reload-vulnerable code in PlayerExploredTile and elsewhere that partially hid map changes you can not see is gone. Serialization is now about as simple as I think it can be short of the DOM-removal. - We now have a general solution to the problem of keeping a player's view of the map consistent in spite of unseen changes. The view no longer changes with save-reload. Cheers, Mike Pope
signature.asc
Description: PGP signature
------------------------------------------------------------------------------ Introducing Performance Central, a new site from SourceForge and AppDynamics. Performance Central is your source for news, insights, analysis and resources for efficient Application Performance Management. Visit us today! http://pubads.g.doubleclick.net/gampad/clk?id=48897511&iu=/4140/ostg.clktrk
_______________________________________________ Freecol-developers mailing list Freecol-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/freecol-developers