diff --git a/godot/scenes/characters/character_wrapper.gd b/godot/scenes/characters/character_wrapper.gd index 6bf28cd..e817dd2 100644 --- a/godot/scenes/characters/character_wrapper.gd +++ b/godot/scenes/characters/character_wrapper.gd @@ -1,28 +1,35 @@ -extends Node3D +extends CharacterBody3D class_name CharacterWrapper @export var die_script: GDScript = null -@export var owner_placeholder: Node3D = null +@export var owner_placeholder: CharacterBody3D = null + +@export var interpolation_speed: float = 10.0 # How quickly the model corrects position +@export var velocity_influence: float = 1.0 # How much velocity is used for smoothing # Called when the node enters the scene tree for the first time. func _ready() -> void: - # Characters should be always controlled by the server and synced accross client - # The owner should be responsible for the syncronization, since this node is - # just a dummy that is following the controller - #set_multiplayer_authority(1) - - - pass # Replace with function body. -func _physics_process(delta: float) -> void: set_multiplayer_authority(multiplayer.get_unique_id()) - if owner_placeholder: - #global_transform.origin = owner_placeholder.global_transform.origin - global_transform.origin = global_transform.origin.lerp(owner_placeholder.global_position, delta * 10) - global_rotation = owner_placeholder.global_rotation + global_position = owner_placeholder.global_position + +func _physics_process(delta: float) -> void: + #if not is_on_floor(): + #velocity += get_gravity() * delta + #global_position = owner_placeholder.global_position + + var server_pos = owner_placeholder.global_transform.origin + var server_velocity = (server_pos - owner_placeholder.global_transform.origin) / delta + + velocity = owner_placeholder.velocity + global_transform.origin = global_transform.origin.lerp(server_pos, interpolation_speed * delta) + global_transform.origin += velocity * velocity_influence * delta + velocity = velocity.lerp(server_velocity, delta * interpolation_speed) + move_and_slide() + # Set the owner placeholder, so the characters can send the requests to a node # it depends on -func set_owner_placeholder(owner: Node3D): - owner_placeholder = owner +func set_owner_placeholder(owner_placeholder: Node3D): + owner_placeholder = owner_placeholder func die(): push_warning("TODO: Implement ragdoll kind of dying and respawn character as an object") diff --git a/godot/scenes/characters/y-bot/character.tscn b/godot/scenes/characters/y-bot/character.tscn index 22b24ca..d8d6753 100644 --- a/godot/scenes/characters/y-bot/character.tscn +++ b/godot/scenes/characters/y-bot/character.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=20 format=4 uid="uid://ddwrs0so7swxn"] +[gd_scene load_steps=21 format=4 uid="uid://ddwrs0so7swxn"] [ext_resource type="Script" path="res://scenes/characters/character_wrapper.gd" id="1_k4p2i"] [ext_resource type="Script" path="res://scenes/characters/hit_detected.gd" id="2_oqdj0"] @@ -2322,7 +2322,11 @@ _data = { "t_pose": SubResource("Animation_jk3i7") } -[node name="Character" type="Node3D"] +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_gp5it"] + +[node name="Character" type="CharacterBody3D"] +collision_layer = 0 +collision_mask = 0 script = ExtResource("1_k4p2i") [node name="Model" type="Node3D" parent="."] @@ -3015,6 +3019,9 @@ libraries = { "": SubResource("AnimationLibrary_1yo1h") } +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("CapsuleShape3D_gp5it") + [connection signal="body_part_hit" from="Model/Body/Skeleton3D/HeadAttachment/Area" to="." method="_on_area_body_part_hit"] [connection signal="body_part_hit" from="Model/Body/Skeleton3D/TorsoAttachment/Area" to="." method="_on_area_body_part_hit"] [connection signal="body_part_hit" from="Model/Body/Skeleton3D/RightHipAttachment/Area" to="." method="_on_area_body_part_hit"] diff --git a/godot/scenes/maps/base/map_controller.gd b/godot/scenes/maps/base/map_controller.gd index 1db0f17..aee71a1 100644 --- a/godot/scenes/maps/base/map_controller.gd +++ b/godot/scenes/maps/base/map_controller.gd @@ -27,6 +27,7 @@ func _ready() -> void: client_node = Node3D.new() client_node.name = "ClientNode" add_child(client_node) + # add objects spawner if not OS.has_feature("dedicated_server"): _request_spawn.rpc_id(1) @@ -65,7 +66,9 @@ func _spawn_player_controller_node(x: float, y: float, z: float): player_node.shared_node.global_position = Vector3(x,y,z) controlled_node.bind_player_node() - +func spawn_player_model(owner_node: CharacterBody3D): + player_spawner.spawn_player_model(owner_node) + func _remove_player(id: int): player_spawner.remove_player(id) diff --git a/godot/scenes/maps/base/player_spawner/player_spawner.gd b/godot/scenes/maps/base/player_spawner/player_spawner.gd index a03c135..9338a4a 100644 --- a/godot/scenes/maps/base/player_spawner/player_spawner.gd +++ b/godot/scenes/maps/base/player_spawner/player_spawner.gd @@ -25,14 +25,16 @@ func spawn_players(spawn_location: SpawnController, id: int) -> Error: _get_root().add_child(char) char.shared_node.global_position = new_position - #var model_scene: PackedScene = ResourceLoader.load("res://scenes/characters/y-bot/character.tscn") - #var model: CharacterWrapper = model_scene.instantiate() - #model.global_position = new_position - #model.set_owner_placeholder(char) - #_get_model_root().add_child(model) return OK return ERR_UNAUTHORIZED +func spawn_player_model(owner_node: CharacterBody3D): + var model_scene: PackedScene = ResourceLoader.load("res://scenes/characters/y-bot/character.tscn") + var model: CharacterWrapper = model_scene.instantiate() + model.global_position = owner_node.global_position + model.owner_placeholder = owner_node + _get_model_root().add_child(model) + func remove_player(id: int) -> Error: if multiplayer.is_server(): var found_childen: Array[Node] =_get_root().get_children() diff --git a/godot/scenes/player/player_node.gd b/godot/scenes/player/player_node.gd index 3964acf..814ace2 100644 --- a/godot/scenes/player/player_node.gd +++ b/godot/scenes/player/player_node.gd @@ -39,9 +39,9 @@ func _ready() -> void: hud_camera = hud.camera gun_mount = hud.gun_mount _load_weapon() - for child in controlled_node.find_child("Model").find_children("*"): - if child is MeshInstance3D: - child.set_layer_mask_value(1, false) + #for child in controlled_node.find_child("Model").find_children("*"): + #if child is MeshInstance3D: + #child.set_layer_mask_value(1, false) # Load the default weapon and set the current attack properties func _load_weapon() -> void: @@ -64,19 +64,17 @@ func initial_position_sync(): func _input(event): if multiplayer.get_unique_id() == get_multiplayer_authority(): if Input.is_action_just_pressed("jump"): jump() - if Input.is_action_just_released("shoot"): shooting = false + if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: look_dir = event.relative * 1 shared_node.rotation.y -= look_dir.x * camera_sens * 1.0 camera_mount.rotation.x = clamp(camera_mount.rotation.x - look_dir.y * camera_sens * 1.0, -1.5, 1.5) controlled_node.set_rotation_x.rpc_id(1, camera_mount.rotation.x) controlled_node.set_rotation_y.rpc_id(1, shared_node.rotation.y) - if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right") or Input.is_action_pressed("move_forward") or Input.is_action_pressed("move_backward"): - moving = true - else: - moving = false + input_direction = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") controlled_node.set_input_direction.rpc_id(1, input_direction) + if Input.is_action_just_pressed("shoot"): shooting = true if Input.is_action_just_released("shoot"): shooting = false diff --git a/godot/scenes/player/server_node.gd b/godot/scenes/player/server_node.gd index 4319afa..c91f9ef 100644 --- a/godot/scenes/player/server_node.gd +++ b/godot/scenes/player/server_node.gd @@ -23,12 +23,7 @@ func _ready() -> void: shared_node.set_collision_mask_value(3, true) map_controller = find_parent("Map") _load_weapon() - var model_scene: PackedScene = ResourceLoader.load("res://scenes/characters/y-bot/character.tscn") - var model: CharacterWrapper = model_scene.instantiate() - model.global_position = shared_node.global_position - model.set_owner_placeholder(shared_node) - shared_node.add_child(model) - + map_controller.spawn_player_model(shared_node) # Load the default weapon and set the current attack properties func _load_weapon() -> void: @@ -55,12 +50,10 @@ func _physics_process(delta: float) -> void: var direction := (shared_node.transform.basis * Vector3(input_direction.x, 0, input_direction.y)).normalized() if shared_node.is_on_floor(): if direction: - $SharedNode/Character/Model/AnimationPlayer.play("riffle_run") #first_view_legs_anim.play("Run Forward") shared_node.velocity.x = direction.x * consts.DEFAULT_CHARACTER_SPEED shared_node.velocity.z = direction.z * consts.DEFAULT_CHARACTER_SPEED else: - $SharedNode/Character/Model/AnimationPlayer.play("riffle_idle") shared_node.velocity.x = move_toward(shared_node.velocity.x, 0, consts.DEFAULT_CHARACTER_SPEED) shared_node.velocity.z = move_toward(shared_node.velocity.z, 0, consts.DEFAULT_CHARACTER_SPEED) shared_node.move_and_slide() diff --git a/godot/scenes/player/server_node.tscn b/godot/scenes/player/server_node.tscn index f13dc43..fe6cff7 100644 --- a/godot/scenes/player/server_node.tscn +++ b/godot/scenes/player/server_node.tscn @@ -1,39 +1,29 @@ -[gd_scene load_steps=6 format=3 uid="uid://clq0b7tbincut"] +[gd_scene load_steps=4 format=3 uid="uid://clq0b7tbincut"] [ext_resource type="Script" path="res://scenes/player/server_node.gd" id="1_bau14"] [ext_resource type="PackedScene" uid="uid://cirun2v34nfpg" path="res://scenes/player/shared_node.tscn" id="1_ybp5y"] -[ext_resource type="PackedScene" uid="uid://ddwrs0so7swxn" path="res://scenes/characters/y-bot/character.tscn" id="3_eykxo"] [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_2dhi2"] -properties/0/path = NodePath("SharedNode:position") +properties/0/path = NodePath("SharedNode:rotation") properties/0/spawn = true properties/0/replication_mode = 1 -properties/1/path = NodePath("SharedNode:rotation") +properties/1/path = NodePath(".:owner_id") properties/1/spawn = true -properties/1/replication_mode = 1 -properties/2/path = NodePath(".:owner_id") +properties/1/replication_mode = 2 +properties/2/path = NodePath(".:input_direction") properties/2/spawn = true -properties/2/replication_mode = 2 -properties/3/path = NodePath(".:input_direction") +properties/2/replication_mode = 1 +properties/3/path = NodePath(".:jumping") properties/3/spawn = true -properties/3/replication_mode = 0 -properties/4/path = NodePath(".:jumping") -properties/4/spawn = true -properties/4/replication_mode = 0 - -[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_8la7e"] -properties/0/path = NodePath("SharedNode:position") -properties/0/spawn = false -properties/0/replication_mode = 0 +properties/3/replication_mode = 1 [node name="ServerNode" type="Node3D"] script = ExtResource("1_bau14") [node name="SharedNode" parent="." instance=ExtResource("1_ybp5y")] -[node name="Character" parent="SharedNode" instance=ExtResource("3_eykxo")] -transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0, 0, 0) -visible = false +[node name="CSGBox3D" type="CSGBox3D" parent="SharedNode"] +transform = Transform3D(0.190118, 0, 0, 0, 0.190118, 0, 0, 0, 0.190118, 0, 1.62415, -2.41805) [node name="MainSynchronizer" type="MultiplayerSynchronizer" parent="."] replication_config = SubResource("SceneReplicationConfig_2dhi2") @@ -43,10 +33,4 @@ visibility_update_mode = 1 wait_time = 0.1 autostart = true -[node name="PositionSync" type="MultiplayerSynchronizer" parent="."] -replication_interval = 0.05 -delta_interval = 0.05 -replication_config = SubResource("SceneReplicationConfig_8la7e") -visibility_update_mode = 1 - [connection signal="timeout" from="ReconciliationTimer" to="." method="_on_reconciliation_timer_timeout"] diff --git a/godot/scenes/tmp_node.gd b/godot/scenes/tmp_node.gd new file mode 100644 index 0000000..ee8ff18 --- /dev/null +++ b/godot/scenes/tmp_node.gd @@ -0,0 +1,15 @@ +extends CharacterBody3D +class_name TmpNode + +@export var owner_placeholder: CharacterBody3D = null + +func _ready() -> void: + set_multiplayer_authority(multiplayer.get_unique_id()) + global_position = owner_placeholder.global_position + +func _physics_process(delta: float) -> void: + # Add the gravity. + if not is_on_floor(): + velocity += get_gravity() * delta + velocity = owner_placeholder.velocity + move_and_slide() diff --git a/godot/scenes/tmp_node.tscn b/godot/scenes/tmp_node.tscn new file mode 100644 index 0000000..a77bce6 --- /dev/null +++ b/godot/scenes/tmp_node.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=3 format=3 uid="uid://kjeyhc8qpykm"] + +[ext_resource type="Script" path="res://scenes/tmp_node.gd" id="1_vutt1"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_crgjo"] +size = Vector3(0.01, 0.01, 0.01) + +[node name="TmpNode" type="CharacterBody3D"] +collision_layer = 0 +collision_mask = 0 +script = ExtResource("1_vutt1") + +[node name="CSGBox3D" type="CSGBox3D" parent="."] +transform = Transform3D(32.0413, 0, 0, 0, 32.0413, 0, 0, 0, 32.0413, 0, 565.322, 0) + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.54251, 0) +shape = SubResource("BoxShape3D_crgjo")