EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Support::Windows Servers (https://www.eqemulator.org/forums/forumdisplay.php?f=587)
-   -   Acceptable/efficient syntax (https://www.eqemulator.org/forums/showthread.php?t=40039)

AdrianD 09-30-2015 07:51 PM

I reverted the bit in \client_process.cpp.

I could use a bit of assistance with something most would consider basic.

I need to insert something that checks the no rent code.

This is as far as I got:
Code:

        if (RuleB(Pets, PetLogPersistence) == false)
        {
                SetPet(0);
        }
               
        else (RuleB(Pets, PetLogPersistence) == true);
        {

                database.LoadPetInfo(this);
                /*
                This was moved before the spawn packets are sent
                in hopes that it adds more consistency...
                Remake pet
                */
                if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) {
                        MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size);
                if (GetPet() && GetPet()->IsNPC()) {
                        NPC *pet = GetPet()->CastToNPC();
                        pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items);
                        pet->CalcBonuses();
                        pet->SetHP(m_petinfo.HP);
                        pet->SetMana(m_petinfo.Mana);
                        }
                m_petinfo.SpellID = 0;
                }
        }

This is some of the no rent code:
Code:

void Client::RemoveNoRent(bool client_update)


bool deletenorent = database.NoRentExpired(GetName());
        if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items
                if (RuleB(Inventory, TransformSummonedBags))
                        DisenchantSummonedBags(false);
                RemoveNoRent(false);
        }

More than hints please.

Thanks

Uleat 09-30-2015 08:00 PM

I'm not seeing the end goal clearly defined...

You're wanting to check a client's norent items inside of a load pets function?

Shendare 09-30-2015 08:06 PM

Looks like he's wanting pets to poof like No Rent items. By the code snippet above, it looks like the best thing would be to move the "if PetLogPersistance==false { SetPet(0); }" bit to just after the "RemoveNoRent(false);" line within the "if (deletenorent) { }" block.

AdrianD 09-30-2015 08:26 PM

Thanks for the replies.

Quote:

it looks like the best thing would be to move the "if PetLogPersistance==false { SetPet(0); }" bit to just after the "RemoveNoRent(false);" line within the "if (deletenorent) { }" block.
Ah, I was thinking of going back to that. Thank you.

There are some basic understandings I am missing. Hopefully I'll get it soon and more will open up.

AdrianD 09-30-2015 08:55 PM

Ok.

I added a rule check <\zone\client_packet.cpp(1677)>
Code:

        if (RuleB(Pets, PetLogPersistence) == true)
        {
                database.LoadPetInfo(this);
                /*
                This was moved before the spawn packets are sent
                in hopes that it adds more consistency...
                Remake pet
                */
                if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) {
                        MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size);
                        if (GetPet() && GetPet()->IsNPC()) {
                                NPC *pet = GetPet()->CastToNPC();
                                pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items);
                                pet->CalcBonuses();
                                pet->SetHP(m_petinfo.HP);
                                pet->SetMana(m_petinfo.Mana);
                        }
                        m_petinfo.SpellID = 0;
                }
        }

...and reverted this section <\zone\client_process.cpp(844)>
Code:

        bool deletenorent = database.NoRentExpired(GetName());
        if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items
                if (RuleB(Inventory, TransformSummonedBags))
                        DisenchantSummonedBags(false);
                RemoveNoRent(false);
// added 9/30/15 no rent check (this may need fixing when introducing suspended minion)
        if (RuleB(Pets, PetLogPersistence) == false)
                {
                        SetPet(0);
                }
        }


As far as client crash from previous, I am uncertain what was causing it but, the wireless connection it had previous was not good. Getting to login server was difficult. I fixed that and logged a character with a pet (+30 minutes). I did not see the pet window but the pet was still an entry in the DB, like previous.

I will review what you said about this Uleat.

Thanks

EDIT: something isn't right with the norent check - I'll check back but, I've had enough for now

Uleat 09-30-2015 10:11 PM

SetPet() is an inherited function from the class Mob: https://github.com/EQEmu/Server/blob.../pets.cpp#L542

