Road Kill Kenny Posted October 13, 2011 Share Posted October 13, 2011 File Name: RakNet in Leadwerks Tutorial Files File Submitter: Engineer Ken File Submitted: 13 Oct 2011 File Category: C++ In this tutorial series you will learn how to use RakNet in Leadwerks to network your games. The attached .h and .cpp files will be needed for the tutorial and can be altered for your personal use for your own games. The video tutorials can be found as follows: - Part 0 Setup - - Part 1A Server - - Part 1B Server -http://www.youtube.com/watch?v=QDweY9fbflM Click here to download this file Quote STS - Scarlet Thread Studios AKA: Engineer Ken Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now! Link to comment Share on other sites More sharing options...
Rick Posted October 13, 2011 Share Posted October 13, 2011 Nice tutorial. Noticed you are using a switch statement (not sure if it's just because of the tutorial to keep it simple) but a long time ago someone showed me how to get some easy C++ "events" working. When I use RakNet I always use this because messing around with a giant switch statement is a pain after it gets huge (which in networking and dealing with messages it generally does). Usage: class Server { private: // the message id is the key, and the event which I make take a packet and a bitstream is the data stored map<RakNet::MessageID, Event2<RakNet::Packet*, RakNet::BitStream*>> _networkEvents; // network event handlers. this becomes where you handle the network messages void OnNewIncomingConnection(RakNet::Packet* p, RakNet::BitStream* reader){} void OnRequestLogin(RakNet::Packet* p, RakNet::BitStream* reader) {} public: // assign the function "event" to the raknet message id. for each new message you just define the function like above and then add this 1 liner to link the function to the message // note that you can link multiple functions to the same message and when you raise the event each function will be called automatically for you, which can come in handy sometimes Server::Server(void) { _networkEvents[iD_NEW_INCOMING_CONNECTION].Bind(this, &Server::OnNewIncomingConnection); } // your main loop becomes nice and small and never changes now void Server::Run() { while(1) { for (_packet = _peer->Receive(); _packet; _peer->DeallocatePacket(_packet), _packet = _peer->Receive()) { // if we registered this event then call the method it's bound to if(_networkEvents.find((RakNet::MessageID)_packet->data[0]) != _networkEvents.end()) { RakNet::BitStream reader(_packet->data, _packet->length, false); // this calls the function(s) for the message _networkEvents[_packet->data[0]].Raise(_packet, &reader); } } } } }; Your head will probably explode if you try to understand this code below (it took me some time to really fully understand what's happening and feel comfortable making changes) but if you can understand it you can add different event function signatures (return a value and/or take a different amount of parameters). I've found this code so useful in C++ in many different ways. From networking events to gui events to game events. If you can't understand it know that you can just copy and paste it in a header and use it as: Event2<type1, type2> myEvent; The file below is only setup to take 2 parameters of any type and return void. The code below doesn't have this but at some point I set it up to also take non class method points so you were able to mix and match class methods and non class functions to be fired which can be nice too. EventHandler.h #pragma once #include <list> using namespace std; template<class P, class Q> class TFunctor2 { public: virtual void Call(P var1, Q var2)=0; }; template <class TClass, class param1, class param2> class TSpecificFunctor2 : public TFunctor2<param1, param2> { private: void (TClass::*fpt)(param1, param2); TClass* pt2Object; public: TSpecificFunctor2(TClass* _pt2Object, void(TClass::*_fpt)(param1, param2)) { pt2Object = _pt2Object; fpt=_fpt; } virtual void Call(param1 var1, param2 var2) { (*pt2Object.*fpt)(var1, var2); } }; template<class T1, class T2> class Event2 { public: list<TFunctor2<T1, T2>* > mCaller; template<class Target> Event2(Target* t, void (Target::*fnPtr)(T1, T2)) { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); } Event2(){} template<class Target> void Bind(Target* t, void (Target::*fnPtr)(T1, T2)) { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); } void Raise(T1 V1, T2 V2) { list<TFunctor2<T1, T2>*>::reverse_iterator iter; for (iter = mCaller.rbegin(); iter!= mCaller.rend(); iter++) { (*iter)->Call(V1, V2); } } void Clear() { mCaller.clear(); } }; ////////////////////////////////////////////////// class TFunctor { public: virtual void Call()=0; }; template <class TClass> class TSpecificFunctor : public TFunctor { private: void (TClass::*fpt)(); TClass* pt2Object; public: TSpecificFunctor(TClass* _pt2Object, void(TClass::*_fpt)()) { pt2Object = _pt2Object; fpt=_fpt; } virtual void Call() { (*pt2Object.*fpt)(); } }; class Event0 { public: list<TFunctor* > mCaller; template<class Target> Event0(Target* t, void (Target::*fnPtr)()) { mCaller.push_back(new TSpecificFunctor<Target>(t,fnPtr)); } Event0(){} template<class Target> void Bind(Target* t, void (Target::*fnPtr)()) { mCaller.push_back(new TSpecificFunctor<Target>(t,fnPtr)); } void Raise() { list<TFunctor*>::reverse_iterator iter; for (iter = mCaller.rbegin(); iter!= mCaller.rend(); iter++) { (*iter)->Call(); } } void Clear() { mCaller.clear(); } }; Quote Link to comment Share on other sites More sharing options...
Road Kill Kenny Posted October 13, 2011 Author Share Posted October 13, 2011 cool. Thanks for posting that. The reason I use switch case is because its the only way I know how... Though it is also very simple to see and understand if you are trying to learn RakNet so for the purpose of this tutorial I'm going to stick with it. However, post away any code that may be useful because I'm sure people will explore things on their own once they have the basics down. TBH I'm not a very good programmer, I just really wanted to learn how to do networking and I'm happy to share what I learnt about RakNet, hence most of what you posted goes straight over my head XD... But I'm sure there are plenty that would get it and be able to implement it into my networking stuff for the better. (Hopefully I'll get it some day I guess the real purpose of this series of tutorials is to de-mystify networking with RakNet in Leadwerks. I think that there are a lot of really good programmers that are a lot better than me at general programming. However, it seems like a lot of people are also almost.... 'scared' (for lack of a better word) of networking or fear it is to difficult to even try. I guess what I'm saying is: Its not as bad as it looks peeps . If I can do it then so can you! In later tutorials I hope to touch on the more..... itchy topics i'll say such as: hiding/disguising lag and networking techniques other than simply the code. Edit: So what I gather from your code (after a quick look) you are using some function to determine message identifier and then calling a function depending on what the ID is... Have I got the basic jist? Quote STS - Scarlet Thread Studios AKA: Engineer Ken Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now! Link to comment Share on other sites More sharing options...
DaDonik Posted October 13, 2011 Share Posted October 13, 2011 Thanks for uploading these! Will come in very handy when i get my hands on networking Quote (Win7 64bit) && (i7 3770K @ 3,5ghz) && (16gb DDR3 @ 1600mhz) && (Geforce660TI) Link to comment Share on other sites More sharing options...
Clackdor Posted October 13, 2011 Share Posted October 13, 2011 Thanks Ken. I'll be watching these. Networking is way way down on my to-do list, but I'm somewhat excited to dig into it. I find myself thinking about step 301 despite being on step 7. Rick, Quote Link to comment Share on other sites More sharing options...
Flexman Posted October 13, 2011 Share Posted October 13, 2011 Thanks Ken for taking time out to make those and put them up for the community. I have been using quite large CASE statements myself but easier on the eye with careful grouping. I like the code Rick posted, that's quite useful and not too dissimilar from a special FX system. Never considered it for networking. Quote 6600 2.4G / GTX 460 280.26 / 4GB Windows 7 Author: GROME Terrain Modeling for Unity, UDK, Ogre3D from PackT Tricubic Studios Ltd. ~ Combat Helo Link to comment Share on other sites More sharing options...
Josh Posted October 13, 2011 Share Posted October 13, 2011 There is a section for community tutorials here, and you can upload attachments with your post: http://www.leadwerks.com/werkspace/page/Documentation/LE2/tutorials Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Road Kill Kenny Posted October 13, 2011 Author Share Posted October 13, 2011 There is a section for community tutorials here, and you can upload attachments with your post: http://www.leadwerks.com/werkspace/page/Documentation/LE2/tutorials Ah I forgot about that. I will move it this afternoon. Quote STS - Scarlet Thread Studios AKA: Engineer Ken Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now! Link to comment Share on other sites More sharing options...
Pixel Perfect Posted October 13, 2011 Share Posted October 13, 2011 I have no need for Networking atm but when I do I know where to come. Thanks for posting this Ken Quote Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++ Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.