29 #include "../../bscript/bstruct.h" 30 #include "../../clib/cfgelem.h" 31 #include "../../clib/clib_endian.h" 32 #include "../../clib/logfacility.h" 33 #include "../../clib/passert.h" 34 #include "../../clib/stlutil.h" 35 #include "../../clib/streamsaver.h" 36 #include "../../plib/systemstate.h" 37 #include "../clidata.h" 39 #include "../globals/uvars.h" 40 #include "../item/item.h" 41 #include "../item/itemdesc.h" 42 #include "../mkscrobj.h" 43 #include "../mobile/charactr.h" 44 #include "../network/cgdata.h" 45 #include "../network/client.h" 46 #include "../network/packethelper.h" 47 #include "../network/packets.h" 48 #include "../pktboth.h" 49 #include "../pktout.h" 50 #include "../pktoutid.h" 51 #include "../realms/realm.h" 52 #include "../scrdef.h" 53 #include "../scrsched.h" 54 #include "../syshook.h" 56 #include "../uoscrobj.h" 57 #include "../uworld.h" 61 #ifdef USE_SYSTEM_ZLIB 64 #include "../../../lib/zlib/zlib.h" 73 #define BYTES_PER_TILE 5 103 InitDesign( _height, _width, xoffset, yoffset );
148 if ( floor_num == -1 )
159 if ( floor_num == -1 )
168 for ( HouseFloorZColumn::iterator itr = column->begin(), itrend = column->end(); itr != itrend;
173 if ( ( ( existing_height == 0 ) && ( adding_height == 0 ) ) ||
174 ( ( existing_height != 0 ) && ( adding_height != 0 ) ) )
177 column->erase( itr );
191 if ( floor_num == -1 )
200 for ( HouseFloorZColumn::iterator itr = column->begin(), itrend = column->end(); itr != itrend;
204 if ( ( itr->z == z ) && ( t_height >= minheight ) )
206 column->erase( itr );
218 if ( floor_num == -1 )
226 for ( HouseFloorZColumn::iterator itr = column->begin(), itrend = column->end(); itr != itrend;
229 if ( itr->graphic == graphic )
231 column->erase( itr );
243 if ( x +
xoff == 0 || y +
yoff == 0 ||
248 bool floor_exists =
false;
255 for ( HouseFloorZColumn::iterator itr = column->begin(), itrend = column->end(); itr != itrend;
265 if ( floor_exists ==
false )
283 xitr != xitrend; ++xitr )
285 for ( HouseFloorRow::iterator yitr = xitr->begin(), yitrend = xitr->end(); yitr != yitrend;
301 unsigned long cbuflen =
302 ( ( (
unsigned long)( ( (
float)( ubuflen ) ) * 1.001f ) ) + 12 );
303 unsigned char* uncompressed =
new unsigned char[ubuflen];
304 memset( uncompressed, 0, ubuflen );
305 unsigned char* compressed =
new unsigned char[cbuflen];
306 memset( compressed, 0, cbuflen );
309 for ( HouseFloor::const_iterator xitr =
Elements[floor].
data.begin(),
311 xitr != xitrend; ++xitr )
314 for ( HouseFloorRow::const_iterator yitr = xitr->begin(), yitrend = xitr->end();
315 yitr != yitrend; ++yitr )
317 for ( HouseFloorZColumn::const_iterator zitr = yitr->begin(), zitrend = yitr->end();
318 zitr != zitrend; ++zitr, ++i )
325 uncompressed[nextindex++] = (
u8 )( ( zitr->graphic >> 8 ) & 0xFF );
326 uncompressed[nextindex++] = (
u8 )( zitr->graphic & 0xFF );
328 uncompressed[nextindex++] = (
u8)zitr->xoffset;
329 uncompressed[nextindex++] = (
u8)zitr->yoffset;
330 uncompressed[nextindex++] = (
u8)zitr->z;
335 *uncompr_length = nextindex;
337 int ret = compress2( compressed, &cbuflen, uncompressed, nextindex, Z_DEFAULT_COMPRESSION );
340 delete[] uncompressed;
341 *compr_length = cbuflen;
350 delete[] uncompressed;
360 return total == 0 ?
true :
false;
365 unsigned int size = 0;
375 unsigned char size = 0;
391 if ( multidef ==
nullptr )
393 ERROR_PRINT <<
"Trying to add Multi to customhouse, multiid 0x" << fmt::hexu( multiid )
394 <<
" multi definition doesn't exist!\n";
398 for ( MultiDef::Components::const_iterator itr = multidef->
components.begin(),
413 ch_elem.
z =
static_cast<u8>( m_elem->
z + z );
422 while ( elem.
remove_prop( prefix.c_str(), &line ) )
448 for ( HouseFloor::const_iterator xitr =
Elements[i].
data.begin(),
450 xitr != xitrend; ++xitr )
452 for ( HouseFloorRow::const_iterator yitr = xitr->begin(), yitrend = xitr->end();
453 yitr != yitrend; ++yitr )
455 for ( HouseFloorZColumn::const_iterator zitr = yitr->begin(), zitrend = yitr->end();
456 zitr != zitrend; ++zitr )
458 sw() <<
"\t" << prefix <<
"\t " << zitr->graphic <<
" " << zitr->xoffset <<
" " 459 << zitr->yoffset <<
" " << (
u16)zitr->z <<
'\n';
475 for ( HouseFloor::const_iterator xitr =
Elements[i].
data.begin(),
477 xitr != xitrend; ++xitr, x++ )
479 os <<
"X: " << x << std::endl;
480 for ( HouseFloorRow::const_iterator yitr = xitr->begin(), yitrend = xitr->end();
481 yitr != yitrend; ++yitr, y++ )
483 os <<
"\tY: " << y << std::endl;
484 for ( HouseFloorZColumn::const_iterator zitr = yitr->begin(), zitrend = yitr->end();
485 zitr != zitrend; ++zitr )
487 os <<
"\t\t" << zitr->graphic <<
" " << zitr->xoffset <<
" " << zitr->yoffset <<
" " 488 << (
u16)zitr->z << std::endl;
514 UHouse::Components::iterator itr = comp->begin();
515 while ( itr != comp->end() )
518 if ( item !=
nullptr && !item->
orphan() )
522 itr = comp->erase( itr );
534 for ( UHouse::Components::const_iterator itr = comp->begin(), end = comp->end(); itr != end;
538 if ( item !=
nullptr && !item->
orphan() )
546 elem.
z = item->
z - house->
z;
557 xitr != xitrend; ++xitr )
559 for ( HouseFloorRow::iterator yitr = xitr->begin(), yitrend = xitr->end(); yitr != yitrend;
562 HouseFloorZColumn::iterator zitr = yitr->begin();
563 while ( zitr != yitr->end() )
568 if ( add_as_component )
571 if ( component !=
nullptr )
573 bool res = house->
add_component( component, zitr->xoffset, zitr->yoffset, zitr->
z );
575 "Couldn't add newly created door as house component. Please " 576 "report this bug on the forums." );
579 zitr = yitr->erase( zitr );
585 if ( add_as_component )
588 if ( component !=
nullptr )
590 bool res = house->
add_component( component, zitr->xoffset, zitr->yoffset, zitr->
z );
592 "Couldn't add newly created teleporter as house component. " 593 "Please report this bug on the forums." );
596 zitr = yitr->erase( zitr );
612 for ( HouseFloor::const_iterator xitr =
Elements[i].
data.begin(),
614 xitr != xitrend; ++xitr )
616 for ( HouseFloorRow::const_iterator yitr = xitr->begin(), yitrend = xitr->end();
617 yitr != yitrend; ++yitr )
619 for ( HouseFloorZColumn::const_iterator zitr = yitr->begin(), zitrend = yitr->end();
620 zitr != zitrend; ++zitr )
623 itemstruct->addMember(
"graphic",
new Bscript::BLong( zitr->graphic ) );
624 itemstruct->addMember(
"xoffset",
new Bscript::BLong( zitr->xoffset ) );
625 itemstruct->addMember(
"yoffset",
new Bscript::BLong( zitr->yoffset ) );
627 arr->addElement( itemstruct.release() );
632 return arr.release();
638 msg->WriteFlipped<
u16>( 17u );
641 msg->Write<
u8>( 0x5u );
643 msg->Write<
u32>( 0xFFFFFFFFu );
644 msg->Write<
u8>( 0xFFu );
655 while ( !itemlist.empty() )
659 itemlist.pop_front();
667 if ( house ==
nullptr )
686 std::vector<u8> newvec;
696 if ( house ==
nullptr )
708 if ( chr !=
nullptr && chr->
client !=
nullptr )
716 std::vector<u8> newvec;
726 if ( house ==
nullptr )
736 if ( z == 0 && realx < house->WorkingDesign.width && realy < ( house->
WorkingDesign.
height - 1 ) )
747 if ( z == CustomHouseDesign::custom_house_z_xlate_table[1] )
752 std::vector<u8> newvec;
767 if ( house ==
nullptr )
773 std::vector<u8> newvec;
778 if ( chr !=
nullptr && chr->
client !=
nullptr )
789 if ( house ==
nullptr )
800 if ( house ==
nullptr || chr ==
nullptr )
808 if ( sd.
config_nodie(
"misc/customhousecommit.ecl", 0, 0 ) )
826 if ( house ==
nullptr )
830 if ( floor < 1 || floor > 4 )
838 house->
z + CustomHouseDesign::custom_house_z_xlate_table[floor],
849 if ( house ==
nullptr )
860 if ( house ==
nullptr )
864 std::vector<u8> newvec;
866 if ( chr !=
nullptr && chr->
client !=
nullptr )
875 if ( chr !=
nullptr && chr->
client !=
nullptr && house !=
nullptr )
885 if ( house ==
nullptr )
889 std::vector<u8> newvec;
892 if ( chr !=
nullptr && chr->
client !=
nullptr )
900 if ( house ==
nullptr )
909 if ( z < -3 || z > 12 || z % 3 != 0 )
916 std::vector<u8> newvec;
925 if ( house ==
nullptr )
930 u8 z =
static_cast<u8>(
cfBEu32(
remove.zoffset ) );
935 if ( chr !=
nullptr && chr->
client !=
nullptr )
941 std::vector<u8> newvec;
953 std::vector<u8>* stored_packet;
958 const unsigned int data_offset = 17;
999 unsigned long sbuflen =
1004 std::vector<u8> packet( sbuflen );
1017 for (
int i = 0; i < planes; i++ )
1020 data = pdesign->
Compress( i, &ulen, &clen );
1021 if ( data ==
nullptr )
1027 planeheader |= ( ( mode << 4 ) << 24 );
1028 planeheader |= ( ( i & 0xF ) << 24 );
1029 planeheader |= ( ( ulen & 0xFF ) << 16 );
1030 planeheader |= ( ( clen & 0xFF ) << 8 );
1031 planeheader |= ( ( ( ulen >> 4 ) & 0xF0 ) | ( ( clen >> 8 ) & 0xF ) );
1032 u32* p_planeheader =
reinterpret_cast<u32*
>( &( packet[buffer_len + data_offset] ) );
1033 *p_planeheader =
ctBEu32( planeheader );
1035 memcpy( &( packet[buffer_len + data_offset] ), data, clen );
1039 msg->
msglen =
ctBEu16( static_cast<u16>( buffer_len ) + data_offset );
1043 stored_packet->swap( packet );
1049 house->
x, house->
y, house->
realm, range,
1050 [&](
Mobile::Character* chr ) { CustomHousesSendFull( house, chr->client, design ); } );
1056 msg->WriteFlipped<
u16>( 13u );
1065 if ( custom ==
false && _custom ==
true )
1066 CustomHouseSetInitialState();
1072 int ysize, xsize, xbase, ybase;
1076 xbase = abs( def.
minrx );
1077 ybase = abs( def.
minry );
1078 CurrentDesign.Clear();
1079 CurrentDesign.InitDesign( ysize + 1, xsize, xbase,
1081 WorkingDesign.Clear();
1082 WorkingDesign.InitDesign( ysize + 1, xsize, xbase,
1084 BackupDesign.Clear();
1085 BackupDesign.InitDesign( ysize + 1, xsize, xbase,
1088 CurrentDesign.AddMultiAtOffset( multiid, 0, 0, 0 );
1089 WorkingDesign = CurrentDesign;
1090 std::vector<u8> newvec;
1091 WorkingCompressed.swap( newvec );
1093 std::vector<u8> newvec2;
1094 CurrentCompressed.swap( newvec2 );
1100 WorkingDesign = CurrentDesign;
1103 CurrentDesign.FillComponents(
this );
1104 WorkingDesign.FillComponents(
this,
false );
1107 std::vector<u8> newvec;
1108 WorkingCompressed.swap( newvec );
1110 std::vector<u8> newvec2;
1111 CurrentCompressed.swap( newvec2 );
1113 if ( chr && chr->
client )
static Item * create(u32 objtype, u32 serial=0)
CustomHouseDesign WorkingDesign
void SetWidth(u32 _width)
std::list< CUSTOM_HOUSE_ELEMENT > HouseFloorZColumn
int floor_sizes[CUSTOM_HOUSE_NUM_PLANES]
CustomHouseDesign & operator=(const CustomHouseDesign &design)
static const char custom_house_z_xlate_table[CUSTOM_HOUSE_NUM_PLANES]
void Add(CUSTOM_HOUSE_ELEMENT &elem)
CH_ADD_MULTI ch_add_multi
std::list< Items::Item * > ItemList
std::vector< Component > Components
static bool isEditableItem(UHouse *house, Items::Item *item)
Tells wether an item should be show in custom house design or not.
void SetHeight(u32 _height)
bool config_nodie(const std::string &name, const Plib::Package *pkg, const char *mainpfx)
static void list_contents(const UHouse *house, ItemList &items_in, MobileList &chrs_in)
void CustomHousesErase(Core::PKTBI_D7 *msg)
bool call(Bscript::BObjectImp *p0)
ExportedFunction * close_customhouse_hook
static UHouse * FindWorkingHouse(u32 chrserial)
void SetCustom(bool custom)
bool ValidLocation(u32 xidx, u32 yidx)
void CustomHousesSynch(Core::PKTBI_D7 *msg)
bool move_character_to(Mobile::Character *chr, unsigned short x, unsigned short y, short z, int flags, Realms::Realm *oldrealm)
Components * get_components()
std::list< Mobile::Character * > MobileList
CustomHouseDesign CurrentDesign
Bscript::ObjArray * list_parts() const
#define STAIR_MULTIID_MAX
std::vector< u8 > CurrentCompressed
static void InRange(u16 x, u16 y, const Realms::Realm *realm, unsigned range, F &&f)
CustomHouseDesign BackupDesign
void CustomHouseStopEditing(Mobile::Character *chr, UHouse *house)
const ItemDesc & find_itemdesc(unsigned int objtype)
void CustomHousesCommit(Core::PKTBI_D7 *msg)
void AddComponents(UHouse *house)
CH_DELETE_ROOF ch_delete_roof
bool EraseGraphicAt(u16 graphic, u32 xoffset, u32 yoffset, u8 z)
size_t estimatedSize() const
std::unique_ptr< Network::ClientTransmit > clientTransmit
void AddElement(CUSTOM_HOUSE_ELEMENT &elem)
void destroy_item(Item *item)
void InitDesign(u32 _height, u32 _width, s32 xoffset, s32 yoffset)
void CustomHousesQuit(Core::PKTBI_D7 *msg)
NetworkManager networkManager
static char z_to_custom_house_table(char z)
void printProperties(Clib::StreamWriter &sw, const std::string &prefix) const
void Send(Client *client, int len=-1) const
void CustomHousesQuit(Mobile::Character *chr, bool drop_changes)
void CustomHousesRoofRemove(Core::PKTBI_D7 *msg)
void testprint(std::ostream &os) const
char tileheight(unsigned short tilenum)
void ReplaceDirtFloor(u32 x, u32 y)
void AcceptHouseCommit(Mobile::Character *chr, bool accept)
CH_SELECT_FLOOR ch_select_floor
bool DeleteStairs(u16 id, s32 x, s32 y, s8 z)
Mobile::Character * find_character(u32 serial)
#define passert_always_r(exp, reason)
std::unordered_map< u64, ScriptDiffData > data
void FillComponents(UHouse *house, bool add_as_component=true)
void CustomHousesSendFullToInRange(UHouse *house, int design, int range)
CH_SELECT_ROOF ch_select_roof
void CustomHouseSetInitialState()
unsigned char * Compress(int floor, u32 *uncompr_length, u32 *compr_length)
const int MOVEITEM_FORCELOCATION
bool remove_prop(const char *propname, std::string *value)
void send_item(Client *client, const Item *item)
void CustomHousesBackup(Core::PKTBI_D7 *msg)
unsigned int TotalSize() const
std::vector< u8 > WorkingCompressed
CustomHouseElements Elements[CUSTOM_HOUSE_NUM_PLANES]
unsigned char NumUsedPlanes() const
void AddMultiAtOffset(u16 multiid, s8 x, s8 y, s8 z)
void CustomHousesClear(Core::PKTBI_D7 *msg)
void AddOrReplace(CUSTOM_HOUSE_ELEMENT &elem)
void CustomHousesSelectFloor(Core::PKTBI_D7 *msg)
const MultiDef & multidef() const
void CustomHousesSendFull(UHouse *house, Network::Client *client, int design)
void CustomHousesRestore(Core::PKTBI_D7 *msg)
bool Erase(u32 xoffset, u32 yoffset, u8 z, int minheight=0)
#define CUSTOM_HOUSE_NUM_PLANES
Multi::UMulti * find_supporting_multi(unsigned short x, unsigned short y, short z) const
void start_script(const char *filename, Bscript::BObjectImp *param0, Bscript::BObjectImp *param1)
Bscript::BObjectImp * make_mobileref(Mobile::Character *chr)
void readProperties(Clib::ConfigElem &elem, const std::string &prefix)
void CustomHousesAdd(Core::PKTBI_D7 *msg)
CUSTOM_HOUSE_PLANE_BUFFER buffer[1]
void CustomHousesRoofSelect(Core::PKTBI_D7 *msg)
void CustomHousesRevert(Core::PKTBI_D7 *msg)
bool add_component(Items::Item *item, s32 xoff, s32 yoff, s16 zoff)
const MultiDef * MultiDefByMultiID(u16 multiid)
void CustomHousesAddMulti(Core::PKTBI_D7 *msg)
static void ClearComponents(UHouse *house)
void CustomHousesSendShort(UHouse *house, Network::Client *client)