A module can declare messages of its own and exchange them with a player's client. Only a client that says it understands them takes part. An official client never receives one, so a module must work without them, and players on an unmodified client play as before.
messages = {
kill_tally = { category = 0xC0, subtype = 0x01, dir = "out",
fields = { { "kills", "u32" }, { "last_map", "str32" } } },
tally_request = { category = 0xC0, subtype = 0x02, dir = "in", rate = 2,
fields = { { "reset", "bool" } },
on = function(m, player, msg) m:send(player, "kill_tally", { kills = 0, last_map = "" }) end },
},
categoryandsubtypename the message. The free categories differ per version: Dragonborn, Age of Patron, RF Online 1.5 and Golden Age. Two modules may not declare one pair, and an inbound pair the game itself handles is refused.fieldsare positional and little-endian, in the order written.diris"out"(server to client, the default),"in"or"both". An inbound message needson = function(m, player, msg), andmsgholds the decoded fields.rateis how many a client may send per second, 5 by default. More are dropped and counted.m:send(player, name, fields)sends one, with every declared field given. It returnsfalse, and sends nothing, to a client that never said it understands them.
After an operator reloads a module, a client has the old list until it asks again.
From GoMMO Client
GoMMO Client fetches a server's declared messages after it enters the world, so no client code is written per module. A script or an agent reads and sends them with module_catalog, module_last, module_send and module_refresh; see the Client Automation API.
examples/boss_hud.lua on Dragonborn and Age of Patron and examples/new_message.lua on Golden Age and 1.5 are complete modules with one message each way.
Field Kinds
bool, cstr, f32, f64, i16, i32, i64, i8, str:N, u16, u32, u64, u8. str:N is a fixed N-byte string holding N-1 bytes, and may be written strN. cstr ends at a NUL byte.