From 7e68215283e5d279c147e44864ac56dac630026d Mon Sep 17 00:00:00 2001 From: limuy Date: Sun, 23 Jun 2024 10:54:27 +0800 Subject: [PATCH] feat:add set up server --- gdrust/Cargo.lock | 7 +++ gdrust/Cargo.toml | 1 + gdrust/proto/proto/connect.proto | 11 +++- gdrust/src/fight_items/block_drawer.rs | 6 +- gdrust/src/fight_items/health_bar.rs | 4 +- gdrust/src/multi.rs | 87 +++++++++++++++++++------- gdrust/src/player.rs | 8 +-- gdrust/src/ui/multi_enter.rs | 6 +- gdrust/src/weapons/enchanted_sword.rs | 29 ++++++--- gdrust/src/weapons/star_wrath.rs | 30 ++++----- scenes/multi_game.tscn | 60 +++++------------- scenes/multi_join.tscn | 69 ++++++++++++++++++++ scenes/multi_set_up.tscn | 34 ++++++++++ scenes/weapons/enchanted_sword.tscn | 10 --- scripts/multi_game/select.gd | 19 ++++++ scripts/start/multi_game.gd | 2 +- 16 files changed, 269 insertions(+), 114 deletions(-) create mode 100644 scenes/multi_join.tscn create mode 100644 scenes/multi_set_up.tscn create mode 100644 scripts/multi_game/select.gd diff --git a/gdrust/Cargo.lock b/gdrust/Cargo.lock index 1489cef..5dc65d5 100644 --- a/gdrust/Cargo.lock +++ b/gdrust/Cargo.lock @@ -213,6 +213,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +[[package]] +name = "collection_literals" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186dce98367766de751c42c4f03970fc60fc012296e706ccbb9d5df9b6c1e271" + [[package]] name = "colorchoice" version = "1.0.1" @@ -360,6 +366,7 @@ dependencies = [ "assert_cmd", "base", "bytes", + "collection_literals", "derive", "godot", "prost", diff --git a/gdrust/Cargo.toml b/gdrust/Cargo.toml index 183612b..e56211f 100644 --- a/gdrust/Cargo.toml +++ b/gdrust/Cargo.toml @@ -24,6 +24,7 @@ base = { path = "base" } prost = "0" prost-types = { version = "0", optional = true } bytes = "1" +collection_literals = "1" [dev-dependencies] assert_cmd = "2" diff --git a/gdrust/proto/proto/connect.proto b/gdrust/proto/proto/connect.proto index f80cc2c..d025a9c 100644 --- a/gdrust/proto/proto/connect.proto +++ b/gdrust/proto/proto/connect.proto @@ -17,4 +17,13 @@ message Response { string message = 2; } -message CreateObj { string path = 1; } +message CreateObj { + string path = 1; + int32 id = 2; +} + +message UpdateObj { + int32 id = 1; + int32 attr = 2; + bytes val = 3; +} diff --git a/gdrust/src/fight_items/block_drawer.rs b/gdrust/src/fight_items/block_drawer.rs index 3f7dee4..57d4562 100644 --- a/gdrust/src/fight_items/block_drawer.rs +++ b/gdrust/src/fight_items/block_drawer.rs @@ -49,7 +49,7 @@ impl INode2D for BlockDrawer { ]; let mut staticbody = self.get_staticbody(); for i in 0..4 { - let mut colliison_obj = CollisionPolygon2D::new_alloc(); + let mut collision_obj = CollisionPolygon2D::new_alloc(); let mut line = PackedVector2Array::new(); let start_point = points[i % 4]; let end_point = points[(i + 1) % 4]; @@ -66,8 +66,8 @@ impl INode2D for BlockDrawer { let end_near = end_point + offset_vec; line.push(end_near); line.push(end_point); - colliison_obj.set_polygon(line); - staticbody.add_child(colliison_obj.upcast()); + collision_obj.set_polygon(line); + staticbody.add_child(collision_obj.upcast()); } } diff --git a/gdrust/src/fight_items/health_bar.rs b/gdrust/src/fight_items/health_bar.rs index 9b2fdd4..3f52c44 100644 --- a/gdrust/src/fight_items/health_bar.rs +++ b/gdrust/src/fight_items/health_bar.rs @@ -26,8 +26,6 @@ impl INode2D for HealthBar { } } - fn ready(&mut self) {} - fn draw(&mut self) { // godot_print!("again!"); let start_pos = Vector2::new(Self::START_POSITION_X, Self::START_POSITION_Y); @@ -47,6 +45,8 @@ impl INode2D for HealthBar { .width(Self::WIDTH) .done(); } + + fn ready(&mut self) {} } #[godot_api()] diff --git a/gdrust/src/multi.rs b/gdrust/src/multi.rs index c047bab..25e1d46 100644 --- a/gdrust/src/multi.rs +++ b/gdrust/src/multi.rs @@ -1,3 +1,4 @@ +use crate::{get_multi_single, get_tokio_runtime, MultiSingle}; use ::proto::ProtoRequest; use anyhow::anyhow; use bytes::{Bytes, BytesMut}; @@ -5,28 +6,22 @@ use godot::classes::{INode, Node}; use godot::prelude::*; use prost::Message; use proto::connect::Join; -use std::collections::HashMap; +use std::process::{Child, Command}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; use tokio::net::TcpStream; use tokio::sync::mpsc; -use crate::{get_multi_single, get_tokio_runtime, MultiSingle}; - pub struct MultiPlayerConnection {} impl MultiPlayerConnection {} -enum Requests { - Proto(ProtoRequest), - Wrong(String), - ExitSuccess, -} - pub struct MultiManagerImpl { - clients: HashMap, + /// 发送器 socket: Option>, - receiver: Option>, + /// 接收读取到的指令 + receiver: Option>, + is_host: bool, } async fn send(sender: mpsc::Sender, data: BytesMut) -> anyhow::Result<()> { @@ -46,7 +41,7 @@ async fn write_loop( } async fn read_loop( - send_channel: std::sync::mpsc::Sender, + send_channel: std::sync::mpsc::Sender, mut read_socket: OwnedReadHalf, ) -> anyhow::Result<()> { let mut buf = BytesMut::new(); @@ -60,12 +55,10 @@ async fn read_loop( if n == 0 { if buf.is_empty() { godot_print!("Connection closed"); - send_channel.send(Requests::ExitSuccess)?; break; } else { let err_msg = "Connection reset by peer"; godot_error!("{}", err_msg); - send_channel.send(Requests::Wrong(err_msg.to_string()))?; return Err(anyhow::anyhow!(err_msg)); } } @@ -73,9 +66,9 @@ async fn read_loop( Ok(()) } -fn parse_request(buf: &BytesMut) -> Option { +fn parse_request(buf: &BytesMut) -> Option { match Join::decode(&buf[..]) { - Ok(v) => Some(Requests::Proto(ProtoRequest::Join(v))), + Ok(v) => Some(ProtoRequest::Join(v)), Err(_) => None, } } @@ -123,14 +116,45 @@ impl MultiManagerImpl { pub fn close(&mut self) { self.socket = None; } + + pub fn send_data(&mut self, data: Bytes) { + let socket = self.socket.clone(); + get_tokio_runtime().spawn(async { + match socket { + Some(socket) => { + socket.send(data).await?; + } + None => { + // Ignore in single mode + } + } + anyhow::Ok(()) + }); + } + + pub fn alloc_id(&mut self) -> usize { + let socket = self.socket.clone(); + // socket.unwrap().blocking_send(value); + // get_tokio_runtime().spawn(async { + // match socket { + // Some(socket) => {} + // None => {} + // } + // }) + todo!() + } + + pub fn is_host(&mut self, val: bool) { + self.is_host = val; + } } impl MultiManagerImpl { pub fn new() -> Self { Self { - clients: HashMap::new(), socket: None, receiver: None, + is_host: false, } } } @@ -139,16 +163,13 @@ impl MultiManagerImpl { #[class(base = Node)] pub struct MultiManager { base: Base, - multi_impl: MultiSingle, + server: Option, } #[godot_api()] impl INode for MultiManager { fn init(base: Base) -> Self { - Self { - base, - multi_impl: get_multi_single().clone(), - } + Self { base, server: None } } } @@ -156,4 +177,26 @@ impl INode for MultiManager { impl MultiManager { #[func] fn add_new_player(&mut self) {} + + #[func] + fn set_up_server(&mut self) { + get_multi_single().lock().unwrap().is_host(true); + self.server = Some( + Command::new("your_command") + .spawn() + .expect("Failed to start process"), + ); + } +} + +impl Drop for MultiManager { + fn drop(&mut self) { + match &mut self.server { + None => {} + Some(data) => { + data.kill().expect("Stop server failed"); + data.wait().expect("Waited failed"); + } + } + } } diff --git a/gdrust/src/player.rs b/gdrust/src/player.rs index f925aad..ff132b1 100644 --- a/gdrust/src/player.rs +++ b/gdrust/src/player.rs @@ -63,10 +63,6 @@ impl ICharacterBody2D for Player { } } - fn ready(&mut self) { - debug_check!(self) - } - fn physics_process(&mut self, delta: f64) { let input_obj = Input::singleton(); let mut down_rate = 1.0; @@ -148,6 +144,10 @@ impl ICharacterBody2D for Player { } } } + + fn ready(&mut self) { + debug_check!(self) + } } #[godot_api] diff --git a/gdrust/src/ui/multi_enter.rs b/gdrust/src/ui/multi_enter.rs index c8e703a..5c13edb 100644 --- a/gdrust/src/ui/multi_enter.rs +++ b/gdrust/src/ui/multi_enter.rs @@ -28,8 +28,8 @@ impl IButton for MultiEnter { impl MultiEnter { #[func] fn connect_to_server(&mut self, ip: String) -> bool { - let mult_manager = get_multi_single(); - let mut lock = mult_manager.lock().unwrap(); + let multi_manager = get_multi_single(); + let mut lock = multi_manager.lock().unwrap(); match lock.connect_to_server(ip) { Ok(_) => true, Err(err) => { @@ -50,4 +50,4 @@ impl MultiEnter { dialog.set_text(text.into()); dialog.popup_centered() } -} +} \ No newline at end of file diff --git a/gdrust/src/weapons/enchanted_sword.rs b/gdrust/src/weapons/enchanted_sword.rs index d53bfbd..3e994a0 100644 --- a/gdrust/src/weapons/enchanted_sword.rs +++ b/gdrust/src/weapons/enchanted_sword.rs @@ -1,24 +1,40 @@ +use crate::get_multi_single; use godot::{ classes::{ISprite2D, Sprite2D}, prelude::*, }; +use proto::connect; use std::collections::HashMap; #[derive(GodotClass)] -#[class(init, base = Sprite2D)] +#[class(base = Sprite2D)] struct EnchantedSword { - properties: HashMap, + properties: HashMap>, base: Base, } #[godot_api] impl ISprite2D for EnchantedSword { + fn init(base: Base) -> Self { + let mut properties = HashMap::new(); + properties.insert( + "position".to_string(), + Box::new(|| { + // let data = connect::UpdateObj {}; + let data = todo!(); + get_multi_single().lock().unwrap().send_data(data) + }), + ); + Self { + base, + properties: HashMap::new(), + } + } + fn get_property(&self, name: StringName) -> Option { match self.properties.get(&name.to_string()) { None => {} - Some(val) => { - val.callv((&[self.base().to_variant()]).into()); - } + Some(val) => val(), } None } @@ -26,9 +42,8 @@ impl ISprite2D for EnchantedSword { #[godot_api] impl EnchantedSword { - #[func] /// 设置要检测的属性 - fn set_monitor(&mut self, property_name: String, func: Callable) { + fn set_monitor(&mut self, property_name: String, func: Box) { self.properties.insert(property_name, func); } } diff --git a/gdrust/src/weapons/star_wrath.rs b/gdrust/src/weapons/star_wrath.rs index cad8c94..bb66f76 100644 --- a/gdrust/src/weapons/star_wrath.rs +++ b/gdrust/src/weapons/star_wrath.rs @@ -32,21 +32,6 @@ impl IArea2D for StarWrath { } } - fn ready(&mut self) { - // for debug - // 检查是否是当前场景 - debug_check!(self); - if self.base().get_tree().unwrap().get_current_scene().unwrap() - == self.base().clone().upcast() - { - let mut fight_time = self.get_fight_timer(); - fight_time.start(); - self.start(); - } else { - self.base_mut().hide(); - } - } - fn process(&mut self, delta: f64) { let mut animation = self.get_animation(); // animation.play_ex().name("Wave".into()).done(); @@ -61,6 +46,21 @@ impl IArea2D for StarWrath { } if self.state == State::Wave1 {} } + + fn ready(&mut self) { + // for debug + // 检查是否是当前场景 + debug_check!(self); + if self.base().get_tree().unwrap().get_current_scene().unwrap() + == self.base().clone().upcast() + { + let mut fight_time = self.get_fight_timer(); + fight_time.start(); + self.start(); + } else { + self.base_mut().hide(); + } + } } #[godot_api] diff --git a/scenes/multi_game.tscn b/scenes/multi_game.tscn index 162bc46..0cdb825 100644 --- a/scenes/multi_game.tscn +++ b/scenes/multi_game.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=2 format=3 uid="uid://vmiwhsyggblr"] +[gd_scene load_steps=2 format=3 uid="uid://dertwnnfyebti"] -[ext_resource type="Script" path="res://scripts/multi_game/enter.gd" id="1_4xv50"] +[ext_resource type="Script" path="res://scripts/multi_game/select.gd" id="1_a2215"] [node name="MultiGame" type="Control"] layout_mode = 3 @@ -10,60 +10,28 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -[node name="Ok" type="MultiEnter" parent="."] -layout_mode = 1 -anchors_preset = -1 -anchor_left = 0.5 -anchor_top = 0.81 -anchor_right = 0.5 -anchor_bottom = 0.81 -offset_left = -15.5 -offset_top = -31.0 -offset_right = 15.5 -grow_horizontal = 2 -grow_vertical = 0 -text = "OK" -script = ExtResource("1_4xv50") - -[node name="WrongDialog" type="AcceptDialog" parent="Ok"] -title = "Warning!" - -[node name="Input" type="VBoxContainer" parent="."] +[node name="Select" type="VBoxContainer" parent="."] layout_mode = 1 anchors_preset = 8 anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 -offset_left = -100.0 -offset_top = -50.0 -offset_right = 100.0 -offset_bottom = 50.0 +offset_left = -20.0 +offset_top = -20.0 +offset_right = 20.0 +offset_bottom = 20.0 grow_horizontal = 2 grow_vertical = 2 +script = ExtResource("1_a2215") -[node name="IPBox" type="HBoxContainer" parent="Input"] -layout_mode = 2 - -[node name="IPTip" type="Label" parent="Input/IPBox"] -layout_mode = 2 -text = "IP" - -[node name="IP" type="LineEdit" parent="Input/IPBox"] -layout_mode = 2 -size_flags_horizontal = 3 -text = "127.0.0.1:6789" -placeholder_text = "format like 127.0.0.1:6789" - -[node name="PlayerBox" type="HBoxContainer" parent="Input"] -layout_mode = 2 - -[node name="PlayerTip" type="Label" parent="Input/PlayerBox"] +[node name="Join" type="Button" parent="Select"] layout_mode = 2 -text = "Player" +text = "Join to server" -[node name="Player" type="LineEdit" parent="Input/PlayerBox"] +[node name="Setup" type="Button" parent="Select"] layout_mode = 2 -placeholder_text = "Limuy" +text = "Set up server" -[connection signal="pressed" from="Ok" to="Ok" method="_on_pressed"] +[connection signal="pressed" from="Select/Join" to="Select" method="_on_join_pressed"] +[connection signal="pressed" from="Select/Setup" to="Select" method="_on_setup_pressed"] diff --git a/scenes/multi_join.tscn b/scenes/multi_join.tscn new file mode 100644 index 0000000..162bc46 --- /dev/null +++ b/scenes/multi_join.tscn @@ -0,0 +1,69 @@ +[gd_scene load_steps=2 format=3 uid="uid://vmiwhsyggblr"] + +[ext_resource type="Script" path="res://scripts/multi_game/enter.gd" id="1_4xv50"] + +[node name="MultiGame" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Ok" type="MultiEnter" parent="."] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.5 +anchor_top = 0.81 +anchor_right = 0.5 +anchor_bottom = 0.81 +offset_left = -15.5 +offset_top = -31.0 +offset_right = 15.5 +grow_horizontal = 2 +grow_vertical = 0 +text = "OK" +script = ExtResource("1_4xv50") + +[node name="WrongDialog" type="AcceptDialog" parent="Ok"] +title = "Warning!" + +[node name="Input" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -100.0 +offset_top = -50.0 +offset_right = 100.0 +offset_bottom = 50.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="IPBox" type="HBoxContainer" parent="Input"] +layout_mode = 2 + +[node name="IPTip" type="Label" parent="Input/IPBox"] +layout_mode = 2 +text = "IP" + +[node name="IP" type="LineEdit" parent="Input/IPBox"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "127.0.0.1:6789" +placeholder_text = "format like 127.0.0.1:6789" + +[node name="PlayerBox" type="HBoxContainer" parent="Input"] +layout_mode = 2 + +[node name="PlayerTip" type="Label" parent="Input/PlayerBox"] +layout_mode = 2 +text = "Player" + +[node name="Player" type="LineEdit" parent="Input/PlayerBox"] +layout_mode = 2 +placeholder_text = "Limuy" + +[connection signal="pressed" from="Ok" to="Ok" method="_on_pressed"] diff --git a/scenes/multi_set_up.tscn b/scenes/multi_set_up.tscn new file mode 100644 index 0000000..5f54154 --- /dev/null +++ b/scenes/multi_set_up.tscn @@ -0,0 +1,34 @@ +[gd_scene format=3 uid="uid://shdywgibimvd"] + +[node name="MultiSetUp" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Start" type="Button" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -48.0 +offset_top = -15.5 +offset_right = 48.0 +offset_bottom = 15.5 +grow_horizontal = 2 +grow_vertical = 2 +text = "Start Game" + +[node name="Panel" type="Panel" parent="."] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="Players" type="Label" parent="Panel"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 23.0 diff --git a/scenes/weapons/enchanted_sword.tscn b/scenes/weapons/enchanted_sword.tscn index ba4f598..b7426cb 100644 --- a/scenes/weapons/enchanted_sword.tscn +++ b/scenes/weapons/enchanted_sword.tscn @@ -5,22 +5,12 @@ [ext_resource type="PackedScene" uid="uid://bi0hwjyalpjn6" path="res://scenes/bullets/enchanted_beam.tscn" id="3_ndj1h"] [node name="EnchantedSword" type="EnchantedSword"] -_import_path = NodePath("") -unique_name_in_owner = false -process_mode = 0 -process_priority = 0 -process_physics_priority = 0 -process_thread_group = 0 -physics_interpolation_mode = 0 -auto_translate_mode = 0 -editor_description = "" z_index = 1 position = Vector2(574, 291) rotation = -5.57284 scale = Vector2(3, 3) texture = ExtResource("1_cwcxs") offset = Vector2(8.27271, -8.17079) -enchanted_beam = ExtResource("3_ndj1h") script = ExtResource("2_h56vq") enchanted_beam = ExtResource("3_ndj1h") metadata/_edit_group_ = true diff --git a/scripts/multi_game/select.gd b/scripts/multi_game/select.gd new file mode 100644 index 0000000..b4509dc --- /dev/null +++ b/scripts/multi_game/select.gd @@ -0,0 +1,19 @@ +extends VBoxContainer + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + pass + + +func _on_join_pressed() -> void: + get_tree().change_scene_to_file("res://scenes/multi_join.tscn") + + +func _on_setup_pressed() -> void: + get_tree().change_scene_to_file("res://scenes/multi_set_up.tscn") diff --git a/scripts/start/multi_game.gd b/scripts/start/multi_game.gd index 67e6847..2afa0d0 100644 --- a/scripts/start/multi_game.gd +++ b/scripts/start/multi_game.gd @@ -12,4 +12,4 @@ func _process(delta: float) -> void: func _on_pressed() -> void: - get_tree().change_scene_to_file("res://scenes/multi_game.tscn") + get_tree().change_scene_to_file("res://scenes/multi_join.tscn")