WIP: Add rust logic for the plater physics
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

This commit is contained in:
Nikolai Rodionov 2025-01-31 19:51:01 +01:00
parent f6141f0462
commit 221734d8c7
Signed by: allanger
GPG Key ID: 09F8B434D0FDD99B
15 changed files with 459 additions and 15 deletions

0
.gdextension Normal file
View File

View File

@ -1,2 +1,3 @@
Containerfile
helm
rust/src

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
# Godot 4+ specific ignores
.godot/
rust/target

View File

@ -1,3 +1,10 @@
FROM rust:1.84.1 AS lib_builder
RUN apt-get update -y && apt-get install -y gcc musl-dev build-essential pkg-config cmake
RUN rustup toolchain install stable
WORKDIR /src
COPY rust/ .
RUN cargo build
FROM ghcr.io/allanger/dumb-downloader as dudo
RUN apt-get update -y && apt-get install unzip -y
ENV RUST_LOG=info
@ -18,6 +25,7 @@ FROM ubuntu as builder
RUN apt-get update -y && apt-get install fontconfig -y
WORKDIR /src
COPY --from=dudo /out/godot /usr/bin/godot
COPY --from=lib_builder /src/target/debug/libopen_strike_2.so /src/rust/target/debug/libopen_strike_2.so
RUN mkdir -p /root/.local/share/godot/export_templates/4.3.stable/
COPY --from=dudo /out/templates /root/.local/share/godot/export_templates/4.3.stable
COPY . .

265
rust/Cargo.lock generated Normal file
View File

