J3b: chat, the player list (with each player's land) and admin commands across lands; sleep needs everyone in every land, with a 'waiting for everyone else' message
This commit is contained in:
@@ -50,6 +50,9 @@ var _hub_link: Dictionary = {} ## {"conn": _hub, "buf": the partial line
|
||||
## Called once a server is listening. `args` are the command-line flags.
|
||||
func server_started(args: Dictionary) -> void:
|
||||
land = String(args.get("land", ""))
|
||||
roster = []
|
||||
if not Net.players_changed.is_connected(rebuild_roster):
|
||||
Net.players_changed.connect(rebuild_roster)
|
||||
if not land.is_empty():
|
||||
hub_port = int(args.get("hub-port", Net.DEFAULT_PORT))
|
||||
_hub = StreamPeerTCP.new()
|
||||
@@ -215,6 +218,8 @@ func _hub_tick(delta: float) -> void:
|
||||
print("[lands] the %s's server stopped" % l)
|
||||
_drain_output(s)
|
||||
servers.erase(l)
|
||||
rebuild_roster()
|
||||
PlayerNet.beds_changed()
|
||||
continue
|
||||
if s.conn != null:
|
||||
for msg in _read(s):
|
||||
@@ -253,6 +258,23 @@ func _from_land(l: String, msg: Dictionary) -> void:
|
||||
_send_land(l, {"t": "tunnel", "dug": _tunnel_dug_here()})
|
||||
"host_left":
|
||||
Net._host_left.call_deferred()
|
||||
"roster":
|
||||
servers[l].list = msg.get("list", [])
|
||||
rebuild_roster()
|
||||
"line":
|
||||
# Chat from that land: everyone here, and every other land.
|
||||
Chat._all(String(msg.text), String(msg.kind), false)
|
||||
for other in servers:
|
||||
if other != l:
|
||||
_send_land(other, msg)
|
||||
"cmd":
|
||||
Chat.run_remote(String(msg.line), {"id": String(msg.id), "name": String(msg.name), "land": l, "peer": int(msg.peer)})
|
||||
"beds":
|
||||
servers[l].beds = [int(msg.alive), int(msg.asleep)]
|
||||
# Tell the lands the running total (minus their own), so each can
|
||||
# say "N of M asleep", then see if the night passes.
|
||||
_push_bed_totals()
|
||||
PlayerNet.beds_changed()
|
||||
|
||||
## Sends `msg` to land `l`'s server.
|
||||
func _send_land(l: String, msg: Dictionary) -> void:
|
||||
@@ -302,9 +324,11 @@ func _land_tick() -> void:
|
||||
send_hub({"t": "hello", "land": land})
|
||||
send_hub({"t": "ready"})
|
||||
var n := Net.players.size()
|
||||
if n != _last_players:
|
||||
if n != _last_players or _roster_dirty:
|
||||
_last_players = n
|
||||
_roster_dirty = false
|
||||
send_hub({"t": "players", "n": n})
|
||||
send_hub({"t": "roster", "list": _here_list()})
|
||||
for msg in _read(_hub_link):
|
||||
_from_hub(msg)
|
||||
elif st == StreamPeerTCP.STATUS_ERROR or (st == StreamPeerTCP.STATUS_NONE and _said_hello):
|
||||
@@ -336,12 +360,116 @@ func _from_hub(msg: Dictionary) -> void:
|
||||
Net.push_clock()
|
||||
"tunnel":
|
||||
tunnel_dug = int(msg.dug)
|
||||
"roster":
|
||||
roster = msg.get("list", [])
|
||||
Net.push_roster()
|
||||
"line":
|
||||
Chat._all(String(msg.text), String(msg.kind), false)
|
||||
"reply":
|
||||
if Net.players.has(int(msg.peer)):
|
||||
Chat._s2c_line.rpc_id(int(msg.peer), String(msg.text), "reply")
|
||||
"kick":
|
||||
var kp: int = Net.peer_by_name(String(msg.name))
|
||||
if kp != 0:
|
||||
Net.kick(kp, String(msg.reason))
|
||||
"config":
|
||||
Net.reload_config()
|
||||
Net.broadcast_rules()
|
||||
"weather":
|
||||
Net.set_weather(String(msg.state))
|
||||
"save":
|
||||
WorldNet.save()
|
||||
"night":
|
||||
PlayerNet.pass_night_here(float(msg.secs))
|
||||
"beds_total":
|
||||
PlayerNet._hub_beds = [int(msg.alive), int(msg.asleep)]
|
||||
hub_message.emit(msg)
|
||||
|
||||
func send_hub(msg: Dictionary) -> void:
|
||||
if _hub != null and _hub.get_status() == StreamPeerTCP.STATUS_CONNECTED:
|
||||
_hub.put_data((JSON.stringify(msg) + "\n").to_utf8_buffer())
|
||||
|
||||
# --- everyone, everywhere (J3b) ------------------------------------------------------------
|
||||
|
||||
## Everyone on every land: [{"name", "id", "land", "admin"}]. The hub builds
|
||||
## it from its own players and what each land reports; every land and every
|
||||
## player's game gets a copy (Net.roster), for the player list and /players.
|
||||
var roster: Array = []
|
||||
var _roster_dirty := false
|
||||
|
||||
## The players on this server, as the roster lists them.
|
||||
func _here_list() -> Array:
|
||||
var out: Array = []
|
||||
for p in Net.players.values():
|
||||
out.append({"name": String(p.name), "id": String(p.id), "land": here(), "admin": bool(p.get("admin", false))})
|
||||
return out
|
||||
|
||||
## Hub: the roster again (its players changed, or a land's did), sent out.
|
||||
func rebuild_roster() -> void:
|
||||
if not hub:
|
||||
if not land.is_empty():
|
||||
_roster_dirty = true # (a land server: tell the hub, next tick)
|
||||
return
|
||||
var out: Array = _here_list()
|
||||
for l in servers:
|
||||
for e in servers[l].get("list", []):
|
||||
var e2: Dictionary = (e as Dictionary).duplicate()
|
||||
e2.land = l
|
||||
out.append(e2)
|
||||
roster = out
|
||||
Net.push_roster()
|
||||
for l in servers:
|
||||
_send_land(l, {"t": "roster", "list": out})
|
||||
|
||||
## The land a player called `n` is in ("" = not on anywhere).
|
||||
func land_of_name(n: String) -> String:
|
||||
for e in roster:
|
||||
if String(e.name).to_lower() == n.to_lower():
|
||||
return String(e.land)
|
||||
return ""
|
||||
|
||||
## Chat or a server message, from here to every other land.
|
||||
func relay_line(text: String, kind: String) -> void:
|
||||
if hub:
|
||||
for l in servers:
|
||||
_send_land(l, {"t": "line", "text": text, "kind": kind})
|
||||
elif not land.is_empty():
|
||||
send_hub({"t": "line", "text": text, "kind": kind})
|
||||
|
||||
## Hub: sends `msg` to every land.
|
||||
func tell_lands(msg: Dictionary) -> void:
|
||||
for l in servers:
|
||||
_send_land(l, msg)
|
||||
|
||||
## Hub: sends `msg` to land `l`.
|
||||
func tell_land(l: String, msg: Dictionary) -> void:
|
||||
_send_land(l, msg)
|
||||
|
||||
## Hub: tells each land the alive/asleep everywhere BUT that land, so a land
|
||||
## server can show the right "N of M" and know when all are abed.
|
||||
func _push_bed_totals() -> void:
|
||||
var here_alive: int = PlayerNet._alive().size()
|
||||
var here_asleep: int = PlayerNet._alive().filter(func(q): return q.in_bed).size()
|
||||
for l in servers:
|
||||
var a := here_alive
|
||||
var s := here_asleep
|
||||
for other in servers:
|
||||
if other != l:
|
||||
var b: Array = servers[other].get("beds", [0, 0])
|
||||
a += int(b[0])
|
||||
s += int(b[1])
|
||||
_send_land(l, {"t": "beds_total", "alive": a, "asleep": s})
|
||||
|
||||
## Hub: how many are alive, and how many asleep, in every other land.
|
||||
func beds_elsewhere() -> Array:
|
||||
var alive := 0
|
||||
var asleep := 0
|
||||
for l in servers:
|
||||
var b: Array = servers[l].get("beds", [0, 0])
|
||||
alive += int(b[0])
|
||||
asleep += int(b[1])
|
||||
return [alive, asleep]
|
||||
|
||||
## Land server: a pass for player `id` to go back to the hub.
|
||||
func pass_home(id: String) -> String:
|
||||
var p := Crypto.new().generate_random_bytes(16).hex_encode()
|
||||
|
||||
Reference in New Issue
Block a user