Samien d4414eeec5 https://github.com/facebookarchive/RakNet.git 1 год назад
..
CMakeLists.txt d4414eeec5 https://github.com/facebookarchive/RakNet.git 1 год назад
ComprehensivePCGame.cpp d4414eeec5 https://github.com/facebookarchive/RakNet.git 1 год назад
ComprehensivePCGame_vc9.vcproj d4414eeec5 https://github.com/facebookarchive/RakNet.git 1 год назад
readme.txt d4414eeec5 https://github.com/facebookarchive/RakNet.git 1 год назад

readme.txt

------------------ TECHNICAL OVERVIEW ------------------

Project: ComprehensivePCGame

Description: Project demonstrating integration of UPNP, HTTPConnection2, NATPunchthrough, TeamManager, ReplicaManager3, FullyConnectedMesh2, RPC4, and ReadyEvent plugins combined to provide complete network functionality found in typical PC peer to peer games.

Dependencies: Listed plugins, MiniUPnP Project. NATCompleteServer can be used as-is for the server

To build MiniUPNP
1. Include DependentExtensions\miniupnpc-1.6.20120410 in the include paths
2. Define STATICLIB in the preprocessor if necessary (See DependentExtensions\miniupnpc-1.5\declspec.h)
3. Link ws2_32.lib IPHlpApi.Lib

Related projects: Each of the plugins has its own sample project.

For help and support, please visit http://vwww.jenkinssoftware.com

------------------ NETWORKING FLOW ------------------