@ -0,0 +1,265 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "gdextension-api"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8707eca996b28193b772a4a9a28a97364bb93c97e3c313542e812f2963fb93"
[[package]]
name = "gensym"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "913dce4c5f06c2ea40fc178c06f777ac89fc6b1383e90c254fafb1abe4ba3c82"
dependencies = [
"proc-macro2",
"quote",
"syn",
"uuid",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "glam"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
[[package]]
name = "godot"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6985eb6c22a0370c40d67db1f225f62222a2e04966f76d0beb53245e745744fa"
dependencies = [
"godot-core",
"godot-macros",
]
[[package]]
name = "godot-bindings"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77d85815de344b419513c9854b82c49aad45c7dd9fa4fcc10302aaf6ce6e07c7"
dependencies = [
"gdextension-api",
]
[[package]]
name = "godot-cell"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4750f0da2c2286f8a0f1e2b0aeb5adb2178251086119e1a96186c34cd8857ba1"
[[package]]
name = "godot-codegen"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fd9382da869c3e5f4ba9614f43157bb96f5acf3d1f8341bc25147b7aeebd49a"
dependencies = [
"godot-bindings",
"heck",
"nanoserde",
"proc-macro2",
"quote",
"regex",
]
[[package]]
name = "godot-core"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7d014ea57227d84955d9db7bba53654e5e9040f3b5a41d6aad370707cad5b7a"
dependencies = [
"glam",
"godot-bindings",
"godot-cell",
"godot-codegen",
"godot-ffi",
]
[[package]]
name = "godot-ffi"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a93bc8ea912fc629cc7c6ad889f919e99b4e7f32cd912cc65b9be2a986dc6eb"
dependencies = [
"gensym",
"godot-bindings",
"godot-codegen",
"libc",
"paste",
]
[[package]]
name = "godot-macros"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66b16a49485735010c107030dc2e9fa8701fb3bf45194e34b14d1305ad5a8b4f"
dependencies = [
"godot-bindings",
"proc-macro2",
"quote",
"venial",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "libc"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "nanoserde"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de9cf844ab1e25a0353525bd74cb889843a6215fa4a0d156fd446f4857a1b99"
dependencies = [
"nanoserde-derive",
]
[[package]]
name = "nanoserde-derive"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e943b2c21337b7e3ec6678500687cdc741b7639ad457f234693352075c082204"
[[package]]
name = "open-strike-2"
version = "0.1.0"
dependencies = [
"godot",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "proc-macro2"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "syn"
version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
[[package]]
name = "uuid"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
dependencies = [
"getrandom",
]
[[package]]
name = "venial"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6816bc32f30bf8dd1b3adb04de8406c7bf187d2f923bd9e4c0b99365d012613f"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

10
rust/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "open-strike-2"
version = "0.1.0"
edition = "2021"
[dependencies]
godot = "0.2.3"
[lib]
crate-type = ["cdylib"]

31
rust/src/lib.rs Normal file
View File

@ -0,0 +1,31 @@
use godot::prelude::*;
use godot::classes::Sprite2D;
use godot::classes::ISprite2D;
struct MyExtension;
mod player;
#[gdextension]
unsafe impl ExtensionLibrary for MyExtension {}
#[derive(GodotClass)]
#[class(base=Sprite2D)]
struct Player {
speed: f64,
angular_speed: f64,
base: Base<Sprite2D>
}
#[godot_api]
impl ISprite2D for Player {
fn init(base: Base<Sprite2D>) -> Self {
godot_print!("Hello, world!"); // Prints to the Godot console
Self {
speed: 400.0,
angular_speed: std::f64::consts::PI,
base,
}
}
}

View File

2
rust/src/player/mod.rs Normal file
View File

@ -0,0 +1,2 @@
mod server_node;
mod client_node;

View File

@ -0,0 +1,94 @@
use godot::classes::{CharacterBody3D, ICharacterBody3D};
use godot::obj::WithBaseField;
use godot::prelude::*;
#[derive(GodotClass)]
#[class(base=CharacterBody3D)]
struct PlayerServerNode {
base: Base<CharacterBody3D>,
jumping: bool,
input_direction: Vector2,
input_rotation: Vector3,
}
const JUMP_VELOCITY: f32 = 4.5;
const SPEED: f32 = 5.0;
#[godot_api]
impl ICharacterBody3D for PlayerServerNode{
fn init(base: Base<CharacterBody3D>) -> Self {
Self {
base,
jumping: false,
input_direction: Vector2::new(0.0, 0.0),
input_rotation: Vector3::new(0.0, 0.0, 0.0),
}
}
fn ready(&mut self) {}
fn physics_process(&mut self, delta: f64) {
if !self.base().is_on_floor() {
let new_gravity = self.base().get_gravity() * delta as f32;
let new_velocity = self.base().get_velocity() + new_gravity;
self.base_mut().set_velocity(new_velocity);
}
if self.base().is_on_floor() && self.jumping {
let mut new_velocity = self.base().get_velocity();
new_velocity.y = JUMP_VELOCITY;
self.base_mut().set_velocity(new_velocity);
}
self.jumping = false;
if self.base().is_on_floor() {
let direction = self.base().get_transform().basis * Vector3::new(self.input_direction.x, 0.0, self.input_direction.y);
if direction.length() > 0.0 {
let direction = direction.normalized();
let new_velocity = Vector3::new(
direction.x * SPEED,
self.base().get_velocity().y,
direction.z * SPEED,
);
self.base_mut().set_velocity(new_velocity);
} else {
let moved = self.base().get_velocity().clone().move_toward(Vector3::new(0.0, 0.0, 0.0), SPEED);
let new_velocity = Vector3::new(
moved.x,
self.base().get_velocity().y,
moved.z,
);
self.base_mut().set_velocity(new_velocity);
}
}
self.base_mut().move_and_slide();
}
}
#[godot_api]
impl PlayerServerNode {
#[rpc(any_peer, call_local, unreliable_ordered)]
fn jump(&mut self) {
self.jumping = true
}
#[rpc(any_peer, call_local, unreliable_ordered)]
fn set_input_direction(&mut self, new_input_direction: Vector2) {
self.input_direction = new_input_direction;
}
#[rpc(any_peer, call_local, unreliable_ordered)]
fn set_rotation_x(&mut self, x: f32) {
let mut new_rotation = self.base().get_rotation();
new_rotation.x = x;
self.base_mut().set_rotation(new_rotation);
}
#[rpc(any_peer, call_local, unreliable_ordered)]
fn set_rotation_y(&mut self, y: f32) {
let mut new_rotation = self.base().get_rotation();
new_rotation.y = y;
self.base_mut().set_rotation(new_rotation);
}
}

14
rust_bindings.gdextension Normal file
View File

@ -0,0 +1,14 @@
[configuration]
entry_symbol = "gdext_rust_init"
compatibility_minimum = 4.1
reloadable = true
[libraries]
linux.debug.x86_64 = "res://rust/target/debug/libopen_strike_2.so"
linux.release.x86_64 = "res://rust/target/release/libopen_strike_2.so"
windows.debug.x86_64 = "res://rust/target/debug/open_strike_2.dll"
windows.release.x86_64 = "res://rust/target/release/open_strike_2.dll"
macos.debug = "res://rust/target/debug/libopen_strike_2.dylib"
macos.release = "res://rust/target/release/libopen_strike_2.dylib"
macos.debug.arm64 = "res://rust/target/debug/libopen_strike_2.dylib"
macos.release.arm64 = "res://rust/target/release/libopen_strike_2.dylib"

View File

@ -5,7 +5,7 @@ class_name PlayerPlaceholder
@export var initial_position: Vector3 = Vector3(0, 0, 0)
# -- Components
@onready var client_node: CharacterBody3D = $PlayerControlledNode
@onready var server_node: CharacterBody3D = $ServerControlledNode
@onready var server_node: PlayerServerNode = $ServerControlledNode
@export var character_speed: int = 5
@ -16,6 +16,7 @@ func _ready() -> void:
client_node.set_multiplayer_authority(owner_id)
$PlayerControlledNode/CameraMount.set_multiplayer_authority(owner_id)
switch_players_camera.rpc_id(owner_id)
server_node.global_position = initial_position
client_node.global_position = server_node.global_position
client_node.rotation.y = server_node.rotation.y
client_node.rotation.x = server_node.rotation.x
@ -25,7 +26,8 @@ func _ready() -> void:
if owner_id != multiplayer.get_unique_id():
client_node.queue_free()
else:
client_node._add_legs_to_first_view()
pass
#client_node._add_legs_to_first_view()
# Called every frame. 'delta' is the elapsed time since the previous frame.

View File

@ -101,7 +101,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.786919, 0)
shape = SubResource("CapsuleShape3D_taqso")
[node name="CameraMount" type="Node3D" parent="PlayerControlledNode"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.29568, -0.340905)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.29568, -0.412934)
[node name="Camera3D" type="Camera3D" parent="PlayerControlledNode/CameraMount"]
cull_mask = 524287
@ -194,21 +194,31 @@ collide_with_areas = true
[node name="Node3D" type="Node3D" parent="PlayerControlledNode"]
[node name="ServerControlledNode" type="CharacterBody3D" parent="."]
[node name="ServerControlledNodeBak" type="CharacterBody3D" parent="."]
collision_layer = 4
script = ExtResource("3_f1bhn")
[node name="CollisionShape3D" type="CollisionShape3D" parent="ServerControlledNode"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.786919, 0)
shape = SubResource("CapsuleShape3D_taqso")
[node name="Dummy" parent="ServerControlledNode" instance=ExtResource("6_e3cnh")]
[node name="Dummy" parent="ServerControlledNodeBak" instance=ExtResource("6_e3cnh")]
visible = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="ServerControlledNodeBak"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.57384, 0)
shape = SubResource("CapsuleShape3D_taqso")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_7vlrn")
[node name="Timer" type="Timer" parent="."]
wait_time = 0.1
[node name="ServerControlledNode" type="PlayerServerNode" parent="."]
collision_layer = 4
[node name="CollisionShape3D" type="CollisionShape3D" parent="ServerControlledNode"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.786919, 0)
shape = SubResource("CapsuleShape3D_taqso")
[node name="CSGBox3D" type="CSGBox3D" parent="ServerControlledNode"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.47058, 0)
[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"]

View File

@ -54,10 +54,11 @@ func _input(event):
camera_mount.rotation.x = clamp(camera_mount.rotation.x - look_dir.y * camera_sens * 1.0, -1.5, 1.5)
server_node.set_rotation_y.rpc_id(1, rotation.y)
server_node.set_rotation_x.rpc_id(1, rotation.x)
#server_node.set_input_direction.rpc_id(1, rotation.x, rotation.y)
@onready var server_node: ServerControlledPlayer = $"../ServerControlledNode"
@onready var server_node: PlayerServerNode = $"../ServerControlledNode"
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
func _physics_process(delta: float) -> void:
if multiplayer.get_unique_id() == get_multiplayer_authority():
if !paused:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
@ -75,13 +76,14 @@ func _process(delta: float) -> void:
var direction := (transform.basis * Vector3(input_direction.x, 0, input_direction.y)).normalized()
if is_on_floor():
if direction:
first_view_legs_anim.play("Run Forward")
#first_view_legs_anim.play("Run Forward")
gun_mount_anim.play("move")
velocity.x = direction.x * placeholder.character_speed
velocity.z = direction.z * placeholder.character_speed
else:
velocity.x = move_toward(velocity.x, 0, placeholder.character_speed)
velocity.z = move_toward(velocity.z, 0, placeholder.character_speed)
func _process(delta: float) -> void:
move_and_slide()

View File

@ -3,7 +3,8 @@ extends CharacterBody3D
const JUMP_VELOCITY = 4.5
func _ready() -> void:
global_position = $"..".initial_position
pass
@export_category("ServerControlledPlayer")
@onready var placeholder: Node3D = $'..'
@ -20,13 +21,14 @@ func set_rotation_y(new_rotation_y: float):
@rpc("call_local", "any_peer", "unreliable_ordered")
func set_rotation_x(new_rotation_x: float):
$"..".rotation.x = new_rotation_x
rotation.x = new_rotation_x
@rpc("call_local", "any_peer", "unreliable_ordered")
func jump():
jumping = true
var jumping := false
func _physics_process(delta: float) -> void:
func _process(delta: float) -> void:
if not is_on_floor():
velocity += get_gravity() * delta
if is_on_floor() && jumping:
@ -41,4 +43,6 @@ func _physics_process(delta: float) -> void:
else:
velocity.x = move_toward(velocity.x, 0, placeholder.character_speed)
velocity.z = move_toward(velocity.z, 0, placeholder.character_speed)
func _physics_process(delta: float) -> void:
move_and_slide()