Add more documentation for world messages

This commit is contained in:
lcdr
2020-11-07 21:52:26 +01:00
parent 5edd32ea82
commit 08f508a388
5 changed files with 200 additions and 15 deletions

View File

@@ -1,4 +1,4 @@
//! Client-received auth messsages.
//! Client-received auth messages.
use std::io::Result as Res;
use endio::{LEWrite, Serialize};

View File

@@ -1,3 +1,4 @@
//! Client-received world messages.
use std::io::Result as Res;
use endio::{Deserialize, LERead, LEWrite, Serialize};
@@ -8,7 +9,9 @@ use crate::common::{ObjId, LuString33, LuWString33, LVec};
use super::{Lot, Vector3, ZoneId};
use super::gm::client::SubjectGameMessage;
/// All LU messages that can be received by a client from a world server.
pub type LuMessage = crate::general::client::LuMessage<ClientMessage>;
/// All messages that can be received by a client from a world server.
pub type Message = crate::raknet::client::Message<LuMessage>;
impl From<ClientMessage> for Message {
@@ -17,6 +20,7 @@ impl From<ClientMessage> for Message {
}
}
/// All client-received world messages.
#[derive(Debug, Deserialize, PartialEq, Serialize, FromVariants, VariantTests)]
#[non_exhaustive]
#[post_disc_padding=1]
@@ -29,7 +33,7 @@ pub enum ClientMessage {
SubjectGameMessage(SubjectGameMessage) = 12,
TransferToWorld(TransferToWorld) = 14,
BlueprintLoadItemResponse(BlueprintLoadItemResponse) = 23,
FriendRequest(FriendRequest) = 27,
AddFriendRequest(AddFriendRequest) = 27,
TeamInvite(TeamInvite) = 35,
MinimumChatModeResponse(MinimumChatModeResponse) = 57,
MinimumChatModeResponsePrivate(MinimumChatModeResponsePrivate) = 58,
@@ -81,9 +85,26 @@ pub struct LoadStaticZone {
pub instance_type: InstanceType,
}
/**
Provides the list of characters of the client's account.
### Trigger
Receipt of [`CharacterListRequest`](super::server::WorldMessage::CharacterListRequest). Also sent in response to [`CharacterCreateRequest`](super::server::CharacterCreateRequest) after [`CharacterCreateResponse`] if the creation is successful.
### Handling
Display the characters to the user for selection.
### Response
None.
### Notes
The LU client can't handle sending more than four characters.
*/
#[derive(Debug, PartialEq)]
pub struct CharacterListResponse {
/// Index into the list of characters below, specifying which character was used last.
pub selected_char: u8,
/// The list of characters.
pub chars: Vec<CharListChar>,
}
@@ -114,6 +135,7 @@ impl<'a, W: LEWrite> Serialize<LE, W> for &'a CharacterListResponse
}
}
/// A character from the [`CharacterListResponse`] message.
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CharListChar {
pub obj_id: ObjId,
@@ -138,25 +160,67 @@ pub struct CharListChar {
pub equipped_items: LVec<Lot, u16>,
}
/**
Reports the result of a character create request.
### Trigger
Receipt of [`CharacterCreateRequest`](super::server::CharacterCreateRequest).
### Handling
If the variant is not [`Success`](CharacterCreateResponse::Success), display an appropriate error message and let the user try again. If successful, wait for the updated [`CharacterListResponse`] packet to arrive and display the new character list.
### Response
None.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[repr(u8)]
pub enum CharacterCreateResponse {
/// The character has been successfully created.
Success,
/// Something went wrong during creation.
GeneralFailure,
/// The selected name is not allowed by the name moderation policy.
NameNotAllowed,
/// The ThreePartName is already in use.
PredefinedNameInUse,
/// The custom name is already in use.
CustomNameInUse,
}
/**
Reports the result of a character delete request.
### Trigger
Receipt of [`CharacterDeleteRequest`](super::server::CharacterDeleteRequest).
### Handling
Delete the character locally if [`success`](Self::success) is `true`, else display an error message and keep the character.
### Response
None.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CharacterDeleteResponse {
/// Whether the deletion was successful.
pub success: bool,
}
/**
Tells the client to open a connection to another server instance.
### Trigger
The server can send this at any time, but typically does when a launchpad or command is used to go to another world. Other reasons can include the instance shutting down, or exceeding its player limit.
### Response
Close the connection after the connection to the other instance has been established.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TransferToWorld {
/// The host to connect to.
pub redirect_ip: LuString33,
/// The port to connect to.
pub redirect_port: u16,
/// If this is `true`, the original LU client displays a "Mythran dimensional shift succeeded" announcement.
pub is_maintenance_transfer: bool,
}
@@ -167,15 +231,43 @@ pub struct BlueprintLoadItemResponse {
pub dest_item_id: ObjId,
}
/**
Informs the client that another player has asked them to be their friend.
### Trigger
Receipt of `ChatMessage::AddFriendRequest` (todo). Note that friend requests should be supported even if the recipient is on another instance, so a relay infrastructure like a chat server is necessary and needs to be accounted for.
### Handling
Display a dialog to the player asking them whether to accept or deny the request.
### Response
Respond with [`AddFriendResponse`](crate::chat::server::AddFriendResponse) once the user has made their choice.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct FriendRequest {
pub struct AddFriendRequest {
/// Name of the requesting character.
pub sender_name: LuWString33,
/// Whether the request is asking to be best friends instead of just normal friends.
pub is_best_friend_request: bool,
}
/**
Informs the client that another player has asked them to be their friend.
### Trigger
Receipt of `ChatMessage::TeamInvite` (todo). Note that team invites should be supported even if the recipient is on another instance, so a relay infrastructure like a chat server is necessary and needs to be accounted for.
### Handling
Display a dialog to the player asking them whether to accept or deny the request.
### Response
Respond with [`TeamInviteResponse`](crate::chat::server::TeamInviteResponse) once the user has made their choice.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TeamInvite {
/// Name of the requesting character.
pub sender_name: LuWString33,
/// Object ID of the requesting character.
pub sender_id: ObjId,
}
@@ -193,7 +285,20 @@ pub struct MinimumChatModeResponsePrivate {
pub recipient_gm_level: u8,
}
/**
Notifies the client that its free trial status has changed.
### Trigger
Sent by the server when the status changes.
### Handling
Display appropriate UI, celebration, etc.
### Response
None.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct UpdateFreeTrialStatus {
/// Whether the player is on free trial.
pub is_free_trial: bool,
}

View File

@@ -1,5 +1,5 @@
ClientMessage::FriendRequest(
FriendRequest {
ClientMessage::AddFriendRequest(
AddFriendRequest {
sender_name: lu!("VolcanicHippieDuck"),
is_best_friend_request: false,
},

View File

@@ -13,8 +13,10 @@ use super::gm::server::SubjectGameMessage;
pub use crate::general::server::GeneralMessage;
/// All messages that can be received by a world server.
pub type Message = crate::raknet::server::Message<LuMessage>;
/// All LU messages that can be received by a world server.
#[derive(Debug, Deserialize, PartialEq, Serialize, VariantTests)]
#[repr(u16)]
pub enum LuMessage {
@@ -22,6 +24,7 @@ pub enum LuMessage {
World(WorldMessage) = ServiceId::World as u16,
}
/// All server-received world messages.
#[derive(Debug, Deserialize, PartialEq, Serialize, VariantTests)]
#[post_disc_padding=1]
#[repr(u32)]
@@ -99,32 +102,83 @@ impl<'a, W: Write+LEWrite> Serialize<LE, W> for &'a ClientValidation
}
}
/**
Requests a new character to be created.
### Trigger
The player creating a new character and submitting it to the server.
### Handling
Check if the predefined name is available. If the custom name is set, check if it is available as well. If your server has a name policy, check if the custom name is known to be unacceptable.
If all checks pass, create the character and save it to the database using the information specified in this message.
### Response
Respond with [`CharacterCreateResponse`](super::client::CharacterCreateResponse), using the appropriate variant to indicate the result. If the character creation is successful, additionally send a [`CharacterListResponse`](super::client::CharacterListResponse) afterwards with the new character included.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[trailing_padding=1]
pub struct CharacterCreateRequest {
/// The custom name, or blank if the predefined name is to be used.
pub char_name: LuWString33,
pub predef_name_id_1: u32,
pub predef_name_id_2: u32,
pub predef_name_id_3: u32,
/// First part of the predefined name.
pub predef_name_id_1: u32, // todo: enum
/// Second part of the predefined name.
pub predef_name_id_2: u32, // todo: enum
/// Third part of the predefined name.
pub predef_name_id_3: u32, // todo: enum
#[padding=9]
pub shirt_color: u32,
/// Chosen torso color.
pub torso_color: u32, // todo: enum
#[padding=4]
pub pants_color: u32,
pub hair_style: u32,
pub hair_color: u32,
/// Chosen legs color.
pub legs_color: u32, // todo: enum
/// Chosen hair style.
pub hair_style: u32, // todo: enum
/// Chosen hair color.
pub hair_color: u32, // todo: enum
#[padding=8]
pub eyebrow_style: u32,
pub eye_style: u32,
pub mouth_style: u32,
/// Chosen eyebrow style.
pub eyebrow_style: u32, // todo: enum
/// Chosen eye style.
pub eye_style: u32, // todo: enum
/// Chosen mouth style.
pub mouth_style: u32, // todo: enum
}
/**
Indicates that the player has chosen a character to play with.
### Trigger
The player selecting the character in the character selection screen and pressing play.
### Handling
Do what's necessary to let the character join the world it was last in. In the common case of the world server instance being different from the current instance, redirect the client to the world instance.
### Response
Respond with [`LoadStaticZone`](super::client::LoadStaticZone) if you're not switching instances, or [`TransferToWorld`](super::client::TransferToWorld) if you do.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CharacterLoginRequest {
/// The object ID of the chosen character.
pub char_id: ObjId,
}
/**
Requests a character to be deleted.
### Trigger
The player deleting the character and confirming with their password.
### Handling
Delete the character from the database, with appropriate cascading deletes, such as deleting the characters from any friends lists they're in.
### Response
Respond with [`CharacterDeleteResponse`](super::client::CharacterDeleteResponse) indicating whether deletion was successful.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CharacterDeleteRequest {
/// The object ID of the chosen character.
pub char_id: ObjId,
}
@@ -135,8 +189,18 @@ pub struct GeneralChatMessage {
pub message: LuVarWString<u32>,
}
/**
Reports to the server that client-side loading has finished.
### Trigger
The client finishing a zone load initiated by [`LoadStaticZone`](super::client::LoadStaticZone).
### Handling / Response
Respond with `CreateCharacter` (todo). Add the client to your server's replica manager, so that existing objects in range are replicated using `ReplicaManagerCreation` (todo). Create the character's replica object and and let the replica manager broadcast its creation to all clients in range. Finally, send [`ServerDoneLoadingAllObjects`](crate::world::gm::client::GameMessage::ServerDoneLoadingAllObjects) from the character object to the client.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct LevelLoadComplete {
/// The ID of the zone that was loaded. Servers should not trust this, as a player could use it to get into zones they don't belong.
pub zone_id: ZoneId,
}
@@ -147,11 +211,27 @@ pub enum RouteMessage {
Chat(ChatMessage) = ServiceId::Chat as u16,
}
/**
Asks the server whether a string the player entered is acceptable.
### Trigger
The player entering a string in the chat box. This message is sent as the player is typing, before pressing enter.
### Handling
Check whether the [`string`](Self::string) is acceptable per the server's moderation policy, taking into account the player's chat mode, channel, best friend status with possible recipient.
### Response
Respond with `ChatModerationString` (todo), indicating whether the string is ok, or if not, the spans that are not acceptable.
### Notes
This message is only for quick player feedback on acceptability. Final string submissions by the player will be sent in different messages (e.g. [`GeneralChatMessage`] or `Mail` (todo)). Those messages will need to be checked for moderation as well. This means that there's no harm in trusting the client to provide accurate context ([`chat_mode`](Self::chat_mode), [`chat_channel`](Self::chat_channel), [`recipient_name`](Self::recipient_name) in this message.
*/
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct StringCheck {
pub chat_mode: u8, // todo: type?
pub chat_channel: u8, // todo: type?
pub recipient_name: LuWString42,
/// The string to be checked.
pub string: LuVarWString<u16>,
}