diff --git a/Net/network_manager.gd b/Net/network_manager.gd new file mode 100644 index 0000000..4111e15 --- /dev/null +++ b/Net/network_manager.gd @@ -0,0 +1,345 @@ +extends Node + +## Client-server session manager for VRyHungry (listen-server model). +## +## Registered as the "NetworkManager" autoload. Owns transport (ENet), tracks +## the session, and is the single place that reassigns multiplayer authority +## (only the server does so). The world scene (main.gd) registers its spawners +## here via [method register_world]; higher layers (players, items, stations) +## build on top of this in later phases. + +const DEFAULT_PORT := 24565 +const MAX_CLIENTS := 7 + +## Emitted on every peer (including the server for its own local player) when a +## player peer joins. On the server this fires for each remote peer; the server +## uses it to spawn that peer's player. +signal player_joined(peer_id: int) +signal player_left(peer_id: int) +signal session_started(is_server: bool) +signal session_ended() +signal connection_failed() + +# World hooks, registered by main.gd once the scene tree exists. +var _world: Node = null +var _players_spawner: MultiplayerSpawner = null +var _items_spawner: MultiplayerSpawner = null + +var _log_file: FileAccess + + +func _ready() -> void: + _open_log() + multiplayer.peer_connected.connect(_on_peer_connected) + multiplayer.peer_disconnected.connect(_on_peer_disconnected) + multiplayer.connected_to_server.connect(_on_connected_to_server) + multiplayer.connection_failed.connect(_on_connection_failed) + multiplayer.server_disconnected.connect(_on_server_disconnected) + + +# --- Public API ------------------------------------------------------------ + +## Start hosting. The host is peer 1 and also plays (listen server). +func host(port: int = DEFAULT_PORT) -> Error: + var peer := ENetMultiplayerPeer.new() + var err := peer.create_server(port, MAX_CLIENTS) + if err != OK: + log_line("HOST failed to create_server on port %d: %s" % [port, error_string(err)]) + return err + multiplayer.multiplayer_peer = peer + log_line("HOST started on port %d (peer id %d)" % [port, multiplayer.get_unique_id()]) + session_started.emit(true) + # The host's own local player joins immediately. + _on_player_present(multiplayer.get_unique_id()) + return OK + + +## Join an existing host. +func join(address: String = "127.0.0.1", port: int = DEFAULT_PORT) -> Error: + var peer := ENetMultiplayerPeer.new() + var err := peer.create_client(address, port) + if err != OK: + log_line("JOIN failed to create_client %s:%d: %s" % [address, port, error_string(err)]) + return err + multiplayer.multiplayer_peer = peer + log_line("JOIN connecting to %s:%d ..." % [address, port]) + return OK + + +## Leave the session and tear down transport. +func leave() -> void: + _go_offline() + log_line("Session ended") + session_ended.emit() + + +# Restore Godot's default OfflineMultiplayerPeer (rather than leaving the peer +# null), so is_multiplayer_authority()/get_unique_id() keep working while we are +# back in single-player / menu state. +func _go_offline() -> void: + if multiplayer.multiplayer_peer: + multiplayer.multiplayer_peer.close() + multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new() + + +# --- Item spawning --------------------------------------------------------- + +## Spawn a networked item. Server-only when online (replicates to all peers via +## the ItemsSpawner); works directly when offline. Returns the new node on the +## machine that owns spawning, else null. +func spawn_item(scene_path: String, xform: Transform3D) -> Node: + if is_online() and not is_server(): + return null + var data := {"scene": scene_path, "xform": xform} + if is_online() and _items_spawner: + return _items_spawner.spawn(data) + # Offline: instantiate directly under the world. + var inst := _spawn_item_from_data(data) + if _world and inst: + _world.add_child(inst) + return inst + + +# MultiplayerSpawner custom spawn function: runs on every peer to build the node +# from the replicated payload. +func _spawn_item_from_data(data: Variant) -> Node: + var scene: PackedScene = load(data["scene"]) + if not scene: + push_error("spawn_item: could not load scene %s" % str(data.get("scene"))) + return null + var inst := scene.instantiate() + if inst is Node3D: + inst.transform = data["xform"] + return inst + + +# --- Item grab-authority transfer ----------------------------------------- + +## A client (or host) requests authority over an item it just grabbed. Runs on +## the server. If the item was snapped into a station, the station releases it +## so the grabber cleanly takes ownership. +@rpc("any_peer", "reliable") +func request_item_authority(item_path: NodePath) -> void: + if not is_server(): + return + var sender := multiplayer.get_remote_sender_id() + # Assign authority + held state first (disables the item on the server so its + # snap zone won't re-grab it), then release it from any station. + _set_item_authority.rpc(item_path, sender) + var item := get_node_or_null(item_path) + if item: + _release_from_snap_zones(item) + + +## A player releases an item, forwarding its throw velocity so the server can +## resume simulating it. Runs on the server. If released next to a station, the +## server snaps it in (server-authoritative placement). +@rpc("any_peer", "reliable") +func release_item_authority(item_path: NodePath, lin: Vector3, ang: Vector3) -> void: + if not is_server(): + return + _set_item_authority.rpc(item_path, 1) + var item := get_node_or_null(item_path) + if item is RigidBody3D: + item.freeze = false + item.linear_velocity = lin + item.angular_velocity = ang + _try_snap_into_station(item) + + +# All station snap zones in the world (nodes in the "station" group). +func _station_snap_zones() -> Array: + var zones := [] + for station in get_tree().get_nodes_in_group("station"): + var zone = station.get_node_or_null("XRToolsSnapZone") + if zone: + zones.append(zone) + return zones + + +# If the item is snapped into any station, drop it from that station. +func _release_from_snap_zones(item: Node) -> void: + for zone in _station_snap_zones(): + if zone.picked_up_object == item: + zone.drop_object() + + +# Snap the item into the nearest empty station snap zone within grab range. +func _try_snap_into_station(item: Node) -> void: + if not (item is Node3D): + return + for zone in _station_snap_zones(): + if is_instance_valid(zone.picked_up_object): + continue + if zone.global_position.distance_to(item.global_position) <= zone.grab_distance: + zone.pick_up_object(item) + return + + +# Server broadcasts an authority assignment so every peer agrees on who owns the +# item (set_multiplayer_authority is a local call and must run everywhere). +@rpc("authority", "call_local", "reliable") +func _set_item_authority(item_path: NodePath, peer: int) -> void: + var item := get_node_or_null(item_path) + if not item: + return + item.set_multiplayer_authority(peer) # recursive: item + synchronizer + NetPickable + var np := item.get_node_or_null("NetPickable") + if np: + np.net_held_by = 0 if peer == 1 else peer + np.apply_held_state() + + +func is_server() -> bool: + return is_online() and multiplayer.is_server() + + +## True only when a real ENet session is active. Godot installs a default +## OfflineMultiplayerPeer, so a non-null peer alone does not mean "online". +func is_online() -> bool: + var p := multiplayer.multiplayer_peer + return p != null and not (p is OfflineMultiplayerPeer) + + +## True on the machine that owns authoritative world logic: the server when +## online, or the single player when offline. Station logic and spawning should +## only run where this is true, so state has one source of truth. +func owns_world() -> bool: + return not is_online() or is_server() + + +# --- Station work-progress seam ------------------------------------------- + +## Reusable entry point for a client to contribute work to a station (e.g. a +## future chopping/gesture station). The client detects the gesture locally and +## calls this; the server validates and accumulates. Timer-driven stations like +## the Hob don't need it, but it is the drop-in seam for input-driven ones. +@rpc("any_peer", "reliable") +func submit_work(station_path: NodePath, amount: float) -> void: + if not is_server(): + return + var station := get_node_or_null(station_path) + if station and station.has_method("add_work"): + station.add_work(multiplayer.get_remote_sender_id(), amount) + + +## Called by main.gd once the world scene is ready, passing its spawners. +func register_world(world: Node, players_spawner: MultiplayerSpawner, items_spawner: MultiplayerSpawner) -> void: + _world = world + _players_spawner = players_spawner + _items_spawner = items_spawner + if _items_spawner: + _items_spawner.spawn_function = _spawn_item_from_data + log_line("World registered (players_spawner=%s items_spawner=%s)" % [str(players_spawner != null), str(items_spawner != null)]) + + +## Called by main.gd after it has registered the world and connected its +## player_joined/left listeners. Kicks off any menu- or command-line-driven +## session so that session signals never fire before the world is listening. +func world_ready() -> void: + consume_pending_session() + + +# --- Menu-driven session request ------------------------------------------- + +# Set by the main menu's Host/Join buttons before switching to the multiplayer +# scene; consumed once that scene's world is ready to listen for session +# signals (avoids a race between change_scene_to_file and connection callbacks). +var pending_action := "" +var pending_ip := "" + +func request_host() -> void: + pending_action = "host" + +func request_join(ip: String) -> void: + pending_action = "join" + pending_ip = ip + +func consume_pending_session() -> void: + if pending_action == "host": + pending_action = "" + host() + elif pending_action == "join": + pending_action = "" + join(pending_ip) + else: + _handle_cmdline() + + +# --- Session signal handlers ---------------------------------------------- + +func _on_peer_connected(peer_id: int) -> void: + log_line("peer_connected: %d" % peer_id) + # Only the server reacts by materialising that peer's player. + if is_server(): + _on_player_present(peer_id) + +func _on_peer_disconnected(peer_id: int) -> void: + log_line("peer_disconnected: %d" % peer_id) + if is_server(): + _on_player_absent(peer_id) + +func _on_connected_to_server() -> void: + log_line("connected_to_server (my id=%d)" % multiplayer.get_unique_id()) + session_started.emit(false) + +func _on_connection_failed() -> void: + log_line("connection_failed") + _go_offline() + connection_failed.emit() + +func _on_server_disconnected() -> void: + log_line("server_disconnected") + _go_offline() + session_ended.emit() + + +# Player materialise/dematerialise. Phase 2 wires these to the PlayersSpawner; +# for now they announce presence so the transport layer is independently testable. +func _on_player_present(peer_id: int) -> void: + log_line("player_present: %d" % peer_id) + player_joined.emit(peer_id) + +func _on_player_absent(peer_id: int) -> void: + log_line("player_absent: %d" % peer_id) + player_left.emit(peer_id) + + +# --- Command-line driven test bootstrap ----------------------------------- + +func _handle_cmdline() -> void: + var args := OS.get_cmdline_user_args() + if args.has("--server"): + log_line("cmdline: --server") + host() + elif args.has("--join"): + var idx := args.find("--join") + var addr := "127.0.0.1" + if idx + 1 < args.size(): + addr = args[idx + 1] + log_line("cmdline: --join %s" % addr) + join(addr) + + +# --- Logging --------------------------------------------------------------- + +func _open_log() -> void: + var dir := OS.get_environment("TEMP") + if dir.is_empty(): + dir = OS.get_environment("TMPDIR") + if dir.is_empty(): + dir = "user://" + var path := dir.path_join("vryhungry_net_%d.log" % OS.get_process_id()) + _log_file = FileAccess.open(path, FileAccess.WRITE) + log_line("=== NetworkManager log (pid %d) ===" % OS.get_process_id()) + +func log_line(s: String) -> void: + var id := 0 + var p := multiplayer.multiplayer_peer + if p != null and p.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED: + id = multiplayer.get_unique_id() + var line := "[NET %d] %s" % [id, s] + print(line) + if _log_file: + _log_file.store_line(line) + _log_file.flush() diff --git a/Net/network_manager.gd.uid b/Net/network_manager.gd.uid new file mode 100644 index 0000000..eb73e4b --- /dev/null +++ b/Net/network_manager.gd.uid @@ -0,0 +1 @@ +uid://deefoory0vqmm diff --git a/Scenes/mainMenu.tscn b/Scenes/mainMenu.tscn new file mode 100644 index 0000000..715890a --- /dev/null +++ b/Scenes/mainMenu.tscn @@ -0,0 +1,166 @@ +[gd_scene format=3 uid="uid://c1nv4w33fedj6"] + +[ext_resource type="Script" uid="uid://b4ldkd3ngs0vp" path="res://main.gd" id="1_72gy5"] +[ext_resource type="PackedScene" uid="uid://j5s5wus7tuhb" path="res://XROrigin.tscn" id="2_8wkh3"] +[ext_resource type="Material" uid="uid://cmia50cfqxxo4" path="res://Textures/dev_material_3d.tres" id="3_m56cs"] +[ext_resource type="PackedScene" uid="uid://j7caslh27nor" path="res://Stations/Hob.tscn" id="4_5kvh0"] +[ext_resource type="Sky" uid="uid://c1abtpwhdm2d5" path="res://Textures/sky/NightSkyHDRI009_16K.tres" id="5_l1qm6"] +[ext_resource type="PackedScene" uid="uid://c0lknik4noobs" path="res://Items/BurgerBuns.tscn" id="6_bktvt"] +[ext_resource type="PackedScene" uid="uid://c6rift56ql3f8" path="res://Stations/BurgerBunsDispenser.tscn" id="7_1nkd0"] +[ext_resource type="PackedScene" uid="uid://bp3v1jl8pctro" path="res://Containers/plate.tscn" id="8_l1owj"] +[ext_resource type="PackedScene" uid="uid://dpot5qie20vf6" path="res://Items/burger.tscn" id="9_220hi"] +[ext_resource type="PackedScene" uid="uid://b3m2ag8g5rj4r" path="res://Items/hamburger.tscn" id="10_qacki"] +[ext_resource type="PackedScene" uid="uid://e4i6o5oriecx" path="res://Items/PickupCube.tscn" id="11_npf8s"] +[ext_resource type="PackedScene" uid="uid://dvrk268s7gkxh" path="res://Stations/sink.tscn" id="12_8apyq"] +[ext_resource type="PackedScene" uid="uid://cnjwtnhwh0i8q" path="res://Stations/dirt_station.tscn" id="13_jnwcx"] +[ext_resource type="PackedScene" uid="uid://cfc4ho67u4r5e" path="res://Items/cooked_burger.tscn" id="14_1lg2m"] +[ext_resource type="PackedScene" uid="uid://efaec6ymgabo" path="res://Stations/Counter.tscn" id="15_yy81s"] +[ext_resource type="PackedScene" uid="uid://clujaf3u776a3" path="res://addons/godot-xr-tools/objects/viewport_2d_in_3d.tscn" id="16_vp"] +[ext_resource type="PackedScene" path="res://UI/main_menu_panel.tscn" id="17_panel"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_vlqg6"] +size = Vector3(5, 0.1, 5) + +[sub_resource type="BoxMesh" id="BoxMesh_24d3s"] +material = ExtResource("3_m56cs") +size = Vector3(15, 0.1, 15) + +[sub_resource type="Environment" id="Environment_bvwq1"] +background_mode = 2 +sky = ExtResource("5_l1qm6") +reflected_light_source = 2 +ssr_enabled = true +ssao_enabled = true +ssil_enabled = true +sdfgi_enabled = true + +[node name="Main" type="Node3D" unique_id=1312265607] +script = ExtResource("1_72gy5") + +[node name="XROrigin3D" parent="." unique_id=2055526621 instance=ExtResource("2_8wkh3")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.36171648, 0, 0.81835127) + +[node name="MainMenuPanel3D" parent="." unique_id=1448860532 instance=ExtResource("16_vp")] +transform = Transform3D(5, 0, 0, 0, 5, 0, 0, 0, 5, 0.36171648, 2.543398, -1.9758987) +screen_size = Vector2(0.6, 0.4) +scene = ExtResource("17_panel") +viewport_size = Vector2(600, 400) +transparent = 1 +scene_properties_keys = PackedStringArray("main_menu_panel.gd") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=1376644384] +transform = Transform3D(-0.8660254, -0.43301278, 0.24999999, 0.3022632, -0.05510214, 0.9516306, -0.39829266, 0.8997021, 0.17860365, 0, 0, 0) + +[node name="Floor" type="StaticBody3D" parent="." unique_id=122279514] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0) + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor" unique_id=958841648] +shape = SubResource("BoxShape3D_vlqg6") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Floor/CollisionShape3D" unique_id=1939997056] +mesh = SubResource("BoxMesh_24d3s") + +[node name="Hob" parent="." unique_id=1687971542 instance=ExtResource("4_5kvh0")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.29336345, 0.8981018, -1.484) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1177077250] +environment = SubResource("Environment_bvwq1") + +[node name="BurgerBuns" parent="." unique_id=1088240294 instance=ExtResource("6_bktvt")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.8162017, 1.6081157, -1.4714175) + +[node name="BurgerBunsDispenser" parent="." unique_id=1720683779 instance=ExtResource("7_1nkd0")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.832131, 0.40028095, -1.4813508) + +[node name="Plate" parent="." unique_id=190487773 instance=ExtResource("8_l1owj")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.5717233, 1.5454081, 1.5373346) + +[node name="burger" parent="." unique_id=1417604760 instance=ExtResource("9_220hi")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.6888188, 1.4195822, -1.7110313) + +[node name="burger2" parent="." unique_id=1584460510 instance=ExtResource("9_220hi")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.6931299, 1.5300478, -1.71225) + +[node name="burger3" parent="." unique_id=1884095916 instance=ExtResource("9_220hi")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.69027674, 1.4969791, -1.7210286) + +[node name="burger4" parent="." unique_id=1844818864 instance=ExtResource("9_220hi")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.69134104, 1.4543622, -1.7210286) + +[node name="Hamburger" parent="." unique_id=761091445 instance=ExtResource("10_qacki")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.9352558, 1.623975, 1.2447833) + +[node name="PickableObject" parent="." unique_id=1675596942 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, 0.6225724, 1.4792972, -1.0473135) + +[node name="PickableObject2" parent="." unique_id=713087634 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, 0.6359743, 1.4639391, -1.1673055) + +[node name="PickableObject3" parent="." unique_id=879935619 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, 0.5142721, 1.4792972, -1.0473135) + +[node name="PickableObject4" parent="." unique_id=198541902 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, 0.5276739, 1.4639391, -1.1673055) + +[node name="Hamburger2" parent="." unique_id=1349934579 instance=ExtResource("10_qacki")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.9857153, 1.5329368, 0.9472374) + +[node name="PickableObject5" parent="." unique_id=1021333509 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, 0.73287535, 1.4792972, -1.0473135) + +[node name="PickableObject6" parent="." unique_id=1268843669 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, 0.7462772, 1.4639391, -1.1673055) + +[node name="Sink" parent="." unique_id=2055277359 instance=ExtResource("12_8apyq")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3147688, 0.9045367, -1.4940417) + +[node name="DirtStation" parent="." unique_id=160842153 instance=ExtResource("13_jnwcx")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.0864775, 0.8981018, -1.244947) + +[node name="Plate2" parent="." unique_id=356790445 instance=ExtResource("8_l1owj")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.5730225, 1.499024, 0.59790254) + +[node name="CookedBurger" parent="." unique_id=1127807542 instance=ExtResource("14_1lg2m")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.30671906, 1.4131018, -1.0928738) + +[node name="CookedBurger2" parent="." unique_id=160088590 instance=ExtResource("14_1lg2m")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.30671906, 1.4496142, -1.0928738) + +[node name="CookedBurger3" parent="." unique_id=992183367 instance=ExtResource("14_1lg2m")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.3344773, 1.4398065, -0.7096845) + +[node name="CookedBurger4" parent="." unique_id=1837607086 instance=ExtResource("14_1lg2m")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.30671906, 1.525444, -1.0928738) + +[node name="BurgerBuns2" parent="." unique_id=1210358958 instance=ExtResource("6_bktvt")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.3596323, 1.4110342, -0.22482127) + +[node name="PickableObject7" parent="." unique_id=641653545 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, -1.3556751, 1.4792972, 0.28881657) + +[node name="PickableObject8" parent="." unique_id=1733819363 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, -1.3422732, 1.4639391, 0.16882455) + +[node name="PickableObject9" parent="." unique_id=12419746 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, -1.4639754, 1.4792972, 0.28881657) + +[node name="PickableObject10" parent="." unique_id=313160217 instance=ExtResource("11_npf8s")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, -1.4505737, 1.4639391, 0.16882455) + +[node name="Counter" parent="." unique_id=1487893288 instance=ExtResource("15_yy81s")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.7124918, 0.90304357, -1.4886917) + +[node name="Counter2" parent="." unique_id=368890752 instance=ExtResource("15_yy81s")] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -1.7648025, 0.90304357, -0.4458799) + +[node name="Counter3" parent="." unique_id=1498817646 instance=ExtResource("15_yy81s")] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -1.7648025, 0.90304357, 0.55367994) + +[node name="Counter4" parent="." unique_id=906748771 instance=ExtResource("15_yy81s")] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -1.7648025, 0.90304357, 1.5539298) + +[node name="Hamburger3" parent="." unique_id=369573848 instance=ExtResource("10_qacki")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.7201865, 1.5329367, 0.14773655) + +[node name="Plate3" parent="." unique_id=2004250522 instance=ExtResource("8_l1owj")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.5818124, 1.499024, -0.4634577) diff --git a/Scenes/multiPlayer.tscn b/Scenes/multiPlayer.tscn new file mode 100644 index 0000000..075a06c --- /dev/null +++ b/Scenes/multiPlayer.tscn @@ -0,0 +1,165 @@ +[gd_scene format=3 uid="uid://c30i6h32w8p47"] + +[ext_resource type="Script" uid="uid://d1cefhe3yyyds" path="res://Scenes/multiplayer_world.gd" id="1_kdan8"] +[ext_resource type="PackedScene" uid="uid://j5s5wus7tuhb" path="res://XROrigin.tscn" id="2_g30gi"] +[ext_resource type="Material" uid="uid://cmia50cfqxxo4" path="res://Textures/dev_material_3d.tres" id="3_75ecy"] +[ext_resource type="PackedScene" uid="uid://j7caslh27nor" path="res://Stations/Hob.tscn" id="4_y6cjq"] +[ext_resource type="Sky" uid="uid://c1abtpwhdm2d5" path="res://Textures/sky/NightSkyHDRI009_16K.tres" id="5_c3xgf"] +[ext_resource type="PackedScene" uid="uid://c0lknik4noobs" path="res://Items/BurgerBuns.tscn" id="6_urxur"] +[ext_resource type="PackedScene" uid="uid://c6rift56ql3f8" path="res://Stations/BurgerBunsDispenser.tscn" id="7_3a3tq"] +[ext_resource type="PackedScene" uid="uid://bp3v1jl8pctro" path="res://Containers/plate.tscn" id="8_8xmyt"] +[ext_resource type="PackedScene" uid="uid://dpot5qie20vf6" path="res://Items/burger.tscn" id="9_6lx3u"] +[ext_resource type="PackedScene" uid="uid://b3m2ag8g5rj4r" path="res://Items/hamburger.tscn" id="10_p5bqy"] +[ext_resource type="PackedScene" uid="uid://e4i6o5oriecx" path="res://Items/PickupCube.tscn" id="11_jl027"] +[ext_resource type="PackedScene" uid="uid://dvrk268s7gkxh" path="res://Stations/sink.tscn" id="12_j3sw5"] +[ext_resource type="PackedScene" uid="uid://cnjwtnhwh0i8q" path="res://Stations/dirt_station.tscn" id="13_sbg0f"] +[ext_resource type="PackedScene" uid="uid://cfc4ho67u4r5e" path="res://Items/cooked_burger.tscn" id="14_lt5wx"] +[ext_resource type="PackedScene" uid="uid://efaec6ymgabo" path="res://Stations/Counter.tscn" id="15_7pgth"] +[ext_resource type="PackedScene" uid="uid://caf0xanmxbshy" path="res://Stations/table.tscn" id="16_8yyag"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_vlqg6"] +size = Vector3(5, 0.1, 5) + +[sub_resource type="BoxMesh" id="BoxMesh_24d3s"] +material = ExtResource("3_75ecy") +size = Vector3(15, 0.1, 15) + +[sub_resource type="Environment" id="Environment_bvwq1"] +background_mode = 2 +sky = ExtResource("5_c3xgf") +reflected_light_source = 2 +ssr_enabled = true +ssao_enabled = true +ssil_enabled = true +sdfgi_enabled = true + +[node name="Main" type="Node3D" unique_id=1312265607] +script = ExtResource("1_kdan8") + +[node name="XROrigin3D" parent="." unique_id=2055526621 instance=ExtResource("2_g30gi")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.36171648, 0, 0.81835127) + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=1376644384] +transform = Transform3D(-0.8660254, -0.43301278, 0.24999999, 0.3022632, -0.05510214, 0.9516306, -0.39829266, 0.8997021, 0.17860365, 0, 0, 0) + +[node name="Floor" type="StaticBody3D" parent="." unique_id=122279514] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0) + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor" unique_id=958841648] +shape = SubResource("BoxShape3D_vlqg6") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Floor/CollisionShape3D" unique_id=1939997056] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00018164515, 0.0006352663, -0.002532661) +mesh = SubResource("BoxMesh_24d3s") + +[node name="Hob" parent="." unique_id=1687971542 instance=ExtResource("4_y6cjq")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.29336345, 0.8981018, -1.484) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1177077250] +environment = SubResource("Environment_bvwq1") + +[node name="BurgerBuns" parent="." unique_id=1088240294 instance=ExtResource("6_urxur")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.8162017, 1.6081157, -1.4714175) + +[node name="BurgerBunsDispenser" parent="." unique_id=1720683779 instance=ExtResource("7_3a3tq")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.832131, 0.40028095, -1.4813508) + +[node name="Plate" parent="." unique_id=190487773 instance=ExtResource("8_8xmyt")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.5717233, 1.5454081, 1.5373346) + +[node name="burger" parent="." unique_id=1417604760 instance=ExtResource("9_6lx3u")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.6888188, 1.4195822, -1.7110313) + +[node name="burger2" parent="." unique_id=1584460510 instance=ExtResource("9_6lx3u")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.6931299, 1.5300478, -1.71225) + +[node name="burger3" parent="." unique_id=1884095916 instance=ExtResource("9_6lx3u")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.69027674, 1.4969791, -1.7210286) + +[node name="burger4" parent="." unique_id=1844818864 instance=ExtResource("9_6lx3u")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.69134104, 1.4543622, -1.7210286) + +[node name="Hamburger" parent="." unique_id=761091445 instance=ExtResource("10_p5bqy")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.9352558, 1.623975, 1.2447833) + +[node name="PickableObject" parent="." unique_id=1675596942 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, 0.6225724, 1.4792972, -1.0473135) + +[node name="PickableObject2" parent="." unique_id=713087634 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, 0.6359743, 1.4639391, -1.1673055) + +[node name="PickableObject3" parent="." unique_id=879935619 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, 0.5142721, 1.4792972, -1.0473135) + +[node name="PickableObject4" parent="." unique_id=198541902 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, 0.5276739, 1.4639391, -1.1673055) + +[node name="Hamburger2" parent="." unique_id=1349934579 instance=ExtResource("10_p5bqy")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.9857153, 1.5329368, 0.9472374) + +[node name="PickableObject5" parent="." unique_id=1021333509 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, 0.73287535, 1.4792972, -1.0473135) + +[node name="PickableObject6" parent="." unique_id=1268843669 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, 0.7462772, 1.4639391, -1.1673055) + +[node name="Sink" parent="." unique_id=2055277359 instance=ExtResource("12_j3sw5")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3140475, 0.9061539, -1.4941733) + +[node name="DirtStation" parent="." unique_id=160842153 instance=ExtResource("13_sbg0f")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.0864775, 0.8981018, -1.244947) + +[node name="Plate2" parent="." unique_id=356790445 instance=ExtResource("8_8xmyt")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.5730225, 1.499024, 0.59790254) + +[node name="CookedBurger" parent="." unique_id=1127807542 instance=ExtResource("14_lt5wx")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.30671906, 1.4131018, -1.0928738) + +[node name="CookedBurger2" parent="." unique_id=160088590 instance=ExtResource("14_lt5wx")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.30671906, 1.4496142, -1.0928738) + +[node name="CookedBurger3" parent="." unique_id=992183367 instance=ExtResource("14_lt5wx")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.3344773, 1.4398065, -0.7096845) + +[node name="CookedBurger4" parent="." unique_id=1837607086 instance=ExtResource("14_lt5wx")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.30671906, 1.525444, -1.0928738) + +[node name="BurgerBuns2" parent="." unique_id=1210358958 instance=ExtResource("6_urxur")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.3596323, 1.4110342, -0.22482127) + +[node name="PickableObject7" parent="." unique_id=641653545 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, -1.3556751, 1.4792972, 0.28881657) + +[node name="PickableObject8" parent="." unique_id=1733819363 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, -1.3422732, 1.4639391, 0.16882455) + +[node name="PickableObject9" parent="." unique_id=12419746 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, 0, -2.6077032e-08, 1.4901161e-08, 1, -1.4639754, 1.4792972, 0.28881657) + +[node name="PickableObject10" parent="." unique_id=313160217 instance=ExtResource("11_jl027")] +transform = Transform3D(1, 0, -2.2351742e-08, -2.9802322e-08, 1.0000001, -5.293956e-23, -2.6077032e-08, 1.4901161e-08, 1, -1.4505737, 1.4639391, 0.16882455) + +[node name="Counter" parent="." unique_id=1487893288 instance=ExtResource("15_7pgth")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.7124918, 0.90304357, -1.4886917) + +[node name="Counter2" parent="." unique_id=368890752 instance=ExtResource("15_7pgth")] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -1.7648025, 0.90304357, -0.4458799) + +[node name="Counter3" parent="." unique_id=1498817646 instance=ExtResource("15_7pgth")] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -1.7648025, 0.90304357, 0.55367994) + +[node name="Counter4" parent="." unique_id=906748771 instance=ExtResource("15_7pgth")] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -1.7648025, 0.90304357, 1.5539298) + +[node name="Table" parent="." unique_id=1863572470 instance=ExtResource("16_8yyag")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.633146, 0.9030438, 1.1343781) +initial_thinking_time = 8.0 +initial_primary_time = 40.0 +initial_friend_time = 3.0 +initial_eating_time = 3.0 + +[node name="Hamburger3" parent="." unique_id=369573848 instance=ExtResource("10_p5bqy")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.7201865, 1.5329367, 0.14773655) + +[node name="Plate3" parent="." unique_id=2004250522 instance=ExtResource("8_8xmyt")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.5818124, 1.499024, -0.4634577) diff --git a/Scenes/multiplayer_world.gd b/Scenes/multiplayer_world.gd new file mode 100644 index 0000000..0c056b4 --- /dev/null +++ b/Scenes/multiplayer_world.gd @@ -0,0 +1,29 @@ +extends Node3D + +## World script for the multiplayer scene. Consumes the host/join request set +## by the main menu, and returns to the menu if the session ends. +## +## Connection-level only for now: no PlayersSpawner/ItemsSpawner here since the +## networked Player/NetPickable scenes aren't ported yet (out of scope for this +## change) — peers connect, but avatars/items don't sync. + +var xr_interface: XRInterface + + +func _ready() -> void: + xr_interface = XRServer.find_interface("OpenXR") + if xr_interface and xr_interface.is_initialized(): + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) + get_viewport().use_xr = true + + NetworkManager.session_ended.connect(_on_session_ended) + NetworkManager.connection_failed.connect(_on_connection_failed) + NetworkManager.world_ready() + + +func _on_session_ended() -> void: + get_tree().change_scene_to_file("res://Scenes/mainMenu.tscn") + + +func _on_connection_failed() -> void: + get_tree().change_scene_to_file("res://Scenes/mainMenu.tscn") diff --git a/Scenes/multiplayer_world.gd.uid b/Scenes/multiplayer_world.gd.uid new file mode 100644 index 0000000..95f2c29 --- /dev/null +++ b/Scenes/multiplayer_world.gd.uid @@ -0,0 +1 @@ +uid://d1cefhe3yyyds diff --git a/Textures/dev_material_3d.tres b/Textures/dev_material_3d.tres index 1c71701..85f8d56 100644 --- a/Textures/dev_material_3d.tres +++ b/Textures/dev_material_3d.tres @@ -4,12 +4,13 @@ [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0gbf8"] transparency = 1 -albedo_color = Color(0.62908286, 0.62908286, 0.62908286, 1) +albedo_color = Color(0.11502249, 0.11502249, 0.11502249, 1) albedo_texture = ExtResource("1_3jxsn") uv1_triplanar = true [resource] next_pass = SubResource("StandardMaterial3D_0gbf8") +albedo_color = Color(0, 0, 0, 1) metallic = 1.0 metallic_specular = 0.0 roughness = 0.0 diff --git a/UI/main_menu_panel.gd b/UI/main_menu_panel.gd new file mode 100644 index 0000000..18f6fae --- /dev/null +++ b/UI/main_menu_panel.gd @@ -0,0 +1,105 @@ +extends Control + +## The 2D UI rendered inside the main menu's world-space viewport +## (XRToolsViewport2DIn3D). Lets the player pick John's scene, host a +## multiplayer game, or join one by IP, driving scene switches + NetworkManager +## directly. + +const JON_SCENE := "res://Scenes/JonScene.tscn" +const MULTIPLAYER_SCENE := "res://Scenes/multiPlayer.tscn" + +var _ip := "127.0.0.1" + +@onready var _root_view: Control = %RootView +@onready var _join_view: Control = %JoinView +@onready var _ip_label: Label = %IPLabel +@onready var _status: Label = %Status +@onready var _keypad: GridContainer = %Keypad +@onready var _john_btn: Button = %JohnButton +@onready var _host_btn: Button = %HostButton +@onready var _join_menu_btn: Button = %JoinMenuButton +@onready var _join_btn: Button = %JoinButton +@onready var _back_btn: Button = %BackButton + + +func _ready() -> void: + if _bypass_menu_for_cmdline(): + return + for child in _keypad.get_children(): + if child is Button: + child.pressed.connect(_on_key.bind(child.text)) + _john_btn.pressed.connect(_on_john_pressed) + _host_btn.pressed.connect(_on_host_pressed) + _join_menu_btn.pressed.connect(_show_join_view) + _join_btn.pressed.connect(_on_join_pressed) + _back_btn.pressed.connect(_show_root_view) + _show_root_view() + _refresh_ip() + + +## --server / --join on the command line skip straight to the multiplayer +## scene, same as the previously headless-tested main.tscn flow. +func _bypass_menu_for_cmdline() -> bool: + var args := OS.get_cmdline_user_args() + if args.has("--server"): + NetworkManager.request_host() + get_tree().change_scene_to_file.call_deferred(MULTIPLAYER_SCENE) + return true + if args.has("--join"): + var idx := args.find("--join") + var addr := "127.0.0.1" + if idx + 1 < args.size(): + addr = args[idx + 1] + NetworkManager.request_join(addr) + get_tree().change_scene_to_file.call_deferred(MULTIPLAYER_SCENE) + return true + return false + + +func _show_root_view() -> void: + _root_view.visible = true + _join_view.visible = false + + +func _show_join_view() -> void: + _root_view.visible = false + _join_view.visible = true + + +func _on_key(key: String) -> void: + match key: + "DEL": + _ip = _ip.substr(0, max(0, _ip.length() - 1)) + _: + if _ip.length() < 21: + _ip += key + _refresh_ip() + + +func _refresh_ip() -> void: + _ip_label.text = _ip if not _ip.is_empty() else "_" + + +func _on_john_pressed() -> void: + NetworkManager.leave() + get_tree().change_scene_to_file.call_deferred(JON_SCENE) + + +func _on_host_pressed() -> void: + NetworkManager.request_host() + get_tree().change_scene_to_file.call_deferred(MULTIPLAYER_SCENE) + + +func _on_join_pressed() -> void: + if _ip.is_empty(): + set_status("Enter an IP first") + return + NetworkManager.request_join(_ip) + get_tree().change_scene_to_file.call_deferred(MULTIPLAYER_SCENE) + + +## Called by network_manager (e.g. on connection_failed after a bounce back to +## this menu) to show feedback. +func set_status(text: String) -> void: + if _status: + _status.text = text diff --git a/UI/main_menu_panel.gd.uid b/UI/main_menu_panel.gd.uid new file mode 100644 index 0000000..5b97426 --- /dev/null +++ b/UI/main_menu_panel.gd.uid @@ -0,0 +1 @@ +uid://crs47shds8bm4 diff --git a/UI/main_menu_panel.tscn b/UI/main_menu_panel.tscn new file mode 100644 index 0000000..6b43b39 --- /dev/null +++ b/UI/main_menu_panel.tscn @@ -0,0 +1,203 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://UI/main_menu_panel.gd" id="1_panel"] + +[node name="MainMenuPanel" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource("1_panel") + +[node name="Background" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color(0.09, 0.1, 0.13, 1) + +[node name="Margin" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +theme_override_constants/margin_left = 24 +theme_override_constants/margin_top = 16 +theme_override_constants/margin_right = 24 +theme_override_constants/margin_bottom = 16 + +[node name="Title" type="Label" parent="Margin"] +layout_mode = 2 +size_flags_vertical = 0 +theme_override_font_sizes/font_size = 26 +text = "VRyHungry" +horizontal_alignment = 1 + +[node name="RootView" type="VBoxContainer" parent="Margin"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 14 + +[node name="Spacer" type="Control" parent="Margin/RootView"] +custom_minimum_size = Vector2(0, 36) +layout_mode = 2 + +[node name="JohnButton" type="Button" parent="Margin/RootView"] +unique_name_in_owner = true +layout_mode = 2 +custom_minimum_size = Vector2(0, 64) +theme_override_font_sizes/font_size = 26 +text = "Play John's Scene" + +[node name="HostButton" type="Button" parent="Margin/RootView"] +unique_name_in_owner = true +layout_mode = 2 +custom_minimum_size = Vector2(0, 64) +theme_override_font_sizes/font_size = 26 +text = "Host Multiplayer" + +[node name="JoinMenuButton" type="Button" parent="Margin/RootView"] +unique_name_in_owner = true +layout_mode = 2 +custom_minimum_size = Vector2(0, 64) +theme_override_font_sizes/font_size = 26 +text = "Join Multiplayer" + +[node name="JoinView" type="VBoxContainer" parent="Margin"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="Title" type="Label" parent="Margin/JoinView"] +layout_mode = 2 +theme_override_font_sizes/font_size = 22 +text = "Join Multiplayer" +horizontal_alignment = 1 + +[node name="IPLabel" type="Label" parent="Margin/JoinView"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_font_sizes/font_size = 34 +text = "127.0.0.1" +horizontal_alignment = 1 + +[node name="Status" type="Label" parent="Margin/JoinView"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_colors/font_color = Color(0.8, 0.8, 0.5, 1) +theme_override_font_sizes/font_size = 16 +text = "Enter host IP, then Join" +horizontal_alignment = 1 + +[node name="Keypad" type="GridContainer" parent="Margin/JoinView"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +theme_override_constants/h_separation = 8 +theme_override_constants/v_separation = 8 +columns = 3 + +[node name="B1" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "1" + +[node name="B2" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "2" + +[node name="B3" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "3" + +[node name="B4" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "4" + +[node name="B5" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "5" + +[node name="B6" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "6" + +[node name="B7" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "7" + +[node name="B8" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "8" + +[node name="B9" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "9" + +[node name="BDot" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "." + +[node name="B0" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 26 +text = "0" + +[node name="BDel" type="Button" parent="Margin/JoinView/Keypad"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 22 +text = "DEL" + +[node name="Buttons" type="HBoxContainer" parent="Margin/JoinView"] +layout_mode = 2 +theme_override_constants/separation = 10 + +[node name="JoinButton" type="Button" parent="Margin/JoinView/Buttons"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +custom_minimum_size = Vector2(0, 56) +theme_override_font_sizes/font_size = 24 +text = "JOIN" + +[node name="BackButton" type="Button" parent="Margin/JoinView/Buttons"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +custom_minimum_size = Vector2(0, 56) +theme_override_font_sizes/font_size = 24 +text = "BACK" diff --git a/XROrigin.tscn b/XROrigin.tscn index 3a1ee5a..99968e7 100644 --- a/XROrigin.tscn +++ b/XROrigin.tscn @@ -7,6 +7,7 @@ [ext_resource type="PackedScene" uid="uid://diyu06cw06syv" path="res://addons/godot-xr-tools/player/player_body.tscn" id="4_6xr3x"] [ext_resource type="PackedScene" uid="uid://b6bk2pj8vbj28" path="res://addons/godot-xr-tools/functions/movement_turn.tscn" id="4_rd8py"] [ext_resource type="Script" uid="uid://ck4yn3hxuobj7" path="res://addons/godot-xr-tools/player/player_body.gd" id="5_rd8py"] +[ext_resource type="PackedScene" uid="uid://cqhw276realc" path="res://addons/godot-xr-tools/functions/function_pointer.tscn" id="6_ptr"] [node name="XROrigin3D" type="XROrigin3D" unique_id=2055526621] @@ -25,6 +26,10 @@ strafe = true [node name="FunctionPickup" parent="XRControllerLeftHand" unique_id=2133415351 instance=ExtResource("3_rd8py")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.009340696, -0.0074635968, 0.024033919) +[node name="FunctionPointer" parent="XRControllerLeftHand" instance=ExtResource("6_ptr")] +show_laser = 2 +show_target = true + [node name="XRControllerRightHand" type="XRController3D" parent="." unique_id=202756852] tracker = &"right_hand" @@ -39,6 +44,10 @@ smooth_turn_speed = 3.5 [node name="FunctionPickup" parent="XRControllerRightHand" unique_id=1876210450 instance=ExtResource("3_rd8py")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.0074635968, 0.024033919) +[node name="FunctionPointer" parent="XRControllerRightHand" instance=ExtResource("6_ptr")] +show_laser = 2 +show_target = true + [node name="PlayerBody" type="CharacterBody3D" parent="." unique_id=1444632058 groups=["player_body"] instance=ExtResource("4_6xr3x")] process_priority = -100 process_physics_priority = -100 diff --git a/openxr_action_map.tres b/openxr_action_map.tres index 27d9d65..ad32196 100644 --- a/openxr_action_map.tres +++ b/openxr_action_map.tres @@ -248,154 +248,6 @@ binding_path = "/user/hand/right/output/haptic" interaction_profile_path = "/interaction_profiles/khr/generic_controller" bindings = [SubResource("OpenXRIPBinding_r3qn1"), SubResource("OpenXRIPBinding_n01b8"), SubResource("OpenXRIPBinding_pjtev"), SubResource("OpenXRIPBinding_nqyri"), SubResource("OpenXRIPBinding_86uui"), SubResource("OpenXRIPBinding_nrtxc"), SubResource("OpenXRIPBinding_qovyo"), SubResource("OpenXRIPBinding_d6uso"), SubResource("OpenXRIPBinding_hvi7v"), SubResource("OpenXRIPBinding_7dxun"), SubResource("OpenXRIPBinding_rp8ih"), SubResource("OpenXRIPBinding_0uca0"), SubResource("OpenXRIPBinding_rjtq8"), SubResource("OpenXRIPBinding_lce2q"), SubResource("OpenXRIPBinding_ckeh6"), SubResource("OpenXRIPBinding_538mi"), SubResource("OpenXRIPBinding_548p5"), SubResource("OpenXRIPBinding_6o0wr"), SubResource("OpenXRIPBinding_fsghu"), SubResource("OpenXRIPBinding_88umk"), SubResource("OpenXRIPBinding_4uneg"), SubResource("OpenXRIPBinding_67o31"), SubResource("OpenXRIPBinding_lf1a1"), SubResource("OpenXRIPBinding_x1adc"), SubResource("OpenXRIPBinding_j1vtv"), SubResource("OpenXRIPBinding_tud50")] -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_xri1r"] -action = SubResource("OpenXRAction_oi0ij") -binding_path = "/user/hand/left/input/aim/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_etqcv"] -action = SubResource("OpenXRAction_oi0ij") -binding_path = "/user/hand/right/input/aim/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_og5pg"] -action = SubResource("OpenXRAction_m08eo") -binding_path = "/user/hand/left/input/aim/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_nwe40"] -action = SubResource("OpenXRAction_m08eo") -binding_path = "/user/hand/right/input/aim/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ts2ff"] -action = SubResource("OpenXRAction_c4j1d") -binding_path = "/user/hand/left/input/grip/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yhsv0"] -action = SubResource("OpenXRAction_c4j1d") -binding_path = "/user/hand/right/input/grip/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sf2dt"] -action = SubResource("OpenXRAction_sopde") -binding_path = "/user/hand/left/input/grip_surface/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_67dwi"] -action = SubResource("OpenXRAction_sopde") -binding_path = "/user/hand/right/input/grip_surface/pose" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_hswdx"] -action = SubResource("OpenXRAction_iphn4") -binding_path = "/user/hand/left/input/menu/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7gr0f"] -action = SubResource("OpenXRAction_iphn4") -binding_path = "/user/hand/right/input/system/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_uvspk"] -action = SubResource("OpenXRAction_wdehm") -binding_path = "/user/hand/left/input/x/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ica2g"] -action = SubResource("OpenXRAction_wdehm") -binding_path = "/user/hand/right/input/a/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_5fecu"] -action = SubResource("OpenXRAction_clfly") -binding_path = "/user/hand/left/input/x/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_0nfxl"] -action = SubResource("OpenXRAction_clfly") -binding_path = "/user/hand/right/input/a/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_sbe0d"] -action = SubResource("OpenXRAction_e1frq") -binding_path = "/user/hand/left/input/y/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_rf1ko"] -action = SubResource("OpenXRAction_e1frq") -binding_path = "/user/hand/right/input/b/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jx7ge"] -action = SubResource("OpenXRAction_l7aq8") -binding_path = "/user/hand/left/input/y/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_d2w1t"] -action = SubResource("OpenXRAction_l7aq8") -binding_path = "/user/hand/right/input/b/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_v2kct"] -action = SubResource("OpenXRAction_6ivru") -binding_path = "/user/hand/left/input/trigger/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_37uq4"] -action = SubResource("OpenXRAction_6ivru") -binding_path = "/user/hand/right/input/trigger/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_kooyb"] -action = SubResource("OpenXRAction_vfhwq") -binding_path = "/user/hand/left/input/trigger/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_51qre"] -action = SubResource("OpenXRAction_vfhwq") -binding_path = "/user/hand/right/input/trigger/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_fncxp"] -action = SubResource("OpenXRAction_5w03k") -binding_path = "/user/hand/left/input/trigger/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_qi50k"] -action = SubResource("OpenXRAction_5w03k") -binding_path = "/user/hand/right/input/trigger/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_h5icu"] -action = SubResource("OpenXRAction_typ1r") -binding_path = "/user/hand/left/input/squeeze/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_b1sv6"] -action = SubResource("OpenXRAction_typ1r") -binding_path = "/user/hand/right/input/squeeze/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yu2t6"] -action = SubResource("OpenXRAction_clvbf") -binding_path = "/user/hand/left/input/squeeze/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_labib"] -action = SubResource("OpenXRAction_clvbf") -binding_path = "/user/hand/right/input/squeeze/value" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_altuc"] -action = SubResource("OpenXRAction_3k6la") -binding_path = "/user/hand/left/input/thumbstick" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_7p0fp"] -action = SubResource("OpenXRAction_3k6la") -binding_path = "/user/hand/right/input/thumbstick" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_yjnix"] -action = SubResource("OpenXRAction_i8esw") -binding_path = "/user/hand/left/input/thumbstick/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_pgh0x"] -action = SubResource("OpenXRAction_i8esw") -binding_path = "/user/hand/right/input/thumbstick/click" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_lplyu"] -action = SubResource("OpenXRAction_um1hv") -binding_path = "/user/hand/left/input/thumbstick/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_ifnya"] -action = SubResource("OpenXRAction_um1hv") -binding_path = "/user/hand/right/input/thumbstick/touch" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_jl4vo"] -action = SubResource("OpenXRAction_sow2k") -binding_path = "/user/hand/left/output/haptic" - -[sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_1n6j6"] -action = SubResource("OpenXRAction_sow2k") -binding_path = "/user/hand/right/output/haptic" - -[sub_resource type="OpenXRInteractionProfile" id="OpenXRInteractionProfile_o1nfs"] -interaction_profile_path = "/interaction_profiles/oculus/touch_controller" -bindings = [SubResource("OpenXRIPBinding_xri1r"), SubResource("OpenXRIPBinding_etqcv"), SubResource("OpenXRIPBinding_og5pg"), SubResource("OpenXRIPBinding_nwe40"), SubResource("OpenXRIPBinding_ts2ff"), SubResource("OpenXRIPBinding_yhsv0"), SubResource("OpenXRIPBinding_sf2dt"), SubResource("OpenXRIPBinding_67dwi"), SubResource("OpenXRIPBinding_hswdx"), SubResource("OpenXRIPBinding_7gr0f"), SubResource("OpenXRIPBinding_uvspk"), SubResource("OpenXRIPBinding_ica2g"), SubResource("OpenXRIPBinding_5fecu"), SubResource("OpenXRIPBinding_0nfxl"), SubResource("OpenXRIPBinding_sbe0d"), SubResource("OpenXRIPBinding_rf1ko"), SubResource("OpenXRIPBinding_jx7ge"), SubResource("OpenXRIPBinding_d2w1t"), SubResource("OpenXRIPBinding_v2kct"), SubResource("OpenXRIPBinding_37uq4"), SubResource("OpenXRIPBinding_kooyb"), SubResource("OpenXRIPBinding_51qre"), SubResource("OpenXRIPBinding_fncxp"), SubResource("OpenXRIPBinding_qi50k"), SubResource("OpenXRIPBinding_h5icu"), SubResource("OpenXRIPBinding_b1sv6"), SubResource("OpenXRIPBinding_yu2t6"), SubResource("OpenXRIPBinding_labib"), SubResource("OpenXRIPBinding_altuc"), SubResource("OpenXRIPBinding_7p0fp"), SubResource("OpenXRIPBinding_yjnix"), SubResource("OpenXRIPBinding_pgh0x"), SubResource("OpenXRIPBinding_lplyu"), SubResource("OpenXRIPBinding_ifnya"), SubResource("OpenXRIPBinding_jl4vo"), SubResource("OpenXRIPBinding_1n6j6")] - [sub_resource type="OpenXRIPBinding" id="OpenXRIPBinding_unnrh"] action = SubResource("OpenXRAction_oi0ij") binding_path = "/user/hand/left/input/aim/pose" @@ -618,4 +470,4 @@ bindings = [SubResource("OpenXRIPBinding_jyu76"), SubResource("OpenXRIPBinding_a [resource] action_sets = [SubResource("OpenXRActionSet_ngwcy")] -interaction_profiles = [SubResource("OpenXRInteractionProfile_akdt0"), SubResource("OpenXRInteractionProfile_o1nfs"), SubResource("OpenXRInteractionProfile_d3nfp"), SubResource("OpenXRInteractionProfile_m1cgb")] +interaction_profiles = [SubResource("OpenXRInteractionProfile_akdt0"), SubResource("OpenXRInteractionProfile_d3nfp"), SubResource("OpenXRInteractionProfile_m1cgb")] diff --git a/project.godot b/project.godot index 7c782e2..eec2178 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="GodotVR2" -run/main_scene="uid://clw8ai6kngqxb" +run/main_scene="uid://c1nv4w33fedj6" config/features=PackedStringArray("4.7", "GL Compatibility") config/icon="res://icon.svg" @@ -19,9 +19,12 @@ config/icon="res://icon.svg" XRToolsUserSettings="*uid://bqgb8i74tm0t" XRToolsRumbleManager="*uid://by853dk86g1qw" +NetworkManager="*res://Net/network_manager.gd" [display] +window/size/viewport_width=1920 +window/size/viewport_height=1080 window/stretch/mode="canvas_items" window/stretch/aspect="expand"