diff options
author | metamuffin <metamuffin@disroot.org> | 2024-06-23 20:05:28 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-06-23 20:05:28 +0200 |
commit | 3885cbfae528608350804f704dba9c82fdbfd027 (patch) | |
tree | 384a37820cf43d1868493600a8e0566c78b9ab4a /client/multiplayer.gd | |
parent | 93221433e704e1c98cc84c55caefddb85c2d5717 (diff) | |
download | hurrycurry-3885cbfae528608350804f704dba9c82fdbfd027.tar hurrycurry-3885cbfae528608350804f704dba9c82fdbfd027.tar.bz2 hurrycurry-3885cbfae528608350804f704dba9c82fdbfd027.tar.zst |
move files around
Diffstat (limited to 'client/multiplayer.gd')
-rw-r--r-- | client/multiplayer.gd | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/client/multiplayer.gd b/client/multiplayer.gd new file mode 100644 index 00000000..534ef663 --- /dev/null +++ b/client/multiplayer.gd @@ -0,0 +1,205 @@ +# Undercooked - a game about cooking +# Copyright 2024 nokoe +# Copyright 2024 metamuffin +# Copyright 2024 tpart +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, version 3 of the License only. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +extends Node + +signal init(player_id: int) +signal update_map(tile: int, pos: Array, neighbors: Array) +signal clear_message(player: int) +signal text_message(player: int, text: String) +signal item_message(player: int, item: int) +signal add_player(player: int, name: String, pos: Vector2, character: int) +signal remove_player(player: int) +signal position(player: int, position: Vector2, rotation: float) +signal take_item(tile: Vector2i, player: int) +signal put_item(tile: Vector2i, player: int) +signal set_tile_item(tile: Vector2i, item: int) +signal remove_tile_item(tile: Vector2i) +signal set_progress(tile: Vector2i, progress: float, warn: bool) +signal set_finished(tile: Vector2i, warn: bool) + +var connected := false +var socket := WebSocketPeer.new() + +var item_names = [] +var tile_names = [] +var tile_collide = [] +var tile_interact = [] +var item_idx_from_name: Dictionary = {} +var player_id = -1 + +var tileid_by_pos: Dictionary = {} + +func connectClient(url: String): + socket.connect_to_url(url) + connected = true + +func _process(_delta): + if connected: + socket.poll() + var state = socket.get_ready_state() + if state == WebSocketPeer.STATE_OPEN: + while socket.get_available_packet_count(): + handle_packet(socket.get_packet()) + elif state == WebSocketPeer.STATE_CONNECTING: + print("connecting") + elif state == WebSocketPeer.STATE_CLOSING: + # Keep polling to achieve proper close. + print("closing") + pass + elif state == WebSocketPeer.STATE_CLOSED: + var code = socket.get_close_code() + var reason = socket.get_close_reason() + print("WebSocket closed with code: %d, reason %s. Clean: %s" % [code, reason, code != - 1]) + +func handle_packet(bytes: PackedByteArray): + var decoded = decode_packet(bytes) + + if decoded == null: + return + + var packet_type: String = decoded["type"] + match packet_type: + "init": + player_id = decoded["id"] + item_names = decoded["data"]["item_names"] + tile_names = decoded["data"]["tile_names"] + tile_collide = decoded["data"]["tile_collide"] + tile_interact = decoded["data"]["tile_interact"] + for i in range(item_names.size()): + item_idx_from_name[item_names[i]] = i + emit_signal("init", player_id) + "add_player": + var id = decoded["id"] + var player_name = decoded["name"] + var pos = decoded["position"] + var character = decoded["character"] + emit_signal("add_player", id, player_name, pos_to_vec2(pos), character) + "remove_player": + var id = decoded["id"] + emit_signal("remove_player", id) + "position": + var player = decoded["player"] + var pos = decoded["pos"] + var rot = decoded["rot"] + emit_signal("position", player, pos_to_vec2(pos), rot) + "take_item": + var tile = pos_to_vec2i(decoded["tile"]) + var player = decoded["player"] + emit_signal("take_item", tile, player) + "put_item": + var tile = pos_to_vec2i(decoded["tile"]) + var player_id = decoded["player"] + emit_signal("take_item", tile, player_id) + "set_active": + var tile = pos_to_vec2i(decoded["tile"]) + var warn = decoded["warn"] + var progress = decoded.get("progress") + if progress != null: + emit_signal("set_progress", tile, decoded["progress"], warn) + else: + emit_signal("set_finished", tile, warn) + "set_tile_item": + var tile = pos_to_vec2i(decoded["tile"]) + var item = decoded.get("item") + if item != null: + emit_signal("set_tile_item", tile, item) + else: + emit_signal("remove_tile_item", tile) + "set_player_item": + var player = decoded["player"] + var item = decoded.get("item") + if item != null: + emit_signal("set_player_item", player, decoded["item"]) + else: + emit_signal("remove_player_item", player) + "update_map": + var tile: int = decoded["tile"] + var pos: Array = decoded["pos"] + var neighbors: Array = decoded["neighbors"] + tileid_by_pos[str(Vector2i(pos[0],pos[1]))] = tile + emit_signal("update_map", pos, tile_names[tile], neighbors) + "communicate": + var player = decoded["player"] + var message = decoded.get("message") + if message != null: + var item = message.get("item") + var text = message.get("text") + if item != null: + emit_signal("item_message", player, item) + elif text != null: + emit_signal("text_message", player, text) + else: + push_error("neither text nor item provided") + else: + emit_signal("clear_message", player) + "error": + var message = decoded["message"] + push_warning("server error: %s" % message) + _: + push_error("Unrecognized packet type: %s" % packet_type) + +func send_join(player_name: String, character: int): + send_packet({ + "type": "join", + "name": player_name, + "character": character + }) + +func send_position(pos: Vector2, rotation: float): + send_packet({ + "type": "position", + "pos": [pos.x, pos.y], + "rot": rotation + }) + +func send_interact(pos: Vector2i, edge: bool): + send_packet({ + "type": "interact", + "pos": [pos.x, pos.y], + "edge": edge + }) + +func send_packet(packet): + var json = JSON.stringify(packet) + socket.send_text(json) + +func decode_packet(bytes: PackedByteArray): + var json = JSON.new() + var in_str = bytes.get_string_from_utf8() + var error = json.parse(in_str) + if error == OK: + return json.data + else: + print("Decode of packet failed: %s in %s" % [json.get_error_message(), in_str]) + return null + +func pos_to_vec2(pos: Array) -> Vector2: + return Vector2(pos[0], pos[1]) + +func pos_to_vec2i(pos: Array) -> Vector2i: + return Vector2i(pos[0], pos[1]) + +func get_tile_collision(pos: Vector2i) -> bool: + var t = tileid_by_pos.get(str(pos)) + if t == null: return false + else: return tile_collide[t] + +func get_tile_interactive(pos: Vector2i) -> bool: + var t = tileid_by_pos.get(str(pos)) + if t == null: return false + else: return tile_interact[t] |