diff --git a/src/common/Common.h b/src/common/Common.h index 5cfd5a63..b03618ef 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -758,7 +758,7 @@ namespace Core::Common SubTag2 }; - enum LandPermissionSlot + enum LandFlagsSlot { FreeCompany, Private, @@ -774,6 +774,15 @@ namespace Core::Common Private = 2, }; + enum LandFlags : uint32_t + { + ESTATE_BUILT = 0x1, + ESTATE_HAS_AETHERYTE = 0x2, + UNKNOWN_1 = 0x4, + UNKNOWN_2 = 0x8, + UNKNOWN_3 = 0x10, + }; + struct LandIdent { int16_t landId; //00 @@ -782,10 +791,10 @@ namespace Core::Common int16_t worldId; //06 }; - struct LandPermissionSet + struct LandFlagSet { LandIdent landIdent; - uint32_t permissionMask; //08 + uint32_t landFlags; //08 uint32_t unkown1; //12 }; @@ -834,7 +843,7 @@ namespace Core::Common Venue = 11, }; - enum WardEstateFlags : uint8_t + enum WardlandFlags : uint8_t { IsEstateOwned = 1, IsPublicEstate = 2, diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index a7c3533f..74b997d1 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -193,8 +193,9 @@ namespace Core::Network::Packets HousingEstateGreeting = 0x0227, // updated 4.4 - LandPermissionSlot = 0x0228, // updated 4.4 - LandPermission = 0x0229, // updated 4.4 + HousingUpdateLandFlagsSlot = 0x0228, // updated 4.4 + HousingLandFlags = 0x0229, // updated 4.4 + HousingShowEstateGuestAccess = 0x022A, // updated 4.4 LandSetYardInitialize = 0x022C, // updated 4.4 @@ -204,6 +205,8 @@ namespace Core::Network::Packets SharedEstateSettingsResponse = 0x023C, // updated 4.4 + LandUpdateHouseName = 0x024D, // updated 4.4 + LandSetMap = 0x0251, // updated 4.4 ////////////////////////////////////////////////// @@ -302,6 +305,7 @@ namespace Core::Network::Packets LinkshellEventHandler1 = 0x1151, // updated 4.1 ?? LandRenameHandler = 0x0171, // updated 4.4 + HousingUpdateHouseGreeting = 0x0172, // updated 4.4 SetSharedEstateSettings = 0x0177, // updated 4.4 diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index 88e6134e..69ba674c 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -199,14 +199,18 @@ struct FFXIVIpcInventoryModifyHandler : struct FFXIVIpcRenameLandHandler : FFXIVIpcBasePacket< LandRenameHandler > { - /* 0000 */ uint16_t landId; - /* 0002 */ uint16_t wardNum; - /* 0004 */ uint16_t zoneId; - /* 0006 */ uint16_t worldId; - /* 0008 */ char landName[20]; + /* 0000 */ Common::LandIdent ident; + /* 0008 */ char houseName[20]; /* 0028 */ uint32_t padding; }; +struct FFXIVIpcHousingUpdateHouseGreeting : + FFXIVIpcBasePacket< HousingUpdateHouseGreeting > +{ + /* 0000 */ Common::LandIdent ident; + /* 0008 */ char greeting[200]; +}; + struct FFXIVIpcBuildPresetHandler : FFXIVIpcBasePacket< BuildPresetHandler > { diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 2c25972d..215a14d0 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1575,24 +1575,24 @@ struct FFXIVIpcPerformNote : FFXIVIpcBasePacket< PerformNote > uint8_t data[32]; }; -struct FFXIVIpcLandPermissionSlot : FFXIVIpcBasePacket< LandPermissionSlot > +struct FFXIVIpcHousingUpdateLandFlagsSlot : FFXIVIpcBasePacket< HousingUpdateLandFlagsSlot > { uint32_t type; uint32_t unknown; - Common::LandPermissionSet permissionSet; + Common::LandFlagSet flagSet; }; -struct FFXIVIpcLandPermission : FFXIVIpcBasePacket< LandPermission > +struct FFXIVIpcHousingLandFlags : FFXIVIpcBasePacket< HousingLandFlags > { - Common::LandPermissionSet freeCompanyHouse; // 00 + Common::LandFlagSet freeCompanyHouse; // 00 uint64_t unkown1; - Common::LandPermissionSet privateHouse; // 24 + Common::LandFlagSet privateHouse; // 24 uint64_t unkown2; - Common::LandPermissionSet apartment; // 48 + Common::LandFlagSet apartment; // 48 uint64_t unkown3; - Common::LandPermissionSet sharedHouse[2]; //72 + Common::LandFlagSet sharedHouse[2]; //72 uint64_t unkown4; - Common::LandPermissionSet unkownHouse; + Common::LandFlagSet unkownHouse; uint64_t unkown5; }; @@ -1640,10 +1640,17 @@ struct FFXIVIpcLandInfoSign : FFXIVIpcBasePacket< LandInfoSign > struct FFXIVIpcLandRename : FFXIVIpcBasePacket< LandRename > { Common::LandIdent landIdent; - char landName[20]; + char houseName[20]; uint32_t padding; }; +struct FFXIVIpcLandUpdateHouseName : FFXIVIpcBasePacket< LandUpdateHouseName > +{ + uint32_t unknown[3]; + char houseName[20]; + uint32_t unknown2[2]; +}; + struct FFXIVIpcLandSetMap : FFXIVIpcBasePacket< LandSetMap > { uint8_t u1; @@ -1723,13 +1730,17 @@ struct FFXIVIpcHousingWardInfo : FFXIVIpcBasePacket< HousingWardInfo > struct FFXIVIpcHousingEstateGreeting : FFXIVIpcBasePacket< HousingEstateGreeting > { - uint8_t plotId; - uint8_t pad[3]; // unsure - uint16_t territoryTypeId; - uint16_t unk; + Common::LandIdent landIdent; char message[200]; }; +struct FFXIVIpcHousingShowEstateGuestAccess : + FFXIVIpcBasePacket< HousingShowEstateGuestAccess > +{ + uint32_t unknown[2]; + Common::LandIdent ident; +}; + /** * Structural representation of the packet sent by the server * to show the current shared estate settings diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 6f2866d6..79f24075 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -94,8 +94,8 @@ Core::Entity::Player::Player() : for ( uint8_t i = 0; i < 5; i++ ) { - memset( &m_landPermission[i], 0xFF, 8 ); - memset( &m_landPermission[i].permissionMask, 0, 8 ); + memset( &m_landFlags[i], 0xFF, 8 ); + memset( &m_landFlags[i].landFlags, 0, 8 ); } m_objSpawnIndexAllocator.init( MAX_DISPLAYED_EOBJS ); @@ -1290,6 +1290,12 @@ void Core::Entity::Player::sendDebug( const std::string& message ) //Grey Text queuePacket( std::make_shared< ChatPacket >( *getAsPlayer(), ChatType::ServerDebug, message ) ); } +void Core::Entity::Player::sendLogMessage( uint32_t messageId, uint32_t param2, uint32_t param3, + uint32_t param4, uint32_t param5, uint32_t param6 ) +{ + queuePacket( makeActorControl144( getId(), ActorControlType::LogMsg, messageId, param2, param3, param4, param5, param6 ) ); +} + void Core::Entity::Player::updateHowtosSeen( uint32_t howToId ) { uint8_t index = howToId / 8; @@ -1587,10 +1593,20 @@ void Core::Entity::Player::sendZonePackets() auto pHousingMgr = g_fw.get< HousingMgr >(); if( Core::LandPtr pLand = pHousingMgr->getLandByOwnerId( getId() ) ) { - setLandPermissions( LandPermissionSlot::Private, 0x00, pLand->getLandId(), pLand->getWardNum(), pLand->getTerritoryTypeId() ); + uint32_t state = 0; + + if( pLand->getHouse() ) + { + state |= ESTATE_BUILT; + + // todo: remove this, debug for now + state |= ESTATE_HAS_AETHERYTE; + } + + setLandFlags( LandFlagsSlot::Private, state, pLand->getLandId(), pLand->getWardNum(), pLand->getTerritoryTypeId() ); } - sendLandPermissions(); + sendLandFlags(); auto initZonePacket = makeZonePacket< FFXIVIpcInitZone >( getId() ); initZonePacket->data().zoneId = getCurrentZone()->getTerritoryTypeId(); @@ -1768,47 +1784,53 @@ bool Core::Entity::Player::isOnEnterEventDone() const return m_onEnterEventDone; } -void Core::Entity::Player::setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, +void Core::Entity::Player::setLandFlags( uint8_t flagSlot, uint32_t landFlags, int16_t landId, int16_t wardNum, int16_t zoneId ) { - m_landPermission[ permissionSet ].landIdent.landId = landId; - m_landPermission[ permissionSet ].landIdent.wardNum = wardNum; - m_landPermission[ permissionSet ].landIdent.territoryTypeId = zoneId; - m_landPermission[ permissionSet ].landIdent.worldId = 67; - m_landPermission[ permissionSet ].permissionMask = permissionMask; - m_landPermission[ permissionSet ].unkown1 = 0; + m_landFlags[ flagSlot ].landIdent.landId = landId; + m_landFlags[ flagSlot ].landIdent.wardNum = wardNum; + m_landFlags[ flagSlot ].landIdent.territoryTypeId = zoneId; + m_landFlags[ flagSlot ].landIdent.worldId = 67; + m_landFlags[ flagSlot ].landFlags = landFlags; + m_landFlags[ flagSlot ].unkown1 = 0; } -void Core::Entity::Player::sendLandPermissions() +void Core::Entity::Player::sendLandFlags() { - auto landPermissions = makeZonePacket< FFXIVIpcLandPermission >( getId() ); + auto landFlags = makeZonePacket< FFXIVIpcHousingLandFlags >( getId() ); - landPermissions->data().freeCompanyHouse = m_landPermission[Common::LandPermissionSlot::FreeCompany]; - landPermissions->data().privateHouse = m_landPermission[Common::LandPermissionSlot::Private]; - landPermissions->data().apartment = m_landPermission[Common::LandPermissionSlot::Apartment]; - landPermissions->data().sharedHouse[0] = m_landPermission[Common::LandPermissionSlot::SharedHouse1]; - landPermissions->data().sharedHouse[1] = m_landPermission[Common::LandPermissionSlot::SharedHouse2]; - memset( &landPermissions->data().unkownHouse, 0xFF, 8 ); - memset( &landPermissions->data().unkownHouse.permissionMask, 0, 8 ); - landPermissions->data().unkownHouse.permissionMask = 2; - landPermissions->data().unkown1 = 0; - landPermissions->data().unkown2 = 0; - landPermissions->data().unkown3 = 0; - landPermissions->data().unkown4 = 0; - landPermissions->data().unkown5 = 0; + landFlags->data().freeCompanyHouse = m_landFlags[ Common::LandFlagsSlot::FreeCompany ]; + landFlags->data().privateHouse = m_landFlags[ Common::LandFlagsSlot::Private ]; + landFlags->data().apartment = m_landFlags[ Common::LandFlagsSlot::Apartment ]; + landFlags->data().sharedHouse[ 0 ] = m_landFlags[ Common::LandFlagsSlot::SharedHouse1 ]; + landFlags->data().sharedHouse[ 1 ] = m_landFlags[ Common::LandFlagsSlot::SharedHouse2 ]; - queuePacket( landPermissions ); + queuePacket( landFlags ); } -void Core::Entity::Player::sendLandPermissionSlot( uint8_t slotId, uint8_t landId, uint8_t wardId, uint16_t zoneId ) +void Core::Entity::Player::sendLandFlagsSlot( Common::LandFlagsSlot slot ) { - auto landPermissions = makeZonePacket< FFXIVIpcLandPermissionSlot >( getId() ); - landPermissions->data().type = slotId; + auto landFlags = makeZonePacket< FFXIVIpcHousingUpdateLandFlagsSlot >( getId() ); - landPermissions->data().permissionSet.landIdent.landId = landId; - landPermissions->data().permissionSet.landIdent.wardNum = wardId; - landPermissions->data().permissionSet.landIdent.territoryTypeId = zoneId; - landPermissions->data().permissionSet.landIdent.worldId = 67; - landPermissions->data().permissionSet.permissionMask = 0; - queuePacket( landPermissions ); + uint32_t type = 0; + + switch( slot ) + { + case LandFlagsSlot::Private: + type = static_cast< uint32_t >( LandType::Private ); + break; + + case LandFlagsSlot::FreeCompany: + type = static_cast< uint32_t >( LandType::FreeCompany ); + break; + + default: + // todo: other/unsupported land types + return; + } + + landFlags->data().type = type; + landFlags->data().flagSet = m_landFlags[ slot ]; + + queuePacket( landFlags ); } \ No newline at end of file diff --git a/src/servers/sapphire_zone/Actor/Player.h b/src/servers/sapphire_zone/Actor/Player.h index 6462e6ea..9633a618 100644 --- a/src/servers/sapphire_zone/Actor/Player.h +++ b/src/servers/sapphire_zone/Actor/Player.h @@ -757,16 +757,18 @@ namespace Core::Entity void sendDebug( const std::string& message ); + void sendLogMessage( uint32_t messageId, uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0, uint32_t param5 = 0, uint32_t param6 = 0 ); + bool isDirectorInitialized() const; void setDirectorInitialized( bool isInitialized ); // Housing Handling ////////////////////////////////////////////////////////////////////////////////////////////////////// - void setLandPermissions( uint8_t permissionSet, uint32_t permissionMask, int16_t landId, int16_t wardNum, int16_t zoneId ); + void setLandFlags( uint8_t permissionSet, uint32_t landFlags, int16_t landId, int16_t wardNum, int16_t zoneId ); - void sendLandPermissions(); - void sendLandPermissionSlot( uint8_t slotId, uint8_t landId, uint8_t wardId, uint16_t zoneId ); + void sendLandFlags(); + void sendLandFlagsSlot( Common::LandFlagsSlot slot ); // Player Battle Handling ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1025,7 +1027,7 @@ namespace Core::Entity uint8_t m_searchSelectClass; // class selected to show up in profile // housing info - Common::LandPermissionSet m_landPermission[5]; + Common::LandFlagSet m_landFlags[5]; Common::ActiveLand m_activeLand; diff --git a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp index f1962bf4..86da3c95 100644 --- a/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/sapphire_zone/DebugCommand/DebugCommandHandler.cpp @@ -730,7 +730,7 @@ void Core::DebugCommandHandler::script( char* data, Entity::Player& player, std: for( auto it = scripts.begin(); it != scripts.end(); ++it ) { auto script = *it; - player.sendDebug( " - '" + script->library_name + + player.sendDebug( " - '" + script->library_name + ", num scripts: " + std::to_string( script->scripts.size() ) ); } } @@ -1018,8 +1018,8 @@ void Core::DebugCommandHandler::housing( char* data, Entity::Player& player, std auto pHousing = std::dynamic_pointer_cast< HousingZone >( pZone ); if( pHousing ) { - player.setLandPermissions( permissionSet, 0, pHousing->getLandSetId(), pHousing->getWardNum(), pHousing->getTerritoryTypeId() ); - player.sendLandPermissions(); + player.setLandFlags( permissionSet, 0, pHousing->getLandSetId(), pHousing->getWardNum(), pHousing->getTerritoryTypeId() ); + player.sendLandFlags(); } else player.sendDebug( "You aren't in a housing Zone." ); diff --git a/src/servers/sapphire_zone/Network/GameConnection.cpp b/src/servers/sapphire_zone/Network/GameConnection.cpp index bfeda82f..71028d7a 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.cpp +++ b/src/servers/sapphire_zone/Network/GameConnection.cpp @@ -85,6 +85,9 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive, setZoneHandler( ClientZoneIpcType::BuildPresetHandler, "BuildPresetHandler", &GameConnection::buildPresetHandler ); setZoneHandler( ClientZoneIpcType::LandRenameHandler, "LandRenameHandler", &GameConnection::landRenameHandler ); + setZoneHandler( ClientZoneIpcType::HousingUpdateHouseGreeting, "HousingUpdateHouseGreeting", + &GameConnection::housingUpdateGreetingHandler ); + setZoneHandler( ClientZoneIpcType::TalkEventHandler, "EventHandlerTalk", &GameConnection::eventHandlerTalk ); setZoneHandler( ClientZoneIpcType::EmoteEventHandler, "EventHandlerEmote", &GameConnection::eventHandlerEmote ); setZoneHandler( ClientZoneIpcType::WithinRangeEventHandler, "EventHandlerWithinRange", @@ -225,7 +228,7 @@ void Core::Network::GameConnection::handleZonePacket( Core::Network::Packets::FF else { pLog->debug( sessionStr + " Undefined Zone IPC : Unknown ( " + - Util::intToHexString( static_cast< uint32_t >( opcode ), 4 ) + " )" ); + Util::intToHexString( static_cast< uint32_t >( opcode ), 4 ) + " )" ); pLog->debug( "Dump:\n" + Util::binaryToHexDump( const_cast< uint8_t* >( &pPacket.data[ 0 ] ), pPacket.segHdr.size ) ); } diff --git a/src/servers/sapphire_zone/Network/GameConnection.h b/src/servers/sapphire_zone/Network/GameConnection.h index c6ab31ae..9ab043f2 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.h +++ b/src/servers/sapphire_zone/Network/GameConnection.h @@ -152,7 +152,7 @@ namespace Core::Network DECLARE_HANDLER( cfRegisterRoulette ); DECLARE_HANDLER( cfDutyAccepted ); - + DECLARE_HANDLER( actionHandler ); DECLARE_HANDLER( gm1Handler ); @@ -165,6 +165,8 @@ namespace Core::Network DECLARE_HANDLER( landRenameHandler ); + DECLARE_HANDLER( housingUpdateGreetingHandler ); + DECLARE_HANDLER( buildPresetHandler ); DECLARE_HANDLER( tellHandler ); diff --git a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp index 137e8424..444a01dc 100644 --- a/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/ClientTriggerHandler.cpp @@ -10,9 +10,7 @@ #include "Zone/Zone.h" #include "Zone/ZonePosition.h" -#include "Zone/HousingZone.h" #include "Zone/HousingMgr.h" -#include "Zone/Land.h" #include "Network/GameConnection.h" @@ -364,31 +362,49 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR } case ClientTriggerType::RequestEstateRename: { - // removed temporarly, there is no such thing as a LandName -/* auto landRenamePacket = makeZonePacket< Server::FFXIVIpcLandRename >( player.getId() ); + uint16_t territoryTypeId = param11 & 0xFFFF; + uint16_t worldId = param11 >> 16; uint8_t ward = ( param12 & 0xFF00 ) >> 8; uint8_t plot = ( param12 & 0xFF ); - auto zone = player.getCurrentZone(); + auto pHousingMgr = g_fw.get< HousingMgr >(); + if( !pHousingMgr ) + break; - auto hZone = std::dynamic_pointer_cast< HousingZone >( zone ); + pHousingMgr->requestEstateRename( player, territoryTypeId, worldId, ward, plot ); - auto land = hZone->getLand( plot ); + break; + } + case ClientTriggerType::RequestEstateEditGreeting: + { + uint16_t territoryTypeId = param11 & 0xFFFF; + uint16_t worldId = param11 >> 16; - if( !land ) - { - auto pHousingMgr = g_fw.get< HousingMgr >(); - land = pHousingMgr->getLandByOwnerId( player.getId() ); - } + uint8_t ward = ( param12 & 0xFF00 ) >> 8; + uint8_t plot = ( param12 & 0xFF ); - landRenamePacket->data().landId = land->getLandId(); - landRenamePacket->data().wardNum = land->getWardNum(); - landRenamePacket->data().worldId = 67; - landRenamePacket->data().zoneId = land->getZoneId(); - memcpy( &landRenamePacket->data().landName, land->getLandName().c_str(), 20 ); + auto pHousingMgr = g_fw.get< HousingMgr >(); + if( !pHousingMgr ) + break; - player.queuePacket( landRenamePacket ); */ + pHousingMgr->requestEstateEditGreeting( player, territoryTypeId, worldId, ward, plot ); + + break; + } + case ClientTriggerType::RequestEstateEditGuestAccessSettings: + { + uint16_t territoryTypeId = param11 & 0xFFFF; + uint16_t worldId = param11 >> 16; + + uint8_t ward = ( param12 & 0xFF00 ) >> 8; + uint8_t plot = ( param12 & 0xFF ); + + auto pHousingMgr = g_fw.get< HousingMgr >(); + if( !pHousingMgr ) + break; + + pHousingMgr->requestEstateEditGuestAccess( player, territoryTypeId, worldId, ward, plot ); break; } diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index 821b9b3d..e6cd8a16 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -20,6 +20,7 @@ #include "Zone/HousingMgr.h" #include "Zone/Land.h" #include "Zone/ZonePosition.h" +#include "Zone/House.h" #include "Network/PacketWrappers/InitUIPacket.h" #include "Network/PacketWrappers/PingPacket.h" @@ -657,15 +658,32 @@ void Core::Network::GameConnection::landRenameHandler( const Core::Network::Pack { const auto packet = ZoneChannelPacket< Client::FFXIVIpcRenameLandHandler >( inPacket ); - uint32_t landSetId = ( static_cast< uint32_t >( packet.data().zoneId ) << 16 ) | packet.data().wardNum; auto pHousingMgr = g_fw.get< HousingMgr >(); - auto pLand = pHousingMgr->getHousingZoneByLandSetId( landSetId )->getLand( packet.data().landId ); + auto landSetId = pHousingMgr->toLandSetId( packet.data().ident.territoryTypeId, packet.data().ident.wardNum ); + + auto pZone = pHousingMgr->getHousingZoneByLandSetId( landSetId ); + if( !pZone ) + return; + + auto pLand = pZone->getLand( packet.data().ident.landId ); if( !pLand ) return; - // TODO set estate name - //pLand->setLandName( packet.data().landName ); + // todo: check perms for fc houses and shit + if( pLand->getPlayerOwner() != player.getId() ) + return; + + auto pHouse = pLand->getHouse(); + if( pHouse ) + pHouse->setHouseName( packet.data().houseName ); + + // todo: this packet is weird, retail sends it with some unknown shit at the start but it doesn't seem to do anything + auto nameUpdatePacket = makeZonePacket< Server::FFXIVIpcLandUpdateHouseName >( player.getId() ); + memcpy( &nameUpdatePacket->data().houseName, &packet.data().houseName, sizeof( packet.data().houseName ) ); + + // todo: who does this get sent to? just the person who renamed it? + player.queuePacket( nameUpdatePacket ); } void Core::Network::GameConnection::buildPresetHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, @@ -676,3 +694,13 @@ void Core::Network::GameConnection::buildPresetHandler( const Core::Network::Pac auto pHousingMgr = g_fw.get< HousingMgr >(); pHousingMgr->buildPresetEstate( player, packet.data().plotNum, packet.data().itemId ); } + +void Core::Network::GameConnection::housingUpdateGreetingHandler( const Core::Network::Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) +{ + const auto packet = ZoneChannelPacket< Client::FFXIVIpcHousingUpdateHouseGreeting >( inPacket ); + + auto pHousingMgr = g_fw.get< HousingMgr >(); + + pHousingMgr->updateEstateGreeting( player, packet.data().ident, std::string( packet.data().greeting ) ); +} diff --git a/src/servers/sapphire_zone/Zone/House.cpp b/src/servers/sapphire_zone/Zone/House.cpp index 333bfec4..498a0781 100644 --- a/src/servers/sapphire_zone/Zone/House.cpp +++ b/src/servers/sapphire_zone/Zone/House.cpp @@ -35,6 +35,9 @@ Core::House::House( uint32_t houseId, uint32_t landSetId, uint8_t landId, uint8_ stmt->setUInt( 2, m_houseId ); pDB->execute( stmt ); + + // todo: make this nicer/configurable? + m_houseName = "Estate #" + std::to_string( landId + 1 ); } else { @@ -45,11 +48,10 @@ Core::House::House( uint32_t houseId, uint32_t landSetId, uint8_t landId, uint8_ auto housePartColours = res->getBlobVector( "HousePartColours" ); auto models = reinterpret_cast< uint32_t* >( &housePartModels[ 0 ] ); - auto colours = &housePartColours[ 0 ]; for( auto i = 0; i < 8; i++ ) { - m_houseParts[ i ] = { models[ i ], colours[ i ] }; + m_houseParts[ i ] = { models[ i ], housePartColours[ i ] }; } } } @@ -143,4 +145,28 @@ uint32_t Core::House::getHousePart( Common::HousePartSlot slot ) const Core::House::HousePartsArray const& Core::House::getHouseParts() const { return m_houseParts; +} + +const std::string& Core::House::getHouseName() const +{ + return m_houseName; +} + +const std::string& Core::House::getHouseGreeting() const +{ + return m_estateMessage; +} + +void Core::House::setHouseGreeting( const std::string& greeting ) +{ + m_estateMessage = greeting; + + updateHouseDb(); +} + +void Core::House::setHouseName( const std::string& name ) +{ + m_houseName = name; + + updateHouseDb(); } \ No newline at end of file diff --git a/src/servers/sapphire_zone/Zone/House.h b/src/servers/sapphire_zone/Zone/House.h index 17abaaba..ec2d3df4 100644 --- a/src/servers/sapphire_zone/Zone/House.h +++ b/src/servers/sapphire_zone/Zone/House.h @@ -25,6 +25,12 @@ namespace Core uint16_t getTerritoryTypeId() const; uint32_t getHouseId() const; + const std::string& getHouseName() const; + void setHouseName( const std::string& name ); + + const std::string& getHouseGreeting() const; + void setHouseGreeting( const std::string& greeting ); + //functions void setHousePart( Common::HousePartSlot slot, uint32_t id ); void setHousePartColor( Common::HousePartSlot slot, uint32_t id ); diff --git a/src/servers/sapphire_zone/Zone/HousingMgr.cpp b/src/servers/sapphire_zone/Zone/HousingMgr.cpp index 0ff6dd85..09476248 100644 --- a/src/servers/sapphire_zone/Zone/HousingMgr.cpp +++ b/src/servers/sapphire_zone/Zone/HousingMgr.cpp @@ -9,6 +9,7 @@ #include #include +#include #include "Actor/Player.h" @@ -19,6 +20,7 @@ #include "Land.h" #include "Framework.h" #include "ServerMgr.h" +#include "House.h" using namespace Core::Common; using namespace Core::Network; @@ -97,7 +99,15 @@ void Core::HousingMgr::sendLandSignOwned( Entity::Player& player, uint8_t wardId landInfoSignPacket->data().landIdent.wardNum = land->getWardNum(); landInfoSignPacket->data().landIdent.worldId = 67; landInfoSignPacket->data().landIdent.territoryTypeId = land->getTerritoryTypeId(); + landInfoSignPacket->data().houseIconAdd = land->getSharing(); landInfoSignPacket->data().ownerId = player.getContentId(); // should be real owner contentId, not player.contentId() + + if( auto house = land->getHouse() ) + { + std::strcpy( landInfoSignPacket->data().estateName, house->getHouseName().c_str() ); + std::strcpy( landInfoSignPacket->data().estateGreeting, house->getHouseGreeting().c_str() ); + } + memcpy( &landInfoSignPacket->data().ownerName, playerName.c_str(), playerName.size() ); player.queuePacket( landInfoSignPacket ); @@ -157,11 +167,10 @@ Core::LandPurchaseResult Core::HousingMgr::purchaseLand( Entity::Player& player, pLand->setState( HouseState::sold ); pLand->setLandType( Common::LandType::Private ); - player.setLandPermissions( LandPermissionSlot::Private, 0x00, plot, + player.setLandFlags( LandFlagsSlot::Private, 0x00, plot, pHousing->getWardNum(), pHousing->getTerritoryTypeId() ); - player.sendLandPermissionSlot( static_cast< uint8_t >( LandType::Private ), plot, pHousing->getWardNum(), - pHousing->getTerritoryTypeId() ); + player.sendLandFlagsSlot( LandFlagsSlot::Private ); //pLand->setLandName( "Private Estate" + std::to_string( pHousing->getWardNum() ) + "-" + std::to_string( plot ) ); pLand->updateLandDb(); @@ -210,9 +219,9 @@ bool Core::HousingMgr::relinquishLand( Entity::Player& player, uint8_t plot ) pLand->setLandType( Common::LandType::none ); pLand->updateLandDb(); - player.setLandPermissions( LandPermissionSlot::Private, 0x00, 0xFF, 0xFF, 0xFF ); + player.setLandFlags( LandFlagsSlot::Private, 0x00, 0xFF, 0xFF, 0xFF ); - player.sendLandPermissionSlot( static_cast< uint8_t >( LandType::Private ), 0xFF, 0xFF, 0xFF ); + player.sendLandFlagsSlot( LandFlagsSlot::Private ); auto screenMsgPkt2 = makeActorControl143( player.getId(), ActorControl::LogMsg, 3351, 0x1AA, pLand->getWardNum() + 1, plot + 1 ); @@ -251,14 +260,14 @@ void Core::HousingMgr::sendWardLandInfo( Entity::Player& player, uint8_t wardId, switch( land->getLandType() ) { case LandType::FreeCompany: - entry.infoFlags = Common::WardEstateFlags::IsEstateOwned | Common::WardEstateFlags::IsFreeCompanyEstate; + entry.infoFlags = Common::WardlandFlags::IsEstateOwned | Common::WardlandFlags::IsFreeCompanyEstate; // todo: send FC name break; case LandType::Private: - entry.infoFlags = Common::WardEstateFlags::IsEstateOwned; + entry.infoFlags = Common::WardlandFlags::IsEstateOwned; auto owner = land->getPlayerOwner(); std::string playerName = g_fw.get< Core::ServerMgr >()->getPlayerNameFromDb( owner ); @@ -310,5 +319,110 @@ void Core::HousingMgr::buildPresetEstate( Entity::Player& player, uint8_t plotNu // todo: wtf are these flags player.playScene( 0x000B0095, 0, 4164955899, 0, 1, plotNum, nullptr ); - // todo: send perms/flags for house + player.setLandFlags( LandFlagsSlot::Private, ESTATE_BUILT, pLand->getLandId(), pLand->getWardNum(), pLand->getTerritoryTypeId() ); + player.sendLandFlagsSlot( LandFlagsSlot::Private ); +} + +void Core::HousingMgr::requestEstateRename( Entity::Player& player, uint16_t territoryTypeId, uint16_t worldId, uint8_t wardId, uint8_t plotId ) +{ + auto landSetId = toLandSetId( territoryTypeId, wardId ); + auto hZone = getHousingZoneByLandSetId( landSetId ); + + if( !hZone ) + return; + + auto land = hZone->getLand( plotId ); + + auto house = land->getHouse(); + if( !house ) + return; + + auto landRenamePacket = makeZonePacket< Server::FFXIVIpcLandRename >( player.getId() ); + + landRenamePacket->data().landIdent.landId = land->getLandId(); + landRenamePacket->data().landIdent.wardNum = land->getWardNum(); + landRenamePacket->data().landIdent.worldId = 67; + landRenamePacket->data().landIdent.territoryTypeId = land->getTerritoryTypeId(); + memcpy( &landRenamePacket->data().houseName, house->getHouseName().c_str(), 20 ); + + player.queuePacket( landRenamePacket ); +} + +void Core::HousingMgr::requestEstateEditGreeting( Entity::Player& player, uint16_t territoryTypeId, uint16_t worldId, uint8_t wardId, uint8_t plotId ) +{ + auto landSetId = toLandSetId( territoryTypeId, wardId ); + auto hZone = getHousingZoneByLandSetId( landSetId ); + + if( !hZone ) + return; + + auto land = hZone->getLand( plotId ); + if( !land ) + return; + + auto house = land->getHouse(); + if( !house ) + return; + + auto estateGreetingPacket = makeZonePacket< Server::FFXIVIpcHousingEstateGreeting >( player.getId() ); + + estateGreetingPacket->data().landIdent.landId = land->getLandId(); + estateGreetingPacket->data().landIdent.wardNum = land->getWardNum(); + estateGreetingPacket->data().landIdent.worldId = 67; + estateGreetingPacket->data().landIdent.territoryTypeId = land->getTerritoryTypeId(); + memcpy( &estateGreetingPacket->data().message, house->getHouseGreeting().c_str(), sizeof( estateGreetingPacket->data().message ) ); + + player.queuePacket( estateGreetingPacket ); +} + +void Core::HousingMgr::updateEstateGreeting( Entity::Player& player, const Common::LandIdent& ident, const std::string& greeting ) +{ + auto landSetId = toLandSetId( ident.territoryTypeId, ident.wardNum ); + auto zone = getHousingZoneByLandSetId( landSetId ); + + if( !zone ) + return; + + auto land = zone->getLand( ident.landId ); + if( !land ) + return; + + // todo: implement proper permissions checks + if( land->getPlayerOwner() != player.getId() ) + return; + + auto house = land->getHouse(); + if( !house ) + return; + + house->setHouseGreeting( greeting ); + + // Greeting updated. + player.sendLogMessage( 3381 ); +} + +void Core::HousingMgr::requestEstateEditGuestAccess( Entity::Player& player, uint16_t territoryTypeId, uint16_t worldId, uint8_t wardId, uint8_t plotId ) +{ + auto landSetId = toLandSetId( territoryTypeId, wardId ); + auto hZone = getHousingZoneByLandSetId( landSetId ); + + if( !hZone ) + return; + + auto land = hZone->getLand( plotId ); + if( !land ) + return; + + // todo: add proper permission check + if( land->getPlayerOwner() != player.getId() ) + return; + + auto packet = makeZonePacket< FFXIVIpcHousingShowEstateGuestAccess >( player.getId() ); + + packet->data().ident.landId = plotId; + packet->data().ident.territoryTypeId = territoryTypeId; + packet->data().ident.wardNum = wardId; + packet->data().ident.worldId = worldId; + + player.queuePacket( packet ); } diff --git a/src/servers/sapphire_zone/Zone/HousingMgr.h b/src/servers/sapphire_zone/Zone/HousingMgr.h index cacaa9c1..bd3c39db 100644 --- a/src/servers/sapphire_zone/Zone/HousingMgr.h +++ b/src/servers/sapphire_zone/Zone/HousingMgr.h @@ -36,6 +36,13 @@ namespace Core void buildPresetEstate( Entity::Player& player, uint8_t plotNum, uint32_t presetItem ); + void requestEstateRename( Entity::Player& player, uint16_t territoryTypeId, uint16_t worldId, uint8_t wardId, uint8_t plotId ); + + void requestEstateEditGreeting( Entity::Player& player, uint16_t territoryTypeId, uint16_t worldId, uint8_t wardId, uint8_t plotId ); + void updateEstateGreeting( Entity::Player& player, const Common::LandIdent& ident, const std::string& greeting ); + + void requestEstateEditGuestAccess( Entity::Player& player, uint16_t territoryTypeId, uint16_t worldId, uint8_t wardId, uint8_t plotId ); + private: };