#include "client.h" #include #include #include #include #include #include "opcode.h" #include "utils.h" #include "room.h" #include "furnitureprofile.h" #include "nexusserver.h" #define DG QString("Dg[_Dshelves_norjaX~Dshelves_polyfonYmAshelves_siloXQHtable_polyfon_smallYmAchair_polyfonZbBtable_norja_medY_Itable_silo_medX~Dtable_plasto_4legY_Itable_plasto_roundY_Itable_plasto_bigsquareY_Istand_polyfon_zZbBchair_siloX~Dsofa_siloX~Dcouch_norjaX~Dchair_norjaX~Dtable_polyfon_medYmAdoormat_loveZbBdoormat_plainZ[Msofachair_polyfonX~Dsofa_polyfonZ[Msofachair_siloX~Dchair_plastyX~Dchair_plastoYmAtable_plasto_squareY_Ibed_polyfonX~Dbed_polyfon_one[dObed_trad_oneYmAbed_tradYmAbed_silo_oneYmAbed_silo_twoYmAtable_silo_smallX~Dbed_armas_twoYmAbed_budget_oneXQHbed_budgetXQHshelves_armasYmAbench_armasYmAtable_armasYmAsmall_table_armasZbBsmall_chair_armasYmAfireplace_armasYmAlamp_armasYmAbed_armas_oneYmAcarpet_standardY_Icarpet_armasYmAcarpet_polarY_Ifireplace_polyfonY_Itable_plasto_4leg*1Y_Itable_plasto_bigsquare*1Y_Itable_plasto_round*1Y_Itable_plasto_square*1Y_Ichair_plasto*1YmAcarpet_standard*1Y_Idoormat_plain*1Z[Mtable_plasto_4leg*2Y_Itable_plasto_bigsquare*2Y_Itable_plasto_round*2Y_Itable_plasto_square*2Y_Ichair_plasto*2YmAdoormat_plain*2Z[Mcarpet_standard*2Y_Itable_plasto_4leg*3Y_Itable_plasto_bigsquare*3Y_Itable_plasto_round*3Y_Itable_plasto_square*3Y_Ichair_plasto*3YmAcarpet_standard*3Y_Idoormat_plain*3Z[Mtable_plasto_4leg*4Y_Itable_plasto_bigsquare*4Y_Itable_plasto_round*4Y_Itable_plasto_square*4Y_Ichair_plasto*4YmAcarpet_standard*4Y_Idoormat_plain*4Z[Mdoormat_plain*6Z[Mdoormat_plain*5Z[Mcarpet_standard*5Y_Itable_plasto_4leg*5Y_Itable_plasto_bigsquare*5Y_Itable_plasto_round*5Y_Itable_plasto_square*5Y_Ichair_plasto*5YmAtable_plasto_4leg*6Y_Itable_plasto_bigsquare*6Y_Itable_plasto_round*6Y_Itable_plasto_square*6Y_Ichair_plasto*6YmAtable_plasto_4leg*7Y_Itable_plasto_bigsquare*7Y_Itable_plasto_round*7Y_Itable_plasto_square*7Y_Ichair_plasto*7YmAtable_plasto_4leg*8Y_Itable_plasto_bigsquare*8Y_Itable_plasto_round*8Y_Itable_plasto_square*8Y_Ichair_plasto*8YmAtable_plasto_4leg*9Y_Itable_plasto_bigsquare*9Y_Itable_plasto_round*9Y_Itable_plasto_square*9Y_Ichair_plasto*9YmAcarpet_standard*6Y_Ichair_plasty*1X~DpizzaYmAdrinksYmAchair_plasty*2X~Dchair_plasty*3X~Dchair_plasty*4X~Dbar_polyfonY_Iplant_cruddyYmAbottleYmAbardesk_polyfonX~Dbardeskcorner_polyfonX~DfloortileHbar_armasY_Ibartable_armasYmAbar_chair_armasYmAcarpet_softZ@Kcarpet_soft*1Z@Kcarpet_soft*2Z@Kcarpet_soft*3Z@Kcarpet_soft*4Z@Kcarpet_soft*5Z@Kcarpet_soft*6Z@Kred_tvY_Iwood_tvYmAcarpet_polar*1Y_Ichair_plasty*5X~Dcarpet_polar*2Y_Icarpet_polar*3Y_Icarpet_polar*4Y_Ichair_plasty*6X~Dtable_polyfonYmAsmooth_table_polyfonYmAsofachair_polyfon_girlX~Dbed_polyfon_girl_one[dObed_polyfon_girlX~Dsofa_polyfon_girlZ[Mbed_budgetb_oneXQHbed_budgetbXQHplant_pineappleYmAplant_fruittreeY_Iplant_small_cactusY_Iplant_bonsaiY_Iplant_big_cactusY_Iplant_yukkaY_Icarpet_standard*7Y_Icarpet_standard*8Y_Icarpet_standard*9Y_Icarpet_standard*aY_Icarpet_standard*bY_Iplant_sunflowerY_Iplant_roseY_Itv_luxusY_IbathZ\\BsinkY_ItoiletYmAduckYmAtileYmAtoilet_redYmAtoilet_yellYmAtile_redYmAtile_yellYmApresent_gen[~Npresent_gen1[~Npresent_gen2[~Npresent_gen3[~Npresent_gen4[~Npresent_gen5[~Npresent_gen6[~Nbar_basicY_Ishelves_basicXQHsoft_sofachair_norjaX~Dsoft_sofa_norjaX~Dlamp_basicXQHlamp2_armasYmAfridgeY_Idoor[dOdoorB[dOdoorC[dOpumpkinYmAskullcandleYmAdeadduckYmAdeadduck2YmAdeadduck3YmAmenorahYmApuddingYmAhamYmAturkeyYmAxmasduckY_IhouseYmAtriplecandleYmAtree3YmAtree4YmAtree5X~Dham2YmAwcandlesetYmArcandlesetYmAstatueYmAheartY_IvaleduckYmAheartsofaX~DthroneYmAsamovarY_IgiftflowersY_IhabbocakeYmAhologramYmAeasterduckY_IbunnyYmAbasketY_IbirdieYmAediceX~Dclub_sofaZ[Mprize1YmAprize2YmAprize3YmAdivider_poly3X~Ddivider_arm1YmAdivider_arm2YmAdivider_arm3YmAdivider_nor1X~Ddivider_silo1X~Ddivider_nor2X~Ddivider_silo2Z[Mdivider_nor3X~Ddivider_silo3X~DtypingmachineYmAspyroYmAredhologramYmAcameraHjoulutahtiYmAhyacinth1YmAhyacinth2YmAchair_plasto*10YmAchair_plasto*11YmAbardeskcorner_polyfon*12X~Dbardeskcorner_polyfon*13X~Dchair_plasto*12YmAchair_plasto*13YmAchair_plasto*14YmAtable_plasto_4leg*14Y_ImocchamasterY_Icarpet_legocourtYmAbench_legoYmAlegotrophyYmAvalentinescreenYmAedicehcYmArare_daffodil_rugYmArare_beehive_bulbY_IhcsohvaYmAhcammeYmArare_elephant_statueYmArare_fountainY_Irare_standYmArare_globeYmArare_hammockYmArare_elephant_statue*1YmArare_elephant_statue*2YmArare_fountain*1Y_Irare_fountain*2Y_Irare_fountain*3Y_Irare_beehive_bulb*1Y_Irare_beehive_bulb*2Y_Irare_xmas_screenY_Irare_parasol*1Y_Irare_parasol*2Y_Irare_parasol*3Y_Itree1X~Dtree2ZmBwcandleYxBrcandleYxBsoft_jaggara_norjaYmAhouse2YmAdjesko_turntableYmAmd_sofaZ[Mmd_limukaappiY_Itable_plasto_4leg*10Y_Itable_plasto_4leg*15Y_Itable_plasto_bigsquare*14Y_Itable_plasto_bigsquare*15Y_Itable_plasto_round*14Y_Itable_plasto_round*15Y_Itable_plasto_square*14Y_Itable_plasto_square*15Y_Ichair_plasto*15YmAchair_plasty*7X~Dchair_plasty*8X~Dchair_plasty*9X~Dchair_plasty*10X~Dchair_plasty*11X~Dchair_plasto*16YmAtable_plasto_4leg*16Y_Ihockey_scoreY_Ihockey_lightYmAdoorD[dOprizetrophy2*3[rIprizetrophy3*3XrIprizetrophy4*3[rIprizetrophy5*3[rIprizetrophy6*3[rIprizetrophy*1Y_Iprizetrophy2*1[rIprizetrophy3*1XrIprizetrophy4*1[rIprizetrophy5*1[rIprizetrophy6*1[rIprizetrophy*2Y_Iprizetrophy2*2[rIprizetrophy3*2XrIprizetrophy4*2[rIprizetrophy5*2[rIprizetrophy6*2[rIprizetrophy*3Y_Irare_parasol*0Hhc_lmp[fBhc_tblYmAhc_chrYmAhc_dskXQHnestHpetfood1ZvCpetfood2ZvCpetfood3ZvCwaterbowl*4XICwaterbowl*5XICwaterbowl*2XICwaterbowl*1XICwaterbowl*3XICtoy1XICtoy1*1XICtoy1*2XICtoy1*3XICtoy1*4XICgoodie1ZvCgoodie1*1ZvCgoodie1*2ZvCgoodie2X~Dprizetrophy7*3[rIprizetrophy7*1[rIprizetrophy7*2[rIscifiport*0Y_Iscifiport*9Y_Iscifiport*8Y_Iscifiport*7Y_Iscifiport*6Y_Iscifiport*5Y_Iscifiport*4Y_Iscifiport*3Y_Iscifiport*2Y_Iscifiport*1Y_Iscifirocket*9Y_Iscifirocket*8Y_Iscifirocket*7Y_Iscifirocket*6Y_Iscifirocket*5Y_Iscifirocket*4Y_Iscifirocket*3Y_Iscifirocket*2Y_Iscifirocket*1Y_Iscifirocket*0Y_Iscifidoor*10Y_Iscifidoor*9Y_Iscifidoor*8Y_Iscifidoor*7Y_Iscifidoor*6Y_Iscifidoor*5Y_Iscifidoor*4Y_Iscifidoor*3Y_Iscifidoor*2Y_Iscifidoor*1Y_Ipillow*5YmApillow*8YmApillow*0YmApillow*1YmApillow*2YmApillow*7YmApillow*9YmApillow*4YmApillow*6YmApillow*3YmAmarquee*1Y_Imarquee*2Y_Imarquee*7Y_Imarquee*aY_Imarquee*8Y_Imarquee*9Y_Imarquee*5Y_Imarquee*4Y_Imarquee*6Y_Imarquee*3Y_Iwooden_screen*1Y_Iwooden_screen*2Y_Iwooden_screen*7Y_Iwooden_screen*0Y_Iwooden_screen*8Y_Iwooden_screen*5Y_Iwooden_screen*9Y_Iwooden_screen*4Y_Iwooden_screen*6Y_Iwooden_screen*3Y_Ipillar*6Y_Ipillar*1Y_Ipillar*9Y_Ipillar*0Y_Ipillar*8Y_Ipillar*2Y_Ipillar*5Y_Ipillar*4Y_Ipillar*7Y_Ipillar*3Y_Irare_dragonlamp*4Y_Irare_dragonlamp*0Y_Irare_dragonlamp*5Y_Irare_dragonlamp*2Y_Irare_dragonlamp*8Y_Irare_dragonlamp*9Y_Irare_dragonlamp*7Y_Irare_dragonlamp*6Y_Irare_dragonlamp*1Y_Irare_dragonlamp*3Y_Irare_icecream*1Y_Irare_icecream*7Y_Irare_icecream*8Y_Irare_icecream*2Y_Irare_icecream*6Y_Irare_icecream*9Y_Irare_icecream*3Y_Irare_icecream*0Y_Irare_icecream*4Y_Irare_icecream*5Y_Irare_fan*7YxBrare_fan*6YxBrare_fan*9YxBrare_fan*3YxBrare_fan*0YxBrare_fan*4YxBrare_fan*5YxBrare_fan*1YxBrare_fan*8YxBrare_fan*2YxBqueue_tile1*3X~Dqueue_tile1*6X~Dqueue_tile1*4X~Dqueue_tile1*9X~Dqueue_tile1*8X~Dqueue_tile1*5X~Dqueue_tile1*7X~Dqueue_tile1*2X~Dqueue_tile1*1X~Dqueue_tile1*0X~DticketHrare_snowrugX~Dcn_lampZxIcn_sofaYmAsporttrack1*1YmAsporttrack1*3YmAsporttrack1*2YmAsporttrack2*1[~Nsporttrack2*2[~Nsporttrack2*3[~Nsporttrack3*1YmAsporttrack3*2YmAsporttrack3*3YmAfootylampX~Dbarchair_siloX~Ddivider_nor4*4X~Dtraffic_light*1ZxItraffic_light*2ZxItraffic_light*3ZxItraffic_light*4ZxItraffic_light*6ZxIrubberchair*1X~Drubberchair*2X~Drubberchair*3X~Drubberchair*4X~Drubberchair*5X~Drubberchair*6X~Dbarrier*1X~Dbarrier*2X~Dbarrier*3X~Drubberchair*7X~Drubberchair*8X~Dtable_norja_med*2Y_Itable_norja_med*3Y_Itable_norja_med*4Y_Itable_norja_med*5Y_Itable_norja_med*6Y_Itable_norja_med*7Y_Itable_norja_med*8Y_Itable_norja_med*9Y_Icouch_norja*2X~Dcouch_norja*3X~Dcouch_norja*4X~Dcouch_norja*5X~Dcouch_norja*6X~Dcouch_norja*7X~Dcouch_norja*8X~Dcouch_norja*9X~Dshelves_norja*2X~Dshelves_norja*3X~Dshelves_norja*4X~Dshelves_norja*5X~Dshelves_norja*6X~Dshelves_norja*7X~Dshelves_norja*8X~Dshelves_norja*9X~Dchair_norja*2X~Dchair_norja*3X~Dchair_norja*4X~Dchair_norja*5X~Dchair_norja*6X~Dchair_norja*7X~Dchair_norja*8X~Dchair_norja*9X~Ddivider_nor1*2X~Ddivider_nor1*3X~Ddivider_nor1*4X~Ddivider_nor1*5X~Ddivider_nor1*6X~Ddivider_nor1*7X~Ddivider_nor1*8X~Ddivider_nor1*9X~Dsoft_sofa_norja*2X~Dsoft_sofa_norja*3X~Dsoft_sofa_norja*4X~Dsoft_sofa_norja*5X~Dsoft_sofa_norja*6X~Dsoft_sofa_norja*7X~Dsoft_sofa_norja*8X~Dsoft_sofa_norja*9X~Dsoft_sofachair_norja*2X~Dsoft_sofachair_norja*3X~Dsoft_sofachair_norja*4X~Dsoft_sofachair_norja*5X~Dsoft_sofachair_norja*6X~Dsoft_sofachair_norja*7X~Dsoft_sofachair_norja*8X~Dsoft_sofachair_norja*9X~Dsofachair_silo*2X~Dsofachair_silo*3X~Dsofachair_silo*4X~Dsofachair_silo*5X~Dsofachair_silo*6X~Dsofachair_silo*7X~Dsofachair_silo*8X~Dsofachair_silo*9X~Dtable_silo_small*2X~Dtable_silo_small*3X~Dtable_silo_small*4X~Dtable_silo_small*5X~Dtable_silo_small*6X~Dtable_silo_small*7X~Dtable_silo_small*8X~Dtable_silo_small*9X~Ddivider_silo1*2X~Ddivider_silo1*3X~Ddivider_silo1*4X~Ddivider_silo1*5X~Ddivider_silo1*6X~Ddivider_silo1*7X~Ddivider_silo1*8X~Ddivider_silo1*9X~Ddivider_silo3*2X~Ddivider_silo3*3X~Ddivider_silo3*4X~Ddivider_silo3*5X~Ddivider_silo3*6X~Ddivider_silo3*7X~Ddivider_silo3*8X~Ddivider_silo3*9X~Dtable_silo_med*2X~Dtable_silo_med*3X~Dtable_silo_med*4X~Dtable_silo_med*5X~Dtable_silo_med*6X~Dtable_silo_med*7X~Dtable_silo_med*8X~Dtable_silo_med*9X~Dsofa_silo*2X~Dsofa_silo*3X~Dsofa_silo*4X~Dsofa_silo*5X~Dsofa_silo*6X~Dsofa_silo*7X~Dsofa_silo*8X~Dsofa_silo*9X~Dsofachair_polyfon*2X~Dsofachair_polyfon*3X~Dsofachair_polyfon*4X~Dsofachair_polyfon*6X~Dsofachair_polyfon*7X~Dsofachair_polyfon*8X~Dsofachair_polyfon*9X~Dsofa_polyfon*2Z[Msofa_polyfon*3Z[Msofa_polyfon*4Z[Msofa_polyfon*6Z[Msofa_polyfon*7Z[Msofa_polyfon*8Z[Msofa_polyfon*9Z[Mbed_polyfon*2X~Dbed_polyfon*3X~Dbed_polyfon*4X~Dbed_polyfon*6X~Dbed_polyfon*7X~Dbed_polyfon*8X~Dbed_polyfon*9X~Dbed_polyfon_one*2[dObed_polyfon_one*3[dObed_polyfon_one*4[dObed_polyfon_one*6[dObed_polyfon_one*7[dObed_polyfon_one*8[dObed_polyfon_one*9[dObardesk_polyfon*2X~Dbardesk_polyfon*3X~Dbardesk_polyfon*4X~Dbardesk_polyfon*5X~Dbardesk_polyfon*6X~Dbardesk_polyfon*7X~Dbardesk_polyfon*8X~Dbardesk_polyfon*9X~Dbardeskcorner_polyfon*2X~Dbardeskcorner_polyfon*3X~Dbardeskcorner_polyfon*4X~Dbardeskcorner_polyfon*5X~Dbardeskcorner_polyfon*6X~Dbardeskcorner_polyfon*7X~Dbardeskcorner_polyfon*8X~Dbardeskcorner_polyfon*9X~Ddivider_poly3*2X~Ddivider_poly3*3X~Ddivider_poly3*4X~Ddivider_poly3*5X~Ddivider_poly3*6X~Ddivider_poly3*7X~Ddivider_poly3*8X~Ddivider_poly3*9X~Dchair_silo*2X~Dchair_silo*3X~Dchair_silo*4X~Dchair_silo*5X~Dchair_silo*6X~Dchair_silo*7X~Dchair_silo*8X~Dchair_silo*9X~Ddivider_nor3*2X~Ddivider_nor3*3X~Ddivider_nor3*4X~Ddivider_nor3*5X~Ddivider_nor3*6X~Ddivider_nor3*7X~Ddivider_nor3*8X~Ddivider_nor3*9X~Ddivider_nor2*2X~Ddivider_nor2*3X~Ddivider_nor2*4X~Ddivider_nor2*5X~Ddivider_nor2*6X~Ddivider_nor2*7X~Ddivider_nor2*8X~Ddivider_nor2*9X~Dsilo_studydeskX~Dsolarium_norjaY_Isolarium_norja*1Y_Isolarium_norja*2Y_Isolarium_norja*3Y_Isolarium_norja*5Y_Isolarium_norja*6Y_Isolarium_norja*7Y_Isolarium_norja*8Y_Isolarium_norja*9Y_IsandrugX~Drare_moonrugYmAchair_chinaYmAchina_tableYmAsleepingbag*1YmAsleepingbag*2YmAsleepingbag*3YmAsleepingbag*4YmAsafe_siloY_Isleepingbag*7YmAsleepingbag*9YmAsleepingbag*5YmAsleepingbag*10YmAsleepingbag*6YmAsleepingbag*8YmAchina_shelveX~Dtraffic_light*5ZxIdivider_nor4*2X~Ddivider_nor4*3X~Ddivider_nor4*5X~Ddivider_nor4*6X~Ddivider_nor4*7X~Ddivider_nor4*8X~Ddivider_nor4*9X~Ddivider_nor5*2X~Ddivider_nor5*3X~Ddivider_nor5*4X~Ddivider_nor5*5X~Ddivider_nor5*6X~Ddivider_nor5*7X~Ddivider_nor5*8X~Ddivider_nor5*9X~Ddivider_nor5X~Ddivider_nor4X~Dwall_chinaYmAcorner_chinaYmAbarchair_silo*2X~Dbarchair_silo*3X~Dbarchair_silo*4X~Dbarchair_silo*5X~Dbarchair_silo*6X~Dbarchair_silo*7X~Dbarchair_silo*8X~Dbarchair_silo*9X~Dsafe_silo*2Y_Isafe_silo*3Y_Isafe_silo*4Y_Isafe_silo*5Y_Isafe_silo*6Y_Isafe_silo*7Y_Isafe_silo*8Y_Isafe_silo*9Y_Iglass_shelfY_Iglass_chairY_Iglass_stoolY_Iglass_sofaY_Iglass_tableY_Iglass_table*2Y_Iglass_table*3Y_Iglass_table*4Y_Iglass_table*5Y_Iglass_table*6Y_Iglass_table*7Y_Iglass_table*8Y_Iglass_table*9Y_Iglass_chair*2Y_Iglass_chair*3Y_Iglass_chair*4Y_Iglass_chair*5Y_Iglass_chair*6Y_Iglass_chair*7Y_Iglass_chair*8Y_Iglass_chair*9Y_Iglass_sofa*2Y_Iglass_sofa*3Y_Iglass_sofa*4Y_Iglass_sofa*5Y_Iglass_sofa*6Y_Iglass_sofa*7Y_Iglass_sofa*8Y_Iglass_sofa*9Y_Iglass_stool*2Y_Iglass_stool*4Y_Iglass_stool*5Y_Iglass_stool*6Y_Iglass_stool*7Y_Iglass_stool*8Y_Iglass_stool*3Y_Iglass_stool*9Y_ICFC_100_coin_goldZvCCFC_10_coin_bronzeZvCCFC_200_moneybagZvCCFC_500_goldbarZvCCFC_50_coin_silverZvCCF_10_coin_goldZvCCF_1_coin_bronzeZvCCF_20_moneybagZvCCF_50_goldbarZvCCF_5_coin_silverZvChc_crptYmAhc_tvZ\\BgothgateX~DgothiccandelabraYxBgothrailingX~Dgoth_tableYmAhc_bkshlfYmAhc_btlrY_Ihc_crtnYmAhc_djsetYmAhc_frplcZbBhc_lmpstYmAhc_machineYmAhc_rllrXQHhc_rntgnX~Dhc_trllYmAgothic_chair*1X~Dgothic_sofa*1X~Dgothic_stool*1X~Dgothic_chair*2X~Dgothic_sofa*2X~Dgothic_stool*2X~Dgothic_chair*3X~Dgothic_sofa*3X~Dgothic_stool*3X~Dgothic_chair*4X~Dgothic_sofa*4X~Dgothic_stool*4X~Dgothic_chair*5X~Dgothic_sofa*5X~Dgothic_stool*5X~Dgothic_chair*6X~Dgothic_sofa*6X~Dgothic_stool*6X~Dval_cauldronX~Dsound_machineX~Dromantique_pianochair*3Y_Iromantique_pianochair*5Y_Iromantique_pianochair*2Y_Iromantique_pianochair*4Y_Iromantique_pianochair*1Y_Iromantique_divan*3Y_Iromantique_divan*5Y_Iromantique_divan*2Y_Iromantique_divan*4Y_Iromantique_divan*1Y_Iromantique_chair*3Y_Iromantique_chair*5Y_Iromantique_chair*2Y_Iromantique_chair*4Y_Iromantique_chair*1Y_Irare_parasolY_Iplant_valentinerose*3XICplant_valentinerose*5XICplant_valentinerose*2XICplant_valentinerose*4XICplant_valentinerose*1XICplant_mazegateYeCplant_mazeZcCplant_bulrushXICpetfood4Y_Icarpet_valentineZ|Egothic_carpetXICgothic_carpet2Z|Egothic_chairX~Dgothic_sofaX~Dgothic_stoolX~Dgrand_piano*3Z|Egrand_piano*5Z|Egrand_piano*2Z|Egrand_piano*4Z|Egrand_piano*1Z|Etheatre_seatZ@Kromantique_tray2Y_Iromantique_tray1Y_Iromantique_smalltabl*3Y_Iromantique_smalltabl*5Y_Iromantique_smalltabl*2Y_Iromantique_smalltabl*4Y_Iromantique_smalltabl*1Y_Iromantique_mirrortablY_Iromantique_divider*3Z[Mromantique_divider*2Z[Mromantique_divider*4Z[Mromantique_divider*1Z[Mjp_tatami2YGGjp_tatamiYGGhabbowood_chairYGGjp_bambooYGGjp_iroriXQHjp_pillowYGGsound_set_1Y_Isound_set_2Y_Isound_set_3Y_Isound_set_4Y_Isound_set_5Z@Ksound_set_6Y_Isound_set_7Y_Isound_set_8Y_Isound_set_9Y_Isound_machine*1ZIPspotlightY_Isound_machine*2ZIPsound_machine*3ZIPsound_machine*4ZIPsound_machine*5ZIPsound_machine*6ZIPsound_machine*7ZIProm_lampZ|Erclr_sofaXQHrclr_gardenXQHrclr_chairZ|Esound_set_28Y_Isound_set_27Y_Isound_set_26Y_Isound_set_25Y_Isound_set_24Y_Isound_set_23Y_Isound_set_22Y_Isound_set_21Y_Isound_set_20Z@Ksound_set_19Z@Ksound_set_18Y_Isound_set_17Y_Isound_set_16Y_Isound_set_15Y_Isound_set_14Y_Isound_set_13Y_Isound_set_12Y_Isound_set_11Y_Isound_set_10Y_Irope_dividerXQHromantique_clockY_Irare_icecream_campaignY_Ipura_mdl5*1XQHpura_mdl5*2XQHpura_mdl5*3XQHpura_mdl5*4XQHpura_mdl5*5XQHpura_mdl5*6XQHpura_mdl5*7XQHpura_mdl5*8XQHpura_mdl5*9XQHpura_mdl4*1XQHpura_mdl4*2XQHpura_mdl4*3XQHpura_mdl4*4XQHpura_mdl4*5XQHpura_mdl4*6XQHpura_mdl4*7XQHpura_mdl4*8XQHpura_mdl4*9XQHpura_mdl3*1XQHpura_mdl3*2XQHpura_mdl3*3XQHpura_mdl3*4XQHpura_mdl3*5XQHpura_mdl3*6XQHpura_mdl3*7XQHpura_mdl3*8XQHpura_mdl3*9XQHpura_mdl2*1XQHpura_mdl2*2XQHpura_mdl2*3XQHpura_mdl2*4XQHpura_mdl2*5XQHpura_mdl2*6XQHpura_mdl2*7XQHpura_mdl2*8XQHpura_mdl2*9XQHpura_mdl1*1XQHpura_mdl1*2XQHpura_mdl1*3XQHpura_mdl1*4XQHpura_mdl1*5XQHpura_mdl1*6XQHpura_mdl1*7XQHpura_mdl1*8XQHpura_mdl1*9XQHjp_lanternXQHchair_basic*1XQHchair_basic*2XQHchair_basic*3XQHchair_basic*4XQHchair_basic*5XQHchair_basic*6XQHchair_basic*7XQHchair_basic*8XQHchair_basic*9XQHbed_budget*1XQHbed_budget*2XQHbed_budget*3XQHbed_budget*4XQHbed_budget*5XQHbed_budget*6XQHbed_budget*7XQHbed_budget*8XQHbed_budget*9XQHbed_budget_one*1XQHbed_budget_one*2XQHbed_budget_one*3XQHbed_budget_one*4XQHbed_budget_one*5XQHbed_budget_one*6XQHbed_budget_one*7XQHbed_budget_one*8XQHbed_budget_one*9XQHjp_drawerXQHtile_stellaZ[Mtile_marbleZ[Mtile_brownZ[Msummer_grill*1Y_Isummer_grill*2Y_Isummer_grill*3Y_Isummer_grill*4Y_Isummer_chair*1Y_Isummer_chair*2Y_Isummer_chair*3Y_Isummer_chair*4Y_Isummer_chair*5Y_Isummer_chair*6Y_Isummer_chair*7Y_Isummer_chair*8Y_Isummer_chair*9Y_Isound_set_36ZfIsound_set_35ZfIsound_set_34ZfIsound_set_33ZfIsound_set_32Y_Isound_set_31Y_Isound_set_30Y_Isound_set_29Y_Isound_machine_pro[~Nrare_mnstrY_Ione_way_door*1XQHone_way_door*2XQHone_way_door*3XQHone_way_door*4XQHone_way_door*5XQHone_way_door*6XQHone_way_door*7XQHone_way_door*8XQHone_way_door*9XQHexe_rugZ[Mexe_s_tableZGRsound_set_37ZfIsummer_pool*1ZlIsummer_pool*2ZlIsummer_pool*3ZlIsummer_pool*4ZlIsong_diskY_Ijukebox*1[~Ncarpet_soft_tut[~Nsound_set_44Z@Ksound_set_43Z@Ksound_set_42Z@Ksound_set_41Z@Ksound_set_40Z@Ksound_set_39Z@Ksound_set_38Z@Kgrunge_chairZ@Kgrunge_mattressZ@Kgrunge_radiatorZ@Kgrunge_shelfZ@Kgrunge_signZ@Kgrunge_tableZ@Khabboween_crypt[uKhabboween_grassZ@Khal_cauldronZ@Khal_graveZ@Ksound_set_52ZuKsound_set_51ZuKsound_set_50ZuKsound_set_49ZuKsound_set_48ZuKsound_set_47ZuKsound_set_46ZuKsound_set_45ZuKxmas_icelampZ[Mxmas_cstl_wallZ[Mxmas_cstl_twrZ[Mxmas_cstl_gate[~Ntree7Z[Mtree6Z[Msound_set_54Z[Msound_set_53Z[Msafe_silo_pb[dOplant_mazegate_snowZ[Mplant_maze_snowZ[Mchristmas_sleighZ[Mchristmas_reindeer[~Nchristmas_poopZ[Mexe_bardeskZ[Mexe_chairZ[Mexe_chair2Z[Mexe_cornerZ[Mexe_drinksZ[Mexe_sofaZ[Mexe_tableZ[Msound_set_59[~Nsound_set_58[~Nsound_set_57[~Nsound_set_56[~Nsound_set_55[~Nnoob_table*1[~Nnoob_table*2[~Nnoob_table*3[~Nnoob_table*4[~Nnoob_table*5[~Nnoob_table*6[~Nnoob_stool*1[~Nnoob_stool*2[~Nnoob_stool*3[~Nnoob_stool*4[~Nnoob_stool*5[~Nnoob_stool*6[~Nnoob_rug*1[~Nnoob_rug*2[~Nnoob_rug*3[~Nnoob_rug*4[~Nnoob_rug*5[~Nnoob_rug*6[~Nnoob_lamp*1[dOnoob_lamp*2[dOnoob_lamp*3[dOnoob_lamp*4[dOnoob_lamp*5[dOnoob_lamp*6[dOnoob_chair*1[~Nnoob_chair*2[~Nnoob_chair*3[~Nnoob_chair*4[~Nnoob_chair*5[~Nnoob_chair*6[~Nexe_globe[~Nexe_plantZ[Mval_teddy*1[dOval_teddy*2[dOval_teddy*3[dOval_teddy*4[dOval_teddy*5[dOval_teddy*6[dOval_randomizer[dOval_choco[dOteleport_door[dOsound_set_61[dOsound_set_60[dOfortune[dOsw_tableZIPsw_raven[cQsw_chestZIPsand_cstl_wallZIPsand_cstl_twrZIPsand_cstl_gateZIPgrunge_candleZIPgrunge_benchZIPgrunge_barrelZIPrclr_lampZGRprizetrophy9*1ZGRprizetrophy8*1ZGRnouvelle_traxYcPmd_rugZGRjp_tray6ZGRjp_tray5ZGRjp_tray4ZGRjp_tray3ZGRjp_tray2ZGRjp_tray1ZGRarabian_teamkZGRarabian_snakeZGRarabian_rugZGRarabian_pllwZGRarabian_divdrZGRarabian_chairZGRarabian_bigtbZGRarabian_tetblZGRarabian_tray1ZGRarabian_tray2ZGRarabian_tray3ZGRarabian_tray4ZGRPIpost.itHpost.it.vdHphotoHChessHTicTacToeHBattleShipHPokerHwallpaperHfloorHposterZ@KgothicfountainYxBhc_wall_lampZbBindustrialfanZ`BtorchZ\\Bval_heartXBCwallmirrorZ|Ejp_ninjastarsXQHhabw_mirrorXQHhabbowheelZ[Mguitar_skullZ@Kguitar_vZ@Kxmas_light[~Nhrella_poster_3[Nhrella_poster_2ZIPhrella_poster_1[Nsw_swordsZIPsw_stoneZIPsw_holeZIProomdimmerZGRmd_logo_wallZGRmd_canZGRjp_sheet3ZGRjp_sheet2ZGRjp_sheet1ZGRarabian_swordsZGRarabian_wndwZGR") QString categories = "General\nTrade\nScripting\nAdmin Only\n"; //// can I put more music on lol, sure I guess... but just this once Client::Client(QObject *parent, QTcpSocket* sock) : QObject(parent) { // take and store the socket for later use r = NULL; t = PlayerType; loggedin = false; socket = sock; socket->setParent(this); // change the parent so when this client is detroyed, the socket goes with it swimfig = "253,146,160"; height = 0.0; xlocation = 3; ylocation = 3; headface = 2; bodyface = 2; connect(sock, SIGNAL(readyRead()), this, SLOT(gotPacket())); connect(sock, SIGNAL(disconnected()), this, SLOT(deleteLater())); connect(&stepper, SIGNAL(timeout()), this, SLOT(takeStep())); stepper.setSingleShot(true); //socket->writeData("@@\001",3); sendPacket("@@"); } QString Client::getRank(QString name) { //TODO: implement this properly, it's more of a "proof of concept" if (name == "green" || name == "soap") { return "Lead Developer"; } else if (name == "lol") { return "Administrator"; } else if (name == "lewguns" || name == "steph") { return "Moderator"; } else { return "Member"; } } void Client::takeStep() { QString pak = QString("@b"); // this sends to the client that a person has moved pak += QString::number(habboid + 1); pak += " "; pak += QString::number(xlocation); // you can probably figure this out pak += ","; pak += QString::number(ylocation); pak += ","; if (xlocation != xtarg || ylocation != ytarg) { if (ytarg > ylocation) { ylocation++; headface = 4; bodyface = 4; } else if (ytarg < ylocation) { ylocation--; headface = 0; bodyface = 0; } else if (xtarg > xlocation) { xlocation++; headface = 2; bodyface = 2; } else { xlocation--; headface = 6; bodyface = 6; } height = (double) r->heightmap[xlocation][ylocation]; QSqlQuery q; //q.prepare("SELECT z FROM furniture WHERE x/length=:x/length AND y/width=:y/width AND inroom=:room ORDER BY z DESC"); q.prepare("SELECT z FROM furniture WHERE ((rot=2 OR rot=6) AND x/width=:x/width AND y/length=:y/length AND inroom=:room) OR (x/length=:x/length AND y/width=:y/width AND inroom=:room) ORDER BY z DESC"); //SELECT z FROM furniture WHERE ((rot=2 OR rot=6) AND x/width=8/width AND y/length=7/length AND inroom=432) OR (x/length=8/length AND y/width=7/width AND inroom=432) ORDER BY z DESC q.bindValue(":x", xlocation, QSql::Out); q.bindValue(":y", ylocation, QSql::Out); q.bindValue(":room", croomid, QSql::Out); if (q.exec() && q.next()) { height = q.value(0).toDouble(); } pak += QString::number(height); pak += ","; pak += QString::number(headface); pak += ","; //rotation? is this actually rotateion? one is the head's facing direction, one is the body's facing direction. pak += QString::number(bodyface); // what number is what? not sure, I can figure that out after though, its not.. 100% important yet, kk pak += "/flatctrl useradmin/"; // but its slightly different, this packet is when the user has finished walking pak += "mv "; pak += QString::number(xlocation); pak += ","; pak += QString::number(ylocation); pak += ","; QString hei = QString::number(height); if (hei.size() < 2) { hei += ".0"; } pak += hei; // (wow why am I so mean :'c) pak += "/"; stepper.start(410); } else { QSqlQuery q; q.prepare("SELECT sprite, rot, z FROM furniture WHERE ((rot=2 OR rot=6) AND x/width=:x/width AND y/length=:y/length AND inroom=:room) OR (x/length=:x/length AND y/width=:y/width AND inroom=:room) ORDER BY z DESC"); q.bindValue(":x", xlocation, QSql::Out); q.bindValue(":y", ylocation, QSql::Out); q.bindValue(":room", croomid, QSql::Out); if (q.exec() && q.next()) { QSqlQuery q2; q2.prepare("SELECT sitheight, type FROM furniprofiles WHERE sprite=:sp"); q2.bindValue(":sp", q.value(0).toString(), QSql::Out); if (q2.exec() && q2.next()) { if (q2.value(0).toDouble() > 0) { bodyface = q.value(1).toInt(); headface = q.value(1).toInt(); double sitheight = -height; if (q2.value(1).toString().operator ==("sit")) { //sitheight = q2.value(0).toDouble(); sitheight += q.value(2).toDouble(); sitheight += 1; //? } pak += QString::number(height); pak += ","; pak += QString::number(headface); pak += ","; //rotation? is this actually rotateion? one is the head's facing direction, one is the body's facing direction. pak += QString::number(bodyface); // what number is what? not sure, I can figure that out after though, its not.. 100% important yet, kk pak += "/flatctrl useradmin/"; // but its slightly different, this packet is when the user has finished walking pak += "sit "; QString hei = QString::number(sitheight); if (hei.size() < 2) { hei += ".0"; } pak += hei; /// can I finish this real quick? gotta go in liek 30 seconds I wana see if it will work and your taking too long lol pak += "/"; } else { //bodyface = q.value(1).toInt(); //headface = q.value(1).toInt(); pak += QString::number(height); pak += ","; pak += QString::number(headface); pak += ","; //rotation? is this actually rotateion? one is the head's facing direction, one is the body's facing direction. pak += QString::number(bodyface); // what number is what? not sure, I can figure that out after though, its not.. 100% important yet, kk pak += "/flatctrl useradmin/"; // but its slightly different, this packet is when the user has finished walking //pak += "sit "; //height += q2.value(0).toDouble(); //QString hei = QString::number(height); //if(hei.size()< 2){ // hei += ".0"; //} //pak += hei;/// can I finish this real quick? gotta go in liek 30 seconds I wana see if it will work and your taking too long lol //pak += "/"; } } else { pak += QString::number(height); pak += ","; pak += QString::number(headface); pak += ","; //rotation? is this actually rotateion? one is the head's facing direction, one is the body's facing direction. pak += QString::number(bodyface); // what number is what? not sure, I can figure that out after though, its not.. 100% important yet, kk pak += "/flatctrl useradmin/"; // but its slightly different, this packet is when the user has finished walking } } else { pak += QString::number(height); pak += ","; pak += QString::number(headface); pak += ","; //rotation? is this actually rotateion? one is the head's facing direction, one is the body's facing direction. pak += QString::number(bodyface); // what number is what? not sure, I can figure that out after though, its not.. 100% important yet, kk pak += "/flatctrl useradmin/"; // but its slightly different, this packet is when the user has finished walking } } pak += "\r"; r->broadcastPacket(pak); } Client::~Client() { qDebug() << "Client Disconnected"; if (loggedin) { setRoom(NULL); saveToDB(); logged.remove(habboid); } } void Client::setRoom(Room* rr) { stepper.stop(); if (r != NULL) r->leaveRoom(this); r = rr; if (r == NULL) return; r->enterRoom(this); } QString getCategoryString() { QStringList qsl = categories.split("\n"); QString finale = Utils::encodeVL64(qsl.length()); for (int i = 0; i < qsl.length(); i++) { const QString s = qsl.at(i); if (s.length() > 1) { finale += Utils::encodeVL64(s.length()); finale += s; finale += "\002"; } } return finale; } bool running = false; void Client::sendPacket(QString str) { //str = str + "\001"; str.append("\001"); socket->write(str.toStdString().c_str()); socket->flush(); if (str.length() < 400 && false) { str = str.replace("\n", "\\n"); str = str.replace("\r", "\\r"); str = str.replace("\t", "\\t"); qDebug() << "SERVER->CLIENT: " << str << "\n"; } } void Client::addItem(QString sprite, bool openHand) { printf("Requested buy item. Req data:\n"); if (sprite.operator ==("t") || sprite.operator ==("l")) { // cannot add wallpaper using a command } else { QSqlQuery q; QSqlQuery q2; q2.prepare("SELECT stack, width, height, type FROM furniprofiles WHERE sprite=:sp"); q2.bindValue(":sp", sprite, QSql::In); if (q2.exec() && q2.next()) { q.prepare("INSERT INTO furniture (inhand, sprite, stackh, length, width) VALUES(:ih, :s, :stk, :l, :w)"); q.bindValue(":ih", QString::number(habboid), QSql::In); q.bindValue(":s", sprite, QSql::In); q.bindValue(":l", q2.value(1).toInt(), QSql::In); q.bindValue(":w", q2.value(2).toInt(), QSql::In); if (q2.value(3).toString().operator ==("rug")) { q.bindValue(":stk", "0.1", QSql::In); } else { q.bindValue(":stk", q2.value(0).toString(), QSql::In); } q.exec(); } } if (openHand)sendPacket("AC"); } void Client::processCmd(QString r) { if (r.startsWith(":")) { QString cmd = r.right(r.length() - 1); if (cmd.startsWith("additem ")) { QStringList d = cmd.split(" "); if (d.length() == 2) { addItem(d.value(1, NULL), true); } else if (d.length() == 3) { for (int i = 0; i < d.value(2, NULL).toInt(); i++) { addItem(d.value(1, NULL), false); } sendPacket("AC"); } else { //sendPacket("BKError parsing command: invalid number of arguments."); } } else if (cmd.startsWith("help") || cmd.startsWith("command")) { sendPacket("BK NexusServer Commands Menu \n\n:additem [sprite] [count (optional)]\n - adds item(s)\n:help/:commands\n - prints this menu.\n "); } else { sendPacket("BKError processing command: " + cmd); } } } void Client::processPacket(QString packet, int header, int len) { if (!loggedin) { switch (header) { case Opcode::SSOAuth: // CL (SSO-login) { QSqlQuery q; q.prepare("SELECT accountid FROM ssotickets WHERE ticket=:t"); q.bindValue(":t", packet.mid(4,Utils::decodeB64(packet.mid(2,2))), QSql::Out); if(q.exec() && q.next()){ int accountid = q.value(0).toInt(); q.prepare("DELETE FROM ssotickets WHERE accountid=:id"); q.bindValue(":id", accountid, QSql::Out); q.exec(); q.prepare("SELECT figure, sex, email, bdate, motto, username FROM accounts WHERE id=:id"); q.bindValue(":id", accountid, QSql::Out); if (!q.exec()) { sendPacket("BKError connecting to server"); //socket->close(); //disconnect(); break; } if (!q.next()) { // will this work? // report bad login due to credientials sendPacket("@alogin incorrect: Wrong username"); //socket->close(); break; } else { if (isLogged(accountid)) { sendPacket("BKAccount Already Logged In"); break; } sendPacket("@Gclub_habbo"); //sendPacket("@Bfuse_room_queue_default\002fuse_trade\002fuse_use_club_outfits\002fuse_buy_credits\002fuse_login\002default\002default\002fuse_use_special_room_layouts\002fuse_priority_access\002fuse_use_club_outfits\002fuse_use_club_badge\002fuse_habbo_chooser\002fuse_larger_wardrobe\002fuse_club_dances\002fuse_vip\002fuse_use_club_dance\002fuse_extended_buddylist\002fuse_use_club_catalog\002fuse_room_queue_club\002fuse_use_wardrobe\002fuse_use_vip_outfits\002fuse_larger_wardrobe\002"); sendPacket("@Bfuse_room_queue_defaultfuse_tradefuse_buy_creditsfuse_loginfuse_enter_locked_roomsfuse_habbo_chooserfuse_furni_chooserfuse_enter_full_roomsfuse_use_club_outfitsfuse_use_club_badgefuse_use_special_room_layoutsfuse_room_queue_clubfuse_room_queue_defaultfuse_use_club_dancefuse_priority_accessdefault\002"); sendPacket("@C"); habboid = accountid; name = q.value(5).toString(); figure = q.value(0).toString(); gender = q.value(1).toString(); //mission = query.value(3).toString(); email = q.value(2).toString(); bdate = q.value(3).toString(); motto = q.value(4).toString(); loggedin = true; logged.insert(habboid, this); sendPacket("@DH"); break; } }else{ sendPacket("BKError: Invalid SSO ticket!"); } break; } case Opcode::UserAuth: // @D (login packet) { QString username; QString password; int len = Utils::decodeB64(packet.mid(2, 2)); username = packet.mid(4, len); int len2 = Utils::decodeB64(packet.mid(4 + len, 2)); password = packet.mid(6 + len, len2); QSqlQuery query; query.prepare("SELECT id, figure, sex, email, bdate, motto, username FROM accounts WHERE LOWER(username)=:un AND password=:pass"); query.bindValue(":un", username.toLower(), QSql::Out); query.bindValue(":pass", password, QSql::Out); //use//what are you doing, I already fixed it, I want to retur the real username to so the client gets the correct case if (!query.exec()) { sendPacket("BKError connecting to server"); //socket->close(); //disconnect(); break; } if (!query.next()) { // will this work? // report bad login due to credientials sendPacket("@alogin incorrect: Wrong username"); //socket->close(); break; } else { int id = query.value(0).toInt(); if (isLogged(id)) { sendPacket("BKAccount Already Logged In"); break; } sendPacket("@Gclub_habbo"); //sendPacket("@Bfuse_room_queue_default\002fuse_trade\002fuse_use_club_outfits\002fuse_buy_credits\002fuse_login\002default\002default\002fuse_use_special_room_layouts\002fuse_priority_access\002fuse_use_club_outfits\002fuse_use_club_badge\002fuse_habbo_chooser\002fuse_larger_wardrobe\002fuse_club_dances\002fuse_vip\002fuse_use_club_dance\002fuse_extended_buddylist\002fuse_use_club_catalog\002fuse_room_queue_club\002fuse_use_wardrobe\002fuse_use_vip_outfits\002fuse_larger_wardrobe\002"); sendPacket("@Bfuse_room_queue_defaultfuse_tradefuse_buy_creditsfuse_loginfuse_enter_locked_roomsfuse_habbo_chooserfuse_furni_chooserfuse_enter_full_roomsfuse_use_club_outfitsfuse_use_club_badgefuse_use_special_room_layoutsfuse_room_queue_clubfuse_room_queue_defaultfuse_use_club_dancefuse_priority_accessdefault\002"); sendPacket("@C"); habboid = id; name = query.value(6).toString(); figure = query.value(1).toString(); gender = query.value(2).toString(); //mission = query.value(3).toString(); email = query.value(3).toString(); bdate = query.value(4).toString(); motto = query.value(5).toString(); loggedin = true; logged.insert(habboid, this); sendPacket("@DH"); break; } break; } case Opcode::UnknownAuth1: { sendPacket("DZH"); break; }//Ht (unused regisration data (wtf this is the wrong header) case Opcode::UnknownAuth2: { sendPacket("DO"); break; }//Ps (unused regisration data (wtf this is the wrong header) case Opcode::UnknownAuth3: { sendPacket("CY1"); break; }//J1 (unused regisration data (wtf this is the wrong header) case Opcode::UnknownAuth4: { sendPacket("DO"); break; }//98 (unused regisration data (wtf this is the wrong header) case Opcode::RequestDate: // @q (request date) { QDate date = QDate::currentDate(); QString cdate = date.toString("dd-MM-yyyy"); sendPacket("Bc" + cdate); break; } case Opcode::CheckName: //@j (check name) { int namelen = Utils::decodeB64(packet.mid(2, 2)); QString reqname = packet.mid(4, namelen); //bool exists = false; QSqlQuery query; query.prepare("SELECT id FROM accounts WHERE username=:uname"); query.bindValue(":uname", reqname, QSql::Out); sendPacket("@d" + Utils::encodeVL64(query.exec() && (query.size() + 1))); qDebug() << "Resultset size: " << query.size() << "\n"; break; } case Opcode::Register: //B@ (regestration packet) { int len = Utils::decodeB64(packet.mid(4, 2)); int totlen = 6; QString username = packet.mid(totlen, len); totlen += len + 2; len = Utils::decodeB64(packet.mid(totlen, 2)); totlen += 2; QString figure = packet.mid(totlen, len); totlen += len + 2; len = Utils::decodeB64(packet.mid(totlen, 2)); totlen += 2; QString sex = packet.mid(totlen, len); totlen += len + 6; len = Utils::decodeB64(packet.mid(totlen, 2)); totlen += 2; QString email = packet.mid(totlen, len); totlen += len + 2; len = Utils::decodeB64(packet.mid(totlen, 2)); totlen += 2; QString bdate = packet.mid(totlen, len); totlen += len + 11; len = Utils::decodeB64(packet.mid(totlen, 2)); totlen += 2; QString pass = packet.mid(totlen, len); totlen += len + 2; qDebug() << "REGISTRATION REQUEST: \n USERNAME: " << username << "\n PASSWORD: " << pass << "\n FIGURE: " << figure << "\n SEX: " << sex << "\n EMAIL: " << email << "\n BDATE: " << bdate << "\n"; QSqlQuery query; query.prepare("SELECT count(id) FROM accounts WHERE LOWER(username)=:user"); query.bindValue(":user", username.toLower()); if (query.exec() && query.next() && query.value(0).toInt() > 0) { // Account Already Exists return; } query.prepare("INSERT INTO accounts (username, password, figure, sex, email, bdate, motto) VALUES (:username, :password, :figure, :sex, :email, :bdate, :motto)"); query.bindValue(":username", username, QSql::In); query.bindValue(":password", pass, QSql::In); query.bindValue(":figure", figure, QSql::In); query.bindValue(":sex", sex, QSql::In); query.bindValue(":email", email, QSql::In); query.bindValue(":bdate", bdate, QSql::In); query.bindValue(":motto", "unset", QSql::In); bool result = query.exec(); if (result) { qDebug() << "Successfully registered account!\n"; sendPacket("BKAccount successfully created!\nWelcome to the v14 NexusServer test server!"); } else { qDebug() << "ERROR REGISTERING ACCOUNT! ERROR MESSAGE:\n"; sendPacket("BKERROR CREATING ACCOUNT!"); } //qDebug() << packet; break; } case Opcode::Prelogin1: //CJ (pre-login data) { sendPacket("DARAHIIIKHJIPAIQAdd-MM-yyyy\002"); sendPacket("@H[100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,176,177,178,180,185,190,195,200,205,206,207,210,215,220,225,230,235,240,245,250,255,260,265,266,267,270,275,280,281,285,290,295,300,305,500,505,510,515,520,525,530,535,540,545,550,555,565,570,575,580,585,590,595,596,600,605,610,615,620,625,626,627,630,635,640,645,650,655,660,665,667,669,670,675,680,685,690,695,696,700,705,710,715,720,725,730,735,740]"); break; } case Opcode::Prelogin2: //CN (pre-login data) { sendPacket("DARAHIIIKHJIPAIQAdd-MM-yyyy\002"); // ? sendPacket("@H[100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,176,177,178,180,185,190,195,200,205,206,207,210,215,220,225,230,235,240,245,250,255,260,265,266,267,270,275,280,281,285,290,295,300,305,500,505,510,515,520,525,530,535,540,545,550,555,565,570,575,580,585,590,595,596,600,605,610,615,620,625,626,627,630,635,640,645,650,655,660,665,667,669,670,675,680,685,690,695,696,700,705,710,715,720,725,730,735,740]"); sendPacket("DUIH"); break; } default: { //qDebug() << "[" << packet.left(2) << "]: unhandled packet. Length:" << len << " HeaderID: " << header << " Body: " << packet.mid(3, len); QString debugstr = QString("["); debugstr += packet.left(2); debugstr += "]: unhandled packet. Length:"; debugstr += QString::number(len); debugstr += " HeaderID: "; debugstr += QString::number(header); if (len > 2) { debugstr += " Packet body: "; debugstr += packet.mid(2, len); } debugstr += "\n"; printf(debugstr.toStdString().c_str()); break; } } } else { switch (header) { case Opcode::Prelogin1: //CJ (pre-login data) { sendPacket("DARAHIIIKHJIPAIQAdd-MM-yyyy\002"); sendPacket("@H[100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,176,177,178,180,185,190,195,200,205,206,207,210,215,220,225,230,235,240,245,250,255,260,265,266,267,270,275,280,281,285,290,295,300,305,500,505,510,515,520,525,530,535,540,545,550,555,565,570,575,580,585,590,595,596,600,605,610,615,620,625,626,627,630,635,640,645,650,655,660,665,667,669,670,675,680,685,690,695,696,700,705,710,715,720,725,730,735,740]"); break; } case Opcode::Prelogin2: //CN (pre-login data) { sendPacket("DARAHIIIKHJIPAIQAdd-MM-yyyy\002"); // ? sendPacket("@H[100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,176,177,178,180,185,190,195,200,205,206,207,210,215,220,225,230,235,240,245,250,255,260,265,266,267,270,275,280,281,285,290,295,300,305,500,505,510,515,520,525,530,535,540,545,550,555,565,570,575,580,585,590,595,596,600,605,610,615,620,625,626,627,630,635,640,645,650,655,660,665,667,669,670,675,680,685,690,695,696,700,705,710,715,720,725,730,735,740]"); sendPacket("DUIH"); break; } case Opcode::EnterRoom: // @U (enter room) { //QSqlQuery q;// no it does it here //here int id = packet.mid(2, packet.length() - 2).toInt(); // wow my vision is blurring slightly atm Room* room = Room::byID(id); // this does checking and loading if (room == NULL) { sendPacket("BKNo Such Room"); } else { croomid = id; croommodel = room->getModel(); croomoid - room->oid; setRoom(room); //// } break; } case Opcode::RequestAd: // Bv (request ad) { //sendPacket("DBhttp://www.jonnyandrewsblog.com/x/wp-content/uploads/2011/04/BuyMyShitButton.jpg\thttp://208.93.154.34/"); sendPacket("DB0"); break; } case Opcode::RequestCharacter: { sendPacket(QString("@E") + QString::number(habboid) + "\002" + name + "\002" + figure + "\002" + gender + "\002" + motto + "\002Hch=" + swimfig + "\002HH"); //sendPacket("C]" + getCategoryString()); sendPacket("C]PASLGeneralRLTradePRScriptingRQAdmin Only"); //NexusServer::broadcastGlobal("BKUser logged in!"); //sendPacket("@DH"); break; } case Opcode::Unknown1: //? { sendPacket("CP0"); // ? break; } case Opcode::Unknown2: { sendPacket("@r"); break; } case Opcode::RoomInfo: // @B load some room info { sendPacket("@S"); sendPacket(QString("AE") + croommodel + " " + QString::number(croomid)); QSqlQuery q; q.prepare("SELECT color FROM paints WHERE inroom=:id AND placement=\"floor\""); q.bindValue(":id", croomid, QSql::Out); if (q.exec() && q.next()) { sendPacket(QString("@nfloor/") + q.value(0).toString()); } else { sendPacket("@nfloor/0"); } q.prepare("SELECT color FROM paints WHERE inroom=:id AND placement=\"wallpaper\""); q.bindValue(":id", croomid, QSql::Out); if (q.exec() && q.next()) { sendPacket(QString("@nwallpaper/") + q.value(0).toString()); } else { sendPacket("@nwallpaper/0"); } break; } case Opcode::UserList: // @} req user list { Room* r = Room::byID(croomid); QString pak = QString("@\\"); foreach(Client* c, r->listClients()) {// brb, laundry mmk //c = r->getClientById(i); pak += "i:" + QString::number(c->habboid + 1) // how will this know what client to do for make happen do? its not the room id.. its the user's unique in-room id //hello? + "\ra:" + QString::number(c->habboid) + "\rn:" + c->name + "\rf:" + c->figure + "\rl:" + QString::number(c->xlocation) + " " + QString::number(c->ylocation) + " " + QString::number(c->height) + "\rc:" + c->motto + "\rs:" + c->gender + "\rb:"; pak += "\x0d"; } ////// wait,,, pak += dummyfix;// //pak = pak.left(pak.size()-1); sendPacket(pak); sendPacket("@\\"); break; } case Opcode::FurnitureInfo: { sendPacket("@^"); Room* r = Room::byID(croomid); QString pak = QString("@`"); //printf("Room Object: %u\n", r); pak += Utils::encodeVL64(r->furnituremap.size()); foreach(Furniture* f, r->furnituremap) { //printf("Furniture Object: %u\n", f);// ssec //printf("Profile Object: %u\n", f->profile);// ssec pak += QString::number(f->id); pak += "\002"; pak += f->profile->name; pak += "\002"; pak += Utils::encodeVL64(f->x); pak += Utils::encodeVL64(f->y); pak += Utils::encodeVL64(f->profile->width); //length pak += Utils::encodeVL64(f->profile->height); // width pak += Utils::encodeVL64(f->rot); // width pak += QString::number(f->z); pak += "\002"; pak += f->profile->cust; pak += "\002\002\002"; } sendPacket(pak); // cross fingers sendPacket("@m"); // posters break; } case Opcode::Decorations: //paint/floor { QSqlQuery q; QSqlQuery q2; q2.prepare("SELECT status FROM furniture WHERE id=:id"); q2.bindValue(":id", -packet.right(packet.length()-(packet.indexOf("/") + 1)).toInt(), QSql::Out); if (q2.exec() && q2.next()) { QString placement = packet.left(packet.indexOf("/")); placement = placement.right(placement.length() - 2); QSqlQuery q3; q3.prepare("DELETE FROM paints WHERE inroom=:ir AND placement=:pl"); // this doesnt work, paints overlap it should remove the previous one q3.bindValue(":pl", placement, QSql::Out); q3.bindValue(":ir", croomid, QSql::Out); q3.exec(); q.prepare("INSERT INTO paints (inroom, color, placement) VALUES(:ir, :col, :place)"); q.bindValue(":ir", QString::number(croomid), QSql::In); q.bindValue(":col", q2.value(0).toString(), QSql::In); q.bindValue(":place", placement, QSql::In); if (q.exec()) { q.prepare("DELETE FROM furniture WHERE id=:id"); // q.bindValue(":id", -packet.right(packet.length()-(packet.indexOf("/") + 1)).toInt(), QSql::Out); if (q.exec()) { //"@n" + ItemType + "/" + ItemColour Room::byID(croomid)->broadcastPacket("@n" + placement + "/" + q2.value(0).toString()); } } } else { sendPacket(QString("BKError placing wallpaper/floor!\nVariable readout:\nFurniture id: ") + packet.right(packet.length()-(packet.indexOf("/") + 1)) + "\nPlacement: " + packet.left(packet.indexOf("/"))); } break; } case Opcode::BuyItem: //buy item { QStringList data = packet.right(packet.length() - 2).split("\r"); printf("Requested buy item. Req data:\n"); int index = 0; QString sprite; QString catpage; QString selcol; while (data.size() > 0) { printf((QString("[") + QString::number(index) + "]: " + data.first() + "\n").toStdString().c_str()); if (index == 3) { sprite = data.first(); } if (index == 4) { selcol = data.first(); } if (index == 1) { catpage = data.first(); } data.removeFirst(); index++; } QString fullsprite = sprite; sprite = sprite.right(sprite.length()-(sprite.indexOf(" ") + 1)); if (sprite.operator ==("t") || sprite.operator ==("l")) { QSqlQuery q; q.prepare("INSERT INTO furniture (inhand, sprite, status) VALUES(:ih, :s, :st)"); q.bindValue(":ih", QString::number(habboid), QSql::In); q.bindValue(":s", sprite, QSql::In); q.bindValue(":st", selcol, QSql::In); q.exec(); } else if(fullsprite.startsWith("poster")){ QSqlQuery q; q.prepare("INSERT INTO posters (sprite, cust, inhand) VALUES (:sp, :cu, :ih)"); q.bindValue(":sp", fullsprite.left(fullsprite.indexOf(" ")), QSql::In); q.bindValue(":cu", sprite, QSql::In); q.bindValue(":ih", habboid, QSql::In); if(!q.exec()){ sendPacket("BKError buying " + fullsprite); } } else { QSqlQuery q; QSqlQuery q2; q2.prepare("SELECT stack, width, height, type FROM furniprofiles WHERE sprite=:sp"); q2.bindValue(":sp", sprite, QSql::In); if (q2.exec() && q2.next()) { q.prepare("INSERT INTO furniture (inhand, sprite, stackh, length, width) VALUES(:ih, :s, :stk, :l, :w)"); q.bindValue(":ih", QString::number(habboid), QSql::In); q.bindValue(":s", sprite, QSql::In); q.bindValue(":l", q2.value(1).toInt(), QSql::In); q.bindValue(":w", q2.value(2).toInt(), QSql::In); if (q2.value(3).toString().operator ==("rug")) { q.bindValue(":stk", "0.1", QSql::In); } else { q.bindValue(":stk", q2.value(0).toString(), QSql::In); } q.exec(); } } sendPacket("AC"); break; } case Opcode::Heightmap: // @| request heightmap { QSqlQuery q; q.prepare("SELECT map FROM heightmaps WHERE model=:model"); q.bindValue(":model", croommodel, QSql::Out); if (q.exec() && q.next()) { sendPacket("@_" + q.value(0).toString()); } break; } case Opcode::PickupItem: {//pick up item if (croomoid == habboid) { int id = packet.mid(12, packet.length() - 12).toInt(); printf((QString("Attempted to pick up item: ") + QString::number(id) + "\n").toStdString().c_str()); QSqlQuery q; q.prepare("UPDATE furniture SET inroom=-1, inhand=:hid WHERE id=:id"); q.bindValue(":id", id, QSql::Out); q.bindValue(":hid", habboid, QSql::In); if (q.exec()) { Room::byID(croomid)->broadcastPacket("A^" + QString::number(id)); } //QSqlQuery q; QString pak = QString("BL"); q.prepare("SELECT id, sprite, length, width, status, color FROM furniture WHERE inhand=:je"); q.bindValue(":je", habboid, QSql::Out); if (q.exec()) { int i = 0; while (q.next()) { QSqlQuery q2; q2.prepare("SELECT type, name, var, cust, flag, width, height FROM furniprofiles WHERE sprite=:s"); q2.bindValue(":s", q.value(1).toString(), QSql::Out); if (q2.exec() && q2.next()) { pak += "SI\x1E-"; pak += q.value(0).toString(); pak += "\x1E"; pak += QString::number(i); pak += "\x1E"; pak += q2.value(4).toString(); pak += "\x1E"; pak += q.value(0).toString(); pak += "\x1E"; pak += q2.value(1).toString(); // sprite pak += "\x1E"; pak += q2.value(5).toString(); pak += "\x1E"; pak += q2.value(6).toString(); if (q2.value(4).toString().operator ==("S")) { pak += "\x1E"; pak += q2.value(2).toString(); pak += "\x1E"; pak += q2.value(3).toString(); pak += "\x1E"; pak += QString::number(i); pak += "\x1E"; pak += q2.value(1).toString(); // sprite pak += "\x1E"; } else { pak += "\x1E"; } pak += "/"; } } sendPacket(pak + "\r" + QString::number(i)); } } break; } case Opcode::CreateRoom://@] create room { QString tmp = packet.right(packet.length() - 3); QString floor = tmp.left(tmp.indexOf("/")); // lol the client doesnt even change this tmp = tmp.right(tmp.length() - (floor.length() + 1)); QString rname = tmp.left(tmp.indexOf("/")); tmp = tmp.right(tmp.length() - (rname.length() + 1)); QString model = tmp.left(tmp.indexOf("/")); tmp = tmp.right(tmp.length() - (model.length() + 1)); QString accesslevel = tmp.left(tmp.indexOf("/")); // NYI tmp = tmp.right(tmp.length() - (accesslevel.length() + 1)); QSqlQuery q; q.prepare("INSERT INTO rooms (title, desc, owner, ownerstr, usercount, maxcount, category, model, showowner) VALUES (:t,:d,:o,:os,:uc,:mc,:c,:m,:s)"); q.bindValue(":t", rname, QSql::In); q.bindValue(":d", "unset", QSql::In); q.bindValue(":os", name, QSql::In); q.bindValue(":o", habboid, QSql::In); q.bindValue(":uc", 0, QSql::In); q.bindValue(":mc", 25, QSql::In); q.bindValue(":c", 51, QSql::In); q.bindValue(":m", model, QSql::In); q.bindValue(":s", tmp, QSql::In); if (q.exec()) { q.prepare("SELECT id FROM rooms WHERE owner=:h"); q.bindValue(":h", habboid, QSql::Out); if (q.exec()) { while (q.next()) { if (!q.next()) { q.previous(); sendPacket("@{" + q.value(0).toString() + "\r" + rname); break; } } } } else { sendPacket("BKError creating room!"); } break; } case Opcode::ListUserRooms://@P req user room list { QString uname = packet.right(packet.length() - 2); QSqlQuery q; q.prepare("SELECT id, title, usercount, maxcount, desc FROM rooms WHERE ownerstr=:os"); // it doesnt use an id... // and no it doesnt, this code has been working reliably for a week now // so it has to be somethiung epse // else* q.bindValue(":os", uname, QSql::Out); if (q.exec()) { QString pak = QString("@P"); while (q.next()) { Room* r = Room::byID(q.value(0).toInt()); pak += q.value(0).toString(); pak += "\t"; pak += q.value(1).toString(); pak += "\t"; pak += uname; pak += "\topen\tx\t"; pak += QString::number(r->size()); pak += "\t"; pak += QString::number(r->capacity()); pak += "\t"; pak += q.value(4).toString(); pak += "\t"; pak += "\r"; } if (pak.length() > 16) { sendPacket(pak); } else { sendPacket("@y" + uname); } } break; } case Opcode::MiscRoomData: { croomoid = Room::byID(croomid)->oid; if (croomoid == habboid) { sendPacket("@j"); //rights? sendPacket("@o"); //owner } sendPacket("DuIaeCs46118s46116s461173d459989692d1b729b431b0e82c72786"); sendPacket(DG); //sendPacket((QString("") + (char)13)+(char)10); // this is retarded sendPacket("DiH"); QSqlQuery q; q.prepare("SELECT id, status FROM furniture WHERE status !=\"\" AND inroom=:id"); q.bindValue(":id", croomid, QSql::Out); if (q.exec()) { while (q.next()) { //Room::byID(croomid)->broadcastPacket(QString("AX") + QString::number(id) + "\002" + sign + "\002"); sendPacket(QString("AX") + q.value(0).toString() + "\002" + q.value(1).toString() + "\002"); } } break; } case Opcode::PlaceFurniture: // put shit down { QStringList f = packet.right(packet.length() - 2).split(" "); //f.value() int id = -f.value(0, NULL).toInt(); int x = f.value(1, NULL).toInt(); int y = f.value(2, NULL).toInt(); QSqlQuery q2; q2.prepare("SELECT sprite, status FROM furniture WHERE id=:id"); // this query is erroring, any ideas? q2.bindValue(":id", id, QSql::Out); if (q2.exec() && q2.next()) { QString sprite = q2.value(0).toString(); QString status = q2.value(1).toString(); QSqlQuery q; QSqlQuery q4; QSqlQuery q5; q4.prepare("SELECT sprite, z FROM furniture WHERE x=:x AND y=:y AND inroom=:rooom AND stackh > 0.0 ORDER BY z DESC, stackh DESC"); q4.bindValue(":x", x, QSql::Out); q4.bindValue(":y", y, QSql::Out); q4.bindValue(":room", croomid, QSql::Out); Room* r = Room::byID(croomid); double zloc = r->heightmap[x][y]; if (q4.exec() && q4.next()) { q5.prepare("SELECT stack FROM furniprofiles WHERE sprite=:sp"); q5.bindValue(":sp", q4.value(0).toString(), QSql::Out); if (q5.exec() && q5.next()) { zloc = q4.value(1).toDouble(); zloc += q5.value(0).toDouble(); printf((QString("Stacked item ") + QString::number(id) + " up " + QString::number(zloc) + " spaces. (" + q4.value(1).toString() + " + " + q5.value(0).toString() + ")\n").toStdString().c_str()); } else { printf("Error stacking item.\n"); } } q.prepare("UPDATE furniture SET inroom=:ir, inhand=-1, x=:x, y=:y, z=:hei, rot=0 WHERE id=:id"); // this is erroring, is this correct? lol look at the query q.bindValue(":id", id, QSql::Out); q.bindValue(":ir", croomid, QSql::In); q.bindValue(":x", x, QSql::In); q.bindValue(":y", y, QSql::In); //// OMFG OMFG I FIGURED IT OUT q.bindValue(":hei", QString::number(zloc), QSql::In); if (q.exec()) { QSqlQuery q3; q3.prepare("SELECT name, cust, width, height FROM furniprofiles WHERE sprite=:s"); q3.bindValue(":sprite", sprite, QSql::Out); if (q3.exec() && q3.next()) { QString pak = QString("A]"); pak += QString::number(id); pak += "\002"; pak += q3.value(0).toString(); pak += "\002"; pak += Utils::encodeVL64(x); pak += Utils::encodeVL64(y); pak += Utils::encodeVL64(q3.value(2).toInt()); pak += Utils::encodeVL64(q3.value(3).toInt()); pak += "H"; //encoded ROT (NYI) pak += QString::number(zloc); pak += "\002"; pak += q3.value(1).toString(); pak += "\002\002"; //un-used value in here? maybe signiture pak += status; pak += "\002"; r->broadcastPacket(pak); } else { sendPacket("BKError placing item![2]"); } } else { sendPacket("BKError placing item![1]"); //qDebug() << q2.lastError(); } Furniture* fe = new Furniture(); fe->profile = FurnitureProfile::bySprite(sprite); fe->id = id; fe->sprite = sprite; fe->x = x; fe->y = y; fe->z = zloc; fe->rot = 0; fe->status = status; r->furnituremap.insert(fe->id, fe); } Room::byID(croomid)->updateHeightMap(true); break; } case Opcode::RequestRoomList: // BV (req navi data) { //int showfull = Utils::decodeVL64(packet.mid(2,1)); int category = Utils::decodeVL64(packet.right(packet.length() - 3)); switch (category) { case 4: { sendPacket("C\\HPAHGuestrooms[nFbNMAISLJGeneralQD[XKPAHRLJTradeYDAZ~EPAHPRJScriptingRhZtEPAHRQJAdmin OnlyXLA[DFPAH"); //C\HPAHGuestrooms[nFbNMAISLJStaff ZoneQD[XKPAHRLJTrading FloorYDAZ~EPAHPRJThemed RoomsRhZtEPAHRQJGaming and MazesXLA[DFPAH break; } case 3: // really need to code this properly... { sendPacket("C\\HKHPublic Rooms (BROKEN)S][^GIRKIWelcome! LoungeHHKwelcome_lounge[M{Hhh_room_nlobbyHIRdITheatredromeHSHKtheatredromeb}DAHhh_room_theaterHIReIAxe TheatredromeHSHKtheatredrome_axeb}EAHhh_room_theater_axeHIRfIEaster TheatredromeHSHKtheatredrome_easterb}FAHhh_room_theater_easterHIRgIParkHSHKparkb}GAHhh_room_park_de,hh_room_parkHIRhIHouse of flying carrotsHSHKorientb}HAHhh_room_orientHIRiIHabburgersHSHKhabburger'sb}IAHhh_room_habburgerHIRjIHotel KitchenHSHKhotel_kitchenb}JAHhh_room_kitchenHIRkIHabbo CinemaHSHKhabbo_cinemab}KAHhh_room_cinemaHIRlIMain LobbyHSHKmain_lobbyb}LAHhh_room_lobbyHIRmILidoHSHKhabbo_lidob}MAHhh_room_pool,hh_people_poolHIRnIRooftopHSHKrooftopb}NAHhh_room_rooftopHIRoIFootball RoomHSHKballroomb}OAHhh_room_ballroomHIRpITearoomHSHKtearoomb}PAHhh_room_tearoomHI"); break; } default: { QSqlQuery query; query.prepare("SELECT id,title,ownerstr,usercount,maxcount,desc FROM rooms WHERE category=:cat"); query.bindValue(":cat", category, QSql::Out); if (query.exec()) { if (query.size() > 0 || true) { QString packetblob = QString(""); int counte = 0; while (query.next()) { Room* r = Room::byID(query.value(0).toInt()); packetblob += Utils::encodeVL64(query.value(0).toInt()); packetblob += query.value(1).toString(); packetblob += "\002"; packetblob += query.value(2).toString(); packetblob += "\002open\002"; packetblob += Utils::encodeVL64(r->size()); // user count(query.value(0).toInt()) wah?? this doesnt make any sense packetblob += Utils::encodeVL64(r->capacity()); packetblob += query.value(5).toString(); packetblob += "\002"; counte++; } QString packet = QString("C\\H"); QString cati = QString(""); query.prepare("SELECT title FROM privatecats WHERE id=:id"); query.bindValue(":id", category, QSql::Out); query.exec(); query.next(); cati += query.value(0).toString(); packet += Utils::encodeVL64(category); packet += "J"; packet += cati; packet += "I"; packet += Utils::encodeVL64(counte * 15); packet += "PA"; packet += Utils::encodeVL64(counte); sendPacket(packet + packetblob); break; } else { sendPacket("BKUnknown category: " + QString::number(category)); break; } } break; } } break; } case Opcode::Ping: // Cd (ping) { sendPacket("@r"); // Pong break; } case Opcode::Ecotron: // C_ (ecotron) NYI { sendPacket("DpH"); break; } case Opcode::Badges: //B] (req badge info) NYI { sendPacket("CeHH"); break; } case Opcode::HabboClub: // @X (req hc info) NYI { sendPacket("@Gclub_habboPEPAHI"); break; } case Opcode::Credits: // @H (req credit information) { sendPacket("@F420.0"); // credits (always 420, unlimited) sendPacket("DtHH"); //? sendPacket("DpH"); //? sendPacket("DyHH"); //? sendPacket("DzHH"); //? break; } case 4: // log-in packet?! we're already logged in! { sendPacket("@Gclub_habbo"); //sendPacket("@Bfuse_room_queue_default\002fuse_trade\002fuse_use_club_outfits\002fuse_buy_credits\002fuse_login\002default\002default\002fuse_use_special_room_layouts\002fuse_priority_access\002fuse_use_club_outfits\002fuse_use_club_badge\002fuse_habbo_chooser\002fuse_larger_wardrobe\002fuse_club_dances\002fuse_vip\002fuse_use_club_dance\002fuse_extended_buddylist\002fuse_use_club_catalog\002fuse_room_queue_club\002fuse_use_wardrobe\002fuse_use_vip_outfits\002fuse_larger_wardrobe\002"); sendPacket("@Bfuse_room_queue_defaultfuse_tradefuse_buy_creditsfuse_loginfuse_enter_locked_roomsfuse_habbo_chooserfuse_furni_chooserfuse_enter_full_roomsfuse_use_club_outfitsfuse_use_club_badgefuse_use_special_room_layoutsfuse_room_queue_clubfuse_room_queue_defaultfuse_use_club_dancefuse_priority_accessdefault\002"); sendPacket("@C"); sendPacket("@DH"); break; } case 80: { //QString pak = QString(); QString pak = QString("@b"); // this sends to the client that a person has moved pak += QString::number(habboid + 1); pak += " "; pak += QString::number(xlocation); // you can probably figure this out pak += ","; pak += QString::number(ylocation); pak += ","; pak += QString::number(height); pak += ","; pak += QString::number(headface); pak += ","; //rotation? is this actually rotateion? one is the head's facing direction, one is the body's facing direction. pak += QString::number(bodyface); // what number is what? not sure, I can figure that out after though, its not.. 100% important yet, kk pak += "/flatctrl useradmin/"; // but its slightly different, this packet is when the user has finished walking pak += "carryd " + packet.right(packet.length() - 2); +"/\n"; Room::byID(croomid)->broadcastPacket(pak); break; } case 79: { QString tmp = packet.right(packet.length() - 2); int headfacet = tmp.left(tmp.indexOf(" ")).toInt(); tmp = tmp.right(tmp.length() - (tmp.indexOf(" ") + 1)); int bodyfacet = tmp.left(tmp.indexOf(" ")).toInt(); headface = headfacet; bodyface = bodyfacet; break; } case 17: // room search { //printf("Searched: "); break; } case 75: // this packet is send when a client clicks on a tile { //Room* cr = Room::byID(croomid); xtarg = Utils::decodeB64(packet.mid(2, 2)); // the clicked x location ytarg = Utils::decodeB64(packet.mid(4, 2)); // the clicked y location takeStep(); break; } case 102: //Af req cata page { QSqlQuery q; q.prepare("SELECT pagepacket FROM catalog WHERE pagename=:page"); // any better? QString reqpage = packet.mid(13, packet.right(packet.length() - 13).indexOf("/")); q.bindValue(":page", reqpage, QSql::Out); if (q.exec() && q.next()) { QString val = q.value(0).toString(); val = val.left(val.length() - 1); sendPacket(QString("A") + (char) (127) + val); } else { sendPacket(QString("BKError loading page: ") + reqpage); } break; } case 65: //hand { //sendPacket("BL"+); QSqlQuery q; QString pak = QString("BL"); q.prepare("SELECT id, sprite, length, width, status, color FROM furniture WHERE inhand=:je"); q.bindValue(":je", habboid, QSql::Out); int i = 0; if (q.exec()) { while (q.next()) { QSqlQuery q2; q2.prepare("SELECT type, name, var, cust, flag, width, height FROM furniprofiles WHERE sprite=:s"); q2.bindValue(":s", q.value(1).toString(), QSql::Out); if (q2.exec() && q2.next()) { //FurnitureProfile::bySprite(q.value(1).toString()); pak += "SI\x1E-"; pak += q.value(0).toString(); pak += "\x1E"; pak += QString::number(i); pak += "\x1E"; pak += q2.value(4).toString(); pak += "\x1E"; pak += q.value(0).toString(); pak += "\x1E"; pak += q2.value(1).toString(); // sprite pak += "\x1E"; pak += q2.value(5).toString(); pak += "\x1E"; pak += q2.value(6).toString(); if (q2.value(4).toString().operator ==("S")) { pak += "\x1E"; pak += q2.value(2).toString(); pak += "\x1E"; pak += q2.value(3).toString(); pak += "\x1E"; pak += QString::number(i); pak += "\x1E"; pak += q2.value(1).toString(); // sprite pak += "\x1E"; } else { pak += "\x1E"; } pak += "/"; } } q.prepare("SELECT id, sprite, x, y, rot, cust FROM furniture WHERE inhand=:je"); q.bindValue(":je", habboid, QSql::Out); if (q.exec()) { while (q.next()) { //FurnitureProfile::bySprite(q.value(1).toString()); pak += "SI\x1E-"; pak += q.value(0).toString(); pak += "\x1E"; pak += QString::number(i); pak += "\x1EI\x1E"; pak += q.value(0).toString(); pak += "\x1E"; pak += q.value(1).toString(); // sprite pak += "\x1E"; pak += q.value(2).toString(); pak += "\x1E"; pak += q.value(3).toString(); pak += "\x1E"; pak += "/"; } } sendPacket(pak + "\r" + QString::number(i)); } break; } case 63: //@ req item flag list? { sendPacket(DG); sendPacket((QString("") + (char) 13)+(char) 10); //wtf? sendPacket("DiH"); sendPacket("CP0"); break; } case 12: // @L ? { sendPacket("@LNYI\002"); sendPacket("@r"); ///// break; } case 53: { //leave room setRoom(NULL); break; } case 196: { // ping? break; } case 101: //Ae req cata page list { QSqlQuery q; q.prepare("SELECT pagename FROM catalog"); if (q.exec()) { QString pak = QString("A~"); while (q.next()) { pak += q.value(0).toString(); pak += "\t"; pak += q.value(0).toString(); pak += "\r"; } sendPacket(pak); sendPacket("@r"); } break; } case Opcode::SearchUsers: { int len = Utils::decodeB64(packet.mid(2, 2)); QString sname = packet.mid(4, len).toLower(); QSqlQuery q; q.prepare("SELECT id, sex, figure FROM accounts WHERE LOWER(username)=:un"); q.bindValue(":un", sname, QSql::Out); QSqlQuery q2; q2.prepare("SELECT mission FROM consolemissions WHERE LOWER(username)=:un"); q2.bindValue(":un", sname, QSql::Out); if (q.exec()) { if (q.next()) { QString cm; if (q2.exec() && q2.next()) { cm = q2.value(0).toString(); } else { cm = "unset"; } QString paq = QString("B@MESSENGER\002"); paq += Utils::encodeVL64(q.value(0).toInt()); paq += sname; paq += "\002"; paq += Utils::encodeVL64((int) q.value(1).toString().operator ==("M")); paq += cm; paq += "\002"; if (isLogged(q.value(0).toInt())) { paq += "IOnline (Location NYI)\002"; // location NYI paq += "User rank: "; paq += getRank(sname); paq += "\002"; } else { paq += "HLocation NYI\002Last online NYI\002"; } //paq += Utils::encodeVL64(isLogged(q.value(0).toInt())); //paq += "Location NYI\002Last online NYI\002"; paq += q.value(2).toString(); paq += "\002"; //B@MESSENGERPBgreenI Ion hotel view01-07-2011 12:331200118001270073000122001 sendPacket(paq); //sendPacket("BKUser search found something!"); } else { //sendPacket("BKUser search yielded no results!"); sendPacket("B@MESSENGER\002H"); } } else { sendPacket("BKError searching users!"); } break; } case Opcode::RequestFriend: { int len = Utils::decodeB64(packet.mid(2, 2)); // parse the first B64 value from the packet and decode it QString friendname = packet.mid(4, len); QSqlQuery q; q.prepare("SELECT id FROM accounts WHERE LOWER(username)=:u"); q.bindValue(":un", friendname, QSql::Out); if (q.exec()) { if (q.next()) { QSqlQuery q2; q2.prepare("INSERT INTO friends (idone, idtwo, accepted) VALUES(:me, :them, 0)"); q2.bindValue(":me", habboid, QSql::In); q2.bindValue(":them", q.value(0).toInt(), QSql::In); if (!q2.exec()) { sendPacket("BKError adding friend!"); } else { sendPacket(QString("BKAdded friend: ") + friendname); } } else { // friend does not exist? sendPacket("BKError 404! Friend not found!"); // lol 404 } } break; } case 52: { len = Utils::decodeB64(packet.right(packet.length() - 2)); QString message = packet.mid(4, len); processCmd(message); Room* r = Room::byID(croomid); r->broadcastPacket(QString("@X") + Utils::encodeVL64(habboid + 1) + message + "\002"); //r->broadcastPacket(QString("Ei") + Utils::encodeVL64(croomid) + "H"); break; } case 56: { len = Utils::decodeB64(packet.right(packet.length() - 2)); QString message = packet.mid(4, len); processCmd(message); r->broadcastPacket(QString("@Y") + Utils::encodeVL64(habboid + 1) + message + "\002"); break; } case 55: { len = Utils::decodeB64(packet.right(packet.length() - 2)); QString message = packet.mid(4, len); processCmd(message); r->broadcastPacket(QString("@Z") + Utils::encodeVL64(habboid + 1) + message + "\002"); break; } case 152: //BX modify room { sendPacket("C^" + packet.right(packet.size() - 2) + Utils::encodeVL64(51)); break; } case Opcode::updateProfile: { int index = 2; int tlen = 0; int cid = 0; while (index < packet.length() - 2) { cid = Utils::decodeB64(packet.mid(index, 2)); switch (cid) { case 5: // gender { index += 2; tlen = Utils::decodeB64(packet.mid(index, 2)); gender = packet.mid(index + 2, tlen); index += tlen; index += 2; printf("Updated gender: "); printf(gender.toStdString().c_str()); printf("\n"); break; } case 4: // figure { index += 2; tlen = Utils::decodeB64(packet.mid(index, 2)); figure = packet.mid(index + 2, tlen); index += tlen; index += 2; printf("Updated figure: "); printf(figure.toStdString().c_str()); printf("\n"); break; } case 6: // motto { index += 2; tlen = Utils::decodeB64(packet.mid(index, 2)); motto = packet.mid(index + 2, tlen); index += tlen; index += 2; printf("Updated motto: "); printf(motto.toStdString().c_str()); printf("\n"); break; } default: //invalid modification data { index += 2; tlen = Utils::decodeB64(packet.mid(index, 2)); index += tlen; index += 2; printf("Invalid modid: %i(%s), length: %i(%s), data: ", cid, packet.mid(index - (4 + tlen), 2).toStdString().c_str(), tlen, packet.mid(index - (2 + tlen), 2).toStdString().c_str()); printf(packet.mid(index, tlen).toStdString().c_str()); printf("\n"); break; } } } QSqlQuery q; q.prepare("UPDATE accounts SET motto=:m, figure=:f, sex=:g WHERE id=:h"); q.bindValue(":h", habboid, QSql::Out); q.bindValue(":m", motto, QSql::In); q.bindValue(":f", figure, QSql::In); q.bindValue(":g", gender, QSql::In); if (q.exec()) { sendPacket(QString("@E") + QString::number(habboid) // lol dunno if re-sending this packet will work (obviously it does) + "\002" + name + "\002" + figure + "\002" + gender + "\002" + motto + "\002Hch=" + swimfig + "\002HH"); } else { sendPacket("BKError updating account settings!"); } break; } case Opcode::updateRoomSettings1: { //printf(packet.replace("\r", "\\r").replace("\t", "\\t").replace("\n", "\\n").toStdString().c_str()); //printf("\n"); QStringList lst = packet.right(packet.length() - 2).split("/"); QString print = QString("Room update: id: "); print += lst.at(0); print += " name: "; print += lst.at(1); print += " lock: "; print += lst.at(2); print += " unk: "; print += lst.at(3); print += "\n"; printf(print.toStdString().c_str()); QSqlQuery sq; sq.prepare("UPDATE rooms SET title=:d WHERE id=:id AND owner=:h"); sq.bindValue(":id", lst.at(0), QSql::Out); sq.bindValue(":h", habboid, QSql::Out); sq.bindValue(":d", lst.at(1), QSql::In); if (!sq.exec()) { sendPacket("BKError updating room settings! (1)"); } break; } case Opcode::updateRoomSettings2: { // printf(packet.replace("\r", "\\r").replace("\t", "\\t").replace("\n", "\\n").toStdString().c_str()); // printf("\n"); QStringList lst = packet.right(packet.length() - 2).split("/"); QStringList sublst = lst.at(1).split("\r"); QSqlQuery sq; Room* active = Room::byID(lst.at(0).toInt()); if (active == NULL) { // Invalid Room, please add more error handling -.- break; } foreach(QString q, sublst) { // should probably do this with a single query but.. if (q.length() > 3) { if (q.startsWith("description=")) { active->desc = q.right(q.length() - 12); sq.prepare("UPDATE rooms SET desc=:d WHERE id=:id AND owner=:h"); sq.bindValue(":id", lst.at(0), QSql::Out); sq.bindValue(":h", habboid, QSql::Out); sq.bindValue(":d", active->desc, QSql::In); if (!sq.exec()) { sendPacket("BKError updating room settings! (2)"); } } else if (q.startsWith("allsuperuser=")) { //wtf? } else if (q.startsWith("maxvisitors=")) { bool ok; active->maxcount = q.right(q.length() - 12).toInt(&ok); if (!ok) { // String NaN break; } sq.prepare("UPDATE rooms SET maxcount=:d WHERE id=:id AND owner=:h"); sq.bindValue(":id", lst.at(0), QSql::Out); sq.bindValue(":h", habboid, QSql::Out); sq.bindValue(":d", active->maxcount, QSql::In); if (!sq.exec()) { sendPacket("BKError updating room settings! (3)"); } } else { printf("Unknown room update flag: "); printf(q.toStdString().c_str()); printf("\n"); } } } break; } case Opcode::moveFurniture: { if (croomoid == habboid) { QStringList t = packet.right(packet.length() - 2).split(" "); int id = t.value(0, NULL).toInt(); int x = t.value(1, NULL).toInt(); int y = t.value(2, NULL).toInt(); int rot = t.value(3, NULL).toInt(); QSqlQuery q; QSqlQuery q2; QSqlQuery q3; q2.prepare("SELECT sprite, z FROM furniture WHERE x=:x AND y=:y AND inroom=:rooom AND stackh > 0.0 ORDER BY z DESC, stackh DESC"); q2.bindValue(":x", x, QSql::Out); q2.bindValue(":y", y, QSql::Out); q2.bindValue(":room", croomid, QSql::Out); double zloc = Room::byID(croomid)->heightmap[x][y]; if (q2.exec() && q2.next()) { q3.prepare("SELECT stack FROM furniprofiles WHERE sprite=:sp"); q3.bindValue(":sp", q2.value(0).toString(), QSql::Out); if (q3.exec() && q3.next()) { zloc = q2.value(1).toDouble(); zloc += q3.value(0).toDouble(); printf((QString("Stacked item ") + QString::number(id) + " up " + QString::number(zloc) + " spaces. (" + q2.value(1).toString() + " + " + q3.value(0).toString() + ")\n").toStdString().c_str()); } else { printf("Error stacking item.\n"); } } q.prepare("UPDATE furniture SET x=:x, y=:y, rot=:rot, z=:z WHERE id=:id"); q.bindValue(":id", id, QSql::Out); q.bindValue(":x", x, QSql::In); q.bindValue(":y", y, QSql::In); q.bindValue(":z", zloc, QSql::In); q.bindValue(":rot", rot, QSql::In); if (q.exec()) { q.prepare("SELECT sprite, status FROM furniture WHERE id=:id"); q.bindValue(":id", id, QSql::Out); if (q.exec() && q.next()) { QSqlQuery q2; q2.prepare("SELECT name, cust, width, height FROM furniprofiles WHERE sprite=:s"); q2.bindValue(":s", q.value(0).toString(), QSql::Out); if (q2.exec() && q2.next()) { QString pak = QString("A_"); pak += QString::number(id); pak += "\002"; pak += q2.value(0).toString(); pak += "\002"; pak += Utils::encodeVL64(x); pak += Utils::encodeVL64(y); pak += Utils::encodeVL64(q2.value(2).toInt()); pak += Utils::encodeVL64(q2.value(3).toInt()); pak += Utils::encodeVL64(rot); pak += QString::number(zloc); pak += "\002"; pak += q2.value(1).toString(); pak += "\002\002"; pak += q.value(1).toString(); pak += "\002"; Room* c = Room::byID(croomid); Furniture* f = c->furnituremap.value(id, NULL); f->x = x; f->y = y; f->rot = rot; f->z = zloc; c->broadcastPacket(pak); q.prepare("SELECT status FROM furniture WHERE status !=\"\" AND inroom=:ird AND id=:id"); q.bindValue(":ird", croomid, QSql::Out); q.bindValue(":id", id, QSql::Out); if (q.exec()) { while (q.next()) { //Room::byID(croomid)->broadcastPacket(QString("AX") + QString::number(id) + "\002" + sign + "\002"); c->broadcastPacket(QString("AX") + QString::number(id) + "\002" + q.value(0).toString() + "\002"); } } } } } Room::byID(croomid)->updateHeightMap(true); } break; } case 74: { int idlen = Utils::decodeB64(packet.mid(2, 2)); int id = packet.mid(4, idlen).toInt(); int signlen = Utils::decodeB64(packet.mid(4 + idlen, 2)); QString sign = packet.mid(6 + idlen, signlen); QSqlQuery q; q.prepare("UPDATE furniture SET status=:s WHERE id=:id"); q.bindValue(":id", id, QSql::Out); q.bindValue(":s", sign, QSql::In); if (q.exec()) { Room::byID(croomid)->broadcastPacket(QString("AX") + QString::number(id) + "\002" + sign + "\002"); } break; } default: { QString debugstr = QString("["); debugstr += packet.left(2); debugstr += "]: unhandled packet. Length:"; debugstr += QString::number(len); debugstr += " HeaderID: "; debugstr += QString::number(header); if (len > 2) { debugstr += " Packet body: "; debugstr += packet.mid(2, len); } debugstr += "\n"; printf(debugstr.toStdString().c_str()); //qDebug() << QString("[") + packet.left(2) + "]: unhandled packet. Length:" << len << " HeaderID: " << header << " Body: " << packet.mid(2, len); break; } } } } void Client::saveToDB() { // Please Implement } bool Client::isLogged(quint32 id) { return logged.contains(id); } Client* Client::byID(quint32 id) { return logged.value(id, NULL); } QHash Client::logged; void Client::gotPacket() { QByteArray packet = socket->read(Client::socket->bytesAvailable()); //qDebug() << "CLIENT->SERVER: " << packet << "\n"; while (packet.length() > 3) { int len = Utils::decodeB64(packet.left(3)); int header = Utils::decodeB64(packet.mid(3, 2)); QString subpacket = packet.mid(3, len); processPacket(subpacket, header, len); packet = packet.right(packet.length() - (len + 3)); } }