alliedmodders / amxmodx

AMX Mod X - Half-Life 1 Scripting and Administration
http://www.amxmodx.org/
494 stars 197 forks source link

engine_changelevel() strange behavior #854

Closed Giferns closed 4 years ago

Giferns commented 4 years ago

Help us help you

Environment

Description

I face a strange bug. When i pass non-existent map to engine_changelevel(), server replies 'changelevel failed: '.....' not found on server.' After that, if i try to do same action, server doesn't react to it at all. If i try to pass valid map that exists on server, again, nothing happens (map doesn't changed and logfile is still). When i try to change a map by server console command 'changelevel', then server changes the map. I think this behavior is wrong, but don't know how to fix it.

Problematic Code (or Steps to Reproduce)

public concmd_Test(pPlayer) {
    static iValue

    if(!iValue) {
        iValue++
        engine_changelevel("de_dusttttttt") // will broke further valid engine_changelevel() usage
    }
    else {
        engine_changelevel("de_dust2") // it exists, but nothing happens, what a hell?
    }

    return PLUGIN_HANDLED
}

Logs

changelevel failed: 'de_dusttttttt' not found on server.

WPMGPRoSToTeMa commented 4 years ago

You cannot call ChangeLevel twice during the single map (spawncount is increased when a map starts): https://github.com/dreamstalker/rehlds/blob/d870d6bac9714727cb739c31cdb63677ac20422c/rehlds/engine/pr_cmds.cpp#L2335-L2339

Giferns commented 4 years ago

You cannot call ChangeLevel twice during the single map (spawncount is increased when a map starts): https://github.com/dreamstalker/rehlds/blob/d870d6bac9714727cb739c31cdb63677ac20422c/rehlds/engine/pr_cmds.cpp#L2335-L2339

Thx for reply.

But if changing by engine_changelevel() fails, and then i do it through server console (changelevel de_dust2) it works. And if i fail changelevel with wrong map through server console, it also can be changed through engine_changelevel(). Changing breaks only if it fails by engine_changelevel(). What is the difference?

And at least this behavior can be hard to resolve due to server response (it just refuse to change a map and remain silent in console and logs).

WPMGPRoSToTeMa commented 4 years ago

engine_changelevel calls ChangeLevel (PF_changelevel_I), the latter has a guard that prevents executing this function twice during the single map (see the code I've pointed out in my previous comment). PF_changelevel_I doesn't check if map change has failed or not, it just asks to execute changelevel command.

Giferns commented 4 years ago

Yes, i fugured out how it works with engine_changelevel(). Thank you. But i think I need to reformulate. Why we just cant do it as it works when you just type "changelevel de_dusttttttt" in server console? Nothing brokens, and every use with non-existent map will throw console error.

WPMGPRoSToTeMa commented 4 years ago

You can't just change map in the middle of execution, this may break a lot of things. For example, amxmodx reloads all plugins on the map change, so the existing memory of any plugin becomes invalid after map change. Also the engine itself clears all entities, this also may break things when you're in the weapon handler (e.g. deploy) or in any other entity handler (e.g. think).

The best we can do is to add calling IsMapValid check to PF_changelevel_I and to engine_changelevel (for compatibility with non-ReHLDS engine).

Giferns commented 4 years ago

Ok, thanks again, now i understand it completely