SetPet(0), when called from the Client class, is essentially doing this:
Code:

((Mob*)client_inst)->SetPet(nullptr);
There are no Client class-based methods performed at this level and all that is occurring is that you're setting the memory reference for the client's pet to nullptr.

This is ok for other mob-derived classes that don't save their pet buffs, inventories, etc... (they still clean-up as required, though)

But, for client, you should to handle it somewhere at the Client class level..meaning database clean-up, and deletion of any possible pet instances from memory..otherwise,
you will end up with a memory leak (allocated..but, no longer used memory that is not released back to the system - the losses add up)

(If you handle the action before creating an actual in-memory reference, then you won't need to worry about the clean-up.)

AdrianD 10-01-2015 02:27 AM

I appreciate the explanations. I wouldn't have known if you didn't say anything about it. I will digest this in the coming days and try to apply this if I can.

AdrianD 10-01-2015 05:25 PM

I reverted everything that was working with PetLogPersistence. The issue previous was simple and something I overlooked as I quickly wrote it in as I was out the door.

I went back to \zone\client_process.cpp and added queries to the code.

The results are a little better. The entries are deleted until zoning or casting a new pet when new ones are made. I attempted to add database.SavePetInfo(this); <void ZoneDatabase::SavePetInfo(Client *client)> but the result wasn't desireable. (because of <PetInfo *petinfo = nullptr;> happening first maybe?)

The pet window still appears for a short time and the pet=0 entries are non-existent for the char logged 30+ minutes after initial login. (/q resets the entries - unsure if this = LD)

Code:

        bool deletenorent = database.NoRentExpired(GetName());
        if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items
                if (RuleB(Inventory, TransformSummonedBags))
                        DisenchantSummonedBags(false);
                RemoveNoRent(false);

// added 9/30/15 no rent check (this may need fixing when introducing suspended minion - if this was an issue the queries below should fix it)
                if (!RuleB(Pets, PetLogPersistence))
                {
                        SetPet(0);
                       
                        std::string query = StringFormat("DELETE FROM `character_pet_info` WHERE `char_id` = %u AND character_pet_info.pet = 0", CharacterID());
                        auto results = database.QueryDatabase(query);
                       
                        query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u AND character_pet_info.pet = 0", CharacterID());
                        results = database.QueryDatabase(query);
                       
                        query = StringFormat("DELETE FROM `character_pet_inventory` WHERE `char_id` = %u AND character_pet_info.pet = 0", CharacterID());
                        results = database.QueryDatabase(query);                                               
                }
        }


If I knew how to set these queries up in zonedb.cpp and make the connections to it from client_process, I would have. This really isn't that difficult, the concept, the web of connections. It's the syntax or C++ grammar that is the pain in the ass, the huge hindrance for me. I can figure out how the EQEmu system works just by exposure and asking questions where the answer is fairly simple, as has been mentioned.

Thanks

Uleat 10-01-2015 06:49 PM

I wanted to see if there was an existing method to 'delete' pets from clients..but, the only one I found only deleted the inventories and buffs..so, I'm not sure where that
is handled...

(I mean, when a pet dies, it is deleted, right? Otherwise, it would respawn when a client enters the world.)

Shendare 10-01-2015 07:11 PM

Is there just a Pet->Death()? lol

Uleat 10-01-2015 07:37 PM

Well, I followed case GETLOST: back, and SavePetInfo() .. nothing I saw removed the actual pet instance.

I dunno? :P


I know I'm missing something...

AdrianD 10-01-2015 07:43 PM

There is a depop in \spawn2.h and \spawn2.cpp:

Code:

void        Depop();

void Spawn2::Depop() {
        timer.Disable();
        Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn reset, repop disabled", spawn2_id);
        npcthis = nullptr;
}

I saw this while sifting through potential options.

There is different depop for zone.

AdrianD 10-01-2015 08:55 PM

A bit of progress, not much though.

No entry being created like it does when zoning and using <SetPet(0);>

\zonedb.cpp - last 1/2 commented out, unsure what to do to make it create a new blank entry

