pond3r / ggpo Goto Github PK
View Code? Open in Web Editor NEWGood Game, Peace Out Rollback Network SDK
License: MIT License
Good Game, Peace Out Rollback Network SDK
License: MIT License
This happens 100% of the time for me in both the latest version (commit 7ddadef) and the initial GitHub commit (commit 02b9eff), both in my own game and in the VectorWar sample app.
Repro steps
GGPO Assertion Failed
Assertion: _size != (N-1) @ C:\Dev\ggpobugtest\ggpo-master\src\lib\ggpo\ring_buffer.h:39 (pid:16416)
Here's the call stack I get when running player one in a Debug build:
VectorWar.exe!Platform::AssertFailed(char * msg) Line 23 C++
> VectorWar.exe!RingBuffer<GameInput,64>::push(const GameInput & t) Line 39 C++
VectorWar.exe!UdpProtocol::SendInput(GameInput & input) Line 106 C++
VectorWar.exe!Peer2PeerBackend::DoPoll(int timeout) Line 139 C++
VectorWar.exe!Peer2PeerBackend::IncrementFrame() Line 335 C++
VectorWar.exe!ggpo_advance_frame(GGPOSession * ggpo) Line 139 C++
VectorWar.exe!VectorWar_AdvanceFrame(int * inputs, int disconnect_flags) Line 351 C++
VectorWar.exe!VectorWar_RunFrame(HWND__ * hwnd) Line 426 C++
VectorWar.exe!RunMainLoop(HWND__ * hwnd) Line 84 C++
VectorWar.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * __formal, wchar_t * __formal, int __formal) Line 181 C++
And here's a video of it:
So I've been testing GGPO on Linux, which I know isn't a supported plaform yet, and I've run into a small problem. I've noticed that GGPO crashes when the input size is anything larger than 18 bytes. Is 18 bytes the maximum input size that GGPO supports? Or is this simply a bug? I'm using a branch based on PR #52 .
This is something I'm interested in working on but I figured I'd create an issue to track the work in case anyone else wants to jump in.
Currently building fails on Linux with this totally unsurprising error about a missing winsock2.h
:
[ 7%] Building CXX object CMakeFiles/ggpo.dir/src/lib/ggpo/main.cpp.o
In file included from /home/kkremitzki/Desktop/Source/ggpo/git/src/lib/ggpo/main.cpp:8:0:
/home/kkremitzki/Desktop/Source/ggpo/git/src/lib/ggpo/types.h:12:10: fatal error: winsock2.h: No such file or directory
#include <winsock2.h>
^~~~~~~~~~~~
compilation terminated.
CMakeFiles/ggpo.dir/build.make:62: recipe for target 'CMakeFiles/ggpo.dir/src/lib/ggpo/main.cpp.o' failed
Once the build works on Linux I can proceed to getting it packaged for Debian/Ubuntu.
log:
[ 6%] Building CXX object src/CMakeFiles/GGPO.dir/lib/ggpo/bitvector.cpp.o
[ 13%] Building CXX object src/CMakeFiles/GGPO.dir/lib/ggpo/game_input.cpp.o
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp: In member function ‘void GameInput::desc(char*, size_t, bool) const’:
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp:44:20: error: ‘sprintf_s’ was not declared in this scope; did you mean ‘sprintf’?
44 | remaining -= sprintf_s(buf, buf_size, "(frame:%d size:%d ", frame, size);
| ^~~~~~~~~
| sprintf
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp:46:20: error: ‘sprintf_s’ was not declared in this scope; did you mean ‘sprintf’?
46 | remaining -= sprintf_s(buf, buf_size, "(size:%d ", size);
| ^~~~~~~~~
| sprintf
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp:52:18: error: ‘sprintf_s’ was not declared in this scope; did you mean ‘sprintf’?
52 | int c = sprintf_s(buf2, ARRAY_SIZE(buf2), "%2d ", i);
| ^~~~~~~~~
| sprintf
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp:53:10: error: ‘strncat_s’ was not declared in this scope; did you mean ‘strncat’?
53 | strncat_s(buf, remaining, buf2, ARRAY_SIZE(buf2));
| ^~~~~~~~~
| strncat
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp:57:4: error: ‘strncat_s’ was not declared in this scope; did you mean ‘strncat’?
57 | strncat_s(buf, remaining, ")", 1);
| ^~~~~~~~~
| strncat
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp: In member function ‘void GameInput::log(char*, bool) const’:
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp:65:9: error: ‘strcpy_s’ was not declared in this scope; did you mean ‘strcpy’?
65 | strcpy_s(buf, prefix);
| ^~~~~~~~
| strcpy
/home/fabx/Desktop/ggpo/src/lib/ggpo/game_input.cpp:67:4: error: ‘strncat_s’ was not declared in this scope; did you mean ‘strncat’?
67 | strncat_s(buf, ARRAY_SIZE(buf) - strlen(buf), "\n", 1);
| ^~~~~~~~~
| strncat
When I attempt to build ggpo as a .dll
and .lib
file to use as a dependency for my own project, I end up receiving the following error below:
Looking at the code snippet below (udp.cpp
):
void
Udp::SendTo(char *buffer, int len, int flags, struct sockaddr *dst, int destlen)
{
struct sockaddr_in *to = (struct sockaddr_in *)dst;
int res = sendto(_socket, buffer, len, flags, dst, destlen);
if (res == SOCKET_ERROR) {
DWORD err = WSAGetLastError();
Log("unknown error in sendto (erro: %d wsaerr: %d).\n", res, err);
ASSERT(FALSE && "Unknown error in sendto");
}
char dst_ip[1024];
Log("sent packet length %d to %s:%d (ret:%d).\n", len, inet_ntop(AF_INET, (void *)&to->sin_addr, dst_ip, ARRAY_SIZE(dst_ip)), ntohs(to->sin_port), res);
}
I end up getting a SOCKET_ERROR
when the sendto(...)
function is called. It turns out the error I get back is error code: 10093. Based on Microsoft's documentation, error code https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2, error code 10093 means that Win Sockets dependency hasn't been initialized yet.
// assume callbacks, game state, non game state, and port numbers are already defined somewhere else
const int NUM_PLAYERS = 2;
GGPOSession *ggpo = NULL;
GGPOSessionCallbacks cb = { 0 };
cb.begin_game = vw_begin_game_callback;
cb.advance_frame = vw_advance_frame_callback;
cb.load_game_state = vw_load_game_state_callback;
cb.save_game_state = vw_save_game_state_callback;
cb.free_buffer = vw_free_buffer;
cb.on_event = vw_on_event_callback;
cb.log_game_state = vw_log_game_state;
ggpo_start_session(&ggpo, &cb, "rollback_tech_demo", NUM_PLAYERS, sizeof(int), localPort);
ggpo_set_disconnect_timeout(ggpo, 3000);
ggpo_set_disconnect_notify_start(ggpo, 1000);
// Calls to ggpo_add_player() made but omitted to keep simple
int maxTimeIdleMillis = 6;
ggpo_idle(ggpo, maxTimeIdleMillis);
// sends input request over the network using UDP protocol internally
// Looks like this fails because Winsockets hasn't been initialized yet.
ggpo_add_local_input(ggpo, ngs.local_player_handle, &localInputsThisFrame, sizeof(localInputsThisFrame));
ggpo_synchronize_input(ggpo, (void *)allInputs, sizeof(int) * NUM_PLAYERS, &disconnectFlags);
ggpo_advance_frame(ggpo);
The license section of the readme states:
GGPO is available under The MIT License. This means GGPO is free for commercial and non-commercial use. Attribution is not required, but appreciated.
The MIT licence requires some degree of attribution, but this line says GGPO doesn't require attribution. Can this be clarified? Is the intent "no attribution beyond what the licence otherwise requires"?
The github readme is the first thing people will see.
its a (minor) barrier to entry if people miss the documentation as its not referenced in the main readme
Is there a plan to add tests in the future? In my opinion it is very hard to recommend ggpo in a professional setting when there are possible breaking points such as custom data structures.
Tests could make it easier to understand each working parts of the lib as well. I find that the vector war example is a bit bloated because you have to parse through rendering and game logic. I only care about what happens with the inputs and the game state.
DEBUG_BREAK
exit
in release builds (or ever, really).I've been testing GGPO on my current game project and ran into a roadblock. Specifically, in regard to a session with only local players, it seems like GGPO will always return GGPO_ERRORCODE_NOT_SYNCHRONIZED
when trying to add inputs or synchronize inputs.
After spending some time trying to find the source of my issues, I caught this code and comment:
p2p.cpp
void
Peer2PeerBackend::AddRemotePlayer(char *ip,
int port,
int queue)
{
/*
* Start the state machine (xxx: no)
*/
_synchronizing = true;
_endpoints[queue].Init(&_udp, _poll, queue, ip, port, _local_connect_status);
_endpoints[queue].SetDisconnectTimeout(_disconnect_timeout);
_endpoints[queue].SetDisconnectNotifyStart(_disconnect_notify_start);
_endpoints[queue].Synchronize();
}
So it seems to me that GGPO only enters its internal synchronization state machine when at least one remote player is added to the game session. Is this correct? So if I wanted to simulate an online game for local play (I.E. uses the GGPO synchronize_inputs
to respect frame delay settings) how would this be achieved?
Granted I have never done extensive C style programming, it might be my lack of familiarity talking.
Line 79 in e4e11d8
GGPOErrorCode
when there is only one return value possible? Maybe for async uses?Line 51 in e4e11d8
while
in a few places, and they scare me :pI apologize if this might be a stupid question, but I am having troubles in implementing this library in a sample project of mine.
While running the vectorwar demo, everything seems to work fine, without issues. I can compile and execute the game without troubles and the synchronization via GGPO works flawlessly.
However, when I try to implement GGPO in my own project, after the connection between the players has been established (GGPO_EVENTCODE_RUNNING has been issued), whenever I call a ggpo_add_local_input command, it always fails with the above return value (GGPO_ERRORCODE_PREDICTION_THRESHOLD).
Is there any step I have to perform between the first time I receive a GGPO_EVENTCODE_RUNNING and the first ggpo_add_local_input / ggpo_synchronize_input that I am missing?
If not, what could be the cause of this error?
To summarize:
The above issue happens even when running two instances of the game on the same machine, on different ports.
There is no Japanese documentation yet which would be good to have.
I would like to start the translation of the current documentation into Japanese.
Should we add a subdirectory in the doc/ folder (i. e. doc/ja/) or just add a suffix to the markdown documents (i. e. DevelopmentGuide.ja.md)?
Could ggrs set prediction to 0?
Currently it crashs with max_prediction 0 or 1.
This would be useful when it is difficult to provide savestate, ex; unofficial netbattle project.
I propose that a technical specifications document should be created for GGPO. I believe this will make it easier for people to create their own implementations vs having to parse the reference implementation.
I'm currently going through the source code and willing to volunteer to do the bulk of the work on a technical specification document as I was considering making one for myself.
Things that should be included
etc etc
When I translated it into Japanese, there was a part I didn't understand.
(By the way, I'm not good at English.)
your 2-second flash will be entirely consumed by the rollback (line 180)
Is this "2-second" a mistake of "2-frame"?
GGPO will call your advance frame callback many times during a rollback. (line 208)
Does this "advance frame" mean "ggpo_advance_frame" or user defined callback function?
I did a search on the whole project and couldn't find any usage off it.
When is this errorcode returned?
Because I do have issues with input dropping in my project when this ping is 2x higher than set delay input. (this is only an issue with hitinput, block/movement input are handled correctly
I was wondering if there was a way to securely use GGPO without dedicated servers. If I'm not mistaken, games like Brawlhalla use dedicated servers to connect via IP/port. I'm no networking expert, but using NAT traversal techniques like STUN to get an IP and plug that in isn't recommended right?
I was thinking about using Steam P2P so it's not exposing the client IPs but it seems like it'd be a lot of work. If that's been done before, there's a better method, or if I could have some pointers on the best way to implement it I'd be very grateful!
I was wondering if any of the Cross platform pull requests are being considered. Some have been submitted since the beginning of the year & I was wondering if there was a certain direction that this project is going. Is there any assistance needed? #57 looks interesting...
Just to be sure i can't understand from the doc's
Is it p2p network sdk or client server ( UDP ) game networking engine if yes , where are the server code ?
Thanks
I can look into a fix for this something to with the printf format specifiers.
I don't know how tightly coupled they are but it would be nice if they could be isolated from each other and maybe show how to combine them in an example. For example if I use an engine which has its own protocol I might want to skip ggpo's implementation and only use the rollback.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.