Drell
Member
Hello all!
UPDATE: I've decided to post here about my solution, but feel free to PM me about questions.
I've essentially mirrored the GGPO framework in my game using my own code combined with GMNet. Specifically, my game determines a users control set in real time based on the game mode and number of controllers plugged; as a result, I was able to extend the variables that control this functionality to have an additional set of commands to receive controls from the network instead. Remote players update their inputs from the network, and the game state is updated using client side prediction until there's a discrepancy in game states. Each step, the game state is saved locally into a ds_list, and then base64_encoded into a separate ds_list. The base64_encode states are compared, and when there's a mismatch, both games return to the last synchronized state and rerun the game with the correct inputs for each step.
UPDATE: I've decided to post here about my solution, but feel free to PM me about questions.
I've essentially mirrored the GGPO framework in my game using my own code combined with GMNet. Specifically, my game determines a users control set in real time based on the game mode and number of controllers plugged; as a result, I was able to extend the variables that control this functionality to have an additional set of commands to receive controls from the network instead. Remote players update their inputs from the network, and the game state is updated using client side prediction until there's a discrepancy in game states. Each step, the game state is saved locally into a ds_list, and then base64_encoded into a separate ds_list. The base64_encode states are compared, and when there's a mismatch, both games return to the last synchronized state and rerun the game with the correct inputs for each step.
I'm currently building a 2D fighter called Evolver. I completed the code for the versus mode early last month, and the engines for the metroidvania campaign and survival modes are working and tested. As a result, I'm now trying to implement the GGPO netcode (wiki) which uses a frame rollback method to manage networking. Rather than setup a mutual server, GGPO sets up individual sessions on all hosts and simply sends each players inputs to all other players connected to the session. So, all players are essentially running a local game where only the opponents' inputs are networked.
As you may have deduced, this could and would lead to issues with synchronization, thus the rollbacks. GGPO manages desyncs through input prediction and rollback frames. This is dependent on the "gamestate" being "purely functional" meaning the game most move forward at a fixed rate, and for any give game state and inputs, advancing the game by exactly 1 frame must have identical results for each client which is simple enough given GM:S's use of steps.
GGPO runs the session through a C++ object of the class GGPOSession, and that's where my trouble begins. I don't imagine there's any way to use a C++ object in GM:S, so my thinking is to have GM:S start C++ program (which I’ll call BackNet) that initializes the GGPOSession in the background, and then have BackNet pass information to GM:S via buffers. That said, I'm not sure if this is possible or the best method of implementing the GGPO framework.
The download link to the SDK is dead on http://ggpo.org/download, but I got a copy from Tony Cannon (free, non profit license. For profit license is $1,000 I believe, and Tony's email is in docs) which includes a guide and example for a very simple C program he included called Vector War. You can download it from my onedrive, here.
As you may have deduced, this could and would lead to issues with synchronization, thus the rollbacks. GGPO manages desyncs through input prediction and rollback frames. This is dependent on the "gamestate" being "purely functional" meaning the game most move forward at a fixed rate, and for any give game state and inputs, advancing the game by exactly 1 frame must have identical results for each client which is simple enough given GM:S's use of steps.
GGPO runs the session through a C++ object of the class GGPOSession, and that's where my trouble begins. I don't imagine there's any way to use a C++ object in GM:S, so my thinking is to have GM:S start C++ program (which I’ll call BackNet) that initializes the GGPOSession in the background, and then have BackNet pass information to GM:S via buffers. That said, I'm not sure if this is possible or the best method of implementing the GGPO framework.
The download link to the SDK is dead on http://ggpo.org/download, but I got a copy from Tony Cannon (free, non profit license. For profit license is $1,000 I believe, and Tony's email is in docs) which includes a guide and example for a very simple C program he included called Vector War. You can download it from my onedrive, here.
Last edited: