170 lines
4.3 KiB
GDScript
170 lines
4.3 KiB
GDScript
extends Node
|
|
|
|
signal connected
|
|
signal disconnected
|
|
signal login_ok(my_id, players)
|
|
signal player_joined(id, name, x, y, skin_id)
|
|
signal player_left(id)
|
|
signal player_moved(id, x, y, flip_h, frame)
|
|
signal chat_message_received(sender_id, text)
|
|
|
|
signal private_chat_message_received(sender_id, text)
|
|
signal notices_received(data)
|
|
|
|
const DEFAULT_SERVER_URL = "ws://127.0.0.1:8910"
|
|
|
|
var socket := WebSocketPeer.new()
|
|
var my_id: int = -1
|
|
var player_info := {"name": "Player", "skin_id": 0}
|
|
var players := {} # id -> {name, x, y, skin_id}
|
|
var _connected := false
|
|
var next_spawn_position: Vector2 = Vector2.ZERO
|
|
|
|
func _ready():
|
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
|
|
|
func _process(_delta):
|
|
socket.poll()
|
|
var state = socket.get_ready_state()
|
|
|
|
if state == WebSocketPeer.STATE_OPEN:
|
|
if not _connected:
|
|
_connected = true
|
|
_on_connected()
|
|
|
|
while socket.get_available_packet_count():
|
|
var packet = socket.get_packet()
|
|
_on_message(packet.get_string_from_utf8())
|
|
|
|
elif state == WebSocketPeer.STATE_CLOSED:
|
|
if _connected:
|
|
_connected = false
|
|
_on_disconnected()
|
|
|
|
func connect_to_server(url: String = ""):
|
|
if url.is_empty():
|
|
url = DEFAULT_SERVER_URL
|
|
var err = socket.connect_to_url(url)
|
|
if err != OK:
|
|
print("Failed to connect: ", err)
|
|
return err
|
|
|
|
func _on_connected():
|
|
print("Connected to server!")
|
|
# Send login
|
|
send_json({
|
|
"type": "login",
|
|
"name": player_info["name"],
|
|
"skin_id": player_info["skin_id"]
|
|
})
|
|
connected.emit()
|
|
|
|
func _on_disconnected():
|
|
print("Disconnected from server")
|
|
my_id = -1
|
|
players.clear()
|
|
disconnected.emit()
|
|
|
|
func _on_message(data: String):
|
|
var json = JSON.new()
|
|
var err = json.parse(data)
|
|
if err != OK:
|
|
print("JSON parse error: ", data)
|
|
return
|
|
|
|
var msg = json.data
|
|
# if msg.get("type") == "player_move" and int(msg.get("id", -1)) != my_id:
|
|
# print("RAW NET: ", data)
|
|
var msg_type = msg.get("type", "")
|
|
|
|
match msg_type:
|
|
"login_ok":
|
|
my_id = int(msg["id"])
|
|
for p in msg["players"]:
|
|
players[int(p["id"])] = {
|
|
"name": p["name"],
|
|
"x": p["x"],
|
|
"y": p["y"],
|
|
"skin_id": p["skin_id"]
|
|
}
|
|
login_ok.emit(my_id, players)
|
|
|
|
"player_join":
|
|
var id = int(msg["id"])
|
|
players[id] = {
|
|
"name": msg["name"],
|
|
"x": msg["x"],
|
|
"y": msg["y"],
|
|
"skin_id": msg["skin_id"]
|
|
}
|
|
player_joined.emit(id, msg["name"], msg["x"], msg["y"], msg["skin_id"])
|
|
|
|
"player_leave":
|
|
var id = int(msg["id"])
|
|
players.erase(id)
|
|
player_left.emit(id)
|
|
|
|
"player_move":
|
|
var id = int(msg["id"])
|
|
if id != my_id: # Only log others to reduce spam, or log all? Let's log all for now if issue is critical
|
|
print("Net: Recv Move for ID: ", id, " Frame: ", msg.get("frame", 1))
|
|
if players.has(id):
|
|
players[id]["x"] = msg["x"]
|
|
players[id]["y"] = msg["y"]
|
|
player_moved.emit(id, msg["x"], msg["y"], msg.get("flip_h", false), int(msg.get("frame", 1)))
|
|
|
|
"chat":
|
|
var id = int(msg["id"])
|
|
chat_message_received.emit(id, msg["text"])
|
|
|
|
"private_chat":
|
|
var id = int(msg["sender_id"])
|
|
private_chat_message_received.emit(id, msg["text"])
|
|
|
|
"notices_list":
|
|
notices_received.emit(msg.get("data", []))
|
|
|
|
|
|
"scene_peers":
|
|
# Refresh player list for new scene
|
|
players.clear()
|
|
for p in msg["players"]:
|
|
players[int(p["id"])] = {
|
|
"name": p["name"],
|
|
"x": p["x"],
|
|
"y": p["y"],
|
|
"skin_id": p["skin_id"]
|
|
}
|
|
# Emit login_ok to trigger refresh (or we could add a scene_loaded signal)
|
|
login_ok.emit(my_id, players)
|
|
|
|
func send_json(obj: Dictionary):
|
|
if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
|
|
socket.send_text(JSON.stringify(obj))
|
|
|
|
func send_move(x: float, y: float, flip_h: bool, frame: int):
|
|
send_json({"type": "move", "x": x, "y": y, "flip_h": flip_h, "frame": frame})
|
|
|
|
func send_change_scene(scene_name: String, pos: Vector2 = Vector2(-20000, -20000)):
|
|
var data = {"type": "change_scene", "scene": scene_name}
|
|
if pos.x != -20000:
|
|
data["x"] = pos.x
|
|
data["y"] = pos.y
|
|
send_json(data)
|
|
|
|
func send_message(text: String):
|
|
send_json({"type": "chat", "text": text})
|
|
|
|
func send_private_message(target_id: int, text: String):
|
|
send_json({"type": "private_chat", "target_id": target_id, "text": text})
|
|
|
|
func request_notices():
|
|
send_json({"type": "get_notices"})
|
|
|
|
|
|
func set_player_name(n: String):
|
|
player_info["name"] = n
|
|
|
|
func set_skin_id(id: int):
|
|
player_info["skin_id"] = id
|