Sorry this took a while getting out, it took a bit longer than expected to finish.
One of the more useful features of RakNet, particularly for games, is the ReplicaManager plugin. This piece of code handles “replication” of objects, ensuring that all clients have the same state as the server. For example, in some of my previous posts I demonstrated the feature by running a physics simulation on a server and viewing the scene on several connecting clients. Replica is very scaleable and allows for fine-grained control over what aspects of an object are transmitted over the network, how reliable the arrival order is, etc. This tutorial will only cover a basic client-side iPhone integration based on the Replica sample provided with RakNet; more details on the specifics of using the system can be found in the RakNet forums and documentation section.
I’m going to assume that you’ve looked at the previous tutorials using RakNet, and have at least compiled an iOS RakNet library. We’ll need to use that to compile the application in this tutorial.
The first step is to create a new “View-based Application” project for the iPhone. You can name it whatever you want, but I’m using RaknetReplicaSample and this name may appear in some screenshots.
The original RakNet sample was contained in a single .cpp file that would run both a client server, making things a bit confusing to work with. I’ve split the example into several files and added a logger class that will print to a UITextView, which makes things a bit easier on the iOS platform. These files, along with a compiled version of the RakNet sample for OS X, can be downloaded here.
Import these files into your newly created Xcode project and add them to the Classes folder. There are still some hooks to add to the ViewController and AppDelegate files. These are similar to the ones made for the previous tutorial on setting up a RakNet chat client on the iPhone, but there are a few key differences in the ViewController.
We’ll start off with the AppDelegate though. Like last time, we need to setup an NSTimer to run our network loop. Add a new NSTimer to the AppDelegate.h file at the end of the @interface declaration:
NSTimer * mTimer;
And a new method to actually call the network update function:
-(void) networkUpdate: (NSTimer *) pTimer;
The interface should look something like this:
In the corresponding implementation file, <ProjectName>AppDelegate.m, add the following line at the end of the application:didFinishLaunching: method:
mTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target:self selector:@selector(networkUpdate:) userInfo:nil repeats: YES];
Then, add an implementation for the networkUpdate method:
-(void) networkUpdate: (NSTimer *) pTimer
That’s all that needs to be done in AppDelegate. In theViewController.h, add the following includes to the top of the file, directly after UIKit.h. Please keep them in this order as well:
Then add the following items to the @interface declaration:
This is similar to the chat tutorial, but now we had a new “ReplicaManager” instance. This class and its super class handle much of the work behind the object replication process.
We’ll also need to add the following lines after the closing brace on the @interface declaration:
@property (nonatomic,retain) IBOutlet UITextView* mTextView;
In the implementation file for the ViewController, we first need to @synthesize the UITextView by adding the following line after the @implementation declaration:
In the viewDidLoad method, add the following block of code after the call to the super class:
rakPeer = RakNet::RakPeerInterface::GetInstance();
Just like the chat client example, the IP address can and should be changed to suit the environment you’re using. The port needs to remain as it is, since the RakNetReplicaSample server is hardcoded to use this port. The port shouldn’t be a problem for anyone.
Next, add the tickClient method. This method is called by our NSTimer once every 10th of a second and updates the network:
for (packet = rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet = rakPeer->Receive())
Logger::getLogger()->appendLine(@"Connection failed - No free incoming connections\n");
Logger::getLogger()->appendLine(@"Connection request accepeted\n");
memcpy(&msgNumber, packet->data+1, 4);
for (idx=0; idx < replicaListOut.GetSize(); idx++)
Finally, add two lines of clean-up to the viewDidUnload method to disconnect from the network:
Like last time, we also need to tell the compiler that this project will contain some C++ code. This means that all the .m files need to be renamed to .mm, or set to compile as Objective-C++ by right clicking them, going to Get Info, and changing the File Type field to Objective-C++:
That should cover all of the code changes needed. You’ll also need to add a new UITextView to the interface builder and link it to the UITextView created in the ViewController class. This will be used to display output from the server and any connect/disconnect messages.
Like last time, you’ll need to include your RakNet library and add the RakNet source directory to your header search path. At this point, everything should be ready to compile.
To test the app, first start the provided OS X Replica application. Since this application is taken straight from RakNet, it can run as a client, server or peer-to-peer instance. Start it as a server by entering ‘s’ into the console. You can create new objects by pressing ‘c’, and assign them random values with ‘r’. Delete all created objects with the ‘d’ key. All three of these actions will be replicated on the client, and can be verified by checking the output UITextView on the iPhone app.
As always, I’m happy to help sort out any issues that come up with the tutorial. Let me know in the comments if you need anything, or if there are any other specific RakNet samples that you want to see ported to the iPhone.