more commands, unlock only default avatars at beginning
Implement 'avatar add' command Implemented 'player procedure' command
This commit is contained in:
parent
4b86d62d3f
commit
370f141f88
5 changed files with 149 additions and 38 deletions
53
nap_gameserver/src/commands/avatar.rs
Normal file
53
nap_gameserver/src/commands/avatar.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use data::tables;
|
||||||
|
use proto::{AddAvatarPerformType, AddAvatarScNotify, PlayerSyncScNotify};
|
||||||
|
|
||||||
|
use crate::ServerState;
|
||||||
|
|
||||||
|
pub async fn add(args: &[&str], state: &ServerState) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
const USAGE: &str = "Usage: avatar add [player_uid] [avatar_id]";
|
||||||
|
|
||||||
|
if args.len() != 2 {
|
||||||
|
return Ok(USAGE.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let uid = args[0].parse::<u32>()?;
|
||||||
|
let avatar_id = args[1].parse::<u32>()?;
|
||||||
|
|
||||||
|
let Some(player_lock) = state.player_mgr.get_player(uid).await else {
|
||||||
|
return Ok(String::from("player not found"));
|
||||||
|
};
|
||||||
|
|
||||||
|
if !tables::avatar_base_template_tb::iter().any(|tmpl| tmpl.id == avatar_id) {
|
||||||
|
return Ok(format!("avatar with id {avatar_id} doesn't exist"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (session_id, avatar_sync) = {
|
||||||
|
let mut player = player_lock.lock().await;
|
||||||
|
|
||||||
|
player.role_model.add_avatar(avatar_id);
|
||||||
|
(player.current_session_id(), player.role_model.avatar_sync())
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(session) = session_id.map(|id| state.session_mgr.get(id)).flatten() {
|
||||||
|
session
|
||||||
|
.notify(AddAvatarScNotify {
|
||||||
|
avatar_id,
|
||||||
|
perform_type: AddAvatarPerformType::Gacha.into(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
session
|
||||||
|
.notify(PlayerSyncScNotify {
|
||||||
|
avatar: Some(avatar_sync),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
state.player_mgr.save_and_remove(uid).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(format!(
|
||||||
|
"successfully added avatar {avatar_id} to player {uid}"
|
||||||
|
))
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ use rustyline_async::{Readline, ReadlineEvent, SharedWriter};
|
||||||
|
|
||||||
use crate::ServerState;
|
use crate::ServerState;
|
||||||
|
|
||||||
|
mod avatar;
|
||||||
mod player;
|
mod player;
|
||||||
|
|
||||||
pub struct CommandManager {
|
pub struct CommandManager {
|
||||||
|
@ -80,5 +81,7 @@ impl CommandManager {
|
||||||
commands! {
|
commands! {
|
||||||
player::avatar "[player_uid] [avatar_id]" "changes player avatar for main city";
|
player::avatar "[player_uid] [avatar_id]" "changes player avatar for main city";
|
||||||
player::nickname "[player_uid] [nickname]" "changes player nickname";
|
player::nickname "[player_uid] [nickname]" "changes player nickname";
|
||||||
|
player::procedure "[player_uid] [procedure_id]" "changes current beginner procedure id, parameter -1 can be used for skipping it";
|
||||||
|
avatar::add "[player_uid] [avatar_id]" "gives avatar with specified id to player";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub async fn avatar(
|
||||||
};
|
};
|
||||||
|
|
||||||
if !tables::avatar_base_template_tb::iter().any(|tmpl| tmpl.id == avatar_id) {
|
if !tables::avatar_base_template_tb::iter().any(|tmpl| tmpl.id == avatar_id) {
|
||||||
return Ok(format!("section with id {avatar_id} doesn't exist"));
|
return Ok(format!("avatar with id {avatar_id} doesn't exist"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let should_save = {
|
let should_save = {
|
||||||
|
@ -72,15 +72,13 @@ pub async fn nickname(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(session_id) = session_id {
|
if let Some(session) = session_id.map(|id| state.session_mgr.get(id)).flatten() {
|
||||||
if let Some(session) = state.session_mgr.get(session_id) {
|
|
||||||
session
|
session
|
||||||
.notify(PlayerSyncScNotify {
|
.notify(PlayerSyncScNotify {
|
||||||
basic_info: Some(basic_info),
|
basic_info: Some(basic_info),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
state.player_mgr.save_and_remove(uid).await;
|
state.player_mgr.save_and_remove(uid).await;
|
||||||
}
|
}
|
||||||
|
@ -89,3 +87,43 @@ pub async fn nickname(
|
||||||
"successfully changed player {uid} nickname to {nickname}"
|
"successfully changed player {uid} nickname to {nickname}"
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn procedure(
|
||||||
|
args: &[&str],
|
||||||
|
state: &ServerState,
|
||||||
|
) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
|
const USAGE: &str = "Usage: player procedure [uid] [procedure_id]";
|
||||||
|
|
||||||
|
if args.len() != 2 {
|
||||||
|
return Ok(USAGE.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let uid = args[0].parse::<u32>()?;
|
||||||
|
let procedure_id = args[1].parse::<i32>()?;
|
||||||
|
|
||||||
|
if procedure_id != -1
|
||||||
|
&& !tables::procedure_config_template_tb::iter()
|
||||||
|
.any(|tmpl| tmpl.procedure_id == procedure_id)
|
||||||
|
{
|
||||||
|
return Ok(format!("procedure_id {procedure_id} doesn't exist"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(player_lock) = state.player_mgr.get_player(uid).await else {
|
||||||
|
return Ok(String::from("player not found"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let session_id = {
|
||||||
|
let mut player = player_lock.lock().await;
|
||||||
|
player.basic_data_model.beginner_procedure_id = procedure_id;
|
||||||
|
|
||||||
|
player.current_session_id()
|
||||||
|
};
|
||||||
|
|
||||||
|
if session_id.is_none() {
|
||||||
|
state.player_mgr.save_and_remove(uid).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(format!(
|
||||||
|
"successfully changed procedure_id to {procedure_id}"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use data::tables;
|
use proto::{AvatarSync, RoleModelBin};
|
||||||
use proto::RoleModelBin;
|
|
||||||
|
|
||||||
use crate::logic::role::Avatar;
|
use crate::logic::role::Avatar;
|
||||||
|
|
||||||
|
@ -10,16 +9,34 @@ pub struct RoleModel {
|
||||||
impl Default for RoleModel {
|
impl Default for RoleModel {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
avatar_list: tables::avatar_base_template_tb::iter()
|
avatar_list: Self::DEFAULT_AVATARS
|
||||||
.map(|a| a.id)
|
.iter()
|
||||||
.filter(|tmpl_id| *tmpl_id < 2000)
|
.map(|tmpl_id| Avatar::new(*tmpl_id))
|
||||||
.map(|tmpl_id| Avatar::new(tmpl_id))
|
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RoleModel {
|
impl RoleModel {
|
||||||
|
const DEFAULT_AVATARS: [u32; 2] = [1011, 1081];
|
||||||
|
|
||||||
|
pub fn add_avatar(&mut self, template_id: u32) {
|
||||||
|
if !self
|
||||||
|
.avatar_list
|
||||||
|
.iter()
|
||||||
|
.any(|a| a.template_id == template_id)
|
||||||
|
{
|
||||||
|
self.avatar_list.push(Avatar::new(template_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn avatar_sync(&self) -> AvatarSync {
|
||||||
|
AvatarSync {
|
||||||
|
avatar_list: self.avatar_list.iter().map(Avatar::to_client).collect(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_bin(bin: RoleModelBin) -> Self {
|
pub fn from_bin(bin: RoleModelBin) -> Self {
|
||||||
Self {
|
Self {
|
||||||
avatar_list: bin.avatar_list.into_iter().map(Avatar::from_bin).collect(),
|
avatar_list: bin.avatar_list.into_iter().map(Avatar::from_bin).collect(),
|
||||||
|
|
|
@ -2260,7 +2260,7 @@ pub struct PlayerSyncScNotify {
|
||||||
#[prost(message, optional, tag = "7")]
|
#[prost(message, optional, tag = "7")]
|
||||||
pub aklfkgodkde: ::core::option::Option<Dbjpegchcch>,
|
pub aklfkgodkde: ::core::option::Option<Dbjpegchcch>,
|
||||||
#[prost(message, optional, tag = "8")]
|
#[prost(message, optional, tag = "8")]
|
||||||
pub hpebckigilk: ::core::option::Option<Ibgbjekpnnb>,
|
pub avatar: ::core::option::Option<AvatarSync>,
|
||||||
#[prost(message, optional, tag = "9")]
|
#[prost(message, optional, tag = "9")]
|
||||||
pub oalcbialjcp: ::core::option::Option<Lokebkejkad>,
|
pub oalcbialjcp: ::core::option::Option<Lokebkejkad>,
|
||||||
#[prost(message, optional, tag = "10")]
|
#[prost(message, optional, tag = "10")]
|
||||||
|
@ -2865,8 +2865,8 @@ pub struct Cbjppjfbabb {
|
||||||
#[derive(proto_gen::XorFields)]
|
#[derive(proto_gen::XorFields)]
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct Cbegnphfokb {
|
pub struct AddAvatarScNotify {
|
||||||
#[prost(enumeration = "Nnhipbjjhpn", tag = "11")]
|
#[prost(enumeration = "AddAvatarPerformType", tag = "11")]
|
||||||
pub perform_type: i32,
|
pub perform_type: i32,
|
||||||
#[prost(bool, tag = "2")]
|
#[prost(bool, tag = "2")]
|
||||||
pub aobemkmdkgo: bool,
|
pub aobemkmdkgo: bool,
|
||||||
|
@ -13667,7 +13667,7 @@ pub struct Falmoffnjhn {
|
||||||
#[derive(proto_gen::XorFields)]
|
#[derive(proto_gen::XorFields)]
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct Ibgbjekpnnb {
|
pub struct AvatarSync {
|
||||||
#[prost(message, repeated, tag = "11")]
|
#[prost(message, repeated, tag = "11")]
|
||||||
pub avatar_list: ::prost::alloc::vec::Vec<AvatarInfo>,
|
pub avatar_list: ::prost::alloc::vec::Vec<AvatarInfo>,
|
||||||
#[prost(uint32, repeated, tag = "14")]
|
#[prost(uint32, repeated, tag = "14")]
|
||||||
|
@ -29107,7 +29107,7 @@ pub struct Hklkphimdcd {
|
||||||
#[prost(enumeration = "TimePeriodType", tag = "4")]
|
#[prost(enumeration = "TimePeriodType", tag = "4")]
|
||||||
pub feanogfdcjh: i32,
|
pub feanogfdcjh: i32,
|
||||||
#[prost(enumeration = "AvatarType", tag = "5")]
|
#[prost(enumeration = "AvatarType", tag = "5")]
|
||||||
pub hpebckigilk: i32,
|
pub avatar: i32,
|
||||||
}
|
}
|
||||||
#[derive(proto_gen::CmdID)]
|
#[derive(proto_gen::CmdID)]
|
||||||
#[derive(proto_gen::XorFields)]
|
#[derive(proto_gen::XorFields)]
|
||||||
|
@ -37619,7 +37619,7 @@ impl Iojdgcmbnmj {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum Fjfehdiinkj {
|
pub enum Fjfehdiinkj {
|
||||||
Dcljkmhcfdh = 0,
|
None = 0,
|
||||||
Cpehddkeocl = 1,
|
Cpehddkeocl = 1,
|
||||||
Ceemppmehlf = 2,
|
Ceemppmehlf = 2,
|
||||||
}
|
}
|
||||||
|
@ -37630,7 +37630,7 @@ impl Fjfehdiinkj {
|
||||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||||
pub fn as_str_name(&self) -> &'static str {
|
pub fn as_str_name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Fjfehdiinkj::Dcljkmhcfdh => "FJFEHDIINKJ_DCLJKMHCFDH",
|
Fjfehdiinkj::None => "FJFEHDIINKJ_NONE",
|
||||||
Fjfehdiinkj::Cpehddkeocl => "FJFEHDIINKJ_CPEHDDKEOCL",
|
Fjfehdiinkj::Cpehddkeocl => "FJFEHDIINKJ_CPEHDDKEOCL",
|
||||||
Fjfehdiinkj::Ceemppmehlf => "FJFEHDIINKJ_CEEMPPMEHLF",
|
Fjfehdiinkj::Ceemppmehlf => "FJFEHDIINKJ_CEEMPPMEHLF",
|
||||||
}
|
}
|
||||||
|
@ -37638,7 +37638,7 @@ impl Fjfehdiinkj {
|
||||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||||
match value {
|
match value {
|
||||||
"FJFEHDIINKJ_DCLJKMHCFDH" => Some(Self::Dcljkmhcfdh),
|
"FJFEHDIINKJ_NONE" => Some(Self::None),
|
||||||
"FJFEHDIINKJ_CPEHDDKEOCL" => Some(Self::Cpehddkeocl),
|
"FJFEHDIINKJ_CPEHDDKEOCL" => Some(Self::Cpehddkeocl),
|
||||||
"FJFEHDIINKJ_CEEMPPMEHLF" => Some(Self::Ceemppmehlf),
|
"FJFEHDIINKJ_CEEMPPMEHLF" => Some(Self::Ceemppmehlf),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -37649,29 +37649,29 @@ impl Fjfehdiinkj {
|
||||||
#[derive(proto_gen::XorFields)]
|
#[derive(proto_gen::XorFields)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum Nnhipbjjhpn {
|
pub enum AddAvatarPerformType {
|
||||||
Dcljkmhcfdh = 0,
|
None = 0,
|
||||||
Dcldpjgpkag = 1,
|
ShowPopup = 1,
|
||||||
Kcaachafbnc = 2,
|
Gacha = 2,
|
||||||
}
|
}
|
||||||
impl Nnhipbjjhpn {
|
impl AddAvatarPerformType {
|
||||||
/// String value of the enum field names used in the ProtoBuf definition.
|
/// String value of the enum field names used in the ProtoBuf definition.
|
||||||
///
|
///
|
||||||
/// The values are not transformed in any way and thus are considered stable
|
/// The values are not transformed in any way and thus are considered stable
|
||||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||||
pub fn as_str_name(&self) -> &'static str {
|
pub fn as_str_name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Nnhipbjjhpn::Dcljkmhcfdh => "NNHIPBJJHPN_DCLJKMHCFDH",
|
AddAvatarPerformType::None => "ADD_AVATAR_PERFORM_TYPE_NONE",
|
||||||
Nnhipbjjhpn::Dcldpjgpkag => "NNHIPBJJHPN_DCLDPJGPKAG",
|
AddAvatarPerformType::ShowPopup => "ADD_AVATAR_PERFORM_TYPE_SHOW_POPUP",
|
||||||
Nnhipbjjhpn::Kcaachafbnc => "NNHIPBJJHPN_KCAACHAFBNC",
|
AddAvatarPerformType::Gacha => "ADD_AVATAR_PERFORM_TYPE_GACHA",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||||
match value {
|
match value {
|
||||||
"NNHIPBJJHPN_DCLJKMHCFDH" => Some(Self::Dcljkmhcfdh),
|
"ADD_AVATAR_PERFORM_TYPE_NONE" => Some(Self::None),
|
||||||
"NNHIPBJJHPN_DCLDPJGPKAG" => Some(Self::Dcldpjgpkag),
|
"ADD_AVATAR_PERFORM_TYPE_SHOW_POPUP" => Some(Self::ShowPopup),
|
||||||
"NNHIPBJJHPN_KCAACHAFBNC" => Some(Self::Kcaachafbnc),
|
"ADD_AVATAR_PERFORM_TYPE_GACHA" => Some(Self::Gacha),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44829,7 +44829,7 @@ impl Cmmembfifpk {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum Onmblkkmfje {
|
pub enum Onmblkkmfje {
|
||||||
Dcljkmhcfdh = 0,
|
None = 0,
|
||||||
Njkogaelffh = 2,
|
Njkogaelffh = 2,
|
||||||
Dbldnilkljk = 3,
|
Dbldnilkljk = 3,
|
||||||
Lcdlmcjihee = 4,
|
Lcdlmcjihee = 4,
|
||||||
|
@ -44842,7 +44842,7 @@ impl Onmblkkmfje {
|
||||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||||
pub fn as_str_name(&self) -> &'static str {
|
pub fn as_str_name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Onmblkkmfje::Dcljkmhcfdh => "ONMBLKKMFJE_DCLJKMHCFDH",
|
Onmblkkmfje::None => "ONMBLKKMFJE_NONE",
|
||||||
Onmblkkmfje::Njkogaelffh => "ONMBLKKMFJE_NJKOGAELFFH",
|
Onmblkkmfje::Njkogaelffh => "ONMBLKKMFJE_NJKOGAELFFH",
|
||||||
Onmblkkmfje::Dbldnilkljk => "ONMBLKKMFJE_DBLDNILKLJK",
|
Onmblkkmfje::Dbldnilkljk => "ONMBLKKMFJE_DBLDNILKLJK",
|
||||||
Onmblkkmfje::Lcdlmcjihee => "ONMBLKKMFJE_LCDLMCJIHEE",
|
Onmblkkmfje::Lcdlmcjihee => "ONMBLKKMFJE_LCDLMCJIHEE",
|
||||||
|
@ -44852,7 +44852,7 @@ impl Onmblkkmfje {
|
||||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||||
match value {
|
match value {
|
||||||
"ONMBLKKMFJE_DCLJKMHCFDH" => Some(Self::Dcljkmhcfdh),
|
"ONMBLKKMFJE_NONE" => Some(Self::None),
|
||||||
"ONMBLKKMFJE_NJKOGAELFFH" => Some(Self::Njkogaelffh),
|
"ONMBLKKMFJE_NJKOGAELFFH" => Some(Self::Njkogaelffh),
|
||||||
"ONMBLKKMFJE_DBLDNILKLJK" => Some(Self::Dbldnilkljk),
|
"ONMBLKKMFJE_DBLDNILKLJK" => Some(Self::Dbldnilkljk),
|
||||||
"ONMBLKKMFJE_LCDLMCJIHEE" => Some(Self::Lcdlmcjihee),
|
"ONMBLKKMFJE_LCDLMCJIHEE" => Some(Self::Lcdlmcjihee),
|
||||||
|
|
Loading…
Reference in a new issue