Short GNet tutorial
BlitzMax Forums/BlitzMax Tutorials/Short GNet tutorial
| ||
Quick tutorial about GNet. Foreword This is a short tutorial. It doesn't contain much but I hope it helps you if you don't know anything about GNet. And I'm not an expert on GNet or networking so don't ask too difficult questions to me. ;) But this tutorial shows how to create a really simple server and a really simple client and how to move objects around. If you need more information after reading this I suggest you read the manual. If you have any questions you should post them on the forum. Ok, lets begin. Behind the scenes Everything in GNet is an object. You don't send updates or anything because it's taken care of. When you create an object on one of the clients, a copy of this object is created on all other clients. And when you change the values in a local object, it's synced with all other copies. Isn't it neat? :) Writing a simple server Strict ' GNET simple dedicated server ' Create a new host. We call it listen because that's what it does Local listen:TGNetHost = CreateGNetHost() ' Make it listen to the connection. 8086 is the port we want to use but you can change this to whatever ' you want between 1024 and 65535 (if i remember correctly.) If Not GNetListen( listen, 8086 ) Then Print "Unable to listen on port." End EndIf Print "Server started." Local quit_server = False While Not quit_server GNetSync(listen) ' Sync all created objects Local newpeer:TGNetPeer = GNetAccept( listen ) ' Is someone knocking on our port? If newpeer Then ' A new player wants to join us. Print "New player" Print "Players onnected at the moment:" Local peerlist:TList = GNetPeers( listen ) For Local p:TGNetPeer = EachIn peerlist Print " - "+DottedIP( SocketRemoteIP(GNetPeerTCPSocket( p )) ) Next EndIf ' The stuff below isn't needed in this short tutorial. It just prints some debug information so we can see ' that the server is actually working. :) Local olist:TList = GNetObjects( listen ) ' Get all created objects in the game For Local o:TGnetObject = EachIn olist Local state = GNetObjectState( o ) ' Get the state of the object Select state Case GNET_CREATED 'Object has been created print "New object created" Case GNET_SYNCED 'Object is in sync ' do something here if it is needed ' But the object is in sync and everything is just fine. Case GNET_MODIFIED 'Object has been modified ' The object is modified! But no worries. It will be synced automagically. Case GNET_CLOSED 'Object has been closed Print "Connection closed to a peer" ' The object is no longer valid. The player left the game Case GNET_MESSAGE 'Object is a message Object ' I haven't played around with this yet. So you need to read the manual ' yourself about this. ;) EndSelect Next Wend That's basically it. Objects are synced just fine and some debug messages are printed when something interesting is happening. But we need a client too, so we can test this out... Writing a simple client strict ' Simple GNet client Local server:TGNetHost = CreateGNetHost() ' Create a "host" Local serverpeer:TGNetPeer = GNetConnect( server,"127.0.0.1",8086 ) ' Connect to the server If Not serverpeer Then ' Aaaw crap! Start the server first! And check the ip and port! Print "Unable to connect to server." End EndIf Print "Sever contacted!" ' Yaaaay ' Now, create our player. Only needs to create a local one... ' NetObject is our own type. You can find it after the main loop. Local localplayer:NetObject = NetObject.create(server,"DaBomb!",320,240) ' Some graphics... Graphics 640,480,0 ' The main loop While Not KeyDown( KEY_ESCAPE ) ' --------- Logic GNetSync(server) ' Sync objects ' Get objects Local olist:TList = GNetObjects( server ) ' We use this later when we draw players Local plist:TList = CreateList() ' Active players For Local o:TGnetObject = EachIn olist ' The state the object is in Local state = GNetObjectState( o ) Select state Case GNET_CREATED 'Object has been created If GetGNetInt( o, 0 ) = O_AVATAR Then plist.addlast( o ) ' we want to draw this later Print "Joined: "+GetGNetString(o,1) ' Spawn some particles or something to show that ' The player has arrived... EndIf Case GNET_SYNCED 'Object is in sync If GetGNetInt( o, 0 ) = O_AVATAR Then plist.addlast( o ) ' Draw it. endif Case GNET_MODIFIED 'Object has been modified If GetGNetInt( o, 0 ) = O_AVATAR Then plist.addlast( o ) ' Draw it anyway endif Case GNET_CLOSED 'Object has been closed ' Spawn some particles or a sound effect or something. ' This player is no more... EndSelect Next ' We want to controll our local player If KeyDown( KEY_LEFT ) Then LocalPlayer.move(-1,0) If KeyDown( KEY_RIGHT ) Then LocalPlayer.move(1,0) If KeyDown( KEY_UP ) Then LocalPlayer.move(0,-1) If KeyDown( KEY_DOWN ) Then LocalPlayer.move(0,1) ' --------- GFX Cls ' nice and clean ' Draw connected players Local y = 10 For Local dp:TGnetObject = EachIn plist ' Player list at top left Local tmp:String = GetGNetString( dp,1 ) ' Nickname DrawText tmp, 10,y y:+17 ' Draw a rectangle to show where the player is Local xpos = GetGNetInt(dp,2) ' get position Local ypos = GetGNetInt(dp,3) DrawRect xpos-3,ypos-12,7,12 drawtext tmp, xpos,ypos-30 Next ' How many players are there? DrawText "Players: "+plist.count(), 5,y ' Some GNet statistics DrawText "In/out: "+GNetTotalBytesIn()+"/"+GNetTotalBytesOut(), 0,465 Flip ; FlushMem Wend End ' bye bye ' ----- our player TYPE ' So we know what type an object is... Const O_AVATAR = 0 ' Our type Type NetObject Field nobj:TGNetObject ' The actual GNet object Field xpos:Int ' Position on the screen Field ypos:Int Function create:NetObject( connection:TGNetHost, name:String, x:Int, y:Int ) Local no:NetObject = New NetObject no.nobj = CreateGNetObject( connection ) ' Create the GNet object SetGNetInt( no.nobj, 0, O_AVATAR ) ' We use slot 0 as an object type ID no.place(x,y) ' Place the object no.rename(name) ' rename it Return no ' Return it EndFunction Method place( x:Int, y:Int ) xpos = x ' Save the position internally ypos = y SetGNetInt( nobj,2,x ) ' slot 2 and 3 are used for x and y position. SetGNetInt( nobj,3,y ) EndMethod Method Move( xoff:Int, yoff:Int ) xpos:+xoff ypos:+yoff SetGNetInt( nobj,2,xpos ) SetGNetInt( nobj,3,ypos ) EndMethod Method rename( name:String ) SetGNetString( nobj,1,name ) ' slot 1 is used for the nickname EndMethod EndType Tadaaa. That wasn't so hard, was it? We only update our local player, the new x,y values are synced across the network to the other connected players. And we don't have to do anything at all to update the copies the local player got. It's done by GNet. Hope this tutorial was useful. |
| ||
Very useful. Thanks. |
| ||
I just found this: http://www.blitzbasic.com/Community/posts.php?topic=50966#568079 Contains a link to a more advanced example. |
| ||
Any working version of this for the current versions? |
| ||
There is one in the code archives that works (Needs Maxgui to run): Click here! It's hard to find this example (made by WendellM) using the search so that's why I'm posting the link in the Tutorial section as well. |
| ||
although along time passed! thanks! 4 years in a forum is like 4 mintues. besides, all this time betwin messages is a bit sad to me. it just shows you how much priceless time really is. remark: GNet now uses ENet for low level comms. GNetAccept and all peer functions have gone. GNetAccept now built into GNetSync, and GNetConnect now just returns True/False. |