LandSandBoat / server

:sailboat: LandSandBoat - a server emulator for Final Fantasy XI
https://landsandboat.github.io/server/
GNU General Public License v3.0
294 stars 591 forks source link

🔨 Enable the ability to lock players clients #6278

Open N3ckB3ard opened 2 weeks ago

N3ckB3ard commented 2 weeks ago

I affirm:

Describe the feature

PR that added the flag to lock players clients in place: https://github.com/LandSandBoat/server/pull/5194 Flag to be added: https://github.com/LandSandBoat/server/blob/base/src/map/packets/char_update.cpp#L280

Referance to the code this can be utilized in: https://github.com/LandSandBoat/server/blob/base/scripts/commands/menu.lua#L25-L27

Currently there is a unused flag that allows servers to freeze a client in place like a CS event. This flag can be utilized and added to the menu command to lock players in place. If we set this flag there is a additional check that was created to remove the flag here: https://github.com/LandSandBoat/server/blob/base/scripts/commands/menu.lua#L59-L61

I am not a skilled CPP developer nor do I know the correct method of ensuring all conditions of this implementation but I gave it a shot in the effort of experimenting. I tested a simple bool condition for isClientLocked

I added this to these files: https://github.com/LandSandBoat/server/blob/base/src/map/entities/charentity.cpp#L265 *Newline

      isClientLocked        = false;  // Freeze client flag

https://github.com/LandSandBoat/server/blob/base/src/map/entities/charentity.h#L312 *Newline

      bool  isClientLocked;        // Freeze client flag

*Changed https://github.com/LandSandBoat/server/blob/base/src/map/packets/char_update.cpp#L280

      flags1.FreezeFlag   = PChar->isClientLocked;  // Freeze client in place

then added a luautil module to call it

         lua["CBaseEntity"]["setClientLock"] = [this](CLuaBaseEntity* PLuaBaseEntity, bool lockState) -> bool
        {
            TracyZoneScoped;

            CBaseEntity* PEntity = PLuaBaseEntity->GetBaseEntity();
            auto* const PChar = dynamic_cast<CCharEntity*>(PEntity);

            if (PEntity->objtype != TYPE_PC)
            {
                return false;
            }

            PChar->isClientLocked = lockState;

            bool lockedState = PChar->isClientLocked;

            PChar->updatemask |= UPDATE_HP;

            return lockedState;
        };

This allowed me to test !exec target:setClientLock(true) or (false) and I was able to see what restrictions are applied to the client.

I really think something like this can be useful for downstream servers and also added into our menu command for testing. This is a very awesome flag for servers to utilize but I do not know the best way to implement this and is why I have went to open a feature request with as much information I can give. I can think of new ideas like GM commands to lock players or dynamic menus holding players still so they can not spam a NPC interaction endlessly without adding in unnecessary local vars to lock them out. If anyone finds this useful and has the skills to implement this properly I would be incredibly grateful.

Thank you

Allows custom menu and interactions to lock the player client like retail events

WinterSolstice8 commented 2 weeks ago

I'm pretty sure retail uses... something to lock clients briefly interacting with ???s or npcs You can keep running without getting locked and clicking stuff on LSB, but doesn't happen on retail

N3ckB3ard commented 2 weeks ago

I'm pretty sure retail uses... something to lock clients briefly interacting with ???s or npcs You can keep running without getting locked and clicking stuff on LSB, but doesn't happen on retail

Yea retail has a brief interruption on what I suspect to be CS events triggering. I am sure this flag is utilized outside of the request it be used for the menu system Zach created but as a tool to help the custom things feel more retail accurate I really see a lot of use in setting this

zach2good commented 2 weeks ago

You've already written the module for this, so as far as I'm concerned the work here is done? Until someone proves that this has a legitimate use for emulating something in retail, including captures from retail, I'm not interested in adding things solely to support custom development. If there ends up being a retail use for this, by all means we'll legitimise a binding for this 👍

DEs are a perfect example of something that is needed for emulating retail, but people can run with if they want.

Having written and supported a couple of very popular systems now that mainly support custom development (modules and custom menus), they don't result in a more complete retail emulation, more useful code coming back to us, or more valid bug reports.

Xaver-DaRed commented 1 week ago

This does look usefull though. I would have to check, but, this looks like something that could be used. for instance, when changing floors in nyzul, since only 1 player triggers the npc to change floors...

Just an example though, and an unconfirmed one at that. However, I think it would be an usefull tool to have.

Xaver-DaRed commented 1 week ago

Actually, retail locks you after "zone in" until you are fully loaded. Something we dont do.

cocosolos commented 1 week ago

Actually, retail locks you after "zone in" until you are fully loaded. Something we dont do.

I wonder, does this vary by zone? Bastok zones for instance lock you for quite a bit, while East/West Adoulin let you move immediately.

WinterSolstice8 commented 1 week ago

That is from a currently unimplemented field in https://github.com/atom0s/XiPackets/tree/main/world/server/0x000A SendCount