Jump to content

Rare Coredowner Fix


Recommended Posts

  • Forum Moderator

Hello guys,

 

While trying things on my server, I stumbled accross a weird core-downer. It is really simple but I say "weird" because in litteraly 10 years it has never happened to me nor anyone I know. It probably gets triggered by a malfunctioning quest I had taken from 2012 and forgot to remove (quests were not my concern at the time). I didn't want to only remove the quest but instead I decided to fix the coredowner.

 

It happens because the game is not expected to trigger the function get_leader_vid() without a party. However, there is no check at all if it somehow did and on my server it randomly got triggered without a party and the core simply crashed. So instead of digging further, I thus added a check to avoid the core to crash. Please note that my sources were vanilla at that time.

 

  Well, head to questlua_npc.cpp and find the function "npc_get_leader_vid". It should normally look like this:

	//Function "npc_get_leader_vid"
	{
		CQuestManager& q = CQuestManager::instance();
		LPCHARACTER npc = q.GetCurrentNPCCharacterPtr();

		LPPARTY party = npc->GetParty();
		LPCHARACTER leader = party->GetLeader();

		if (leader)
			lua_pushnumber(L, leader->GetVID());
		else
			lua_pushnumber(L, 0);


		return 1;
	}

Then simply check if "party" exists or not; it should look like this:

This is the hidden content, please

Here you are, note that the coredowner is rare, but it can happen so it's better to avoid it.

 

Edited by Gurgarath
  • Metin2 Dev 21
  • Good 4
  • Love 28

Gurgarath
coming soon

Link to comment
Share on other sites

  • Forum Moderator

Thanks for the fix, ymir left a lot of shits like these, this is an official quest example where you could get this crash core.

 

8913eb22fec1c901232c39fdc0479d40.png

 

Normally, if you want to get the party leader vid in some functions, of course we need to check if there's a party before accessing the function and don't even call it.

You just have to use party.is_party before calling the function and everything will be fine, also you could put a message in your quests that player will know there's a problem (not just an error in server side that you will don't know where it comes from). So with that everybody will know that they're missing a condition and will stop the event/dungeon or something else.

if not party.is_party() then
	syschat("You need a party for doing this.")
	return
end

This is an example of how should be the quest: (based on official example < spiderKingEgg)

when 8002.kill with party.is_party() begin
	local npc_leader_vid = npc.get_leader_vid()
	syschat(string.format("%d", npc_leader_vid))
end

So, by doing that you can leave the function without the syserr which is irrelevant since is a condition from game and if something happens the result will be 0 all time.

This is the hidden content, please

 

Edited by Metin2 Dev
Core X - External 2 Internal
  • Metin2 Dev 7
  • Good 4
  • Love 9
Link to comment
Share on other sites

  • Forum Moderator
44 minutes ago, VegaS™ said:

Thanks for the fix, ymir left a lot of shits like these, this is an official quest example where you could get this crash core.

 

8913eb22fec1c901232c39fdc0479d40.png

 

Normally, if you want to get the party leader vid in some functions, of course we need to check if there's a party before accessing the function and don't even call it.

You just have to use party.is_party before calling the function and everything will be fine, also you could put a message in your quests that player will know there's a problem (not just an error in server side that you will don't know where it comes from). So with that everybody will know that they're missing a condition and will stop the event/dungeon or something else.


if not party.is_party() then
	syschat("You need a party for doing this.")
	return
end

This is an example of how should be the quest: (based on official example < spiderKingEgg)


when 8002.kill with party.is_party() begin
	local npc_leader_vid = npc.get_leader_vid()
	syschat(string.format("%d", npc_leader_vid))
end

So, by doing that you can leave the function without the syserr which is irrelevant since is a condition from game and if something happens the result will be 0 all time.


	int npc_get_leader_vid(lua_State * L)
	{
		const LPCHARACTER npc = CQuestManager::instance().GetCurrentNPCCharacterPtr();
		const LPPARTY party = npc->GetParty();
		const LPCHARACTER leader = (party) ? party->GetLeader() : NULL;

		lua_pushnumber(L, (leader) ? static_cast<DWORD>(npc->GetVID()) : 0);
		return 1;
	}

 

 

