Network
network is for an experience made of more than one server. Such an experience is a network. Each server in it is a member. One member is the default: players land on it. Every other member runs only when a pack asks for an instance of it.
An instance has a label. One member can run in several ways, such as 2v2 and 4v4. The label says which. Minefort stores the label and filters on it, and does nothing else with it.
Any server of the network can call network. The pack names a member and a label. Minefort decides the network, the instance’s id and where the instance runs.
-- The default member: a place where players pick how to play.
-- This author calls an instance of "bedwars-arena" an arena.
local waiting = {} -- instance id -> the players who go there when it is online
commands.add("join <label:word>", function(player, args)
local arena, why = network.find{
label = args.label, -- "2v2"
party = player, -- room for the player's whole party
start = { member = "bedwars-arena", slots = 8, data = { map = "castle" } },
}
if not arena then return "No arena now: " .. tostring(why) end
if arena.state == "online" then
player:connect(arena.id)
else
-- It is still starting. Keep the player here until it is online.
waiting[arena.id] = waiting[arena.id] or {}
table.insert(waiting[arena.id], player)
end
end)
network.on_instance(function(instance)
if instance.state ~= "online" then return end
for _, player in waiting[instance.id] or {} do player:connect(instance.id) end
waiting[instance.id] = nil
end)
network.on_gone(function(id) waiting[id] = nil end)
-- The member "bedwars-arena": it says how much room it has.
local me = network.info() -- `me.id` is nil on a server that is not an instance
local map = me and me.data and me.data.map or "castle"
players.on_join(function()
if me and me.id then network.status{ open = math.max(0, me.slots - #players.list()), status = "waiting" } end
end)
-- When the round starts: network.status{ open = 0, status = "playing" }
-- When the round ends, each player goes back to the default member:
-- player:connect(me.network) -- the name of the network
The calls:
network.start{ member, label, slots, data? }starts an instance ofmember. It returns{id, state}at once, withstate = "starting": the instance comes online later.slotsis the number of players the instance takes.datais the pack’s own value for the instance, read there withnetwork.info().network.find{ label, players?, party?, start? }returns{id, state}for the instance to sendplayersplayers to, or nil when no instance has room.- It picks an
onlineinstance with that label and that muchopen, the fullest first. - The room is held for 10 seconds, so two calls do not both get the last place.
playersis 1 unless you set it.partyis a player, or their uuid. When they lead a/party, Minefort holds room for every member. Connect the leader, and the party follows them there. A player who leads no party needs room for one.- With
start = { member, slots, data? }, Minefort starts an instance when none has room, and holds the room on it. Thestateis then"starting". - Use
findwithstart, notfindand thenstart. The default runs on many servers, and each would start its own instance.
- It picks an
network.list(label?)returns a list of the network’s instances. Each one is the instance table below.network.stop(id)stops an instance of this network. It returnstruewhen Minefort accepted it.network.info()returns{network}on every server of a network.networkis the name of the network.- On an instance it returns
{network, id, member, label, slots, data}. idis nil on a server that is not an instance.
- On an instance it returns
network.status{ open, status?, meta? }says where this instance is. It returns nothing and does not yield.openis the number of players the instance takes now.0closes it tofind.statusis the pack’s own word, such as"waiting"or"playing".metais the pack’s own value. Other servers of the network read it.- Minefort takes one status a second. The first call goes at once. Of the calls in the second after it, only the last goes.
network.on_instance(fn)callsfn(instance)when an instance starts or changes. It returns a connection.network.on_gone(fn)callsfn(id)when an instance is gone. It returns a connection.
An instance table:
| Field | Set by | Meaning |
|---|---|---|
id |
Minefort | The instance’s name. player:connect takes it. |
member, label |
the pack that started it | Which member, and which label. |
state |
Minefort | "starting", then "online", then "stopping". |
open |
the instance | The number of players it takes now. |
status |
the instance | Its own word, or nil. |
players |
Minefort | The number of players on it. |
meta |
the instance | Its own value, or nil. |
network does not move players. player:connect(id) does. The instance’s id is the server name it takes. The name of the network, network.info().network, sends a player back to the default member. Do not send a player to an instance that is "starting": keep the player until the instance is "online".
Events come to the default member’s servers only. Call network.list() once at the start, then keep the list from on_instance and on_gone. An event can be lost. Call network.list() again, once a minute at most, to repair the list.
A failed call returns nil and a reason. start, find and info return nil, reason. list returns {}, reason. stop returns false, reason. The reason is Minefort’s word, or one of these:
"unavailable": there is no network here. Every local run answers this."io": the request was not sent."timeout": no answer came in 35 seconds. Astartmay have happened.
find returns nil with no reason when no instance has room.
Limits. A value out of these is an error, and nothing is sent:
label: 1 to 32 characters ofa-z,0-9and-.member: 1 to 40 characters ofa-z,0-9and-.slots: 1 to 200.players: 1 to 64.open: 0 to 200.data: at most 4096 bytes as JSON.meta: at most 512 bytes as JSON.status: at most 32 characters.- An unknown field in a table is an error.
- A network has at most 20 instances in a region, and one
starta second. - Minefort removes an instance with no players for 60 seconds after its first player, or for 5 minutes without one.
Calls yield, like stores, but for status and the two events. Call from scripts, callbacks or tasks.