서버 스크립트

Chain2D.Network

클라이언트와 주고받는 메시지. 입력과 스냅샷은 엔진이 나르므로 여기 오가는 것은 그 밖의 것 — 채팅, 상점, 문을 열었다는 사실 — 입니다. 양쪽 다 표를 주고받습니다: 서버와 클라이언트가 같은 JSON 파일을 박아 쓰기 때문에 보낸 표는 같은 표로 도착합니다. 이름 규칙을 검사하는 쪽은 서버입니다 — 클라이언트의 `Network.send` 는 `Chain2D.` 로 시작하는 이름만 그 자리에서 거부합니다. 채널마다 이 스크립트가 한 벌씩 돌기 때문에, 여기서 닿을 수 있는 사람은 이 채널에 접속해 있는 사람뿐입니다.

Network.on

선언
Chain2D.Network.on(name: string, handler: (player: Player, payload: any?) -> ())
매개변수
namestring클라이언트가 `Network.send` 로 보낼 때 쓰는 이름. 영문 글자로 시작하고 그 뒤로 영문 글자, 숫자, `_`, `-`, `.`, `:` 만 오며 64자까지입니다. 한글은 들어갈 수 없습니다. `Chain2D.` 로 시작하는 이름은 거부됩니다.
handler(player: Player, payload: any?) -> ()메시지가 올 때마다 불립니다. 첫 인자는 보낸 Player, 두 번째는 JSON 으로 읽힌 값입니다. 함수가 아니면 거부됩니다.

클라이언트가 보내는 한 이름의 메시지를 듣습니다. 이름 하나에 핸들러는 하나이고, 이미 등록된 이름을 다시 등록하면 그 자리에서 거부됩니다. `Chain2D.` 로 시작하는 이름도 거부됩니다 — 입력과 스냅샷은 엔진이 처리하므로, 스크립트가 그 이름을 등록하면 절대 오지 않는 핸들러를 갖게 됩니다. 조용히 무시하는 대신 거절하는 이유입니다. 아무도 등록하지 않은 이름으로 온 메시지는 조용히 버려지지만, 알 수 없는 Player 나 그 Player 의 채널이 아닌 곳에서 온 메시지는 버려지는 대신 오류가 됩니다 — 이 채널이 볼 수 없어야 할 것을 본 셈이므로 넘어가지 않습니다. 핸들러 안에서 난 오류도 잡히지 않습니다: 클라이언트의 `Network.on` 은 읽기에 실패해도 스크립트를 죽이지 않지만, 서버는 핸들러를 감싸지 않아서 오류가 그대로 올라가 이 채널의 Runtime 을 멈춥니다. payload 는 클라이언트가 보낸 것이므로 사실이 아니라 주장입니다 — 무엇이 진짜인지는 서버가 자기 `Data` 를 읽어서 정하고, 모양부터 확인하고 시작해야 하는 것도 같은 이유입니다.

Chain2D.Network.on("buy", function(player, payload)
    if type(payload) ~= "table" or type(payload.item) ~= "string" then
        return
    end
    Chain2D.Network.send(player, "bought", { item = payload.item })
end)

Network.send

선언
Chain2D.Network.send(player: Player, name: string, data: any)
매개변수
playerPlayer받을 사람. 지금 접속해 있는 바로 그 Player 여야 합니다. 같은 id 를 가진 다른 표나 이미 나간 사람의 Player 는 거부됩니다.
namestring클라이언트의 `Network.on` 이 듣고 있는 이름. `Network.on` 과 같은 규칙으로 검사하고, `Chain2D.` 로 시작하면 거부됩니다.
dataany보낼 표. JSON 으로 바뀌어 나갑니다. 함수나 `nil` 처럼 JSON 으로 바꿀 수 없는 값, 그리고 바뀐 결과가 2 KiB 를 넘는 값은 거부됩니다.

한 사람에게 메시지를 보냅니다. 클라이언트의 `Network.send` 와 달리 성공 여부를 값으로 돌려주지 않습니다. 보내지 못하는 경우는 모두 거부이고 그 자리에서 오류가 납니다 — 접속해 있지 않은 Player, 규칙에 맞지 않는 이름, JSON 으로 바꿀 수 없거나 2 KiB 를 넘는 값입니다.

Chain2D.Players.playerAdded(function(player)
    Chain2D.Network.send(player, "welcome", { id = player.id })
end)

Network.broadcast

선언
Chain2D.Network.broadcast(name: string, data: any)
매개변수
namestring클라이언트의 `Network.on` 이 듣고 있는 이름. `Network.send` 와 같은 규칙으로 검사합니다.
dataany보낼 표. 한 번만 JSON 으로 바뀌고, 그 문자열이 모두에게 그대로 갑니다. `Network.send` 와 같은 제한을 받습니다 — 다만 2 KiB 검사는 사람마다 실제로 보낼 때 일어납니다.

이 채널에 접속해 있는 모두에게 같은 메시지를 보냅니다. 훑는 목록은 `Chain2D.Players.getPlayers()` 가 주는 것과 같고, 들어온 순서대로입니다. 아무도 없어도 완전히 아무 일도 하지 않는 것은 아닙니다: 이름 검사와 JSON 변환은 목록을 훑기 전에 한 번 일어나므로, 규칙에 맞지 않는 이름이나 JSON 으로 바꿀 수 없는 값은 받는 사람이 없어도 오류입니다. 반대로 크기 제한은 보낼 때마다 검사하므로, 아무도 없으면 2 KiB 를 넘는 표도 아무 말 없이 지나갑니다.

Chain2D.Players.playerAdded(function(player)
    local everyone = Chain2D.Players.getPlayers()
    Chain2D.Network.broadcast("joined", { id = player.id, count = #everyone })
end)