Connect and be ready for messages

The simplest way to connect, get online, and be ready to receive messages from other clients, is here:

Lacewing Blue

Lacewing Relay

You'll notice they're both the same, as Blue is based on Relay, but with additional features and bugfixes.

At event 8, you are now on a channel; you can loop all the peers already on the channel, send messages on the channel, etc.

The "" in event 1 is the address of a public Relay server run by Darkwire Software, the creators of Lacewing Blue. You can check if it's online and see more servers on Darkwire's Relay page here.

Maintain a peer list

After joining a channel, you will have access to peers on the channel.

This example shows how to maintain a displayable list of peers, starting by looping through the peers already on the channel when you join. You can do that using the Channel > Peer > Loop, or the named-loop variant, Channel > Peer > Loop (with loop name).

You will also have to respond to Channel > Peers > On peer connect, On peer disconnect, and sometimes On peer changed name events, which are all covered below in detail.

(ACO or Advanced Comment Object is used to add further comments; they don't do anything at runtime, so you don't have to copy them. Just read them to understand the code better.)

You don't need to use List object, obviously, but this is a simple example.

The List Object does have a benefit of having alphabetical sorting built into its object properties, though, which can be useful for sorting usernames.

Some people use IconList object so they can give some usernames different icons, others use Tree Control object.

Look for public channels

When you create a channel by using Channel > Join, if the "hidden" parameter in Join is 0, the channel you just created is put in the public channel listing, available for all other clients to see.

To read the list of public channels, you need to first request the list. Once you receive it back from the server, it is stored on your Client extension, ready for looping at any time you want.

(ACO or Advanced Comment Object is used to add further comments; they don't do anything at runtime, so you don't have to copy them. Just read them to understand the code better.)

Servers can reply that they've disabled channel listing, in which case Blue will create an error, but Relay will simply do nothing.

Creating player objects

When creating a player object, auto-selection comes into play, and there's two things to remember:

  1. Make sure you don't have "create at start" property checked, or you'll have an extra player object.
    Since alt values start as 0, and peer IDs start at 0, you could end up with two player objects for one player if you're using peer IDs to select the right player object instance.
    (And ID selection is faster, so you should use IDs instead of names.)
    An Active object's Runtime properties, with Create at start set to unchecked.
  2. Make sure the order of actions is correct; you have to create then set the alt value/alt string. To check the action order, switch to Event List Editor, or double-click any box on the event's row.

You should have events with actions that look like this:

(ACO or Advanced Comment Object is used to add further comments; they don't do anything at runtime, so you don't have to copy them. Just read them to understand the code better.)

The reason for this action order is the Create Object action automatically applies the actions after it (or beneath it) to the newly created objects.

So if you set alterable value/string then create, you'll actually be setting the alterable value for all the existing objects, not the new one. Which makes sense; how can you change something that doesn't exist yet?

Selecting player objects

When selecting a player object (object tied to one specific peer), bear these in mind…

Make sure it's not being deactivated

There's two object properties you want to change to make sure the object is not being deactivated.

An Active object's Runtime properties, with Destroy object if too far from frame unchecked, and Inactivate if too far from window set to No.

Match these two properties as shown in screenshot.

  • Destroy object if too far from frame must be unchecked.
  • Inactivate if too far from window must be set to No.

Use object conditions

Use the conditions based on the object's conditions:

And check the object is on left hand side of expression:

Don't use Compare Two General Values

Don't use Compare Two General Values, as it will not filter the object instances it's used on.

