Jump to content
Jazz

Networking in LUA

Recommended Posts

Josh since enet is already built-in can't you just expose it to LUA or am I missing something?

Share this post


Link to post

Just in case you feel it's to hard of a task to do yourself here is exactly how you do it. I actually just did this so thought I'd share.

 

 

1) Go http://leafo.net/lua-enet

2) Look for the Windows section and click the link to download the file

3) Place the DLL in your game's directory that has your game's exe file

4) Here's is the odd part. This requires lua dll but Leadwerks has it named lua51.dll but this enet dll needs it to be called lua5.1.dll so just make a copy of the existing dll and rename it which is in the same folder as your games exe.

5) In your project this is how you load the package and then everything else works the same as the link above in terms of usage:


-- load the networking library
assert(package.loadlib("enet.dll", "luaopen_enet"))()

Share this post


Link to post

Thank you so much Rick! I've been using luajit for enet with my own compiled dll and it is not fun.

Share this post


Link to post

I haven't gotten into enet that much but the thing I'm not liking so far is that it seems you just send string data. I'm more used to RakNet where I can send different types. I guess I would use a json string to send but that's probably bloating and wasting bytes over the wire. Not sure.

Share this post


Link to post

Steam's Spacewar example does it the same way last I checked so yeah, I miss packing various variables into a packet with RakNet too.

Share this post


Link to post

I haven't gotten into enet that much but the thing I'm not liking so far is that it seems you just send string data.

 

It's pretty easy to make a few C++ classes over ENet that allow you to write data , then expose them with the LuaJit FFI api, or even toLua++ if you wanted. I did this with ENet and used FFI to allow for creation of these classes in Lua without the additional overhead, I don't really want to give my code otu til I get it a little further a long at least, but if anyone wants I could give a quick tutorial or description of how I made my system.

 

Minus all the back end systems, to use my Message/Reader system it writes like this:

Lua:

--Server
netmsg.Register("MsgOne") --If you forgot this part it would still work, but it'd give you a warning telling you it's faster to register this, because then the client downloads it on initial connection instead of while he's playing. (Except when sending messages from the client to the server 'message name' MUST be registered by the server.)
concommand.Register("testmsg", function() --concommand system unrelated to example.
netmsg.Start("MsgOne")
 netmsg.WriteInt16(12345)
 netmsg.WriteFloat(34.4536)
 netmsg.WriteString("Whatever")
 netmsg.WriteVec3(Vec3(12.3, 45.6, 78.9))
netmsg.Broadcast()
end)
--Client
netmsg.Listen("MsgOne", function()
 local int16 = netmsg.Readint16()
 local fl = netmsg.ReadFloat()
 local str = netmsg.ReadString()
 local vec = netmsg.ReadVec3()
System:Print("Message received!")
end)

 

C++:

//Server
Netwerks::Message::Register("MsgOne"); //Inside some sort of initialization function.

static void TestMsgCMD(int argc, char* args[]) { //Unrelated, part of con command system.
Netwerks::Message message("MsgOne");
message.WriteInt16(12345);
message.WriteFloat(34.4536);
message.WriteString("Whatever");
message.WriteVec3(new Vec3(12.3, 45.6, 78.9));
}

//Client
static void RecvTestMsg(Netwerks::Reader* reader) {
int16_t int16 = reader->ReadInt16();
float fl = reader->ReadFloat();
char str[MAX_MSG_STRING_LENGTH];
reader->ReadString(str, sizeof(str));
Leadwerks::Vec3* vec3 = reader->ReadVec3();
Leadwerks::System::Print("Message received!");
}

Netwerks::Handler::Register("MsgOne", &RecvTestMsg); //Also in some sort of initialization method.

 

But for entity variables I made a separate system (that uses this one) to keep certain variables synced.

When I get a little further into my project I'll most likely release a template or something, but for now best I can offer is helping anyone make a similar system.

 

But yeah if you don't want to do this extra work I'd use RakNet, like Rick said you can only send strings through ENet with Lua unless you do something like this.

Share this post


Link to post

You don't want to use JSON in your network code. Idealy people should use something like c structs and write the data out to the network stream as you have zero serialization costs.

Share this post


Link to post

Which given the lua enet pre-built dll doesn't seem to be an option.

Share this post


Link to post

I haven't tried it with lua-enet but you can use lua-MessagePack to encode arbitrary data into a string. It isn't too space efficient but it should work if you don't have a large amount of things to synchronize.

 

http://fperrad.github.io/lua-MessagePack

 

Here is an example of how I encoded a couple Vec3s into a string to be sent via lua-enet (or whateva)

 

mp = require 'Scripts/Functions/MessagePack'

thing1 = Vec3()
thing1.x = 1.123
thing1.y = 2.234
thing1.z = 3.345

thing2 = Vec3()
thing2.x = 4.123
thing2.y = 5.234
thing2.z = 6.345

data = {{x=thing1.x, y=thing1.y, z=thing1.z}, {x=thing2.x, y=thing2.y, z=thing2.z}}

mp.set_number'float'
mp.set_array'with_hole'
mp.set_string'string'

mpac = mp.pack(data)

System:Print("Len="..string.len(mpac))

unpacked_data = mp.unpack(mpac)

System:Print("pos.x="..unpacked_data[1].x.."pos.y="..unpacked_data[1].y.."pos.z="..unpacked_data[1].z)
System:Print("pos.x="..unpacked_data[2].x.."pos.y="..unpacked_data[2].y.."pos.z="..unpacked_data[2].z)

 

Result

Len=45
pos.x=1.1230000257492pos.y=2.2339999675751pos.z=3.3450000286102
pos.x=4.1230001449585pos.y=5.2340002059937pos.z=6.3449997901917

45 bytes compared to 24 if it was raw c++. Not ideal but it'd work.

 

EDIT: I'm dumb, require works fine, no change required to MessagePack.lua

Edited by thehankinator

Share this post


Link to post

I rebuilt lua-enet and linked it to LuaJIT 2.0.2 and enet 1.3.13. The significant result with this build is you don't need to duplicate lua51.dll (Step 4 of Rick's post). I've not thoroughly tested it but if anyone wants it I'll upload it.

Share this post


Link to post

Is this packing library available in C++ as well? I wouldn't recommend anyone really having a Lua server but instead a C++ server app if possible.

Share this post


Link to post

Is this packing library available in C++ as well? I wouldn't recommend anyone really having a Lua server but instead a C++ server app if possible.

I agree, I wouldn't do any heavy lifting in Lua. They have libraries for like every language, for C/C++ there are multiple implementations to choose from.

 

http://msgpack.org

Share this post


Link to post

In your example if you print out mpac what does it show?

Share this post


Link to post

In your example if you print out mpac what does it show?

Prints out garbage because the format bytes are not always alpha numeric when printed as a character plus I don't think the floats are encoded in a way that is human readable when packed. Gotta print each character as a byte. To inspect the packed data I did:

str_mpac = ""
for i=1, string.len(mpac) do
  str_mpac = str_mpac..string.format('%02X', string.byte(string.sub(mpac,i,i)))
end
System:Print(str_mpac)

Which printed

9283A179CA400EF9DBA178CA3F8FBE77A17ACA4056147B83A179CA40A77CEEA178CA4083EF9EA17ACA40CB0A3D

Edited by thehankinator

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...