Skip to content
Draft
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
2 changes: 1 addition & 1 deletion data/dfndata/house/house.dfn
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// Small Brick
[HOUSE 1]
{
ID=0x4068
ID=0x53ec
SPACEX=3
SPACEY=3
CHARX=0
Expand Down
1 change: 1 addition & 0 deletions data/js/server/house/houseSign.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function onUseUnChecked( pUser, iUsed )
{
// Grab reference to multi stored on sign
iMulti = iUsed.multi;
HouseBeginCustomize( pUser, iMulti );

if( ValidateObject( iMulti ))
{
Expand Down
276 changes: 275 additions & 1 deletion source/CPacketReceive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6005,9 +6005,34 @@ void CPIAOSCommand::Receive( void )
UI16 len = tSock->GetWord( 1 );
tSock->Receive( len, false );
}

static const SI08 DESIGN_BASE_Z = 7;

static UI08 ClientLevelToFloor( UI32 clientLevel )
{
// OSI typically: 1=ground, 2=1st, 3=2nd, 4=3rd
if( clientLevel <= 1 ) return 0;
if( clientLevel == 2 ) return 1;
if( clientLevel == 3 ) return 2;
return 3; // allow 4th view if you support it
}

bool CPIAOSCommand::Handle( void )
{
switch( tSock->GetWord( 7 )) // Which subcommand?
UI16 len = tSock->GetWord( 1 );

// 0xD7:
// [0] cmd
// [1-2] len
// [3-6] player serial
// [7-8] subcommand
UI32 playerSer = tSock->GetDWord( 3 );
UI16 subCmd = tSock->GetWord( 7 );

// Debug (optional)
// Console.Print("D7 len=%u player=0x%X sub=0x%04X\n", len, playerSer, subCmd );

switch( subCmd ) // Which subcommand?
{
/*case 0x0002: break; //House Customisation :: Backup
case 0x0003: break; //House Customisation :: Restore
Expand All @@ -6019,6 +6044,255 @@ bool CPIAOSCommand::Handle( void )
case 0x000E: break; //House Customisation :: Synch
case 0x0010: break; //House Customisation :: Clear
case 0x0012: break; //House Customisation :: Switch Floors*/
case 0x0002: // Backup
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

HC_Backup( *s );
HC_BumpRevision( *s );

tSock->Send( &CPHouseDesignStateGeneral( s->houseSerial, s->revision ) );
std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );
tSock->Send( &CPHouseDesignStateDetailed( s->houseSerial, s->revision, sendTiles, true ) );
return true;
}

case 0x0003: // Restore
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

HC_Restore( *s );
HC_BumpRevision( *s );

tSock->Send( &CPHouseDesignStateGeneral( s->houseSerial, s->revision ) );
std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );
tSock->Send( &CPHouseDesignStateDetailed( s->houseSerial, s->revision, sendTiles, true ) );
return true;
}
case 0x0004: // Commit
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

tSock->SysMessage( "pushing commit" );

bool committed = HC_CommitSession( tSock );

if( !committed )
tSock->SysMessage( "Commit failed" );

// Bump revision and resend the *design* to keep ClassicUO in sync
if( committed )
HC_BumpRevision( *s );

std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );

tSock->Send( &CPHouseDesignStateGeneral( s->houseSerial, s->revision ) );
tSock->Send( &CPHouseDesignStateDetailed( s->houseSerial, s->revision, sendTiles, true ) );
return true;
}

case 0x0005: // Destroy item
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

SERIAL houseSerial = s->houseSerial;

UI32 itemID32 = tSock->GetDWord( 10 );
UI16 itemID = ( UI16 ) ( itemID32 & 0xFFFF );

SI16 x16 = ( SI16 ) tSock->GetDWord( 15 );
SI16 y16 = ( SI16 ) tSock->GetDWord( 20 );
SI16 z16 = (SI16)tSock->GetDWord( 25 );

if( x16 < -128 )
x16 = -128;

if( x16 > 127 )
x16 = 127;

if( y16 < -128 )
y16 = -128;

if( y16 > 127 )
y16 = 127;

SI08 x = ( SI08 ) x16;
SI08 y = ( SI08 ) y16;
SI08 pktZ = ( SI08 ) z16;
SI08 z = pktZ;

// OSI frequently sends 0 even when erasing upper floors.
// If packet Z is 0, use the session�s current design plane.
if( pktZ == 0 )
z = SessionDesignZ( s );

// Remove from session using computed Z first
bool removed = HC_RemoveTile( *s, itemID, x, y, z );

// Fall back attempts
if( !removed && z != pktZ )
removed = HC_RemoveTile( *s, itemID, x, y, pktZ );

