Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/src/ipc/zone/client/client_trigger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ pub enum ClientTriggerCommand {
ward_index: u32,
},

/// The client requests to warp to the housing interior's front door.
#[brw(magic = 1122u32)]
HousingMoveToFrontDoor {},

/// The client has requested an apartment building's residents list from either an apartment building entrance or an apartment's front door.
#[brw(magic = 1125u32)]
RequestApartmentList {
Expand Down
78 changes: 78 additions & 0 deletions core/src/ipc/zone/server/housing_interior_furniture.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use crate::common::{LandId, Position};
use binrw::binrw;

#[binrw]
#[derive(Clone, Debug, Default)]
pub struct FurnitureList {
/// The LandId this list is for.
pub land_id: LandId,
pub unk1: u8,
/// The current `index` out of `count` packets to be sent.
pub index: u8,
/// The number of these lists that will be sent.
pub count: u8,
/// Seems to be some sort of outdoor vs indoor flag. If it's 0, it means this is for outdoor furniture, and 100 means it's for an interior.
pub unk2: u8,
/// The actual furnishings.
#[br(count = Furniture::COUNT)]
#[brw(pad_size_to = Furniture::COUNT * Furniture::SIZE)]
#[brw(pad_after = 4)] // Seems to be empty/zeroes
pub furniture: Vec<Furniture>,
}

#[binrw]
#[derive(Copy, Clone, Debug, Default)]
pub struct HousingInteriorDetails {
/// This interior's window style.
pub window_style: u16,
pub unk1: u16, // Sapphire calls this "window color", but windows cannot be dyed?
/// This interior's door style.
pub door_style: u16,
/// This interior door's dye colour. Index into the Stain Excel sheet.
pub door_stain: u16,
/// The light level in the interior. Note that this is actually described in terms of a level of *darkness*. When the client sets the UI light level to 5, the client will send value 0 in the ClientTrigger. Other examples: light level 1 will send 4, light level 2 will send 3, and so on.
pub light_level: u8,
pub unk2: [u8; 3], // likely just padding
/// The ground floor's wall style. In an apartment, this along with ground_floor and ground_chandelier dictate what will decorate the apartment, leaving doors, windows, top floor and cellar all zeroes/blank.
// TODO: It's unclear if these are pairs of u16s or just u32s.
// NOTE: Be careful when experimenting with these values, as invalid combinations of u16s can crash the client, particularly if the interior is an apartment and top floor or cellar values are changed!
pub ground_walls: u32,
/// The ground floor's style/texture.
pub ground_floor: u32,
/// THe ground floor's chandelier. Unknown if this is a model id + toggle, or an item id + toggle.
pub ground_chandelier: u32,
/// The top floor's wall style/texture.
pub top_walls: u32,
/// The top floor's style/texture.
pub top_floor: u32,
/// The top floor's chandelier.
pub top_chandelier: u32,
/// The cellar's wall style/texture.
pub cellar_walls: u32,
/// The cellar's floor syle/texture.
pub cellar_floor: u32,
/// The cellar's chandelier.
pub cellar_chandelier: u32,
pub unk_interior: u32, // Unclear what this is, it can have data in mansions but not apartments or medium houses?
unk3: u32, // Might just be padding, seen as zeroes so far
}

#[binrw]
#[derive(Copy, Clone, Debug, Default)]
pub struct Furniture {
/// Index into the FurnitureCatalogItemList sheet. If 0, no item is present in this entry. Therefore, this index needs to subtract 1 when indexing into the sheet!
pub catalog_id: u16,
pub unk1: u16, // Seems to always be 1 when this item is present.
/// Index into the Stain sheet. Sets the dye for this item.
pub stain: u16,
pub unk2: [u8; 2], // Likely padding, but unsure.
/// This item's rotation.
pub rotation: f32,
/// This item's 3d coordinates in the housing interior.
pub position: Position,
}

impl Furniture {
pub const SIZE: usize = 24;
pub const COUNT: usize = 100;
}
14 changes: 5 additions & 9 deletions core/src/ipc/zone/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ pub use house_list::{House, HouseList};
mod housing_ward;
pub use housing_ward::{HousingWardInfo, HousingWardSummaryItem};

mod housing_interior_furniture;
pub use housing_interior_furniture::{Furniture, FurnitureList, HousingInteriorDetails};

mod housing_occupied_land_info;
pub use housing_occupied_land_info::HousingOccupiedLandInfo;

Expand Down Expand Up @@ -850,12 +853,7 @@ pub enum ServerZoneIpcData {
index: u8,
unk2: [u8; 7], // all padding
},
UnkHousingRelated {
unk1: [u8; 9],
index: u8,
count: u8,
unk2: [u8; 2135],
},
FurnitureList(FurnitureList),
OwnedHousing {
#[brw(pad_after = 8)] // believe these are always empty?
unk1: LandData,
Expand Down Expand Up @@ -1282,9 +1280,7 @@ pub enum ServerZoneIpcData {
#[brw(pad_after = 16)] // Seems to be empty/zeroes
unk: u32,
},
UnkHousingRelated2 {
unk: [u8; 56],
},
HousingInteriorDetails(HousingInteriorDetails),
ApartmentList(ApartmentList),
FriendRemoved {
#[brw(pad_after = 4)] // Seems to be empty/zeroes
Expand Down
10 changes: 5 additions & 5 deletions resources/data/opcodes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -495,10 +495,10 @@ ServerZoneIpcType:
comment: Updates a map effect.
opcode: 746
size: 16
- name: UnkHousingRelated
comment: Unknown purpose.
- name: FurnitureList
comment: Sent by the server to inform the client about furniture (both indoor & outdoor) that exists in this ward or housing interior.
opcode: 376
size: 2146
size: 2416
- name: OwnedHousing
comment: Sent to inform you of which housing you own/have access to.
opcode: 404
Expand Down Expand Up @@ -675,8 +675,8 @@ ServerZoneIpcType:
comment: The server sends the client an error message due to something going wrong with a linkshell.
opcode: 190
size: 24
- name: UnkHousingRelated2
comment: The server sends the client currently unknown information about the housing interior they're entering.
- name: HousingInteriorDetails
comment: The server sends the client exhaustive information (wall/floor textures, window models, etc.) about the housing interior they entered.
opcode: 389
size: 56
- name: ApartmentList
Expand Down
42 changes: 25 additions & 17 deletions servers/world/src/zone_connection/zone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ use crate::{
lua::{LuaContent, LuaZone},
};
use kawari::{
common::{HandlerId, HandlerType, Position, timestamp_secs},
common::{HandlerId, HandlerType, LandId, Position, timestamp_secs},
config::get_config,
constants::OBFUSCATION_ENABLED_MODE,
ipc::zone::{
ActorControlCategory, Condition, ContentRegistrationFlags, House, HouseList, InitZone,
InitZoneFlags, ServerZoneIpcData, ServerZoneIpcSegment, WarpType, WeatherChange,
ActorControlCategory, Condition, ContentRegistrationFlags, FurnitureList, House, HouseList,
HousingInteriorDetails, InitZone, InitZoneFlags, ServerZoneIpcData, ServerZoneIpcSegment,
WarpType, WeatherChange,
},
packet::{ConnectionState, PacketSegment, ScramblerKeyGenerator, SegmentData, SegmentType},
};
Expand Down Expand Up @@ -218,33 +219,40 @@ impl ZoneConnection {
.await;

for index in 0..8 {
self.send_ipc_self(ServerZoneIpcSegment::new(
ServerZoneIpcData::UnkHousingRelated {
unk1: [0xFF; 9],
index,
self.send_ipc_self(ServerZoneIpcSegment::new(ServerZoneIpcData::FurnitureList(
FurnitureList {
count: 8,
unk2: [0; 2135],
index,
..Default::default()
},
))
)))
.await;
}
}

if lua_zone.intended_use == TerritoryIntendedUse::HousingIndoor as u8 {
// Bare minimum stuff to make housing interiors load, hardly anything is known about these for now
let config = get_config();
// Bare minimum stuff to make housing interiors load
self.send_ipc_self(ServerZoneIpcSegment::new(
ServerZoneIpcData::UnkHousingRelated2 { unk: [0; 56] },
ServerZoneIpcData::HousingInteriorDetails(HousingInteriorDetails::default()),
))
.await;

self.send_ipc_self(ServerZoneIpcSegment::new(
ServerZoneIpcData::UnkHousingRelated {
unk1: [0; 9], // Slight hack for now: these need to be something other than 0xFF or housing items can't spawn via plugins
index: 0,
// The LandId is currently set so that plugins like HousingPos/Buildingway can plop stuff down
self.send_ipc_self(ServerZoneIpcSegment::new(ServerZoneIpcData::FurnitureList(
FurnitureList {
land_id: LandId {
id: 128,
ward: 1,
territory_type_id: lua_zone.zone_id,
world_id: config.world.world_id,
},
count: 1,
unk2: [0xFF; 2135], // Slight hack for now: if it's all zeroes, plugins like housingpos won't be able to arbitrarily spawn client-side-only housing items
index: 0,
unk2: 100, // Indoors
..Default::default()
},
))
)))
.await;
}

Expand Down
Loading