# Undercooked - a game about cooking # Copyright 2024 nokoe # Copyright 2024 metamuffin # # 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 . # class_name Game extends Node3D @onready var camera: FollowCamera = $FollowCamera @onready var mp: Multiplayer = $Multiplayer @onready var marker: Marker = $Marker var marker_target = Vector3(0,0,0) var player_id: int = -1 var item_names: Array = [] var tile_names: Array = [] var tile_collide: Array = [] var tile_interact: Array = [] var item_idx_from_name: Dictionary = {} var tile_by_pos: Dictionary = {} var players := {} func _ready(): mp.connection_closed.connect(func(reason: String): Global.error_message = reason; $SceneTransition.instant_to("res://menu/error_menu.tscn") ) mp.init.connect(func(player_id_: int): player_id = player_id_) mp.data.connect(func( item_names_: Array, tile_names_: Array, tile_collide_: Array, tile_interact_: Array ): item_names = item_names_ tile_names = tile_names_ tile_collide = tile_collide_ tile_interact = tile_interact_ item_idx_from_name.clear() for i in range(item_names.size()): item_idx_from_name[item_names[i]] = i ) await mp.init if player_id == -1: push_error("multiplayer has not been initialized") mp.add_player.connect(func(player: int, player_name: String, pos: Vector2, character: int): var player_instance: Player if player == player_id: player_instance = ControllablePlayer.new(player, player_name, pos, character, self) camera.target = player_instance else: player_instance = Player.new(player, player_name, pos, character, self) players[player] = player_instance add_child(player_instance) ) mp.set_tile.connect(set_tile) mp.remove_tile.connect(remove_tile_if_exists) mp.position.connect(func(player: int, pos: Vector2, rot: float): var player_instance: Player = players[player] player_instance.update_position(pos, rot) ) mp.remove_player.connect(func(id: int): var player: Player = players.get(id) if id == player_id: camera.target = self if player != null: if player.hand != null: player.hand.queue_free() players.erase(id) player.queue_free() ) mp.set_tile_item.connect(func(tile: Vector2i, item: int): var t: Tile = tile_by_pos[str(tile)][1] var i = ItemFactory.produce(item_names[item], t.item_base) add_child(i) i.name = item_names[item] t.set_item(i) ) mp.remove_tile_item.connect(func(tile: Vector2i): var t: Tile = tile_by_pos[str(tile)][1] t.take_item().queue_free() ) mp.set_player_item.connect(func(player: int, item: int): var p: Player = players[player] var i = ItemFactory.produce(item_names[item], p.hand_base) add_child(i) i.name = item_names[item] p.set_item(i) ) mp.remove_player_item.connect(func(player: int): var p: Player = players[player] p.remove_item().queue_free() ) mp.take_item.connect(func(tile: Vector2i, player: int): var t: Tile = tile_by_pos[str(tile)][1] var p: Player = players[player] p.take_item(t) ) mp.put_item.connect(func(tile: Vector2i, player: int): var t: Tile = tile_by_pos[str(tile)][1] var p: Player = players[player] p.put_item(t) ) mp.set_progress.connect(func(tile: Vector2i, progress: float, warn: bool): var t: Tile = tile_by_pos[str(tile)][1] t.progress(progress, warn) ) mp.set_finished.connect(func(tile: Vector2i, warn: bool): var t: Tile = tile_by_pos[str(tile)][1] t.finish(warn) ) mp.text_message.connect(func(player: int, text: String): var p: Player = players[player] p.bubble.set_text(text) ) mp.clear_message.connect(func(player: int): var p: Player = players[player] p.bubble.remove_text() ) mp.item_message.connect(func(player: int, item: int): var p: Player = players[player] p.bubble.set_text(item_names[item]) ) mp.send_join(Global.settings["username"], Global.settings["character"]) func _process(delta): marker.position = lerp(marker.position, marker_target, delta * 40.0) func get_tile_collision(pos: Vector2i) -> bool: var t = tile_by_pos.get(str(pos)) if t == null: return true else: return tile_collide[t[0]] func get_tile_interactive(pos: Vector2i) -> bool: var t = tile_by_pos.get(str(pos)) if t == null: return false else: return tile_interact[t[0]] func set_tile(tile: Vector2i, kind: int, neighbors: Array): remove_tile_if_exists(tile) var node_name = str(tile) var tile_name: String = tile_names[kind] neighbors = neighbors.map(func (x): return tile_names[x] if x != null else null) var instance: Tile = TileFactory.produce(tile_name, node_name, neighbors) instance.position = Vector3(tile[0], 0, tile[1]) tile_by_pos[node_name] = [kind, instance] add_child(instance) func remove_tile_if_exists(pos: Vector2i): var node_name = str(pos) var current = tile_by_pos.get(node_name) if current != null: var tile: Tile = current[1] if tile.item != null: tile.item.queue_free() tile_by_pos.erase(node_name) tile.name += "_queued_free" tile.queue_free()