if( !removed )
removed = HC_RemoveTileAnyZ( *s, itemID, x, y );

if( removed )
HC_BumpRevision( *s );

tSock->Send( &CPHouseDesignStateGeneral( houseSerial, s->revision ) );
std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );
tSock->Send( &CPHouseDesignStateDetailed( houseSerial, s->revision, sendTiles, true ) );
return true;
}

// ------------------------------------------------------------
// House customization place item
// ------------------------------------------------------------
case 0x0006:
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

SERIAL houseSerial = s->houseSerial;

UI32 itemID32 = tSock->GetDWord( 10 );
UI16 itemID = ( UI16 ) ( itemID32 & 0xFFFF );

SI16 x16 = ( SI16 ) tSock->GetDWord( 15 );
SI16 y16 = ( SI16 ) tSock->GetDWord( 20 );

// Clamp to SI08 if your struct uses SI08
if( x16 < -128 ) x16 = -128;
if( x16 > 127 ) x16 = 127;
if( y16 < -128 ) y16 = -128;
if( y16 > 127 ) y16 = 127;

SI08 x = ( SI08 ) x16;
SI08 y = ( SI08 ) y16;

//SI08 z = FloorToDesignZ( s->floor );
SI08 z = SessionDesignZ( s );
// Replace anything already at that spot on that floor
HC_RemoveAtXYZ( *s, x, y, z );
HC_AddTile( *s, itemID, x, y, z );
HC_BumpRevision( *s );
char msg[64];
sprintf( msg, "Place floor=%u designZ=%d", (UI32)s->floor, (int)z );
tSock->SysMessage( msg );

tSock->Send( &CPHouseDesignStateGeneral( houseSerial, s->revision ) );
std::vector<HouseTileEntry> combined;
HC_BuildCombinedTiles( *s, combined );
tSock->Send( &CPHouseDesignStateDetailed( houseSerial, s->revision, combined, true ) );
return true;
}
case 0x000C: // House Customization :: Exit
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

SERIAL houseSerial = s->houseSerial;

// Tell client to exit customize mode
tSock->Send( &CPHouseCustomization( houseSerial, false ) );

// Destroy the session
HC_EndSession( tSock );
return true;
}
case 0x000E:
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

SERIAL houseSerial = s->houseSerial;

CPHouseDesignStateGeneral revPkt( houseSerial, s->revision );
tSock->Send( &revPkt );

std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );
tSock->Send( &CPHouseDesignStateDetailed( houseSerial, s->revision, sendTiles, true ) );

return true;
}
case 0x0010: // Clear
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

HC_ClearAll( *s );
HC_BumpRevision( *s );

tSock->Send( &CPHouseDesignStateGeneral( s->houseSerial, s->revision ) );
std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );
tSock->Send( &CPHouseDesignStateDetailed( s->houseSerial, s->revision, sendTiles, true ) );
return true;
}
case 0x0012:
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

SERIAL houseSerial = s->houseSerial;

UI32 level = tSock->GetDWord( 10 );
s->floor = ( UI08 ) level;
// Debug so you can confirm what ClassicUO is sending
char msg[64];
sprintf( msg, "SwitchFloor: level=%u -> z=%d", (UI32)s->floor, (int)FloorToDesignZ( s->floor ) );
tSock->SysMessage( msg );

s->clientLevel = (UI08)level;
s->floor = ClientLevelToFloor( level );

// Move player to correct design Z
CChar *chr = tSock->CurrcharObj();
if( ValidateObject( chr ))
{
chr->SetLocation( chr->GetX(), chr->GetY(), FloorToDesignZ( s->floor ), chr->WorldNumber(), chr->GetInstanceId() );
chr->Teleport();
}

tSock->Send( &CPHouseDesignStateGeneral( houseSerial, s->revision ) );
std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );
tSock->Send( &CPHouseDesignStateDetailed( houseSerial, s->revision, sendTiles, true ) );
return true;
}
case 0x001A: // Revert
{
HouseCustomSession* s = HC_GetSession( tSock );
if( s == nullptr )
return true;

HC_Revert( *s );
HC_BumpRevision( *s );

tSock->Send( &CPHouseDesignStateGeneral( s->houseSerial, s->revision ) );
std::vector<HouseTileEntry> sendTiles;
HC_BuildCombinedTiles( *s, sendTiles );
tSock->Send( &CPHouseDesignStateDetailed( s->houseSerial, s->revision, sendTiles, true ) );
return true;
}
case 0x0019: //Special Moves :: Activate / Deactivate
{
//UI32 unknown = tSock->GetDWord( 9 );
Expand Down
Loading