Jump to content

Peer-to-peer Networking in Leadwerks Game Engine 4.6

Josh

208 views

I'm wrapping up the new multiplayer capabilities for Leadwerks 4.6, and I am very excited about what this offers developers.

We saw previously how the lobby system is used to create or join games, and how to retrieve Steam IDs for messaging. Once we have joined a game we can start sending messages with the P2P::Send command, which includes a few overloads:

static bool P2P::Send(uint64 steamid, const int messageid, const int channel = 0, const int flags = 0);
static bool P2P::Send(uint64 steamid, const int messageid, std::string& data, const int channel = 0, const int flags = 0);
static bool P2P::Send(uint64 steamid, const int messageid, Bank* data, const int channel = 0, const int flags = 0);
static bool P2P::Send(uint64 steamid, const int messageid, Stream* data, const int channel = 0, const int flags = 0);
static bool P2P::Send(uint64 steamid, const int messageid, const void* data, const int size, const int channel = 0, const int flags = 0);

Each message has an ID and can be followed by additional data in the form of a string, bank, or stream. Voice chat is handled automatically, but the rest is up to you to decide what data the messages should contain. I provide examples for text chat, joining and leaving a game, and movement.

Receiving messages from other players is extremely simple:

static Message* P2P::Receive(const int channel = 0);

The message object has information contained within it:

class Message
{
public:
	int id;
	Stream* stream;
	uint64 userid
};

We can evaluate messages based on their ID. For example, here is a text chat message being received:

auto message = P2P::Receive()
if (message)
{
	if (message->id == MESSAGE_CHAT && message->stream != nullptr)
	{
		Print(message->stream->ReadString());
	}
}

A new multiplayer game template will be included, with out-of-the-box support for text and voice chat, public servers, and player movement.

Untitled2.thumb.png.fe53bb518c16a67f5e54a9a2c1c423a0.png

You can download the test app and try it out here:

Thanks to everyone who has helped me test this!

  • Like 1
  • Upvote 1


5 Comments


Recommended Comments

Really cool. Hopefully a network newbie like me can understand this.

Hopefully you can copy and paste this system into the new engine once this update goes live.

 

  • Upvote 1

Share this comment


Link to comment

In Turbo I think we can even add a general-purpose network update script like this:

function Entity:UpdateNetwork()
	local lobby = CurrentLobby()
	if lobby==nil then return end
	if lobby.owner ~= GetSteamID() then return end
	if self.lastupdatenetworktime==nil then
		self.lastupdatenetworktime=0
	end
	local tm = Time:Millisecs()
	if tm - self.lastupdatenetworktime > 1000/30 then
		self.lastupdatenetworktime = tm			
		local pos = self.entity:GetPosition(true)
		local rot = self.entity:GetQuaternion(true)
		local stream = BankStream:Create()
		if self.networkupdatetick==nil then self.networkupdatetick = 0 end
		stream:WriteInt(self.mapID)              
		self.networkupdatetick = self.networkupdatetick + 1
		stream:WriteInt(self.networkupdatetick)
		stream:WriteFloat(pos.x)
		stream:WriteFloat(pos.y)
		stream:WriteFloat(pos.z)
		stream:WriteFloat(rot.x)
		stream:WriteFloat(rot.y)
		stream:WriteFloat(rot.z)
		stream:WriteFloat(rot.w)
		Broadcast(MESSAGE_UPDATEENTITY,stream)
	end
end

And then entities would just automatically sync their orientations. Something like that.

  • Like 1

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Create Your Account

Sign in

Already have an account? Sign in here.

Sign In Now
×