neuro wrote:I think I sort of understand the difference between latest known objects (LKO) and human-player visible objects (HPVO) based on your description. The main difference is one of two properties, it seems:
1) is the list of objects about who controls them? or,
2) is the list of objects about whether or not they're visible?
It's an issue of visibility. Visible objects are the objects (Ships, planets, buildings, fleets, systems) in the game universe that a player has vision of on the current turn. Players generally (probably always?) have visibility each turn of all objects they own (which could be called "objects they control" I suppose), but players can also have visibility of objects they own, but may also have visibility of other objects depending on what the visibilitity and detection systems determines.
I'm just inferring, mind you, but objects in the latter category (HPVO) would be ships the player control (of course they'd always see those and want stats on them, fuel, speed, ships, etc.) and in the former category (LKO) may be ships controlled by the AI or another player.
If the AI controlled ship or fleet is close enough, has low enough stealth, and the player has an object with high enough detection, AI-controlled objects and objects owned by no players could also be visible objects.
In that case, would they be able to select that and see a FleetWnd on those fleets?
Currently only visible fleets are shown on the map and in the FleetWnd. Latest known fleets that aren't visible could be shown, but that would be confusing, since there would be lots of stationary fleets shown where players had previously seen them. Latest known systems are always shown, as these don't move around, so even if they're not visible, it's reasonably safe to show them to players without misleading them. Systems that are known but not visible have fog of war scanline drawn on them, however, to indicate that they're not visible.
If so, they of course we'd want it to show the right stats. But if it's case # 2, and the LKO are HPVO simply because they're visible (not necessarily controlled) because they're copies...then it should resolve itself. As in the "fleet::fuel and fleet::speed" function are setup to use the array / object container of ship objects... from the human's perspective. Basically, the HPVO.
I'm not sure what the point of that was...
But that worries me, architecturally speaking. The Fleet::Fuel (and Fleet::Speed, etc.) functions purpose is to retrieve the fuel for the entire fleet for anyone, human, AI, whatev. If, in the future, an AI were making decisions based on these values (i.e. choose the fleet with the lowest fuel to get to nearest refueling point, etc.) then is this function compromised in pulling data from only the "GetObject<Ship>(*ship_it);" and not the "GetMainObjectMap();" collection? Really, what is the difference between these collections (visibility? control? or is the local GetObject just a temporary collection that's updated with GetMainObject every turn?)
GetMainObjectMap is a utility function I added for convenience... To explain:
The universe contains several ObjectMaps...
There is Universe::m_objects. On the server, this contains all the objects in the universe in their real current state. On the clients, this contains objects that are visible on the current turn to that client's player.
There is also Universe::m_empire_latest_known_objects. On both the server and client, this is a map from empire ID to ObjectMap containing the latest known objects for each empire. On the sever, all empires' latest known objects are stored in this map, and on the clients, generally only the client's empire's latest known objects are included, since empires don't know what the latest known objects for other empires are.
The consequence of this is that on the sever, Universe::m_objects generally contains more objects than each empire's latest known objects, since some objects in the universe aren't visible to some players. However, on the clients, the client's empier's latest known objects generally contains more objects than Universe::m_objects, since some objects the player's empire had vision of on previous turns may not be visible on this turn.
Given that, what GetMainObjectMap does is, on the server, return the Universe::m_objects map of all objects in the universe, and on the client, return the client's player's empire's latest known objects map.
The point of doing that was to ensure that the larger set of objects was checked for the requested objects when calculating something about another object.
In this case, we wanted the fuel of a fleet. If this fleet happened to be not visible to a player on the current turn, it should still be possible for the player's client to estimate the fleet's fuel, but this would require looking up all the ships that were observed to be in that fleet the last time it was visible. ie. the latest known objects in the fleet. Thus, on clients, GetMainObjectMap returns the client's player's latest known objects map.
Conversely, on the server, the game should always be able to know the real true fuel available to the fleet, and doesn't need to check what various players know about the fleet. In that case, the real true gamestate objects should be checked. THus on the server, GetMainObjectMap returns the server's true gamestate set of objects.
However, as above, only the visible objects, in Universe::m_objects, are manipulated by orders on the client, between turn updates. So, if a ship object, for example, is manipulated by an order on the client, then the latest known object of that ship won't be modified, but the visible object will be.
This lead to the situation above, where the latest known version of a ship or fleet was gotten, when the visible version was desired.
Or say there were "observers" watching the game, human non-participants that could see the entire game board. Sure they might not see real-time decisions (i.e. a player scraps / unscraps / rescraps, has coffee comes back, and unscraps), but would the results still display properly?
I'm not sure wha scenario you're evisioning here, but if there were observers in a game, they'd probably be given full visibility of every objects in the game universe.
Lastly, is there documentation I could read to understand this? I've been trolling the wiki, and starting to get a grasp of the Universe. I guess I'm spending waaaaay too much time typing this out.
There's no documentation beyond comments in code and this thread about how the latest known vs. currently visible objects are handled. The basics of the visibility system (which determines what is visible and what isn't) are discussed in the v0.3 design pad.
For many purposes, including anything that's done on the server with objects, you don't need to worry about visible vs. latest known, as the server will manipulate the "real" objects in the universe when processing the gamestate. Whether there are also latest known copies of these objects for each player generally shouldn't matter. During and after turn processing, the visibility system checks which objects are visible to which players, and update each player's latest known objects accordingly. When sending turn updates, the visible objects for each player are sent, as are the player's latest known objects.
Dealing with this isn't very difficult in the UI classes, because there it is known that the code is on the client, so that there are more objects in the latest known objects for the client's player's empire than there are in the visible objects, and it's also known that orders won't modify the latest known objects, and the
However for gamestate classes, like in Fleet, things are more complicated. Within a fleet object's code, you don't know whether the fleet is the real gamestate on the server, a visible and manipulable object on a client, or a possibly-out-of-date object copy in an empire's latest known objects. So, if a fleet needs to calculate its fuel, it can't just get ship objects using GetObject, which looks up objects in Universe::m_objects, as these ships might not exist in Universe::m_objects if the fleet is a previously-visible object on a client whose ships are not visible.
Similarly, code in the Empire class generally gets objects from the "main" object map so that it doesn't need to know whether it's running on the server and accessing the true complete gamestate, or on a client and using the latest known objects. Using just the visible objects on the client wouldn't work well because stuff that empire calculates usually needs to consider previously-known but not currently visible planets and starlane connections.
GetMainObjectMap was a workaround for this issue. On the client, it returned the latest known objects map for the client's empire, and on the server it returned the full set of objects in Universe::m_objects. This was guaranteed to find some representation of an object if it existed to the best knowledge of the server or client on which the code was running. However, due to the duplication of objects, on the client this lead to the issue in this thread, with old version of objects being returned even when visible object versions of them were available.
So, as this illustrates, the system of sending two separate maps of objects to players needs to be revised.
There could be a varient of ObjectMap that just acts as filter on another ObjectMap, based on visibility. Clients could use this to set up a visible objects map that is just a filtered version of the latest known objects map. There would be only one copy of each object on clients, rather than two copies of visible objects, including one in the latest known objects and one in the visible objects. This would eliminate the duplication that lead to the issues earlier in this thread.
In this case, clients would be sent their latest known objects map (which does and would contain all the visible objects, as well as objects last seen on previous turns), and sent nothing extra for the visible objects.
When looking up an object, code that doesn't know whether it's dealing with previously-visible copies or up-to-date versions of an object would just call a single GetObject function. When looking up multiple objects, a similar GetObjectMap function would be used. The same GetObject or GetObjectMap functions would work on the sever or client, so could be used in code that doesn't know where it's running (ie. gamestate stuff like fleet or empire).
On the server, GetObject would get the object from the real gamestate map of objects (Universe::m_objects).
On the client, GetObject would get objects from the empire's latest known objects. For visible objects, this would return the same object as if the search was restricted to visible objects, so that situations such as the one that started this thread wouldn't occur; there would be only a single ship object for each ship known and/or visible to a client's empire, so there would be no issues about which version of the ship was looked up by ID and whether that was the one that was acted on by orders, for example.