(There's a very subtle visual difference.)

As described above under "Use object conditions", the left hand side object, or the object that the condition is running on, is filtered by Fusion as a general rule.

When you use Compare Two General Values like above, Fusion runtime will loop through all the Player objects and checks if any instance has a matching expression, but because it's not an Player condition – it's a System object condition with a Player expression, very important difference – the System object is considered the object to filter selection for, not Player.

Since the System object can't be filtered, and Player isn't filtered either, then you'll end up with a complete mess as all your Player instances do something only one Player instance was meant to do.

(If you think you might have made this mistake, click the System object's icon at the top of the Event Editor. Only events that use it in conditions, actions, or expressions, will show up – that will make it faster to check the conditions.)

Filter all player objects when interacting with them

Don't skip a player-related object if you're using it in actions. You have to filter all the ones you use.

Event 2 is wrong, as when a user disconnects, the single correct Player instance, but all PlayerShadow instances will be destroyed in event 2.

This is because a specific instance was never selected in the conditions, so Fusion didn't filter any of them.

You could also use:

…because at the point condition 3 is run and starts filtering PlayerShadow, condition 2 has already selected the single Player that corresponds to it.

Too many objects being selected?

Make sure you're selecting properly, but also that you're creating properly; both are discussed above.

If you think you are, feel free to use the Select Object extension's count-selection expressions to check how many instances were selected in an event.

Hosting a server

This example and more details about how to connect is covered under the Hosting a server guide.

Expert: Sending a big file with compression

This example is for experts. LB has a file sharing example without compression below.

Lacewing doesn't allow infinite size messages. Compressing is good, and sending in parts is also a good route.

But if you're compressing a big chunk of data, and sending it in parts, you can compress the whole thing using Binary Object.

A general guide:

  1. Read the file size using Binary Quickload's expression.
  2. Resize the Binary object via its Resize action, to match the file size.
  3. Load the file into the Binary object using Binary Quickload object.
  4. Compress using Binary object's zlib compression (if file isn't already compressed).
  5. Send the compressed Binary Object's size to the receiver.
  6. When receiver sees the size, it resizes its Binary Object to match.
  7. Send via the Binary to send > Add Binary action, using the Binary Object's memory address and multiplier of the part size.
  8. When receiving, use Memory Object to copy from Received binary address to the Binary Object on the receiving end. Keep track of how much is left.
  9. When fully received, use Binary Object to decompress again.
  10. On receiving end, save the Binary object
  11. Don't forget to clear the Binary Object on both sender and receiver to free the memory, using their Clear action.

You may want to check at stage 4 that the file comes out the compression smaller than it went in; remember, some file types are internally compressed, and re-compression is bad.

External examples


When following these tutorials, use Lacewing Blue instead of Lacewing Relay, even if the tutorials use Relay; you'll find the actions/conditions/expressions the same, so Relay tutorials will work for Blue, and vice versa.

The reason Blue is preferred is due to it being maintained, so found bugs are fixed. Relay is not maintained, and so there is a Known Relay bugs help topic, and Blue has an Additional features topic as well.

No Lacewing example will break if you use Blue instead of Relay, or if you convert them (without making a mistake).

These examples may be using old servers (ledev, klikfarm, etc). Make sure you use the public servers listed here. While the Lacewing objects do work, the old servers are no longer online.

Don't use the legacy compatibility servers!

Here's the external tutorials list:

  • Lacewing chatroom by Sumo148. (YouTube video, hosted by AlmightyZenTaco; and v2 zip with MFA and EXE file)
  • Lacewing chatroom by therickman (MFA), based on an old example PDF by Darkwire. (PDF)
  • Lacewing multiplayer tutorial by Darwin10011. (YouTube videos: part 1, part 2)
  • Lacewing multiple channel tutorial by Darwin10011. (YouTube video)
  • Lacewing multiplayer tutorial by Animated Ginger. (YouTube video)
  • DizzyDoo's multiplayer game tutorial. (Vimeo videos linked on CT forum thread)
  • PlasmaVoid's multiplayer top-down shooter. (CT forum thread)
  • Several free and cheap examples on ClickStore, as well as some $10 ones. (ClickStore search)

There are Russian and Polish tutorials on YouTube as well.

Lace Chat MFA by LB (Clickteam forum link)

This example will only work properly in Fusion Developer. It shows how to make a Gwerdy-like MDI chat with Lacewing.

Where to go next

There is a whole article dedicated to tips – performance, efficiency, message limitations, etc, discussed in Tips article.

There is also an article on how selection works, how loops work, binary messages, sending vs blasting, how to debug your app, security, etc. Have a browse through all of them; even long-time users of Lacewing will find details of inner workings useful.

If you are working on a server, read the Hosting a server article, as well as the ones linked above.