Files
osirose-new/character-service/src/character_db_client.rs
raven a8755bd3de Add comprehensive documentation and unit tests
Documentation:
- Add detailed README files for all services (auth, character, database, launcher, packet, utils, world)
- Create API documentation for the database service with detailed endpoint specifications
- Document database schema and relationships
- Add service architecture overviews and configuration instructions

Unit Tests:
- Implement comprehensive test suite for database repositories (user, character, session)
- Add gRPC service tests for database interactions
- Create tests for packet service components (bufferpool, connection, packets)
- Add utility service tests (health check, logging, load balancer, redis cache, service discovery)
- Implement auth service user tests
- Add character service tests

Code Structure:
- Reorganize test files into a more consistent structure
- Create a dedicated tests crate for integration testing
- Add test helpers and mock implementations for easier testing
2025-04-09 13:29:53 -04:00

246 lines
6.2 KiB
Rust

use crate::database::{
character_db_service_client::CharacterDbServiceClient, Character, CharacterListRequest, CharacterListResponse,
CharacterRequest, CreateCharacterRequest, CreateCharacterResponse, DeleteCharacterRequest, DeleteCharacterResponse,
};
use serde::{Deserialize, Serialize};
use tonic::transport::Channel;
#[derive(Clone)]
pub struct CharacterDbClient {
client: CharacterDbServiceClient<Channel>,
}
#[derive(Debug, Deserialize, Serialize)]
struct Skill {
id: i32,
}
#[derive(Debug, Deserialize, Serialize)]
struct Item {
item_id: i32,
item_type: i32,
is_created: i32,
gem_option: i32,
durability: f32,
life: f32,
socket: i8,
is_appraised: i8,
grade: u32,
count: i32,
slot: i32,
}
#[derive(Debug, Deserialize, Serialize)]
struct Looks {
race: i32,
face: i32,
hair: i32,
stone: i32,
}
#[derive(Debug, Deserialize, Serialize)]
struct Position {
map_id: i32,
x: f64,
y: f64,
z: f64,
spawn_id: i32,
}
#[derive(Debug, Deserialize, Serialize)]
struct Stats {
job: u16,
str: u16,
dex: u16,
int: u16,
con: u16,
charm: u16,
sense: u16,
max_hp: i32,
hp: i32,
max_mp: i32,
mp: i32,
xp: u64,
level: u16,
head_size: u8,
body_size: u8,
stat_points: u32,
skill_points: u32,
penalty_xp: u32,
stamina: u16,
pat_hp: u16,
pat_cooldown_time: u32,
}
impl CharacterDbClient {
pub async fn connect(endpoint: &str) -> Result<Self, Box<dyn std::error::Error>> {
let client = CharacterDbServiceClient::connect(endpoint.to_string()).await?;
Ok(Self { client })
}
pub async fn get_character(
&mut self,
user_id: &str,
char_id: &str,
) -> Result<Character, Box<dyn std::error::Error>> {
let request = tonic::Request::new(CharacterRequest {
user_id: user_id.parse().unwrap(),
character_id: char_id.parse().unwrap(),
});
let response = self.client.get_character(request).await?;
Ok(response.into_inner())
}
pub async fn get_character_list(
&mut self,
user_id: &str,
) -> Result<CharacterListResponse, Box<dyn std::error::Error>> {
let request = tonic::Request::new(CharacterListRequest {
user_id: user_id.parse().unwrap(),
});
let response = self.client.get_character_list(request).await?;
Ok(response.into_inner())
}
pub async fn create_character(
&mut self,
user_id: &str,
name: &str,
race: i32,
face: i32,
hair: i32,
stone: i32,
) -> Result<CreateCharacterResponse, Box<dyn std::error::Error>> {
let mut hatid = 221;
if 0 == race {
hatid = 222;
}
let inventory = vec![
Item {
item_id: 30,
item_type: 3,
is_created: 0,
gem_option: 0,
durability: 45.0,
life: 100.0,
socket: 0,
grade: 0,
is_appraised: 0,
count: 1,
slot: 3,
},
Item {
item_id: 1,
item_type: 8,
is_created: 0,
gem_option: 0,
durability: 45.0,
life: 100.0,
socket: 0,
grade: 0,
is_appraised: 0,
count: 1,
slot: 7,
},
Item {
item_id: hatid,
item_type: 2,
is_created: 0,
gem_option: 0,
durability: 45.0,
life: 100.0,
socket: 0,
grade: 0,
is_appraised: 0,
count: 1,
slot: 12,
},
];
let skills = vec![
Skill { id: 11 },
Skill { id: 12 },
Skill { id: 16 },
Skill { id: 19 },
Skill { id: 20 },
Skill { id: 21 },
Skill { id: 26 },
Skill { id: 41 },
Skill { id: 42 },
Skill { id: 43 },
Skill { id: 46 },
Skill { id: 47 },
Skill { id: 48 },
Skill { id: 49 },
Skill { id: 60 },
];
let stats = Stats {
job: 0,
str: 10,
dex: 10,
int: 10,
con: 10,
charm: 10,
sense: 10,
max_hp: 81,
hp: 81,
max_mp: 55,
mp: 55,
xp: 0,
level: 1,
head_size: 1,
body_size: 1,
skill_points: 0,
stat_points: 0,
penalty_xp: 0,
stamina: 0,
pat_hp: 0,
pat_cooldown_time: 0,
};
let looks = Looks {
race,
face,
hair,
stone,
};
let position = Position {
map_id: 20,
x: 5200.00,
y: 5200.00,
z: 1.0,
spawn_id: 1,
};
let request = tonic::Request::new(CreateCharacterRequest {
user_id: user_id.parse().unwrap(),
name: name.to_string(),
inventory: serde_json::to_value(inventory)?.to_string(),
skills: serde_json::to_value(skills)?.to_string(),
stats: serde_json::to_value(stats)?.to_string(),
looks: serde_json::to_value(looks)?.to_string(),
position: serde_json::to_value(position)?.to_string(),
});
let response = self.client.create_character(request).await?;
Ok(response.into_inner())
}
pub async fn delete_character(
&mut self,
user_id: &str,
char_id: &str,
delete_type: i32,
) -> Result<DeleteCharacterResponse, Box<dyn std::error::Error>> {
let request = tonic::Request::new(DeleteCharacterRequest {
user_id: user_id.parse().unwrap(),
character_id: char_id.parse().unwrap(),
delete_type,
});
let response = self.client.delete_character(request).await?;
Ok(response.into_inner())
}
}