1. The game phase CONNECTING_TO_SERVER is entered in order to connect to a nat punchthrough server running the project NATCompleteServer found at Samples / NAT Punchthrough. It also connects to the master server at http://masterserver2.raknet.com/ . The NAT punchthrough server must be running at a minimum FeatureList::NAT_PUNCHTHROUGH_SERVER. If the define NAT_TYPE_DETECTION_SERVER is set to 1, the server must be running FeatureList::NAT_TYPE_DETECTION_SERVER.
2. If NAT_TYPE_DETECTION_SERVER is set to 1, then the phase Game::DETERMINE_NAT_TYPE is entered. The result of this is stored in myNatType. Otherwise, the phase Game::SEARCH_FOR_GAMES is entered.
3. SearchForGames() sends a GET request to the master server. In the background, HTTPConnection2 will use TCPInterface to connect to the server and send the command. If it succeeds, TCPInterface will return a valid SystemAddress structure from HasCompletedConnectionAttempt, and later HTTPConnection2::GetResponse() will return true.
4. Upon HTTPConnection2::GetResponse() returning true, if the parsed JSON body for a GET operation has a body, then other systems have uploaded rooms. The variable cloudQueryResult is global. The user is presented the options to join, create, or search for rooms.
5. In CreateRoom(), PostRoomToMaster() is called. PostRoomToMaster() will iterate through the list of users (from the Context of CreateRoom(), just ourself) and serialize the natType of each of those others. It will also serialize the game->gameName variable. Other data such as the names of users, score, locked value, etc. could be serialized too. Two Team classes are also instantiated as the game supports two teams. TM_World::ReferenceTeam() is called right away because you can join teams at any time. However, ReplicaManager3::Reference() is not called yet because we do not want to replicate game objects (including teams) until the host is known from ID_FCM2_NEW_HOST. Lastly, FullyConnectedMesh2::ResetHostCalculation() is called. This resets the internal timer that tracks basically how long the multiplayer game has been playing. This is necessary because the order of how the host migrates follows how long each session has been running.
6. If the user presses 'j' to join a room, NatPunchthroughClient::OpenNAT() is called. Upon ID_NAT_PUNCHTHROUGH_SUCCEEDED, RakPeerInterface::Connect() is called to connect to that system. This system is whichever system last uploaded the session, which is the responsibility of the session host. Note that even if it wasn't the session host, the program would still operate correctly provided that the system connected to has the correct list of participants in the FullyConnectedMesh2 plugin. Also note that the process of joining a session is asynchronous and does not modify data on the server or affect the game in operation. The game phase is updated to NAT_PUNCH_TO_GAME_HOST.
7. If the connection attempt in step 6 fails, or connects and is lost while in phase NAT_PUNCH_TO_GAME_HOST, the rooms are searched again.
8. If the connection attempt in step 6 succeeds, FullyConnectedMesh2::ResetHostCalculation() is called. ID_USER_PACKET_ENUM is then transmitted without data, with the intent that this is a join game request message.
9. Upon ID_USER_PACKET_ENUM, either FullyConnectedMesh2::StartVerifiedJoin() is called or ID_USER_PACKET_ENUM+1 is returned if the session is not joinable. StartVerifiedJoin() will ultimately return ID_FCM2_VERIFIED_JOIN_START, ID_FCM2_VERIFIED_JOIN_ACCEPTED, or ID_FCM2_VERIFIED_JOIN_REJECTED to the requester.
10. ID_FCM2_VERIFIED_JOIN_START means the requester has to perform additional connect steps before the game session can be joined. NatPunchthroughClient::OpenNAT() is performed on each system returned from FullyConnectedMesh2::GetVerifiedJoinRequiredProcessingList(). It may not be necessary to call OpenNAT() on each of these systems, for example if UPNP succeeded, but there is no harm in doing so and it simplifies the code flow. If ID_NAT_PUNCHTHROUGH_SUCCEEDED is returned, the system is connected to. FullyConnectedMesh2 will read connection attempt successes, failures, and NAT punchthrough failures automatically. When all systems in the GetVerifiedJoinRequiredProcessingList() have been processed, the system that sent StartVerifiedJoin() is notified automatically. The process will continue with ID_FCM2_VERIFIED_JOIN_START, or stop with ID_FCM2_VERIFIED_JOIN_ACCEPTED or ID_FCM2_VERIFIED_JOIN_REJECTED.
11. Assuming ID_FCM2_VERIFIED_JOIN_ACCEPTED completed, FullyConnectedMesh2::AddParticipant() is called internally, on all systems automatically. This leads to ID_FCM2_NEW_HOST being returned to the programmer. If this is the first time ID_FCM2_NEW_HOST has been calculated (which is when two systems first connect), then all FullyConnectedMesh2 participants added in stage 10 are registered with ReplicaManager3, TeamManager, and ReadyEvent in RegisterGameParticipant(). If the host is already known, then in the ID_FCM2_VERIFIED_JOIN_ACCEPTED block the new participant(s) are read using GetVerifiedJoinAcceptedAdditionalData(), and added with RegisterGameParticipant().
12. Registering remote systems and game objects with ReplicaManager3 will lead to ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE on each system. Each system creates its own user, so ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE will arrive once from each remote system for that user. Additionally, the host will send the two Team objects. When all downloads are complete from all systems ReplicaManager3::GetAllConnectionDownloadsCompleted() returns true, and the game can proceed.
13. The class Game is implemented as a static object. This means it is created locally on each system, rather than by a network command. It is also not destroyed when a remote system disconnects. See the return calls from QueryConstruction(), QueryActionOnPopConnection() and other operations (see the manual on static objects, under the topic ReplicaManager3). Note that in SampleConnectionRM3::AllocReplica() no statement exists to create a Game instance, as it is not necessary.
14. The class Team is created remotely by the host via QueryConstruction(). The host also serializes the object. Team is not destroyed when the original system that created it disconnects. The host can change - therefore, whoever is currently the host according to FullyConnectedMesh2 automatically takes over replication duties.
15. The class User is is created and serialized by whichever system created it. When that system disconnects, User is deleted automatically due to the return value from QueryActionOnPopConnection().
16. Teams and team members are managed by the TeamManager plugin. The data used by TeamManager is TM_Team in the Team class, and TM_TeamMember in the User class. The only thing of note is that TM_Team and TM_TeamMember is referenced when created by the network in DeserializeConstruction(), but deserialized in PostDeserializeConstruction(). This is because deserialization of the TM_TeamMember requires that any TM_Team objects that team reference has already been created.
17. PostRoomToMaster() is called by the host whenever users leave (in ~User()) or are created (in User::PostDeserializeConstruction()). This is to update the current user count returned from the master server. PostRoomToMaster() is also called by the new host whenever a new system becomes host, so connecting systems know which system to connect to.
18. When a system exists a room by pressing 'e', all connections are closed except the connection to the NAT punchthrough server. The state data maintained by each plugin is cleared. The room entry on the cloud is deleted (only does anything if we are host).
粤ICP备19079148号