diff --git a/api-service/build.rs b/api-service/build.rs index 1b15765..728974a 100644 --- a/api-service/build.rs +++ b/api-service/build.rs @@ -1,6 +1,6 @@ fn main() -> Result<(), Box> { tonic_build::configure() .compile_well_known_types(true) - .compile_protos(&["../proto/auth.proto"], &["../proto"])?; + .compile_protos(&["../proto/common.proto", "../proto/auth.proto"], &["../proto"])?; Ok(()) } diff --git a/api-service/src/axum_gateway.rs b/api-service/src/axum_gateway.rs index 60fcf14..cb6f859 100644 --- a/api-service/src/axum_gateway.rs +++ b/api-service/src/axum_gateway.rs @@ -16,6 +16,9 @@ use auth::{LoginRequest, RegisterRequest}; use log::{error, info}; use tokio::sync::Mutex; +pub mod common { + tonic::include_proto!("common"); +} pub mod auth { tonic::include_proto!("auth"); } diff --git a/auth-service/src/grpc.rs b/auth-service/src/grpc.rs index 04a9033..cf2b0bd 100644 --- a/auth-service/src/grpc.rs +++ b/auth-service/src/grpc.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use crate::auth::auth_service_server::AuthService; -use crate::auth::{LoginRequest, LoginResponse, PasswordResetRequest, PasswordResetResponse, RegisterRequest, RegisterResponse, ResetPasswordRequest, ResetPasswordResponse, ValidateTokenRequest, ValidateTokenResponse, ValidateSessionRequest, ValidateSessionResponse, Empty, LogoutRequest}; +use crate::auth::{LoginRequest, LoginResponse, PasswordResetRequest, PasswordResetResponse, RegisterRequest, RegisterResponse, ResetPasswordRequest, ResetPasswordResponse, ValidateTokenRequest, ValidateTokenResponse, ValidateSessionRequest, ValidateSessionResponse, LogoutRequest}; +use crate::common::{Empty}; use crate::database_client::{DatabaseClient, DatabaseClientTrait}; use crate::session::session_service_client::SessionServiceClient; use crate::session::{CreateSessionRequest, GetSessionRequest, DeleteSessionRequest}; diff --git a/auth-service/src/lib.rs b/auth-service/src/lib.rs index 0bc7ac8..5e76fa2 100644 --- a/auth-service/src/lib.rs +++ b/auth-service/src/lib.rs @@ -3,6 +3,11 @@ pub mod jwt; pub mod database_client; pub mod users; + +pub mod common { + tonic::include_proto!("common"); +} + pub mod auth { tonic::include_proto!("auth"); } diff --git a/character-service/src/character_service.rs b/character-service/src/character_service.rs index ea72e5c..3742886 100644 --- a/character-service/src/character_service.rs +++ b/character-service/src/character_service.rs @@ -82,6 +82,7 @@ impl CharacterService for MyCharacterService { position: serde_json::from_str(&get_character_response.position).unwrap(), looks: serde_json::from_str(&get_character_response.looks).unwrap(), stats: serde_json::from_str(&get_character_response.stats).unwrap(), + skills: serde_json::from_str(&get_character_response.skills).unwrap(), items: serde_json::from_str(&get_character_response.inventory).unwrap(), }; diff --git a/database-service/src/characters.rs b/database-service/src/characters.rs index 28b12dd..7950e11 100644 --- a/database-service/src/characters.rs +++ b/database-service/src/characters.rs @@ -11,6 +11,7 @@ pub struct Character { pub name: String, pub inventory: serde_json::Value, pub stats: serde_json::Value, + pub skills: serde_json::Value, pub looks: serde_json::Value, pub position: serde_json::Value, pub created_at: chrono::NaiveDateTime, @@ -39,7 +40,7 @@ impl CharacterRepository { // Fetch from database let character = sqlx::query_as::<_, Character>( - "SELECT id, user_id, name, inventory, stats, looks, position, \ + "SELECT id, user_id, name, inventory, stats, skills, looks, position, \ created_at, updated_at, extract(epoch from (deleted_at - now()))::BIGINT as deleted_at, is_active \ FROM characters WHERE id = $1 AND is_active = true", ) diff --git a/database-service/src/grpc/character_service.rs b/database-service/src/grpc/character_service.rs index 423a0a3..b0117c0 100644 --- a/database-service/src/grpc/character_service.rs +++ b/database-service/src/grpc/character_service.rs @@ -1,5 +1,5 @@ use serde_json::Value::Null; -use crate::grpc::{Character, CharacterRequest, CharacterListRequest, CharacterListResponse, CreateCharacterRequest, CreateCharacterResponse, DeleteCharacterRequest, DeleteCharacterResponse, Empty}; +use crate::grpc::{Character, CharacterRequest, CharacterListRequest, CharacterListResponse, CreateCharacterRequest, CreateCharacterResponse, DeleteCharacterRequest, DeleteCharacterResponse}; use crate::grpc::character_service_server::CharacterService; use crate::grpc::database_service::MyDatabaseService; use tonic::{Request, Response, Status}; @@ -29,6 +29,7 @@ impl CharacterService for MyDatabaseService { name: character.name, inventory: character.inventory.to_string(), stats: character.stats.to_string(), + skills: character.skills.to_string(), looks: character.looks.to_string(), position: character.position.to_string(), created_at: character.created_at.to_string(), @@ -66,6 +67,7 @@ impl CharacterService for MyDatabaseService { name: character.name, inventory: character.inventory.to_string(), stats: character.stats.to_string(), + skills: character.skills.to_string(), looks: character.looks.to_string(), position: character.position.to_string(), created_at: character.created_at.to_string(), diff --git a/packet-service/src/auth_client.rs b/packet-service/src/auth_client.rs index 92a2c53..ba54516 100644 --- a/packet-service/src/auth_client.rs +++ b/packet-service/src/auth_client.rs @@ -1,5 +1,6 @@ use crate::auth::auth_service_client::AuthServiceClient; -use crate::auth::{Empty, LoginRequest, LoginResponse, LogoutRequest, ValidateSessionRequest, ValidateSessionResponse, ValidateTokenRequest, ValidateTokenResponse}; +use crate::auth::{LoginRequest, LoginResponse, LogoutRequest, ValidateSessionRequest, ValidateSessionResponse, ValidateTokenRequest, ValidateTokenResponse}; +use crate::common::{Empty}; use tonic::transport::Channel; #[derive(Clone, Debug)] diff --git a/packet-service/src/handlers/character.rs b/packet-service/src/handlers/character.rs index bb7f140..57bb031 100644 --- a/packet-service/src/handlers/character.rs +++ b/packet-service/src/handlers/character.rs @@ -189,10 +189,17 @@ pub(crate) async fn handle_select_char_req(stream: &mut TcpStream, packet: Packe let looks = character.looks.unwrap(); let position = character.position.unwrap(); let stats = character.stats.unwrap(); + let skills = character.skills; let items = character.items; let mut equipped_item_list: [EquippedItem; (MAX_VISIBLE_ITEMS as usize)] = core::array::from_fn(|i| EquippedItem::default()); let mut inventory: [srv_inventory_data::Item; (MAX_ITEMS as usize)] = core::array::from_fn(|i| srv_inventory_data::Item::default()); - + let mut skill_list: [u16; (MAX_SKILL_COUNT as usize)] = core::array::from_fn(|i| { + if i < skills.len() { + return skills[i] as u16; + } + 0 + }); + for item in items { if item.slot < MAX_VISIBLE_ITEMS as i32 { let slot = convert_slot(item.slot) as usize; @@ -265,7 +272,7 @@ pub(crate) async fn handle_select_char_req(stream: &mut TcpStream, packet: Packe effects: effect_list, pat_hp: stats.pat_hp as u16, pat_cooldown_time: stats.pat_cooldown_time as u32, - skills: [0u16; (MAX_SKILL_COUNT as usize)], + skills: skill_list, hotbar: hotbar_list, tag: user_id as u32, name: request.name, diff --git a/packet-service/src/main.rs b/packet-service/src/main.rs index e03b680..f45c16d 100644 --- a/packet-service/src/main.rs +++ b/packet-service/src/main.rs @@ -37,6 +37,9 @@ mod character_client; mod connection_state; mod connection_service; +pub mod common { + tonic::include_proto!("common"); +} pub mod auth { tonic::include_proto!("auth"); // Path matches the package name in auth.proto } diff --git a/proto/auth.proto b/proto/auth.proto index 36fc21c..59c2a34 100644 --- a/proto/auth.proto +++ b/proto/auth.proto @@ -2,9 +2,11 @@ syntax = "proto3"; package auth; +import "common.proto"; + service AuthService { rpc Login(LoginRequest) returns (LoginResponse); - rpc Logout(LogoutRequest) returns (Empty); + rpc Logout(LogoutRequest) returns (common.Empty); rpc ValidateToken(ValidateTokenRequest) returns (ValidateTokenResponse); rpc ValidateSession(ValidateSessionRequest) returns (ValidateSessionResponse); rpc RefreshSession(ValidateSessionRequest) returns (ValidateSessionResponse); @@ -74,5 +76,3 @@ message ResetPasswordRequest { message ResetPasswordResponse { string message = 1; } - -message Empty {} \ No newline at end of file diff --git a/proto/character_common.proto b/proto/character_common.proto index 53b8a37..1589d21 100644 --- a/proto/character_common.proto +++ b/proto/character_common.proto @@ -73,10 +73,11 @@ message Character { } message CharacterFull { - string character_id = 1; // Unique ID for the character - string name = 2; // Name of the character - Location position = 3; // Character's position - Looks looks = 4; // Character's Looks - Stats stats = 5; // Character's stats - repeated Item items = 6; // Character inventory + string character_id = 1; // Unique ID for the character + string name = 2; // Name of the character + Location position = 3; // Character's position + Looks looks = 4; // Character's Looks + Stats stats = 5; // Character's stats + repeated int32 skills = 6; // Character's skills + repeated Item items = 7; // Character inventory } \ No newline at end of file diff --git a/proto/character_db_api.proto b/proto/character_db_api.proto index eb4c01d..790c1cf 100644 --- a/proto/character_db_api.proto +++ b/proto/character_db_api.proto @@ -53,12 +53,11 @@ message Character { string name = 3; string inventory = 6; string stats = 7; - string looks = 8; - string position = 9; - string created_at = 10; - string updated_at = 11; - string deleted_at = 12; - bool is_active = 13; + string skills = 8; + string looks = 9; + string position = 10; + string created_at = 11; + string updated_at = 12; + string deleted_at = 13; + bool is_active = 14; } - -message Empty {} diff --git a/proto/chat.proto b/proto/chat.proto new file mode 100644 index 0000000..79465b3 --- /dev/null +++ b/proto/chat.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +package chat; + +import "common.proto"; + +service ChatService { + rpc SendMessage(ChatMessage) returns (common.Empty); +} + +enum MessageType { + MESSAGE_TYPE_UNSPECIFIED = 0; + MESSAGE_TYPE_NORMAL = 1; + MESSAGE_TYPE_SHOUT = 2; + MESSAGE_TYPE_PARTY = 3; + MESSAGE_TYPE_WHISPER = 4; + MESSAGE_TYPE_CLAN = 5; + MESSAGE_TYPE_ALLIED = 6; +} + +message ChatMessage { + MessageType type = 1; + string message = 2; + string target = 3; +} diff --git a/proto/common.proto b/proto/common.proto new file mode 100644 index 0000000..3639c88 --- /dev/null +++ b/proto/common.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +package common; + +message Empty {} \ No newline at end of file diff --git a/proto/session_service_api.proto b/proto/session_service_api.proto index 3aa3839..b65b27f 100644 --- a/proto/session_service_api.proto +++ b/proto/session_service_api.proto @@ -2,11 +2,13 @@ syntax = "proto3"; package session_service_api; +import "common.proto"; + service SessionService { rpc CreateSession (CreateSessionRequest) returns (SessionResponse); rpc GetSession (GetSessionRequest) returns (SessionResponse); rpc RefreshSession (GetSessionRequest) returns (SessionResponse); - rpc DeleteSession (DeleteSessionRequest) returns (Empty); + rpc DeleteSession (DeleteSessionRequest) returns (common.Empty); } message CreateSessionRequest { @@ -34,4 +36,3 @@ message SessionResponse { string ip_address = 6; } -message Empty {} diff --git a/proto/world.proto b/proto/world.proto index 6bb5a8c..1772791 100644 --- a/proto/world.proto +++ b/proto/world.proto @@ -1,17 +1,67 @@ syntax = "proto3"; -package character; +package world; -service CharacterService { +service WorldService { rpc GetCharacter(CharacterRequest) returns (CharacterResponse); + rpc ChangeMap(ChangeMapRequest) returns (ChangeMapResponse); + rpc MoveCharacter(CharacterMoveRequest) returns (CharacterMoveResponse); } message CharacterRequest { string token = 1; string user_id = 2; string char_id = 3; + string session_id = 4; } message CharacterResponse { int32 count = 1; } + +message CharacterMoveRequest { + string session_id = 1; + uint32 target_id = 2; + float x = 3; + float y = 4; + float z = 5; +} + +message CharacterMoveResponse { + int32 id = 1; + int32 target_id = 2; + int32 distance = 3; + float x = 4; + float y = 5; + float z = 6; +} + +message ChangeMapRequest { + int32 id = 1; + float x = 2; + float y = 3; +} + +message ChangeMapResponse { + int32 id = 1; + int32 map_id = 2; + float x = 3; + float y = 4; + int32 move_mode = 5; + int32 ride_mode = 6; +} + +message AttackRequest { + string session_id = 1; + uint32 target_id = 2; +} + +message ObjectHpRequest { + string session_id = 1; + uint32 target_id = 2; +} + +message ObjectHpResponse { + uint32 target_id = 1; + int32 hp = 2; +} diff --git a/session-service/build.rs b/session-service/build.rs index 8bd24e7..ca2df77 100644 --- a/session-service/build.rs +++ b/session-service/build.rs @@ -4,7 +4,7 @@ fn main() { .build_server(true) // Generate gRPC server code .compile_well_known_types(true) .type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]") - .compile_protos(&["../proto/session_service_api.proto"], &["../proto"]) + .compile_protos(&["../proto/common.proto", "../proto/session_service_api.proto"], &["../proto"]) .unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e)); // gRPC Client code diff --git a/session-service/src/main.rs b/session-service/src/main.rs index 86f21d1..7bc06be 100644 --- a/session-service/src/main.rs +++ b/session-service/src/main.rs @@ -15,6 +15,10 @@ use utils::service_discovery::get_service_address; use crate::api::session_service_server::SessionServiceServer; use crate::session_service::SessionServiceImpl; +pub mod common { + tonic::include_proto!("common"); +} + pub mod api { tonic::include_proto!("session_service_api"); } diff --git a/session-service/src/session_service.rs b/session-service/src/session_service.rs index 4cbbd88..12836e7 100644 --- a/session-service/src/session_service.rs +++ b/session-service/src/session_service.rs @@ -3,8 +3,9 @@ use tokio::sync::Mutex; use tonic::{Request, Response, Status}; use serde::{Serialize, Deserialize}; use crate::api::{ - CreateSessionRequest, SessionResponse, GetSessionRequest, DeleteSessionRequest, Empty, + CreateSessionRequest, SessionResponse, GetSessionRequest, DeleteSessionRequest, }; +use crate::common::{Empty}; use crate::api::session_service_server::SessionService; use utils::redis_cache::{Cache, RedisCache}; diff --git a/sql/schema.sql b/sql/schema.sql index 17519c2..c6bb3d8 100644 --- a/sql/schema.sql +++ b/sql/schema.sql @@ -41,6 +41,7 @@ create table characters name varchar(50) not null, inventory jsonb default '{}'::jsonb, stats jsonb default '{}'::jsonb, + skills jsonb default '{}'::jsonb, looks jsonb default '{}'::jsonb, position jsonb default '{}'::jsonb, created_at timestamp default CURRENT_TIMESTAMP,