Communicating with the Server

Take a look at one of Funkland’s core features: its ability to communicate with servers through messages.

Understanding FireEvent and GetTopic


Punkland supports communication between the server and client using the FireEvent and GetTopic methods. Internally, it works by using GetTopic to register a key and a corresponding function. When that key is called via FireEvent, the previously registered function is executed.

GetTopic is a function used to handle events related to a specific topic. By using this function, you can process events associated with a particular topic sent from the client. For example, if you send a FireEvent with the topic "Apple," you can register a function to handle events related to that "Apple" topic.

-- When the client sends a FireEvent with the topic "Apple" 
-- Display the message "Apple" to all clients.
Server.GetTopic("Apple").Add(function()
  Server.SendCenterLabel("Apple")
end)

Client.FireEvent("Apple")

By using GetTopic and FireEvent, you can handle events related to a specific topic and send messages to the client. Conversely, the client can also handle events using the GetTopic method.

Serialization Issues


When communicating via GetTopic and FireEvent, advanced object serialization is not supported. This is because Lua scripts don’t provide such functionality by default. Therefore, if you need to serialize and transmit more complex objects or data types, additional processing is required.

To address this, Funkland offers Utility.JSONParse, Utility.JSONSerialize, as well as the Moonscript-based JSON library functions json.parse and json.serialize. The JSON methods in the Utility class also use Moonscript’s JSON conversion library under the hood.

1. Handling string and number types

In Lua scripts, string and number types can be sent via FireEvent without any additional processing. Below is an example of sending string and number types to the server.

Client.FireEvent("PlainData", "Hello", 1, 2, "World")

Server.GetTopic("PlainData").Add(function(...)
  print(...) -- Print Hello 1 2 World 
end)

2. Handling table types

Tables are a versatile data structure in Lua, allowing you to store and organize various pieces of data. For example, you can store multiple values in a table, serialize it, and then use FireEvent to send it.

Below is an example of serializing a table and using it for communication.

-- Serialize a table on the client side and send it via FireEvent
local data = {name = "John", age = 25, score = 100}
local serializedData = Utility.JSONSerialize(data) -- Serialize the table into a string

Client.FireEvent("TableData", serializedData) -- Send the serialized data using FireEvent

-- On the server side, receive the serialized data, convert it back into a table, and handle it
Server.GetTopic("TableData").Add(function(serializedData)
  local data = Utility.JSONParse(serializedData) -- Convert the serialized data back into a table
  print(data.name) -- Prints "John"
  print(data.age) -- Prints 25
  print(data.score) -- Prints 100
end)

In the example above, the table is serialized and converted into a string before being sent via FireEvent. On the server side, the received serialized data can be converted back into a table for processing. By using this method—serializing tables for communication—you can effectively work around the serialization limitations for advanced objects.

This method only applies to basic Lua types, such as tables. It cannot serialize userdata types provided by Funkland in class form. If a table contains other advanced objects, you may need to extract their properties individually and serialize them in order to communicate.

3. Handling UserData Types

For userdata types, you must individually extract their properties and then serialize them. Once the extracted properties are organized into a table, you can serialize that table and send it via communication channels.

-- Get the unit object
local me = Client.myPlayerUnit() 

-- Put the required properties of the unit object into a table
local serializedData = {
  name = me.name,
  exp = me.exp
}

-- Serialize the table and convert it into a string
local serializedString = Utility.JSONSerialize(serializedData)

-- Send the serialized data with FireEvent
Client.FireEvent("UnitData", serializedString) 

-- On the server side, receive the serialized data, convert it into a unit object, and process it
Server.GetTopic("UnitData").Add(function(serializedString)

  -- Convert the serialized data back into a table
  local unitData = Utility.JSONParse(serializedString) 
  print(unitData.name)
  print(unitData.exp)
  
  --
  -- Process the unit data
  --
end)

In the example above, the name and exp properties of a unit object are extracted, organized into a table, serialized, and then transmitted. On the server side, after receiving the serialized data, it’s converted back into a table and the values are reassigned to the unit object’s properties. By using tables in this manner, you can implement the serialization and communication of advanced objects.

Last updated