diff options
author | nokoe <nokoe@mailbox.org> | 2024-06-25 22:31:17 +0200 |
---|---|---|
committer | nokoe <nokoe@mailbox.org> | 2024-06-25 23:39:19 +0200 |
commit | 8bb065604fbd12b14a7605cfa265ebf38890f628 (patch) | |
tree | 811866aec6093924694605155d9962261c57cb17 /client | |
parent | ab6279e726ac7e10a4c5211a3d3827471fd35ccf (diff) | |
download | hurrycurry-8bb065604fbd12b14a7605cfa265ebf38890f628.tar hurrycurry-8bb065604fbd12b14a7605cfa265ebf38890f628.tar.bz2 hurrycurry-8bb065604fbd12b14a7605cfa265ebf38890f628.tar.zst |
multiplayer refactor
Diffstat (limited to 'client')
-rw-r--r-- | client/game.gd | 116 | ||||
-rw-r--r-- | client/game.tscn | 8 | ||||
-rw-r--r-- | client/map/map.gd | 37 | ||||
-rw-r--r-- | client/map/map.tscn | 44 | ||||
-rw-r--r-- | client/menu/menu_background.gd | 17 | ||||
-rw-r--r-- | client/menu/menu_background.tscn | 5 | ||||
-rw-r--r-- | client/multiplayer.gd | 62 | ||||
-rw-r--r-- | client/player/character/character.gd | 2 | ||||
-rw-r--r-- | client/player/controllable_player.gd | 9 |
9 files changed, 179 insertions, 121 deletions
diff --git a/client/game.gd b/client/game.gd index f3c2f81c..4b90f00c 100644 --- a/client/game.gd +++ b/client/game.gd @@ -18,25 +18,51 @@ class_name Game extends Node3D @onready var camera: FollowCamera = $FollowCamera -@onready var map: Map = $Map @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.connect("connection_closed", func(reason: String): + 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 mp.player_id == -1: + + if player_id == -1: push_error("multiplayer has not been initialized") - mp.connect("add_player", func(player: int, player_name: String, pos: Vector2, character: int): + mp.add_player.connect(func(player: int, player_name: String, pos: Vector2, character: int): var player_instance: Player - if player == mp.player_id: + if player == player_id: player_instance = ControllablePlayer.new(player, player_name, pos, character, self) camera.target = player_instance else: @@ -45,15 +71,19 @@ func _ready(): add_child(player_instance) ) - mp.connect("update_map", map.update) + mp.set_tile.connect(set_tile) + + mp.remove_tile.connect(remove_tile_if_exists) - mp.connect("position", func(player: int, pos: Vector2, rot: float): + mp.position.connect(func(player: int, pos: Vector2, rot: float): var player_instance: Player = players[player] player_instance.update_position(pos, rot) ) - mp.connect("remove_player", func(id: int): + 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() @@ -61,56 +91,86 @@ func _ready(): player.queue_free() ) - mp.connect("set_tile_item", func(tile: Vector2i, item: int): - var t: Tile = map.tile_by_pos[str(tile)] - var i = ItemFactory.produce(mp.item_names[item], t.item_base) + 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 = mp.item_names[item] + i.name = item_names[item] t.set_item(i) ) - mp.connect("remove_tile_item", func(tile: Vector2i): - var t: Tile = map.tile_by_pos[str(tile)] + mp.remove_tile_item.connect(func(tile: Vector2i): + var t: Tile = tile_by_pos[str(tile)][1] t.take_item().queue_free() ) - mp.connect("set_player_item", func(player: int, item: int): + mp.set_player_item.connect(func(player: int, item: int): var p: Player = players[player] - var i = ItemFactory.produce(mp.item_names[item], p.hand_base) + var i = ItemFactory.produce(item_names[item], p.hand_base) add_child(i) - i.name = mp.item_names[item] + i.name = item_names[item] p.set_item(i) ) - mp.connect("remove_player_item", func(player: int): + mp.remove_player_item.connect(func(player: int): var p: Player = players[player] p.remove_item().queue_free() ) - mp.connect("take_item", func(tile: Vector2i, player: int): - var t: Tile = map.tile_by_pos[str(tile)] + 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.connect("put_item", func(tile: Vector2i, player: int): - var t: Tile = map.tile_by_pos[str(tile)] + 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.connect("set_progress", func(tile: Vector2i, progress: float, warn: bool): - var t: Tile = map.tile_by_pos[str(tile)] + 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.connect("set_finished", func(tile: Vector2i, warn: bool): - var t: Tile = map.tile_by_pos[str(tile)] + mp.set_finished.connect(func(tile: Vector2i, warn: bool): + var t: Tile = tile_by_pos[str(tile)][1] t.finish(warn) ) - mp.send_join(Global.username, Global.character) - func _process(delta): marker.position = lerp(marker.position, marker_target, delta * 40.0) + +func get_tile_collision(pos: Vector2i) -> bool: + var t: Array = tile_by_pos.get(str(pos)) + if t == null: return false + else: return tile_collide[t[0]] + +func get_tile_interactive(pos: Vector2i) -> bool: + var t: Array = 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() diff --git a/client/game.tscn b/client/game.tscn index 32479cf5..cfbde85b 100644 --- a/client/game.tscn +++ b/client/game.tscn @@ -1,6 +1,5 @@ -[gd_scene load_steps=10 format=3 uid="uid://c6krh36hoqfg8"] +[gd_scene load_steps=9 format=3 uid="uid://c6krh36hoqfg8"] -[ext_resource type="PackedScene" uid="uid://cs8gxa22c6joh" path="res://map/map.tscn" id="1_ex12v"] [ext_resource type="Script" path="res://game.gd" id="1_sftfn"] [ext_resource type="PackedScene" uid="uid://b31mlnao6ybt8" path="res://player/follow_camera.tscn" id="2_s8y6o"] [ext_resource type="PackedScene" uid="uid://c0euiv7duqfp4" path="res://player/marker.tscn" id="4_igl0o"] @@ -28,10 +27,9 @@ script = ExtResource("1_sftfn") [node name="Multiplayer" type="Node" parent="."] script = ExtResource("6_fbxu8") -[node name="Map" parent="." instance=ExtResource("1_ex12v")] - -[node name="FollowCamera" parent="." instance=ExtResource("2_s8y6o")] +[node name="FollowCamera" parent="." node_paths=PackedStringArray("target") instance=ExtResource("2_s8y6o")] transform = Transform3D(0.728777, 0.294253, -0.618303, 0, 0.902961, 0.429723, 0.684751, -0.313173, 0.658057, -2.36537, 1.99403, 3.29507) +target = NodePath("..") [node name="WorldEnvironment" type="WorldEnvironment" parent="."] environment = SubResource("Environment_m4dli") diff --git a/client/map/map.gd b/client/map/map.gd deleted file mode 100644 index d43d7b45..00000000 --- a/client/map/map.gd +++ /dev/null @@ -1,37 +0,0 @@ -# Undercooked - a game about cooking -# Copyright 2024 nokoe -# Copyright 2024 tpart -# 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 <https://www.gnu.org/licenses/>. -# -class_name Map -extends Node3D - -var tile_by_pos: Dictionary = {} - -func update(pos, tile_name, neighbors): - var node_name = str(pos) - - if has_node(node_name): - queue_free_rename(get_node(node_name)) - - var instance: Tile = TileFactory.produce(tile_name, node_name, neighbors) - - instance.position = Vector3(pos[0], 0, pos[1]) - tile_by_pos[str(Vector2i(pos[0], pos[1]))] = instance - add_child(instance) - -func queue_free_rename(node: Node) -> void: - node.name += "_queued_free" - node.queue_free() diff --git a/client/map/map.tscn b/client/map/map.tscn index 66e2c63a..612729f4 100644 --- a/client/map/map.tscn +++ b/client/map/map.tscn @@ -1,6 +1,44 @@ -[gd_scene load_steps=2 format=3 uid="uid://cs8gxa22c6joh"] +[gd_scene load_steps=2 format=3 uid="uid://duqkg22yre6ry"] -[ext_resource type="Script" path="res://map/map.gd" id="1_stp8c"] +[sub_resource type="GDScript" id="GDScript_qftmc"] +script/source = "# Undercooked - a game about cooking +# Copyright 2024 nokoe +# Copyright 2024 tpart +# 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 <https://www.gnu.org/licenses/>. +# +class_name Map +extends Node3D + +var tile_by_pos: Dictionary = {} + +func update(pos, tile_name, neighbors): + var node_name = str(pos) + + if has_node(node_name): + queue_free_rename(get_node(node_name)) + + var instance: Tile = TileFactory.produce(tile_name, node_name, neighbors) + + instance.position = Vector3(pos[0], 0, pos[1]) + tile_by_pos[str(Vector2i(pos[0], pos[1]))] = instance + add_child(instance) + +func queue_free_rename(node: Node) -> void: + node.name += \"_queued_free\" + node.queue_free() +" [node name="Map" type="Node3D"] -script = ExtResource("1_stp8c") +script = SubResource("GDScript_qftmc") diff --git a/client/menu/menu_background.gd b/client/menu/menu_background.gd index 0e8e87e1..62c38baa 100644 --- a/client/menu/menu_background.gd +++ b/client/menu/menu_background.gd @@ -1,23 +1,21 @@ # Undercooked - a game about cooking # 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 Node3D -@onready var map = $Map - const NULLS = [null,null,null,null] const BUCKETS = [[], ["floor","floor","floor","floor","tomato-crate", "raw-steak-crate"], ["table", "chair", "counter"], ["sink", "stove"]] @@ -28,5 +26,8 @@ func _ready(): var k = randf() * w var bucket = BUCKETS[int(floor(k * BUCKETS.size())) % BUCKETS.size()] if bucket.size() == 0: continue - var tile = bucket[randi() % bucket.size()] - map.update([x,y], tile, NULLS) + var tile_name = bucket[randi() % bucket.size()] + var tile = TileFactory.produce(tile_name, tile_name, NULLS) + + add_child(tile) + tile.position = Vector3(x, 0, y) diff --git a/client/menu/menu_background.tscn b/client/menu/menu_background.tscn index 88ccf49d..5c29e4ac 100644 --- a/client/menu/menu_background.tscn +++ b/client/menu/menu_background.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=11 format=3 uid="uid://l4vm07dtda4j"] +[gd_scene load_steps=10 format=3 uid="uid://l4vm07dtda4j"] [ext_resource type="Script" path="res://menu/menu_background.gd" id="1_ijsg0"] -[ext_resource type="PackedScene" uid="uid://cs8gxa22c6joh" path="res://map/map.tscn" id="2_eg8f5"] [ext_resource type="Shader" path="res://menu/menu_background.gdshader" id="3_5mp8y"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_uw50b"] @@ -42,8 +41,6 @@ shader_parameter/noise = SubResource("NoiseTexture2D_s4fnp") [node name="MenuBackground" type="Node3D"] script = ExtResource("1_ijsg0") -[node name="Map" parent="." instance=ExtResource("2_eg8f5")] - [node name="Camera" type="Camera3D" parent="."] transform = Transform3D(0.614606, 0.499662, -0.610408, -0.00282255, 0.775198, 0.631712, 0.78883, -0.386531, 0.477852, -9.13611, 4.90356, 1.22532) projection = 1 diff --git a/client/multiplayer.gd b/client/multiplayer.gd index b9242a41..db891562 100644 --- a/client/multiplayer.gd +++ b/client/multiplayer.gd @@ -19,7 +19,14 @@ class_name Multiplayer extends Node signal init(player_id: int) -signal update_map(tile: int, pos: Array, neighbors: Array) +signal data( + item_names: Array, + tile_names: Array, + tile_collide: Array, + tile_interact: Array +) +signal set_tile(tile: Vector2i, kind: int, neighbors: Array) +signal remove_tile(tile: Vector2i) signal clear_message(player: int) signal text_message(player: int, text: String) signal item_message(player: int, item: int) @@ -40,15 +47,6 @@ signal connection_closed(reason: String) 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 _ready(): print("Multiplayer connect"); socket.connect_to_url(Global.server_url) @@ -82,14 +80,19 @@ func handle_packet(bytes: PackedByteArray): 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 + var player_id = decoded["id"] emit_signal("init", player_id) + "data": + var item_names = decoded["data"]["item_names"] + var tile_names = decoded["data"]["tile_names"] + var tile_collide = decoded["data"]["tile_collide"] + var tile_interact = decoded["data"]["tile_interact"] + emit_signal("data", + item_names, + tile_names, + tile_collide, + tile_interact + ) "add_player": var id = decoded["id"] var player_name = decoded["name"] @@ -135,11 +138,18 @@ func handle_packet(bytes: PackedByteArray): else: emit_signal("remove_player_item", player) "update_map": - var tile: int = decoded["tile"] - var pos: Array = decoded["pos"] + var tile: Vector2i = pos_to_vec2i(decoded["tile"]) + var kind = decoded.get("kind") var neighbors: Array = decoded["neighbors"] - tileid_by_pos[str(Vector2i(pos[0],pos[1]))] = tile - emit_signal("update_map", pos, tile_names[tile], neighbors.map(func (x): return tile_names[x] if x != null else null)) + if kind != null: + emit_signal( + "set_tile", + tile, + kind, + neighbors, + ) + else: + emit_signal("remove_tile", tile) "communicate": var player = decoded["player"] var message = decoded.get("message") @@ -200,13 +210,3 @@ func pos_to_vec2(pos: Array) -> Vector2: 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] diff --git a/client/player/character/character.gd b/client/player/character/character.gd index dd3e6554..c6ca9b50 100644 --- a/client/player/character/character.gd +++ b/client/player/character/character.gd @@ -71,5 +71,5 @@ func play_animation(name_: String): current_animation = name_ hand_animations.play(name_) -func _on_hand_animations_animation_finished(name_): +func _on_hand_animations_animation_finished(_name): hand_animations.play(current_animation) diff --git a/client/player/controllable_player.gd b/client/player/controllable_player.gd index 3012f557..c4691b67 100644 --- a/client/player/controllable_player.gd +++ b/client/player/controllable_player.gd @@ -66,7 +66,7 @@ func collide(dt: float): for xo in range(-1,2): for yo in range(-1,2): var tile = Vector2i(xo, yo) + Vector2i(self.position_); - if !game.mp.get_tile_collision(tile): continue + if !game.get_tile_collision(tile): continue tile = Vector2(tile) var d = aabb_point_distance(tile, tile + Vector2.ONE, self.position_); if d > PLAYER_SIZE: continue @@ -97,9 +97,10 @@ func update_position(new_position: Vector2, _new_rotation: float): func interact(): var tile_idx = str(target) - var t: Tile = game.map.tile_by_pos.get(tile_idx) - if t != null: - game.marker.set_interactive(game.mp.get_tile_interactive(target)) + var data = game.tile_by_pos.get(tile_idx) + if data != null: + var t: Tile = data[1] + game.marker.set_interactive(game.get_tile_interactive(target)) game.marker.visible = true game.marker_target = t.item_base.global_position if Input.is_action_just_pressed("interact"): |