| 05-22-2011, 07:36 AM | #1 |
I am sure this sort of thing has been thought of quite a bit, but I am not sure if there has been much serious discussion on it. For clarity, by "joining games in progress" I mean basically a scenario where you are currently playing a map and users are able to join it from the custom games list. I believe Reinventing the Craft once toted this idea with socket support, and this post is basically meant to be an alternative (in theory). Again, in theory, the stuff presented in this post would require only the host to run whatever tool would implement this (so possibly a host bot or a tool ran with hosting). It is a pretty fun idea that I was thinking about a little bit after updating some of my Warcraft 3 tools this week. In particular, after staring at my waiting room code in one of my tools the idea cropped up. If you are familiar with the orochi- host bot (which no longer seems to be up), the waiting room I coded was meant to imitate its waiting room. Which basically means that if a user attempts to join a game from the custom games list while it is full, that user will be placed into a waiting room (the user appears alone in a lobby) until such a time that a spot in the real game frees up, or the game starts. Sounds like a simple idea, but I ran into several annoying obstacles during my implementation. For one, assigning a PID to a user before they can enter the lobby, with a limitation of 12 pids. Having more than 12 players basically means you cannot avoid the possible situation that two players may share a PID. I worked around this by having the host maintain a "mapping" of PIDs (host pid to player pid and player pid to host pid conversion tables), in which basically the host only knows the "real" PIDs of players. This method also requires converting packets with PIDs in them before routing them to players. And I had to disable game state based desyncs since the game is obviously different for each player due to different PID mappings. Not sure how the orochi- guy did it, but that about sums up my implementation of the waiting room. Although I have not had much chance to test my implementation much. So I was thinking about how some of the above could be adapted for the ability to join games in progress. Well, first I will describe how I envisioned the join attempt to work. The user joining a game in progress basically will be presented with an empty lobby (where s/he appears alone), which automatically starts if the actual game has less than 12 players present (and perhaps after some other condition checks, such as a waiting queue). Rather than being alone, the player might be presented with a bunch of fake players so that players can be "injected" into slots by the host "seamlessly". So the player loads up the map and enters the game. Obviously the map is not going to match the state of the other players' maps. So this is where the map would have to do some work. The map needs to be synced with the other players'. The practicality of this depends on the map, I would think. An RPG with "instanced" dungeons could probably incorporate such syncing relatively easily. Perhaps some parts of the map do not even need to be synced. Anyway, assuming everything works out alright, it might seem like the player joined a game in progress with no incident and the players in game can continue as if they all started together. So, on to some of the requirements and obstacles I was thinking of to implement the above. Removing desyncs. That sort of thing seems to be necessary on an obvious level, so I will not discuss it. Mapping PIDs. This also is probably necessary. In this case players would be "assigned" a PID (which previously was a fake player) in real time. Most of this so far seems like it is possible given my past experience, though the next obstacle is something I have never dealt with before. The objects that are passed in packets. They will not be the same to different players. In a general sense this is a similar problem as PID differences between players, but on a larger scale. I had a few general ideas as to how it might be worked with. If the packets use something related 1:1 with object handles, then perhaps the map could force such a situation that no object handles are ever reused. Then in theory the player joining the game simply needs to recreate the objects in order to reach the same handles and such as everyone presently in the game. Another idea might be that the host would have to maintain a conversion table similar to the PID conversion tables I used in the waiting room. The table would have to be filled dynamically as the game goes, rather than the PID tables which are assigned to once. One method of filling the table might be to have an "object" count maintained by the host, in which every object created has an ID based on the object count at that time (obj.id = num++). This id should be the same for all players for the same objects (with the objects potentially having different handles and so on). Then the conversion tables would need to be filled up with the right handle-to-handle conversions on the host side for each player. And this would need to be done upon the creation of each new object as well, in all likelihood (with vanilla Wc3 this would likely need to be done with the syncing natives). It should be obvious, but even if this sort of game joining was implemented, the map(s) utilizing it would have a lot of work on their hands. In any case, the idea was fun to think about briefly. If I were to try to implement it I would probably try to add it to one of my tools rather than place it in a host bot, where it might be easier to implement. Though it is probably unlikely I will try anything regarding joining games in progress. Perhaps others would have additional information to add to this discussion though. |
| 05-25-2011, 02:12 AM | #2 |
i do know RGC or some other dota platform has been using some sort of reconnect program...so that a player can rejoin a game in progress...it sounds like what you're describing...only with the clear obvious difference that a dota game is started with full house already and you're proposing starting without full house and letting more people join as the game goes on. i think most maps would not have been designed with this feature in mind but a lot of maps it would not be bad for them or require little extra editing to make this feature work well for them. |
| 05-25-2011, 03:11 AM | #3 |
The two methods of "rejoining" a game in progress, as far as I have seen, utilize either GProxy or some method of saving and reloading the game with all players present (requires recreating the game). I might not have heard of some other methods, I would be interested in hearing about them if so. I do recall there being discussion on the GHost++ forums regarding rejoining in progress games, though I do not think anything has come out of it so far. One method I have seen over there involves a player in game saving the game then transferring it to the joining player. In any case, the method I described here relies on the map doing the "loading" instead of Wc3, which of course is potentially a great amount of work subject to stifling limitations. The method I detailed here, as I see it, probably will not work at all for AoS maps like DotA and many other types of maps. The main reason I say that is because of the complexity of "syncing" the map to the joining player - particularly with a method that involves the map doing all the work. With units constantly moving all over the place over the entire map and such, syncing to the joining player sounds quite complex (if not impossible with the editor's capabilities). A map that has a possible "idle" state lends itself to this sort of syncing though. In a rounds based death match game for example, all of the necessary data could be synced during a round after the player joins, then upon the next round the player can be notified to "render" all the data and join the game. Maps that have encapsulated areas which are normally idle (possibly a dungeon in an RPG map or some such) could probably be synced up without incident. Hero arenas might lend themselves to this type of syncing as well, depending on the design. Turn based and/or trigger heavy maps with mostly trigger based gameplay might lend themselves to this type of syncing as well. For a map like DotA to be able to be synced this way, probably there would have to be a game interrupting event to greatly simplify the syncing process ... some of the elements of such an interruption might be: - all players agree to interrupt the game - all players return to their respective base - all units on the map are paused meeting the condition that each unit is in an able-to-be-synced state (no cooldown on attack, no buffs, etc) - as a generalization of the above, no unable-to-be-synced elements on the map (no flying projectiles, buffs, cooldowns on abilities, etc) - and perhaps more There might be a better way to go about doing it, but above is a quick idea. In any case, such an interruption in gameplay, I wonder how much players would tolerate such a thing (as opposed to just remaking the game). The sort of in progress game joining I detailed in this topic is not a flexible one, in any case. |
| 05-26-2011, 02:39 PM | #4 |
It's kinda interesting to see, the way you're describing, is exactly how Reinventing the Craft did the extended multiplayer. A player would launch a singleplayer map, and the map would connect to a server, which would then sync the map with whatever other connected people did. It worked nicely, but it takes a lot of work, as most of the builtin stuff can't be used anymore, even things like normal attacks have to be controlled by the server, as you need everything to be synced. I did have a map that allowed people to chat and walk around, with support for 255 active connections. |
