# 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 . # 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]