diff --git a/core/src/ipc/zone/server/house_list.rs b/core/src/ipc/zone/server/house_list.rs index 3ca378e4..01de3280 100644 --- a/core/src/ipc/zone/server/house_list.rs +++ b/core/src/ipc/zone/server/house_list.rs @@ -1,23 +1,80 @@ +use crate::ipc::zone::PlotSize; use binrw::binrw; #[binrw] #[brw(little)] -#[derive(Debug, Clone, Copy, Default)] +#[derive(Clone, Copy, Debug, Default)] pub struct House { - pub plot_size: u8, - pub status: u8, + pub plot_size: PlotSize, + pub status: HouseStatus, #[brw(pad_after = 1)] pub flags: u8, pub fc_id: u32, pub fc_crest_id: u32, pub fc_crest_id1: u32, - pub pattern_ids: [u16; 8], - pub colors: [u8; 8], + pub exterior: HouseExterior, +} + +#[binrw] +#[brw(repr = u8)] +#[derive(Clone, Copy, Debug, Default)] +pub enum HouseStatus { + None = 0, + #[default] + UpForAuction = 1, + UnderConstruction = 2, + HouseBuilt = 3, +} + +/// Represents a House's "pattern ids", or in other words, what models make up the house's exterior. 0 indicates that item isn't present. +#[binrw] +#[derive(Clone, Copy, Debug, Default)] +pub struct HouseExterior { + /// The roof's style. + pub roof: u16, + /// The walls' style. + pub walls: u16, + /// The windows' style. + pub windows: u16, + // The front door's style. + pub door: u16, + /// The roof's fixture, like a chimney. + pub roof_fixture: u16, + /// Exterior wall fixture, like an awning. + pub wall_fixture: u16, + /// The flag/banner/crest that resides above the front door. 0 indicates it's not present. + pub above_door_banner: u16, + /// The perimeter fence's style. + pub fence: u16, + /// All of the above's dyes/stains info. + pub colors: HouseExteriorColors, +} + +/// Represents a HouseExterior's dyes/stains. +#[binrw] +#[derive(Clone, Copy, Debug, Default)] +pub struct HouseExteriorColors { + /// The roof. + pub roof: u8, + /// The walls. + pub walls: u8, + /// The windows. + pub windows: u8, + // The front door. + pub door: u8, + /// The roof's fixture. + pub roof_fixture: u8, + /// Exterior wall fixture. + pub wall_fixture: u8, + /// The flag/banner/crest that resides above the front door. + pub above_door_banner: u8, + /// The perimeter fence. + pub fence: u8, } #[binrw] #[brw(little)] -#[derive(Debug, Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct HouseList { pub land_id: u16, pub ward: u16, diff --git a/core/src/ipc/zone/server/mod.rs b/core/src/ipc/zone/server/mod.rs index bd741da1..d21eb376 100644 --- a/core/src/ipc/zone/server/mod.rs +++ b/core/src/ipc/zone/server/mod.rs @@ -111,7 +111,7 @@ mod apartment_list; pub use apartment_list::{ApartmentList, ApartmentListEntry}; mod house_list; -pub use house_list::{House, HouseList}; +pub use house_list::{House, HouseExterior, HouseList, HouseStatus}; mod housing_ward; pub use housing_ward::{HousingWardInfo, HousingWardSummaryItem}; diff --git a/servers/world/src/zone_connection/zone.rs b/servers/world/src/zone_connection/zone.rs index 1f4d9892..83f5d765 100644 --- a/servers/world/src/zone_connection/zone.rs +++ b/servers/world/src/zone_connection/zone.rs @@ -10,9 +10,9 @@ use kawari::{ config::get_config, constants::OBFUSCATION_ENABLED_MODE, ipc::zone::{ - ActorControlCategory, Condition, ContentRegistrationFlags, FurnitureList, House, HouseList, - HousingInteriorDetails, InitZone, InitZoneFlags, ServerZoneIpcData, ServerZoneIpcSegment, - WarpType, WeatherChange, + ActorControlCategory, Condition, ContentRegistrationFlags, FurnitureList, House, + HouseExterior, HouseList, HouseStatus, HousingInteriorDetails, InitZone, InitZoneFlags, + PlotSize, ServerZoneIpcData, ServerZoneIpcSegment, WarpType, WeatherChange, }, packet::{ConnectionState, PacketSegment, ScramblerKeyGenerator, SegmentData, SegmentType}, }; @@ -205,19 +205,70 @@ impl ZoneConnection { } if lua_zone.intended_use == TerritoryIntendedUse::HousingOutdoor as u8 { + let mut houses = [House::default(); 30]; + + // First, populate the houses in this ward. Note that for now, we treat every ward the same. + // TODO: For now, we hardcode 3 prefab houses as demonstration units until we implement more of the system. One cottage, one house and one mansion, all set to be individually owned and locked. Plots 5, 6, and 12 were chosen due to their close proximity to each other. + // Glade house (Wood) + houses[4] = House { + plot_size: PlotSize::Medium, + status: HouseStatus::HouseBuilt, + flags: 0, + exterior: HouseExterior { + roof: 1029, + walls: 3589, + windows: 2562, + door: 514, + ..Default::default() + }, + ..Default::default() + }; + + // Hingan mansion (Mokuzo) + houses[5] = House { + plot_size: PlotSize::Large, + status: HouseStatus::HouseBuilt, + flags: 0, + exterior: HouseExterior { + roof: 1081, + walls: 3632, + windows: 2579, + door: 531, + ..Default::default() + }, + ..Default::default() + }; + + // Highland cottage (Wood) + houses[11] = House { + plot_size: PlotSize::Small, + status: HouseStatus::HouseBuilt, + flags: 0, + exterior: HouseExterior { + roof: 1136, + walls: 3687, + windows: 2598, + door: 550, + ..Default::default() + }, + ..Default::default() + }; + let config = get_config(); self.send_ipc_self(ServerZoneIpcSegment::new(ServerZoneIpcData::HouseList( HouseList { land_id: 0, ward: 0, - territory_type_id: self.player_data.volatile.zone_id as u16, + territory_type_id: lua_zone.zone_id, world_id: config.world.world_id, - subdivision: 0, - houses: [House::default(); 30], + subdivision: 257, // TODO: Figure out more about subdivisions + houses, }, ))) .await; + // Finally, populate the exterior furniture. + // TODO: Actually send some real furniture, once we can do that! for index in 0..8 { self.send_ipc_self(ServerZoneIpcSegment::new(ServerZoneIpcData::FurnitureList( FurnitureList {