When the part /* */ is uncommented it only removes `spell_id` in the DB - pet_struct maybe?
Code:

void ZoneDatabase::DeletePetInfo(Client *client)
{
        std::string query = StringFormat("DELETE FROM `character_pet_info` WHERE `char_id` = %u AND `pet` = 0", client->CharacterID());
        auto results = database.QueryDatabase(query);
        if (!results.Success())
                return;

        query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u AND `pet` = 0", client->CharacterID());
        results = database.QueryDatabase(query);
        if (!results.Success())
                return;

        query = StringFormat("DELETE FROM `character_pet_inventory` WHERE `char_id` = %u AND `pet` = 0", client->CharacterID());
        results = database.QueryDatabase(query);
        if (!results.Success())
                return;

//        PetInfo *petinfo = nullptr;
        /*
        for (int pet = 0; pet < 2; pet++) {
        PetInfo        *petinfo = client->GetPetInfo(pet);
                if (!petinfo)
                        continue;

                query = StringFormat("INSERT INTO `character_pet_info` "
                        "(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) "
                        "VALUES (%u, %u, '%s', %i, %u, %u, %u, %f) "
                        "ON DUPLICATE KEY UPDATE `petname` = '%s', `petpower` = %i, `spell_id` = %u, "
                        "`hp` = %u, `mana` = %u, `size` = %f",
                        client->CharacterID(), pet, petinfo->Name, petinfo->petpower, petinfo->SpellID,
                        petinfo->HP, petinfo->Mana, petinfo->size, // and now the ON DUPLICATE ENTRIES
                        petinfo->Name, petinfo->petpower, petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size);
                results = database.QueryDatabase(query);
                if (!results.Success())
                        return;
                query.clear();
                }        */
}

\client_process.cpp
Code:

bool deletenorent = database.NoRentExpired(GetName());
        if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items
                if (RuleB(Inventory, TransformSummonedBags))
                        DisenchantSummonedBags(false);
                RemoveNoRent(false);

// added 9/30/15 no rent check (this may need fixing when introducing suspended minion - if this was an issue the queries below should fix it)
                if (!RuleB(Pets, PetLogPersistence))
                {                               
                        SetPet(0);
                       
                        database.DeletePetInfo(this);                       
                }
        }

Thanks

AdrianD 10-02-2015 12:42 AM

Added to \client_process.cpp - it's a little smoother, adds the blank row and saves it. The client still shows the pet window momentarily. I would prefer to put <memset(&m_petinfo, 0, sizeof(struct PetInfo));> in the DeletePetInfo part and then run w/e queries are needed to fill in the blanks allowing the removal of <database.SavePetInfo(this);> below.

I would prefer this whole process done a little earlier. Just a guess but, somewhere near <case ServerOP_SyncWorldTime:> (\zone\worldserver.cpp(744).

This also leaves out what Uleat said before about memory loss? which I have no clue about.

\client_process.cpp(841)
Code:

// added 9/30/15 no rent check (this may need fixing when introducing suspended minion - if this was an issue the queries below should fix it)
                if (!RuleB(Pets, PetLogPersistence))
                {
                        SetPet(0);

                        database.DeletePetInfo(this);

                        memset(&m_petinfo, 0, sizeof(struct PetInfo));
                       
                        database.SavePetInfo(this);
                }
        }


AdrianD 10-02-2015 03:06 AM

Last one for a bit:

The two lines below SetPet, <Mob* mypet =......etc.>, gives the same resulting appearance as <SetPet(0);>. (takes a moment to depop) I am unsure if one is better than the other.

\client_process.cpp(841)
Code:

                if (!RuleB(Pets, PetLogPersistence))
                {
                        SetPet(0);

//                    or

                        Mob* mypet = this->GetPet();
                        mypet->CastToNPC()->Depop();

                        database.DeletePetInfo(this);

                        memset(&m_petinfo, 0, sizeof(struct PetInfo));
                       
                        database.SavePetInfo(this);
                }
        }



All times are GMT -4. The time now is 01:16 PM.

Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.