Exactly! I got this crash from this quest but I decided not to mention it because I was unsure if it was sg material or official material. The fact that the check wasn't done quest-wise made me think about sg material. In reality it was ymir who did that shit... I didn't mention the lua fix because as long as the core can crash I prefer fixing the crash, I fixed the quest right after however. But that's a good point you made! Thank you VegaS!

Also, nice rewrite and nice usage of ternary conditions, I kept my fix simple but yours is more efficient.

 

29 minutes ago, Johnny69 said:

There are a lot of crashes because of null pointers in metin2 source.

If you open a server with 1000> players online you will get a lot of crashes (null pointers and other things).

 

Completely... I got two of them in only a few days (including this one). We should maybe keep a global post categorizing all of these. I don't know why they kept all of these flaws.

 

Edited by Metin2 Dev
Core X - External 2 Internal
  • Love 3

Gurgarath
coming soon

Link to comment
Share on other sites

  • Developer
1 hour ago, VegaS™ said:

You just have to use party.is_party before calling the function and everything will be fine

Actually no because party.is_party() verifies if the current pc belongs to a party - which does not meet the requirement of the quest, apparently. That is: to retrieve the vid of the leader of the monster's group in order to progress further (npc).

In short, on this case, having such verification prior to the vid-condition, without fixing it on the source, is not going to address the issue. In fact, it will trigger it in case the player running the quest has a group.

Edited by PACI
  • Love 3

when you return 0 and server doesn't boot:

unknown.png

Link to comment
Share on other sites

I fixed all of this before some months ago, you can check here my functions and compare there is more checks for each one, so you can be sure:

 

Pastebin

 

The specific func:

 


    ALUA(npc_get_leader_vid)
    {
        CQuestManager & q = CQuestManager::instance();
 
        LPCHARACTER npc = q.GetCurrentNPCCharacterPtr();
 
        LPPARTY party = npc ? npc->GetParty() : NULL;
 
        LPCHARACTER leader = party ? party->GetLeader() : NULL;
 
        lua_pushnumber(L, leader ? leader->GetVID() : 0);
 
        return 1;
    }

 

Edited by HITRON
  • Love 2
Link to comment
Share on other sites

  • Forum Moderator

@PACI That's right, i just wrote it fast without thinking about current pc and selected one.

So basically after i checked again, seems that the're two ways to get this:

  • You don't have a party at all.
  • You've a party but your leader is offline and his character pointer is marked as null pointer since he got disconnected.

I think that's why @Gurgarath said it's very rarely this crash, because of offline>null leader and trying to access the function GetVID() of it.

So, if you want to show a message in game while doing the action, you could put this check before accessing the vid and do something with it, players will know that they doesn't satisfy one of these conditions.

if (npc.get_leader_vid() == 0) then
	syschat("You don't have a party or the leader is offline.")
	return
end

And you need to modify the function like this for being able to do this check.

This is the hidden content, please

 

Edited by VegaS™
  • Metin2 Dev 10
  • Good 1
  • Love 9
Link to comment
Share on other sites

On 3/4/2020 at 4:33 PM, Johnny69 said:

There are a lot of crashes because of null pointers in metin2 source.

If you open a server with 1000> players online you will get a lot of crashes (null pointers and other things).

true, has happened also on mine srv.

There is some crashes about cipher too if u are running on cmake

Also i remember that was crash on server timers.

Edited by Flourine
Link to comment
Share on other sites

2 hours ago, dracaryS said:

Thanks bro.

    {
        CQuestManager& q = CQuestManager::instance();
        LPCHARACTER npc = q.GetCurrentNPCCharacterPtr();
        LPPARTY party = npc->GetParty();
        if (!party){
            sys_err("npc_get_leader_vid: Function triggered without party");
            return 1;
        }
        lua_pushnumber(L, party->GetLeader()?party->GetLeader()->GetVID():0);
        return 1;
    }

??
Thanks for the fix, @Gurgarath

Edited by Mr.Black
Link to comment
Share on other sites

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.