|
|
@ -310,6 +310,68 @@ impl<EG: EntityGateway> CharacterServerState<EG> { |
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result<std::option::IntoIter<SendCharacterPacket>, CharacterError> {
|
|
|
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
|
|
|
let mut user = client.user.as_mut().unwrap();
|
|
|
|
user.flags = setflag.flags;
|
|
|
|
self.entity_gateway.set_user(&user);
|
|
|
|
Ok(None.into_iter())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn param_data_chunk_request(&mut self, id: ClientId, _request: &ParamDataChunkRequest) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
|
|
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
|
|
|
let chunk = client.param_index;
|
|
|
|
client.param_index += 1;
|
|
|
|
|
|
|
|
let start = chunk * 0x6800;
|
|
|
|
let end = std::cmp::min((chunk+1)*0x6800, self.param_data.len());
|
|
|
|
|
|
|
|
let mut data = [0u8; 0x6800];
|
|
|
|
data[..end-start].copy_from_slice(&self.param_data[start..end]);
|
|
|
|
|
|
|
|
Ok(vec![SendCharacterPacket::ParamDataChunk(
|
|
|
|
ParamDataChunk {
|
|
|
|
chunk: chunk as u32,
|
|
|
|
data: data,
|
|
|
|
}
|
|
|
|
)])
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: move USERFLAGS over to SessionAction
|
|
|
|
fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
|
|
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
|
|
|
let mut user = client.user.as_mut().unwrap();
|
|
|
|
if user.flags == USERFLAG_NEWCHAR {
|
|
|
|
let mut char = self.entity_gateway.new_character_by_user(&user);
|
|
|
|
char.slot = preview.slot;
|
|
|
|
char.character = preview.character.as_character();
|
|
|
|
let char = Character {
|
|
|
|
id: 9,
|
|
|
|
slot: preview.slot,
|
|
|
|
user_id: user.id,
|
|
|
|
character: preview.character.as_character()
|
|
|
|
};
|
|
|
|
self.entity_gateway.set_character(&char);
|
|
|
|
}
|
|
|
|
if user.flags == USERFLAG_DRESSINGROOM {
|
|
|
|
// TODO: dressing room stuff
|
|
|
|
}
|
|
|
|
|
|
|
|
client.session.action = SessionAction::SelectCharacter;
|
|
|
|
client.session.character_slot = preview.slot as u8;
|
|
|
|
user.flags = 0;
|
|
|
|
self.entity_gateway.set_user(&user);
|
|
|
|
Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard.unwrap_or(0),
|
|
|
|
user.team_id.unwrap_or(1),
|
|
|
|
client.session)),
|
|
|
|
SendCharacterPacket::CharAck(CharAck {
|
|
|
|
slot: preview.slot,
|
|
|
|
code: 0
|
|
|
|
})
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn select_ship(&mut self, menuselect: &MenuSelect) -> Result<Vec<SendCharacterPacket>, CharacterError> {
|
|
|
|
if menuselect.menu != SHIP_MENU_ID {
|
|
|
|
return Err(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item));
|
|
|
@ -371,63 +433,14 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> { |
|
|
|
RecvCharacterPacket::ParamDataRequest(_request) => {
|
|
|
|
Box::new(vec![SendCharacterPacket::ParamDataHeader(self.param_header.clone())].into_iter().map(move |pkt| (id, pkt)))
|
|
|
|
},
|
|
|
|
RecvCharacterPacket::SetFlag(flags) => {
|
|
|
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
|
|
|
let mut user = client.user.as_mut().unwrap();
|
|
|
|
user.flags = flags.flags;
|
|
|
|
self.entity_gateway.set_user(&user);
|
|
|
|
Box::new(None.into_iter())
|
|
|
|
RecvCharacterPacket::SetFlag(flag) => {
|
|
|
|
Box::new(self.set_flag(id, flag)?.map(move |pkt| (id, pkt)))
|
|
|
|
},
|
|
|
|
RecvCharacterPacket::ParamDataChunkRequest(_request) => {
|
|
|
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
|
|
|
let chunk = client.param_index;
|
|
|
|
client.param_index += 1;
|
|
|
|
|
|
|
|
let start = chunk * 0x6800;
|
|
|
|
let end = std::cmp::min((chunk+1)*0x6800, self.param_data.len());
|
|
|
|
|
|
|
|
let mut data = [0u8; 0x6800];
|
|
|
|
data[..end-start].copy_from_slice(&self.param_data[start..end]);
|
|
|
|
|
|
|
|
Box::new(vec![SendCharacterPacket::ParamDataChunk(
|
|
|
|
ParamDataChunk {
|
|
|
|
chunk: chunk as u32,
|
|
|
|
data: data,
|
|
|
|
}
|
|
|
|
)].into_iter().map(move |pkt| (id, pkt)))
|
|
|
|
RecvCharacterPacket::ParamDataChunkRequest(request) => {
|
|
|
|
Box::new(self.param_data_chunk_request(id, request)?.into_iter().map(move |pkt| (id, pkt)))
|
|
|
|
},
|
|
|
|
// TODO: move USERFLAGS over to SessionAction
|
|
|
|
RecvCharacterPacket::CharacterPreview(preview) => {
|
|
|
|
let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?;
|
|
|
|
let mut user = client.user.as_mut().unwrap();
|
|
|
|
if user.flags == USERFLAG_NEWCHAR {
|
|
|
|
let mut char = self.entity_gateway.new_character_by_user(&user);
|
|
|
|
char.slot = preview.slot;
|
|
|
|
char.character = preview.character.as_character();
|
|
|
|
let char = Character {
|
|
|
|
id: 9,
|
|
|
|
slot: preview.slot,
|
|
|
|
user_id: user.id,
|
|
|
|
character: preview.character.as_character()
|
|
|
|
};
|
|
|
|
self.entity_gateway.set_character(&char);
|
|
|
|
}
|
|
|
|
if user.flags == USERFLAG_DRESSINGROOM {
|
|
|
|
// TODO: dressing room stuff
|
|
|
|
}
|
|
|
|
|
|
|
|
client.session.action = SessionAction::SelectCharacter;
|
|
|
|
client.session.character_slot = preview.slot as u8;
|
|
|
|
user.flags = 0;
|
|
|
|
self.entity_gateway.set_user(&user);
|
|
|
|
Box::new(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard.unwrap_or(0),
|
|
|
|
user.team_id.unwrap_or(1),
|
|
|
|
client.session)),
|
|
|
|
SendCharacterPacket::CharAck(CharAck {
|
|
|
|
slot: preview.slot,
|
|
|
|
code: 0
|
|
|
|
})
|
|
|
|
].into_iter().map(move |pkt| (id, pkt)))
|
|
|
|
Box::new(self.character_preview(id, preview)?.into_iter().map(move |pkt| (id, pkt)))
|
|
|
|
},
|
|
|
|
RecvCharacterPacket::MenuSelect(menuselect) => {
|
|
|
|
Box::new(self.select_ship(menuselect)?.into_iter().map(move |pkt| (id, pkt)))
|
|
|
|