Jump to content

[M2Dev] Advanced Files To Build Your Server: Src & Server Files & Client [x64 / DX9Ex / CMake / Python3.14 / FreeType / XChaCha20-Poly1305]


Recommended Posts

  • Active Member
On 9/28/2025 at 4:49 PM, Mind Rapist said:

You converted the entire DB system into Mongo?

No, he's probably just describing his work experience.

  • Metin2 Dev 1
  • Honorable Member
On 10/14/2025 at 11:27 AM, PeaceMaker said:

Is this on master branch already? if not, do you plan to release a development branch so people can also assist?

There is a branch for this.

  • Good 1

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

  • Active+ Member

.png

Anyone knows what that is? Instead of moving to the click the character freezes on spot without moving. If you drag the mouse around while holding down left click the direction will change but the position will remain like that. I don't see any logs or anything.

  • kekw 1
  • Active Member
3 hours ago, Mind Rapist said:

.png

Anyone knows what that is? Instead of moving to the click the character freezes on spot without moving. If you drag the mouse around while holding down left click the direction will change but the position will remain like that. I don't see any logs or anything.

This funny behavior usually occurs when armor's movement speed is broken. Perhaps the itemproto is broken somehow.
Try removing the armor and see if the same problem occurs without it, for example, when the character has no items at all.

  • Metin2 Dev 1
  • Active+ Member
13 hours ago, Helia01 said:

This funny behavior usually occurs when armor's movement speed is broken. Perhaps the itemproto is broken somehow.
Try removing the armor and see if the same problem occurs without it, for example, when the character has no items at all.

That was actually very useful. It is not an armor issue but it's coming from activating Strong Body skill and changing map or relogging. I don't know where I should start looking but here are some relevant info:

 

skilldesc.txt

Spoiler
19	WARRIOR	Strong Body	Iron Body	Steel Body	Increases defence and you won't fall on the ground.	Increases defence	Decreases Moving Speed.	You won't fall over		STANDING_SKILL		cheongeun	19	4			Defence: +%.0f 	7+(40 + 0.2*str + 0.4*con)*k		Moving Speed: -%.0f 	1 + 9*SkillPoint

 

 

slkilltable.txt

Spoiler
20	°Ëdz	1	1	1	0	HP	-(2*atk+(atk+dex*3+str*5+con)*k)	40+120*k			20			ATTACK,USE_MELEE_DAMAGE,SPLASH,CRUSH		NONE				0	0	MELEE	10	0.5	1200	200

 

 

skill_power.txt (from locale/english):

Spoiler
20	 °Ëdz 	5	7	9	11	13	15	17	19	20	22	24	26	28	30	32	34	36	38	40	50	52	55	58	61	63	66	69	72	75	80	82	84	87	90	95	100	110	120	130	150

 

 

skill_proto table from player:

Spoiler
20	°??³	1	1	1	0	HP	-(2*atk + (atk + dex*3 + str*5 + con)*k)	40+120*k			20	-(2*atk + (atk + dex*3 + str*5 + con)*k)		ATTACK,USE_MELEE_DAMAGE,SPLASH,CRUSH		NONE							40+120*k	0	0	MELEE	10	0.5	1200	200

 

 

References of 'cheongeun' in the source:

affect.h

Spoiler
enum EAffectBits
{   
	AFF_NONE,

	AFF_YMIR,
	AFF_INVISIBILITY,
	AFF_SPAWN,

	AFF_POISON,
	AFF_SLOW,
	AFF_STUN,

	AFF_DUNGEON_READY,		// 던전에서 준비 상태
	AFF_DUNGEON_UNIQUE,		// 던전 유니크 (클라이언트에서 컬링되지않음)

	AFF_BUILDING_CONSTRUCTION_SMALL,
	AFF_BUILDING_CONSTRUCTION_LARGE,
	AFF_BUILDING_UPGRADE,

	AFF_MOV_SPEED_POTION,
	AFF_ATT_SPEED_POTION,

	AFF_FISH_MIND,

	AFF_JEONGWIHON,		// 전귀혼
	AFF_GEOMGYEONG,		// 검경
	AFF_CHEONGEUN,		// 천근추
	AFF_GYEONGGONG,		// 경공술
	AFF_EUNHYUNG,		// 은형법
	AFF_GWIGUM,			// 귀검
	AFF_TERROR,			// 공포
	AFF_JUMAGAP,		// 주마갑
	AFF_HOSIN,			// 호신
	AFF_BOHO,			// 보호
	AFF_KWAESOK,		// 쾌속
	AFF_MANASHIELD,		// 마나쉴드
	AFF_MUYEONG,		// 무영진 affect
	AFF_REVIVE_INVISIBLE,	// 부활시 잠시동안 무적
	AFF_FIRE,			// 지속 불 데미지
	AFF_GICHEON,		// 기천대공
	AFF_JEUNGRYEOK,		// 증력술
	AFF_TANHWAN_DASH,		// 탄환격용 달리기어펙트
	AFF_PABEOP,			// 파법술
	AFF_CHEONGEUN_WITH_FALL,	// 천근추
	AFF_POLYMORPH,
	AFF_WAR_FLAG1,
	AFF_WAR_FLAG2,
	AFF_WAR_FLAG3,

	AFF_CHINA_FIREWORK,
	AFF_HAIR,	// 헤어
	AFF_GERMANY, // 독일 

	AFF_BITS_MAX
};

 

char_skill.cpp (int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel))

Spoiler
				// ADD_GRANDMASTER_SKILL
				//if (g_iUseLocale)
				if ( !LC_IsYMIR() )
				{
					if ((pkSk->dwVnum == SKILL_CHUNKEON && GetUsedSkillMasterType(pkSk->dwVnum) < SKILL_GRAND_MASTER))
						affact_flag = AFF_CHEONGEUN_WITH_FALL;
				}
				else 
				{
					if ((pkSk->dwVnum == SKILL_CHUNKEON && GetUsedSkillMasterType(pkSk->dwVnum) < SKILL_MASTER))
						affact_flag = AFF_CHEONGEUN_WITH_FALL;
				}
				// END_OF_ADD_GRANDMASTER_SKILL

 

* No references of 'AFF_CHEONGEUN' (not _WITH_FALL)

 

In client:

playersettingmodule.py (in def __LoadGameWarriorEx(race, path):

Spoiler
chrmgr.RegisterCacheMotionData(chr.MOTION_MODE_GENERAL, chr.MOTION_SKILL+(i*skill.SKILL_GRADEGAP)+19, "cheongeun" + END_STRING + ".msa")

 

 

Is there something wrong with any of these configurations? Should I look somewhere else for the issue? Thanks for your help!

  • Love 2
On 10/24/2025 at 9:18 AM, Mind Rapist said:

That was actually very useful. It is not an armor issue but it's coming from activating Strong Body skill and changing map or relogging. I don't know where I should start looking but here are some relevant info:

 

skilldesc.txt

  Reveal hidden contents
19	WARRIOR	Strong Body	Iron Body	Steel Body	Increases defence and you won't fall on the ground.	Increases defence	Decreases Moving Speed.	You won't fall over		STANDING_SKILL		cheongeun	19	4			Defence: +%.0f 	7+(40 + 0.2*str + 0.4*con)*k		Moving Speed: -%.0f 	1 + 9*SkillPoint

 

 

slkilltable.txt

  Reveal hidden contents
20	°Ëdz	1	1	1	0	HP	-(2*atk+(atk+dex*3+str*5+con)*k)	40+120*k			20			ATTACK,USE_MELEE_DAMAGE,SPLASH,CRUSH		NONE				0	0	MELEE	10	0.5	1200	200

 

 

skill_power.txt (from locale/english):

  Reveal hidden contents
20	 °Ëdz 	5	7	9	11	13	15	17	19	20	22	24	26	28	30	32	34	36	38	40	50	52	55	58	61	63	66	69	72	75	80	82	84	87	90	95	100	110	120	130	150

 

 

skill_proto table from player:

  Reveal hidden contents
20	°??³	1	1	1	0	HP	-(2*atk + (atk + dex*3 + str*5 + con)*k)	40+120*k			20	-(2*atk + (atk + dex*3 + str*5 + con)*k)		ATTACK,USE_MELEE_DAMAGE,SPLASH,CRUSH		NONE							40+120*k	0	0	MELEE	10	0.5	1200	200

 

 

References of 'cheongeun' in the source:

affect.h

  Reveal hidden contents
enum EAffectBits
{   
	AFF_NONE,

	AFF_YMIR,
	AFF_INVISIBILITY,
	AFF_SPAWN,

	AFF_POISON,
	AFF_SLOW,
	AFF_STUN,

	AFF_DUNGEON_READY,		// 던전에서 준비 상태
	AFF_DUNGEON_UNIQUE,		// 던전 유니크 (클라이언트에서 컬링되지않음)

	AFF_BUILDING_CONSTRUCTION_SMALL,
	AFF_BUILDING_CONSTRUCTION_LARGE,
	AFF_BUILDING_UPGRADE,

	AFF_MOV_SPEED_POTION,
	AFF_ATT_SPEED_POTION,

	AFF_FISH_MIND,

	AFF_JEONGWIHON,		// 전귀혼
	AFF_GEOMGYEONG,		// 검경
	AFF_CHEONGEUN,		// 천근추
	AFF_GYEONGGONG,		// 경공술
	AFF_EUNHYUNG,		// 은형법
	AFF_GWIGUM,			// 귀검
	AFF_TERROR,			// 공포
	AFF_JUMAGAP,		// 주마갑
	AFF_HOSIN,			// 호신
	AFF_BOHO,			// 보호
	AFF_KWAESOK,		// 쾌속
	AFF_MANASHIELD,		// 마나쉴드
	AFF_MUYEONG,		// 무영진 affect
	AFF_REVIVE_INVISIBLE,	// 부활시 잠시동안 무적
	AFF_FIRE,			// 지속 불 데미지
	AFF_GICHEON,		// 기천대공
	AFF_JEUNGRYEOK,		// 증력술
	AFF_TANHWAN_DASH,		// 탄환격용 달리기어펙트
	AFF_PABEOP,			// 파법술
	AFF_CHEONGEUN_WITH_FALL,	// 천근추
	AFF_POLYMORPH,
	AFF_WAR_FLAG1,
	AFF_WAR_FLAG2,
	AFF_WAR_FLAG3,

	AFF_CHINA_FIREWORK,
	AFF_HAIR,	// 헤어
	AFF_GERMANY, // 독일 

	AFF_BITS_MAX
};

 

char_skill.cpp (int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel))

  Reveal hidden contents
				// ADD_GRANDMASTER_SKILL
				//if (g_iUseLocale)
				if ( !LC_IsYMIR() )
				{
					if ((pkSk->dwVnum == SKILL_CHUNKEON && GetUsedSkillMasterType(pkSk->dwVnum) < SKILL_GRAND_MASTER))
						affact_flag = AFF_CHEONGEUN_WITH_FALL;
				}
				else 
				{
					if ((pkSk->dwVnum == SKILL_CHUNKEON && GetUsedSkillMasterType(pkSk->dwVnum) < SKILL_MASTER))
						affact_flag = AFF_CHEONGEUN_WITH_FALL;
				}
				// END_OF_ADD_GRANDMASTER_SKILL

 

* No references of 'AFF_CHEONGEUN' (not _WITH_FALL)

 

In client:

playersettingmodule.py (in def __LoadGameWarriorEx(race, path):

  Reveal hidden contents
chrmgr.RegisterCacheMotionData(chr.MOTION_MODE_GENERAL, chr.MOTION_SKILL+(i*skill.SKILL_GRADEGAP)+19, "cheongeun" + END_STRING + ".msa")

 

 

Is there something wrong with any of these configurations? Should I look somewhere else for the issue? Thanks for your help!

Is this happening only for Warrior (M)? Have you tried (W)? How about other characters? Have you checked the mse of the skill?

  • Metin2 Dev 1
  • Active+ Member
13 hours ago, tw1x1 said:

Is this happening only for Warrior (M)? Have you tried (W)? How about other characters? Have you checked the mse of the skill?

I havent checked because I had no idea what it was related to and according to the last comment it has to do with movement speed. MSE sounds like a start but I wouldn't know what to look for that's why I'm a little lost in this situation. I'm surprised nobody else has those because I didn't change absolutely anything anywhere and I am using the latest releases from the thread's repos.

  • 2 weeks later...
On 10/24/2025 at 10:18 AM, Mind Rapist said:

That was actually very useful. It is not an armor issue but it's coming from activating Strong Body skill and changing map or relogging. I don't know where I should start looking but here are some relevant info:

 

skilldesc.txt

  Reveal hidden contents
19	WARRIOR	Strong Body	Iron Body	Steel Body	Increases defence and you won't fall on the ground.	Increases defence	Decreases Moving Speed.	You won't fall over		STANDING_SKILL		cheongeun	19	4			Defence: +%.0f 	7+(40 + 0.2*str + 0.4*con)*k		Moving Speed: -%.0f 	1 + 9*SkillPoint

 

 

slkilltable.txt

  Reveal hidden contents
20	°Ëdz	1	1	1	0	HP	-(2*atk+(atk+dex*3+str*5+con)*k)	40+120*k			20			ATTACK,USE_MELEE_DAMAGE,SPLASH,CRUSH		NONE				0	0	MELEE	10	0.5	1200	200

 

 

skill_power.txt (from locale/english):

  Reveal hidden contents
20	 °Ëdz 	5	7	9	11	13	15	17	19	20	22	24	26	28	30	32	34	36	38	40	50	52	55	58	61	63	66	69	72	75	80	82	84	87	90	95	100	110	120	130	150

 

 

skill_proto table from player:

  Reveal hidden contents
20	°??³	1	1	1	0	HP	-(2*atk + (atk + dex*3 + str*5 + con)*k)	40+120*k			20	-(2*atk + (atk + dex*3 + str*5 + con)*k)		ATTACK,USE_MELEE_DAMAGE,SPLASH,CRUSH		NONE							40+120*k	0	0	MELEE	10	0.5	1200	200

 

 

References of 'cheongeun' in the source:

affect.h

  Reveal hidden contents
enum EAffectBits
{   
	AFF_NONE,

	AFF_YMIR,
	AFF_INVISIBILITY,
	AFF_SPAWN,

	AFF_POISON,
	AFF_SLOW,
	AFF_STUN,

	AFF_DUNGEON_READY,		// 던전에서 준비 상태
	AFF_DUNGEON_UNIQUE,		// 던전 유니크 (클라이언트에서 컬링되지않음)

	AFF_BUILDING_CONSTRUCTION_SMALL,
	AFF_BUILDING_CONSTRUCTION_LARGE,
	AFF_BUILDING_UPGRADE,

	AFF_MOV_SPEED_POTION,
	AFF_ATT_SPEED_POTION,

	AFF_FISH_MIND,

	AFF_JEONGWIHON,		// 전귀혼
	AFF_GEOMGYEONG,		// 검경
	AFF_CHEONGEUN,		// 천근추
	AFF_GYEONGGONG,		// 경공술
	AFF_EUNHYUNG,		// 은형법
	AFF_GWIGUM,			// 귀검
	AFF_TERROR,			// 공포
	AFF_JUMAGAP,		// 주마갑
	AFF_HOSIN,			// 호신
	AFF_BOHO,			// 보호
	AFF_KWAESOK,		// 쾌속
	AFF_MANASHIELD,		// 마나쉴드
	AFF_MUYEONG,		// 무영진 affect
	AFF_REVIVE_INVISIBLE,	// 부활시 잠시동안 무적
	AFF_FIRE,			// 지속 불 데미지
	AFF_GICHEON,		// 기천대공
	AFF_JEUNGRYEOK,		// 증력술
	AFF_TANHWAN_DASH,		// 탄환격용 달리기어펙트
	AFF_PABEOP,			// 파법술
	AFF_CHEONGEUN_WITH_FALL,	// 천근추
	AFF_POLYMORPH,
	AFF_WAR_FLAG1,
	AFF_WAR_FLAG2,
	AFF_WAR_FLAG3,

	AFF_CHINA_FIREWORK,
	AFF_HAIR,	// 헤어
	AFF_GERMANY, // 독일 

	AFF_BITS_MAX
};

 

char_skill.cpp (int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel))

  Reveal hidden contents
				// ADD_GRANDMASTER_SKILL
				//if (g_iUseLocale)
				if ( !LC_IsYMIR() )
				{
					if ((pkSk->dwVnum == SKILL_CHUNKEON && GetUsedSkillMasterType(pkSk->dwVnum) < SKILL_GRAND_MASTER))
						affact_flag = AFF_CHEONGEUN_WITH_FALL;
				}
				else 
				{
					if ((pkSk->dwVnum == SKILL_CHUNKEON && GetUsedSkillMasterType(pkSk->dwVnum) < SKILL_MASTER))
						affact_flag = AFF_CHEONGEUN_WITH_FALL;
				}
				// END_OF_ADD_GRANDMASTER_SKILL

 

* No references of 'AFF_CHEONGEUN' (not _WITH_FALL)

 

In client:

playersettingmodule.py (in def __LoadGameWarriorEx(race, path):

  Reveal hidden contents
chrmgr.RegisterCacheMotionData(chr.MOTION_MODE_GENERAL, chr.MOTION_SKILL+(i*skill.SKILL_GRADEGAP)+19, "cheongeun" + END_STRING + ".msa")

 

 

Is there something wrong with any of these configurations? Should I look somewhere else for the issue? Thanks for your help!

The problem is in the formula for the strong body move speed penalty the one you have atm is -(1+9*k) witch results in -361 at P level so you gotta change that to plain 0 or do my current fix and change it to 0.25*k witch it gives a whole 10% move speed bonus at P level check your db its in there ❤️

 

Edit:

Spoiler

After looking in the game code there is no problem there the problem is in the Database formula for the skill i gave the example for 10% boost for -15% move speed formula should be -0.375*k

 

Edited by Mersh
  • Love 1
1 hour ago, Mersh said:

The problem is in the formula for the strong body move speed penalty the one you have atm is -(1+9*k) witch results in -361 at P level so you gotta change that to plain 0 or do my current fix and change it to 0.25*k witch it gives a whole 10% move speed bonus at P level check your db its in there ❤️

 

Edit:

  Hide contents

After looking in the game code there is no problem there the problem is in the Database formula for the skill i gave the example for 10% boost for -15% move speed formula should be -0.375*k

 

I was about to post my debug info regarding the mov speed and func_move checks, but I guess I was too slow. At first i thought the mse is broken, then thought of affects and lastly added debug for the skill and checking the move speed.

Depending on how much mov speed your char’s got, when strong body affect gets applied, it will still go -

I appreciate your post.

  • Love 1
  • Active+ Member
21 hours ago, Mersh said:

The problem is in the formula for the strong body move speed penalty the one you have atm is -(1+9*k) witch results in -361 at P level so you gotta change that to plain 0 or do my current fix and change it to 0.25*k witch it gives a whole 10% move speed bonus at P level check your db its in there ❤️

 

Edit:

  Hide contents

After looking in the game code there is no problem there the problem is in the Database formula for the skill i gave the example for 10% boost for -15% move speed formula should be -0.375*k

 

Thank you for this it had really started to bug me a lot 😄

I can confirm that this fixes the issue (change to skilldesc and skilltable in the client as well to match).

Btw has anyone tried to create a new character in the game? For me it crashed the db (created a core):

.png

And in case these logs are relative:

Spoiler
...
[2025-11-13 18:44:11.021] [error] [socket_t socket_connect(const char *, WORD)()] HOST 127.0.0.1:9000, could not connect.
[2025-11-13 18:44:11.203] [error] [virtual bool CInputProcessor::Process(LPDESC, const void *, int, int &)()] UNKNOWN HEADER: 108(0x6C) LAST HEADER: 0(0x0)[0], REMAIN BYTES: 15, CHAR: <none>, PHASE: 3, fd: 16 host: XXX.XXX.XXX.XXX
...

...
[2025-11-13 18:44:11.029] [error] [socket_t socket_connect(const char *, WORD)()] HOST 127.0.0.1:9000, could not connect.
[2025-11-13 18:44:12.536] [error] [virtual bool CInputProcessor::Process(LPDESC, const void *, int, int &)()] SEQUENCE 9b878e00 mismatch 0x4e != 0x64 header 254

 

I searched for all the references of `fdwatch_add_fd` but I couldn't figure out if there's a mistake somewhere:

db/ClientManager.cpp

Spoiler
bool CClientManager::Initialize()
{
	int tmpValue;
	
	//BOOT_LOCALIZATION
	if (!InitializeLocalization())
	{
		fprintf(stderr, "Failed Localization Infomation so exit\n");
		return false;
	}
		
	//END_BOOT_LOCALIZATION
	//ITEM_UNIQUE_ID
	
	if (!InitializeNowItemID())
	{
		fprintf(stderr, " Item range Initialize Failed. Exit DBCache Server\n");
		return false;
	}
	//END_ITEM_UNIQUE_ID

	if (!InitializeTables())
	{
		sys_err("Table Initialize FAILED");
		return false;
	}

	CGuildManager::instance().BootReserveWar();

	if (!CConfig::instance().GetValue("BIND_PORT", &tmpValue))
		tmpValue = 5300;

	char szBindIP[128];

	if (!CConfig::instance().GetValue("BIND_IP", szBindIP, 128))
		// strlcpy(szBindIP, "0", sizeof(szBindIP));
		strlcpy(szBindIP, "127.0.0.1", sizeof(szBindIP)); // Fix: Now even if the DB port is publicly available an attacker can't connect to it with a fake auth.

	m_fdAccept = socket_tcp_bind(szBindIP, tmpValue);

	if (m_fdAccept < 0)
	{
		perror("socket");
		return false;
	}

	sys_log(0, "ACCEPT_HANDLE: %u", m_fdAccept);
	fdwatch_add_fd(m_fdWatcher, m_fdAccept, NULL, FDW_READ, false);

	if (!CConfig::instance().GetValue("BACKUP_LIMIT_SEC", &tmpValue))
		tmpValue = 600;

	m_looping = true;

	if (!CConfig::instance().GetValue("PLAYER_DELETE_LEVEL_LIMIT", &m_iPlayerDeleteLevelLimit))
	{
		sys_err("conf/db.txt: Cannot find PLAYER_DELETE_LEVEL_LIMIT, use default level %d", PLAYER_MAX_LEVEL_CONST + 1);
		m_iPlayerDeleteLevelLimit = PLAYER_MAX_LEVEL_CONST + 1;
	}

	if (!CConfig::instance().GetValue("PLAYER_DELETE_LEVEL_LIMIT_LOWER", &m_iPlayerDeleteLevelLimitLower))
	{
		m_iPlayerDeleteLevelLimitLower = 0;
	}

	sys_log(0, "PLAYER_DELETE_LEVEL_LIMIT set to %d", m_iPlayerDeleteLevelLimit);
	sys_log(0, "PLAYER_DELETE_LEVEL_LIMIT_LOWER set to %d", m_iPlayerDeleteLevelLimitLower);

	m_bChinaEventServer = false;

	int	iChinaEventServer = 0;

	if (CConfig::instance().GetValue("CHINA_EVENT_SERVER", &iChinaEventServer))
		m_bChinaEventServer = (iChinaEventServer);

	sys_log(0, "CHINA_EVENT_SERVER %s", CClientManager::instance().IsChinaEventServer()?"true":"false");


	LoadEventFlag();

	// database character-set을 강제로 맞춤
	if (g_stLocale == "big5" || g_stLocale == "sjis")
	    CDBManager::instance().QueryLocaleSet();

	return true;
}

 

 

db/PeerBase.cpp

Spoiler
bool CPeerBase::Accept(socket_t fd_accept)
{
	struct sockaddr_in peer;

	if ((m_fd = socket_accept(fd_accept, &peer)) == INVALID_SOCKET)
	{
		Destroy();
		return false;
	}

	//socket_block(m_fd);
	socket_sndbuf(m_fd, 233016);
	socket_rcvbuf(m_fd, 233016);

	strlcpy(m_host, inet_ntoa(peer.sin_addr), sizeof(m_host));
	m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);
	m_inBuffer = buffer_new(MAX_INPUT_LEN);

	if (!m_outBuffer || !m_inBuffer)
	{
		Destroy();
		return false;
	}

	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);

	OnAccept();
	sys_log(0, "ACCEPT FROM %s", inet_ntoa(peer.sin_addr));
	return true;
}

bool CPeerBase::Connect(const char* host, WORD port)
{
	strlcpy(m_host, host, sizeof(m_host));

	if ((m_fd = socket_connect(host, port)) == INVALID_SOCKET)
		return false;

	m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);

	if (!m_outBuffer)
	{
		Destroy();
		return false;
	}

	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);

	OnConnect();
	return true;
}

void CPeerBase::Close()
{
	OnClose();
}

void CPeerBase::EncodeBYTE(uint8_t b)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, &b, sizeof(uint8_t));
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

void CPeerBase::EncodeWORD(uint16_t w)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, &w, sizeof(uint16_t));
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

void CPeerBase::EncodeDWORD(uint32_t dw)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, &dw, sizeof(uint32_t));
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

void CPeerBase::Encode(const void* data, uint32_t size)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, data, size);
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

...

int CPeerBase::Send()
{
	if (buffer_size(m_outBuffer) <= 0)
		return 0;

	int iBufferLeft = fdwatch_get_buffer_size(m_fdWatcher, m_fd);
	int iBytesToWrite = MIN(iBufferLeft, buffer_size(m_outBuffer));

	if (iBytesToWrite == 0)
		return 0;

	int result = socket_write(m_fd, (const char *) buffer_read_peek(m_outBuffer), iBytesToWrite);

	if (result == 0)
	{
		buffer_read_proceed(m_outBuffer, iBytesToWrite);

		if (buffer_size(m_outBuffer) != 0)
			fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
	}

	return (result);
}

 

 

game/desc.cpp

Spoiler
bool DESC::Setup(LPFDWATCH _fdw, socket_t _fd, const struct sockaddr_in & c_rSockAddr, DWORD _handle, DWORD _handshake)
{
	m_lpFdw		= _fdw;
	m_sock		= _fd;

	m_stHost		= inet_ntoa(c_rSockAddr.sin_addr);
	m_wPort			= c_rSockAddr.sin_port;
	m_dwHandle		= _handle;

	//if (LC_IsEurope() == true || LC_IsNewCIBN())
	//	m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2);
	//else
	//NOTE: 이걸 나라별로 다르게 잡아야할 이유가 있나?
	m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 3); // Default: 2

	m_iMinInputBufferLen = MAX_INPUT_LEN >> 1;
	m_lpInputBuffer = buffer_new(MAX_INPUT_LEN);

	m_SockAddr = c_rSockAddr;

	fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);

	// Ping Event 
	desc_event_info* info = AllocEventInfo<desc_event_info>();

	info->desc = this;
	assert(m_pkPingEvent == NULL);

	m_pkPingEvent = event_create(ping_event, info, ping_event_second_cycle);

#ifndef _IMPROVED_PACKET_ENCRYPTION_
	if (LC_IsEurope())	
	{
		thecore_memcpy(m_adwEncryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
		thecore_memcpy(m_adwDecryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
	}
	else
	{
		thecore_memcpy(m_adwEncryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
		thecore_memcpy(m_adwDecryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
	}
#endif // _IMPROVED_PACKET_ENCRYPTION_

	// Set Phase to handshake
	SetPhase(PHASE_HANDSHAKE);
	StartHandshake(_handshake);

	sys_log(0, "SYSTEM: new connection from [%s] fd: %d handshake %u output input_len %d, ptr %p",
			m_stHost.c_str(), m_sock, m_dwHandshake, buffer_size(m_lpInputBuffer), this);

	Log("SYSTEM: new connection from [%s] fd: %d handshake %u ptr %p", m_stHost.c_str(), m_sock, m_dwHandshake, this);
	return true;
}

 

int DESC::ProcessOutput()
{
	if (buffer_size(m_lpOutputBuffer) <= 0)
		return 0;

	int buffer_left = fdwatch_get_buffer_size(m_lpFdw, m_sock);

	if (buffer_left <= 0)
		return 0;

	int bytes_to_write = MIN(buffer_left, buffer_size(m_lpOutputBuffer));

	if (bytes_to_write == 0)
		return 0;

	int result = socket_write(m_sock, (const char *) buffer_read_peek(m_lpOutputBuffer), bytes_to_write);

	if (result == 0)
	{
		//sys_log(0, "%d bytes written to %s first %u", bytes_to_write, GetHostName(), *(BYTE *) buffer_read_peek(m_lpOutputBuffer));
		//Log("%d bytes written", bytes_to_write);
		max_bytes_written = MAX(bytes_to_write, max_bytes_written);

		total_bytes_written += bytes_to_write;
		current_bytes_written += bytes_to_write;

		buffer_read_proceed(m_lpOutputBuffer, bytes_to_write);

		if (buffer_size(m_lpOutputBuffer) != 0)
			fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, true);
	}

	return (result);
}

 

void DESC::Packet(const void * c_pvData, int iSize)
{
	assert(iSize > 0);

	if (m_iPhase == PHASE_CLOSE) // 끊는 상태면 보내지 않는다.
		return;

	if (!m_lpOutputBuffer)
	{
		sys_err("DESC::Packet: Trying to send packet but output buffer is NULL! (DESC: %p)", this);
		SetPhase(PHASE_CLOSE);
		return;
	}

#ifdef _DEBUG
	const std::string stName = GetCharacter() ? GetCharacter()->GetName() : GetHostName();
	const auto kHeader = *(static_cast<const uint8_t*>(c_pvData));
	sys_log(0, "[N] SENT HEADER : %u(0x%X) to %s  (size %d) ", kHeader, kHeader, stName.c_str(), iSize);
#endif

	if (m_stRelayName.length() != 0)
	{
		// Relay 패킷은 암호화하지 않는다.
		TPacketGGRelay p;

		p.bHeader = HEADER_GG_RELAY;
		strlcpy(p.szName, m_stRelayName.c_str(), sizeof(p.szName));
		p.lSize = iSize;

		if (!packet_encode(m_lpOutputBuffer, &p, sizeof(p)))
		{
			m_iPhase = PHASE_CLOSE;
			return;
		}

		m_stRelayName.clear();

		if (!packet_encode(m_lpOutputBuffer, c_pvData, iSize))
		{
			m_iPhase = PHASE_CLOSE;
			return;
		}
	}
	else
	{
		if (m_lpBufferedOutputBuffer)
		{
			buffer_write(m_lpBufferedOutputBuffer, c_pvData, iSize);

			c_pvData = buffer_read_peek(m_lpBufferedOutputBuffer);
			iSize = buffer_size(m_lpBufferedOutputBuffer);
		}

		// TRAFFIC_PROFILE
		if (g_bTrafficProfileOn)
			TrafficProfiler::instance().Report(TrafficProfiler::IODIR_OUTPUT, *(BYTE *) c_pvData, iSize);
		// END_OF_TRAFFIC_PROFILER

#ifdef _IMPROVED_PACKET_ENCRYPTION_
		int write_point_pos = m_lpOutputBuffer->write_point_pos;
		if (packet_encode(m_lpOutputBuffer, c_pvData, iSize))
		{
			void* buf = m_lpOutputBuffer->mem_data + write_point_pos;
			if (cipher_.activated()) {
				cipher_.Encrypt(buf, iSize);
			}
		}
		else
		{
			m_iPhase = PHASE_CLOSE;
		}
#else
		if (!m_bEncrypted)
		{
			if (!packet_encode(m_lpOutputBuffer, c_pvData, iSize))
			{
				m_iPhase = PHASE_CLOSE;
			}
		}
		else
		{
			if (buffer_has_space(m_lpOutputBuffer) < iSize + 8)
			{
				buffer_adjust_size(m_lpOutputBuffer, iSize);
 
				if (buffer_has_space(m_lpOutputBuffer) < iSize + 8)
				{
					sys_err("desc buffer mem_size overflow. memsize(%u) write_pos(%u) iSize(%d)", 
							m_lpOutputBuffer->mem_size, m_lpOutputBuffer->write_point_pos, iSize);

					m_iPhase = PHASE_CLOSE;
				}
			}
			else
			{
				// 암호화에 필요한 충분한 버퍼 크기를 확보한다.
				/* buffer_adjust_size(m_lpOutputBuffer, iSize + 8); */
				DWORD * pdwWritePoint = (DWORD *) buffer_write_peek(m_lpOutputBuffer);

				if (packet_encode(m_lpOutputBuffer, c_pvData, iSize))
				{
					int iSize2 = TEA_Encrypt(pdwWritePoint, pdwWritePoint, GetEncryptionKey(), iSize);

					if (iSize2 > iSize)
						buffer_write_proceed(m_lpOutputBuffer, iSize2 - iSize);
				}
			}
		}
#endif // _IMPROVED_PACKET_ENCRYPTION_

		SAFE_BUFFER_DELETE(m_lpBufferedOutputBuffer);
	}

	//sys_log(0, "%d bytes written (first byte %d)", iSize, *(BYTE *) c_pvData);
	if (m_iPhase != PHASE_CLOSE)
		fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, true);
}

 

 

game/desc_client.cpp

Spoiler
bool CLIENT_DESC::Connect(int iPhaseWhenSucceed)
{
	if (iPhaseWhenSucceed != 0)
		m_iPhaseWhenSucceed = iPhaseWhenSucceed;

	if (get_global_time() - m_LastTryToConnectTime < 3)	// 3초
		return false;

	m_LastTryToConnectTime = get_global_time();

	if (m_sock != INVALID_SOCKET)
		return false;

	sys_log(0, "SYSTEM: Trying to connect to %s:%d", m_stHost.c_str(), m_wPort);

	m_sock = socket_connect(m_stHost.c_str(), m_wPort);

	if (m_sock != INVALID_SOCKET)
	{
		sys_log(0, "SYSTEM: connected to server (fd %d, ptr %p)", m_sock, this);
		fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);
		fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, false);
		SetPhase(m_iPhaseWhenSucceed);
		return true;
	}
	else
	{
		SetPhase(PHASE_CLIENT_CONNECTING);
		return false;
	}
}

 

 

game/desc_p2p.cpp

Spoiler
bool DESC_P2P::Setup(LPFDWATCH fdw, socket_t fd, const char * host, WORD wPort)
{
	m_lpFdw = fdw;
	m_stHost = host;
	m_wPort = wPort;
	m_sock = fd;

	if (!(m_lpOutputBuffer = buffer_new(1024 * 1024)))
		return false;

	if (!(m_lpInputBuffer = buffer_new(1024 * 1024)))
		return false;

	fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);

	m_iMinInputBufferLen = 1024 * 1024;

	SetPhase(PHASE_P2P);

	sys_log(0, "SYSTEM: new p2p connection from [%s] fd: %d", host, m_sock);
	return true;
}

 

 

game/main.cpp

Spoiler
int start(int argc, char **argv)
{
	std::string st_localeServiceName;

	bool bVerbose = false;
	char ch;

	//_malloc_options = "A";
#if defined(OS_FREEBSD) && defined(DEBUG_ALLOC)
	_malloc_message = WriteMallocMessage;
#endif

	char optstring[] = "npverltI";
	while ((ch = getopt(argc, argv, optstring)) != -1)
	{
		char* ep = NULL;

		switch (ch)
		{
			case 'I': // IP
				strlcpy(g_szPublicIP, argv[optind], sizeof(g_szPublicIP));

				printf("IP %s\n", g_szPublicIP);

				optind++;
				optreset = 1;
				break;

			case 'p': // port
				mother_port = strtol(argv[optind], &ep, 10);

				if (mother_port <= 1024)
				{
					usage();
					return 0;
				}

				printf("port %d\n", mother_port);

				optind++;
				optreset = 1;
				break;

				// LOCALE_SERVICE
			case 'n': 
				{
					if (optind < argc)
					{
						st_localeServiceName = argv[optind++];
						optreset = 1;
					}
				}
				break;
				// END_OF_LOCALE_SERVICE

			case 'v': // verbose
				bVerbose = true;
				break;

			case 'r':
				g_bNoRegen = true;
				break;

				// TRAFFIC_PROFILER
			case 't':
				g_bTrafficProfileOn = true;
				break;
				// END_OF_TRAFFIC_PROFILER
		}
	}

	// LOCALE_SERVICE
	config_init(st_localeServiceName);
	// END_OF_LOCALE_SERVICE

#ifdef OS_WINDOWS
	// In Windows dev mode, "verbose" option is [on] by default.
	bVerbose = true;
#endif
	if (!bVerbose)
		freopen("stdout", "a", stdout);

	bool is_thecore_initialized = thecore_init(passes_per_sec, heartbeat);

	if (!is_thecore_initialized)
	{
		fprintf(stderr, "Could not initialize thecore, check owner of pid, syslog\n");
		exit(0);
	}

	if (false == CThreeWayWar::instance().LoadSetting("forkedmapindex.txt"))
	{
		if (false == g_bAuthServer)
		{
			fprintf(stderr, "Could not Load ThreeWayWar Setting file");
			exit(0);
		}
	}

	signal_timer_disable();
	
	main_fdw = fdwatch_new(4096);

	if ((tcp_socket = socket_tcp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
	{
		perror("socket_tcp_bind: tcp_socket");
		return 0;
	}

	
#ifndef __UDP_BLOCK__
	if ((udp_socket = socket_udp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
	{
		perror("socket_udp_bind: udp_socket");
		return 0;
	}
#endif	

	// if internal ip exists, p2p socket uses internal ip, if not use public ip
	//if ((p2p_socket = socket_tcp_bind(*g_szInternalIP ? g_szInternalIP : g_szPublicIP, p2p_port)) == INVALID_SOCKET)
	if ((p2p_socket = socket_tcp_bind(g_szPublicIP, p2p_port)) == INVALID_SOCKET)
	{
		perror("socket_tcp_bind: p2p_socket");
		return 0;
	}

	fdwatch_add_fd(main_fdw, tcp_socket, NULL, FDW_READ, false);
#ifndef __UDP_BLOCK__
	fdwatch_add_fd(main_fdw, udp_socket, NULL, FDW_READ, false);
#endif
	fdwatch_add_fd(main_fdw, p2p_socket, NULL, FDW_READ, false);

	db_clientdesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, db_addr, db_port, PHASE_DBCLIENT, true);
	if (!g_bAuthServer) {
		db_clientdesc->UpdateChannelStatus(0, true);
	}

	if (g_bAuthServer)
	{
		if (g_stAuthMasterIP.length() != 0)
		{
			fprintf(stderr, "SlaveAuth");
			g_pkAuthMasterDesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, g_stAuthMasterIP.c_str(), g_wAuthMasterPort, PHASE_P2P, true); 
			P2P_MANAGER::instance().RegisterConnector(g_pkAuthMasterDesc);
			g_pkAuthMasterDesc->SetP2P(g_stAuthMasterIP.c_str(), g_wAuthMasterPort, g_bChannel);

		}
		else
		{
			fprintf(stderr, "MasterAuth %d", LC_GetLocalType());
		}
	}
	else
	{
		extern unsigned int g_uiSpamBlockDuration;
		extern unsigned int g_uiSpamBlockScore;
		extern unsigned int g_uiSpamReloadCycle;

		sys_log(0, "SPAM_CONFIG: duration %u score %u reload cycle %u\n",
			g_uiSpamBlockDuration, g_uiSpamBlockScore, g_uiSpamReloadCycle);

		extern void LoadSpamDB();
		LoadSpamDB();
	}

	signal_timer_enable(30);
	return 1;
}

 

 

libthecore/fdwatch.cpp

Spoiler
void fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void * client_data, int rw, int oneshot)
{
	int flag;

	if (fd >= fdw->nfiles)
	{
		sys_err("fd overflow %d", fd);
		return;
	}

	if (fdw->fd_rw[fd] & rw)
		return;

	fdw->fd_rw[fd] |= rw;
	sys_log(2, "FDWATCH_fdw %p fd %d rw %d data %p", fdw, fd, rw, client_data);

	if (!oneshot)
		flag = EV_ADD;
	else
	{
		sys_log(2, "ADD ONESHOT fd_rw %d", fdw->fd_rw[fd]);
		flag = EV_ADD | EV_ONESHOT;
		fdw->fd_rw[fd] |= FDW_WRITE_ONESHOT;
	}

	fdw->fd_data[fd] = client_data;
	fdwatch_register(fdw, flag, fd, rw);
}

 

void fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void* client_data, int rw, int oneshot)
{
	int idx = fdwatch_get_fdidx(fdw, fd);
	if (idx < 0) {
		if (fdw->nselect_fds >= fdw->nfiles) {
			return;
		}
		idx = fdw->nselect_fds;
		fdw->select_fds[fdw->nselect_fds++] = fd;
		fdw->fd_rw[idx] = rw;
	} else {
		fdw->fd_rw[idx] |= rw;
	}
	fdw->fd_data[idx] = client_data;

    if (rw & FDW_READ)
	FD_SET(fd, &fdw->rfd_set);

    if (rw & FDW_WRITE)
	FD_SET(fd, &fdw->wfd_set);
}

 

** No idea as to why it exists twice but these are 2 different functions

 

libthecore/fdwatch.h

Spoiler
void		fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void* client_data, int rw, int oneshot);

 

 

In the end the character is created in the database but no updates inside player_index.

Edited by Mind Rapist
updated information
  • Honorable Member

UPDATE

Latest commits merged:

  • matrix removal
  • slots synced
Edited by Distraught
  • Metin2 Dev 1

992404397646696589.png
Former C++ Developer at Gameloft on DML
Join my Discord: Distraught Labs

5 hours ago, Mind Rapist said:

Thank you for this it had really started to bug me a lot 😄

I can confirm that this fixes the issue (change to skilldesc and skilltable in the client as well to match).

Btw has anyone tried to create a new character in the game? For me it crashed the db (created a core):

.png

And in case these logs are relative:

  Hide contents
...
[2025-11-13 18:44:11.021] [error] [socket_t socket_connect(const char *, WORD)()] HOST 127.0.0.1:9000, could not connect.
[2025-11-13 18:44:11.203] [error] [virtual bool CInputProcessor::Process(LPDESC, const void *, int, int &)()] UNKNOWN HEADER: 108(0x6C) LAST HEADER: 0(0x0)[0], REMAIN BYTES: 15, CHAR: <none>, PHASE: 3, fd: 16 host: XXX.XXX.XXX.XXX
...

...
[2025-11-13 18:44:11.029] [error] [socket_t socket_connect(const char *, WORD)()] HOST 127.0.0.1:9000, could not connect.
[2025-11-13 18:44:12.536] [error] [virtual bool CInputProcessor::Process(LPDESC, const void *, int, int &)()] SEQUENCE 9b878e00 mismatch 0x4e != 0x64 header 254

 

I searched for all the references of `fdwatch_add_fd` but I couldn't figure out if there's a mistake somewhere:

db/ClientManager.cpp

  Reveal hidden contents
bool CClientManager::Initialize()
{
	int tmpValue;
	
	//BOOT_LOCALIZATION
	if (!InitializeLocalization())
	{
		fprintf(stderr, "Failed Localization Infomation so exit\n");
		return false;
	}
		
	//END_BOOT_LOCALIZATION
	//ITEM_UNIQUE_ID
	
	if (!InitializeNowItemID())
	{
		fprintf(stderr, " Item range Initialize Failed. Exit DBCache Server\n");
		return false;
	}
	//END_ITEM_UNIQUE_ID

	if (!InitializeTables())
	{
		sys_err("Table Initialize FAILED");
		return false;
	}

	CGuildManager::instance().BootReserveWar();

	if (!CConfig::instance().GetValue("BIND_PORT", &tmpValue))
		tmpValue = 5300;

	char szBindIP[128];

	if (!CConfig::instance().GetValue("BIND_IP", szBindIP, 128))
		// strlcpy(szBindIP, "0", sizeof(szBindIP));
		strlcpy(szBindIP, "127.0.0.1", sizeof(szBindIP)); // Fix: Now even if the DB port is publicly available an attacker can't connect to it with a fake auth.

	m_fdAccept = socket_tcp_bind(szBindIP, tmpValue);

	if (m_fdAccept < 0)
	{
		perror("socket");
		return false;
	}

	sys_log(0, "ACCEPT_HANDLE: %u", m_fdAccept);
	fdwatch_add_fd(m_fdWatcher, m_fdAccept, NULL, FDW_READ, false);

	if (!CConfig::instance().GetValue("BACKUP_LIMIT_SEC", &tmpValue))
		tmpValue = 600;

	m_looping = true;

	if (!CConfig::instance().GetValue("PLAYER_DELETE_LEVEL_LIMIT", &m_iPlayerDeleteLevelLimit))
	{
		sys_err("conf/db.txt: Cannot find PLAYER_DELETE_LEVEL_LIMIT, use default level %d", PLAYER_MAX_LEVEL_CONST + 1);
		m_iPlayerDeleteLevelLimit = PLAYER_MAX_LEVEL_CONST + 1;
	}

	if (!CConfig::instance().GetValue("PLAYER_DELETE_LEVEL_LIMIT_LOWER", &m_iPlayerDeleteLevelLimitLower))
	{
		m_iPlayerDeleteLevelLimitLower = 0;
	}

	sys_log(0, "PLAYER_DELETE_LEVEL_LIMIT set to %d", m_iPlayerDeleteLevelLimit);
	sys_log(0, "PLAYER_DELETE_LEVEL_LIMIT_LOWER set to %d", m_iPlayerDeleteLevelLimitLower);

	m_bChinaEventServer = false;

	int	iChinaEventServer = 0;

	if (CConfig::instance().GetValue("CHINA_EVENT_SERVER", &iChinaEventServer))
		m_bChinaEventServer = (iChinaEventServer);

	sys_log(0, "CHINA_EVENT_SERVER %s", CClientManager::instance().IsChinaEventServer()?"true":"false");


	LoadEventFlag();

	// database character-set을 강제로 맞춤
	if (g_stLocale == "big5" || g_stLocale == "sjis")
	    CDBManager::instance().QueryLocaleSet();

	return true;
}

 

 

db/PeerBase.cpp

  Reveal hidden contents
bool CPeerBase::Accept(socket_t fd_accept)
{
	struct sockaddr_in peer;

	if ((m_fd = socket_accept(fd_accept, &peer)) == INVALID_SOCKET)
	{
		Destroy();
		return false;
	}

	//socket_block(m_fd);
	socket_sndbuf(m_fd, 233016);
	socket_rcvbuf(m_fd, 233016);

	strlcpy(m_host, inet_ntoa(peer.sin_addr), sizeof(m_host));
	m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);
	m_inBuffer = buffer_new(MAX_INPUT_LEN);

	if (!m_outBuffer || !m_inBuffer)
	{
		Destroy();
		return false;
	}

	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);

	OnAccept();
	sys_log(0, "ACCEPT FROM %s", inet_ntoa(peer.sin_addr));
	return true;
}

bool CPeerBase::Connect(const char* host, WORD port)
{
	strlcpy(m_host, host, sizeof(m_host));

	if ((m_fd = socket_connect(host, port)) == INVALID_SOCKET)
		return false;

	m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);

	if (!m_outBuffer)
	{
		Destroy();
		return false;
	}

	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);

	OnConnect();
	return true;
}

void CPeerBase::Close()
{
	OnClose();
}

void CPeerBase::EncodeBYTE(uint8_t b)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, &b, sizeof(uint8_t));
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

void CPeerBase::EncodeWORD(uint16_t w)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, &w, sizeof(uint16_t));
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

void CPeerBase::EncodeDWORD(uint32_t dw)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, &dw, sizeof(uint32_t));
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

void CPeerBase::Encode(const void* data, uint32_t size)
{
	if (!m_outBuffer)
	{
		sys_err("Not ready to write");
		return;
	}

	buffer_write(m_outBuffer, data, size);
	fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}

...

int CPeerBase::Send()
{
	if (buffer_size(m_outBuffer) <= 0)
		return 0;

	int iBufferLeft = fdwatch_get_buffer_size(m_fdWatcher, m_fd);
	int iBytesToWrite = MIN(iBufferLeft, buffer_size(m_outBuffer));

	if (iBytesToWrite == 0)
		return 0;

	int result = socket_write(m_fd, (const char *) buffer_read_peek(m_outBuffer), iBytesToWrite);

	if (result == 0)
	{
		buffer_read_proceed(m_outBuffer, iBytesToWrite);

		if (buffer_size(m_outBuffer) != 0)
			fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
	}

	return (result);
}

 

 

game/desc.cpp

  Reveal hidden contents
bool DESC::Setup(LPFDWATCH _fdw, socket_t _fd, const struct sockaddr_in & c_rSockAddr, DWORD _handle, DWORD _handshake)
{
	m_lpFdw		= _fdw;
	m_sock		= _fd;

	m_stHost		= inet_ntoa(c_rSockAddr.sin_addr);
	m_wPort			= c_rSockAddr.sin_port;
	m_dwHandle		= _handle;

	//if (LC_IsEurope() == true || LC_IsNewCIBN())
	//	m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2);
	//else
	//NOTE: 이걸 나라별로 다르게 잡아야할 이유가 있나?
	m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 3); // Default: 2

	m_iMinInputBufferLen = MAX_INPUT_LEN >> 1;
	m_lpInputBuffer = buffer_new(MAX_INPUT_LEN);

	m_SockAddr = c_rSockAddr;

	fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);

	// Ping Event 
	desc_event_info* info = AllocEventInfo<desc_event_info>();

	info->desc = this;
	assert(m_pkPingEvent == NULL);

	m_pkPingEvent = event_create(ping_event, info, ping_event_second_cycle);

#ifndef _IMPROVED_PACKET_ENCRYPTION_
	if (LC_IsEurope())	
	{
		thecore_memcpy(m_adwEncryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
		thecore_memcpy(m_adwDecryptionKey, "1234abcd5678efgh", sizeof(DWORD) * 4);
	}
	else
	{
		thecore_memcpy(m_adwEncryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
		thecore_memcpy(m_adwDecryptionKey, "testtesttesttest", sizeof(DWORD) * 4);
	}
#endif // _IMPROVED_PACKET_ENCRYPTION_

	// Set Phase to handshake
	SetPhase(PHASE_HANDSHAKE);
	StartHandshake(_handshake);

	sys_log(0, "SYSTEM: new connection from [%s] fd: %d handshake %u output input_len %d, ptr %p",
			m_stHost.c_str(), m_sock, m_dwHandshake, buffer_size(m_lpInputBuffer), this);

	Log("SYSTEM: new connection from [%s] fd: %d handshake %u ptr %p", m_stHost.c_str(), m_sock, m_dwHandshake, this);
	return true;
}

 

int DESC::ProcessOutput()
{
	if (buffer_size(m_lpOutputBuffer) <= 0)
		return 0;

	int buffer_left = fdwatch_get_buffer_size(m_lpFdw, m_sock);

	if (buffer_left <= 0)
		return 0;

	int bytes_to_write = MIN(buffer_left, buffer_size(m_lpOutputBuffer));

	if (bytes_to_write == 0)
		return 0;

	int result = socket_write(m_sock, (const char *) buffer_read_peek(m_lpOutputBuffer), bytes_to_write);

	if (result == 0)
	{
		//sys_log(0, "%d bytes written to %s first %u", bytes_to_write, GetHostName(), *(BYTE *) buffer_read_peek(m_lpOutputBuffer));
		//Log("%d bytes written", bytes_to_write);
		max_bytes_written = MAX(bytes_to_write, max_bytes_written);

		total_bytes_written += bytes_to_write;
		current_bytes_written += bytes_to_write;

		buffer_read_proceed(m_lpOutputBuffer, bytes_to_write);

		if (buffer_size(m_lpOutputBuffer) != 0)
			fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, true);
	}

	return (result);
}

 

void DESC::Packet(const void * c_pvData, int iSize)
{
	assert(iSize > 0);

	if (m_iPhase == PHASE_CLOSE) // 끊는 상태면 보내지 않는다.
		return;

	if (!m_lpOutputBuffer)
	{
		sys_err("DESC::Packet: Trying to send packet but output buffer is NULL! (DESC: %p)", this);
		SetPhase(PHASE_CLOSE);
		return;
	}

#ifdef _DEBUG
	const std::string stName = GetCharacter() ? GetCharacter()->GetName() : GetHostName();
	const auto kHeader = *(static_cast<const uint8_t*>(c_pvData));
	sys_log(0, "[N] SENT HEADER : %u(0x%X) to %s  (size %d) ", kHeader, kHeader, stName.c_str(), iSize);
#endif

	if (m_stRelayName.length() != 0)
	{
		// Relay 패킷은 암호화하지 않는다.
		TPacketGGRelay p;

		p.bHeader = HEADER_GG_RELAY;
		strlcpy(p.szName, m_stRelayName.c_str(), sizeof(p.szName));
		p.lSize = iSize;

		if (!packet_encode(m_lpOutputBuffer, &p, sizeof(p)))
		{
			m_iPhase = PHASE_CLOSE;
			return;
		}

		m_stRelayName.clear();

		if (!packet_encode(m_lpOutputBuffer, c_pvData, iSize))
		{
			m_iPhase = PHASE_CLOSE;
			return;
		}
	}
	else
	{
		if (m_lpBufferedOutputBuffer)
		{
			buffer_write(m_lpBufferedOutputBuffer, c_pvData, iSize);

			c_pvData = buffer_read_peek(m_lpBufferedOutputBuffer);
			iSize = buffer_size(m_lpBufferedOutputBuffer);
		}

		// TRAFFIC_PROFILE
		if (g_bTrafficProfileOn)
			TrafficProfiler::instance().Report(TrafficProfiler::IODIR_OUTPUT, *(BYTE *) c_pvData, iSize);
		// END_OF_TRAFFIC_PROFILER

#ifdef _IMPROVED_PACKET_ENCRYPTION_
		int write_point_pos = m_lpOutputBuffer->write_point_pos;
		if (packet_encode(m_lpOutputBuffer, c_pvData, iSize))
		{
			void* buf = m_lpOutputBuffer->mem_data + write_point_pos;
			if (cipher_.activated()) {
				cipher_.Encrypt(buf, iSize);
			}
		}
		else
		{
			m_iPhase = PHASE_CLOSE;
		}
#else
		if (!m_bEncrypted)
		{
			if (!packet_encode(m_lpOutputBuffer, c_pvData, iSize))
			{
				m_iPhase = PHASE_CLOSE;
			}
		}
		else
		{
			if (buffer_has_space(m_lpOutputBuffer) < iSize + 8)
			{
				buffer_adjust_size(m_lpOutputBuffer, iSize);
 
				if (buffer_has_space(m_lpOutputBuffer) < iSize + 8)
				{
					sys_err("desc buffer mem_size overflow. memsize(%u) write_pos(%u) iSize(%d)", 
							m_lpOutputBuffer->mem_size, m_lpOutputBuffer->write_point_pos, iSize);

					m_iPhase = PHASE_CLOSE;
				}
			}
			else
			{
				// 암호화에 필요한 충분한 버퍼 크기를 확보한다.
				/* buffer_adjust_size(m_lpOutputBuffer, iSize + 8); */
				DWORD * pdwWritePoint = (DWORD *) buffer_write_peek(m_lpOutputBuffer);

				if (packet_encode(m_lpOutputBuffer, c_pvData, iSize))
				{
					int iSize2 = TEA_Encrypt(pdwWritePoint, pdwWritePoint, GetEncryptionKey(), iSize);

					if (iSize2 > iSize)
						buffer_write_proceed(m_lpOutputBuffer, iSize2 - iSize);
				}
			}
		}
#endif // _IMPROVED_PACKET_ENCRYPTION_

		SAFE_BUFFER_DELETE(m_lpBufferedOutputBuffer);
	}

	//sys_log(0, "%d bytes written (first byte %d)", iSize, *(BYTE *) c_pvData);
	if (m_iPhase != PHASE_CLOSE)
		fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, true);
}

 

 

game/desc_client.cpp

  Reveal hidden contents
bool CLIENT_DESC::Connect(int iPhaseWhenSucceed)
{
	if (iPhaseWhenSucceed != 0)
		m_iPhaseWhenSucceed = iPhaseWhenSucceed;

	if (get_global_time() - m_LastTryToConnectTime < 3)	// 3초
		return false;

	m_LastTryToConnectTime = get_global_time();

	if (m_sock != INVALID_SOCKET)
		return false;

	sys_log(0, "SYSTEM: Trying to connect to %s:%d", m_stHost.c_str(), m_wPort);

	m_sock = socket_connect(m_stHost.c_str(), m_wPort);

	if (m_sock != INVALID_SOCKET)
	{
		sys_log(0, "SYSTEM: connected to server (fd %d, ptr %p)", m_sock, this);
		fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);
		fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_WRITE, false);
		SetPhase(m_iPhaseWhenSucceed);
		return true;
	}
	else
	{
		SetPhase(PHASE_CLIENT_CONNECTING);
		return false;
	}
}

 

 

game/desc_p2p.cpp

  Reveal hidden contents
bool DESC_P2P::Setup(LPFDWATCH fdw, socket_t fd, const char * host, WORD wPort)
{
	m_lpFdw = fdw;
	m_stHost = host;
	m_wPort = wPort;
	m_sock = fd;

	if (!(m_lpOutputBuffer = buffer_new(1024 * 1024)))
		return false;

	if (!(m_lpInputBuffer = buffer_new(1024 * 1024)))
		return false;

	fdwatch_add_fd(m_lpFdw, m_sock, this, FDW_READ, false);

	m_iMinInputBufferLen = 1024 * 1024;

	SetPhase(PHASE_P2P);

	sys_log(0, "SYSTEM: new p2p connection from [%s] fd: %d", host, m_sock);
	return true;
}

 

 

game/main.cpp

  Reveal hidden contents
int start(int argc, char **argv)
{
	std::string st_localeServiceName;

	bool bVerbose = false;
	char ch;

	//_malloc_options = "A";
#if defined(OS_FREEBSD) && defined(DEBUG_ALLOC)
	_malloc_message = WriteMallocMessage;
#endif

	char optstring[] = "npverltI";
	while ((ch = getopt(argc, argv, optstring)) != -1)
	{
		char* ep = NULL;

		switch (ch)
		{
			case 'I': // IP
				strlcpy(g_szPublicIP, argv[optind], sizeof(g_szPublicIP));

				printf("IP %s\n", g_szPublicIP);

				optind++;
				optreset = 1;
				break;

			case 'p': // port
				mother_port = strtol(argv[optind], &ep, 10);

				if (mother_port <= 1024)
				{
					usage();
					return 0;
				}

				printf("port %d\n", mother_port);

				optind++;
				optreset = 1;
				break;

				// LOCALE_SERVICE
			case 'n': 
				{
					if (optind < argc)
					{
						st_localeServiceName = argv[optind++];
						optreset = 1;
					}
				}
				break;
				// END_OF_LOCALE_SERVICE

			case 'v': // verbose
				bVerbose = true;
				break;

			case 'r':
				g_bNoRegen = true;
				break;

				// TRAFFIC_PROFILER
			case 't':
				g_bTrafficProfileOn = true;
				break;
				// END_OF_TRAFFIC_PROFILER
		}
	}

	// LOCALE_SERVICE
	config_init(st_localeServiceName);
	// END_OF_LOCALE_SERVICE

#ifdef OS_WINDOWS
	// In Windows dev mode, "verbose" option is [on] by default.
	bVerbose = true;
#endif
	if (!bVerbose)
		freopen("stdout", "a", stdout);

	bool is_thecore_initialized = thecore_init(passes_per_sec, heartbeat);

	if (!is_thecore_initialized)
	{
		fprintf(stderr, "Could not initialize thecore, check owner of pid, syslog\n");
		exit(0);
	}

	if (false == CThreeWayWar::instance().LoadSetting("forkedmapindex.txt"))
	{
		if (false == g_bAuthServer)
		{
			fprintf(stderr, "Could not Load ThreeWayWar Setting file");
			exit(0);
		}
	}

	signal_timer_disable();
	
	main_fdw = fdwatch_new(4096);

	if ((tcp_socket = socket_tcp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
	{
		perror("socket_tcp_bind: tcp_socket");
		return 0;
	}

	
#ifndef __UDP_BLOCK__
	if ((udp_socket = socket_udp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
	{
		perror("socket_udp_bind: udp_socket");
		return 0;
	}
#endif	

	// if internal ip exists, p2p socket uses internal ip, if not use public ip
	//if ((p2p_socket = socket_tcp_bind(*g_szInternalIP ? g_szInternalIP : g_szPublicIP, p2p_port)) == INVALID_SOCKET)
	if ((p2p_socket = socket_tcp_bind(g_szPublicIP, p2p_port)) == INVALID_SOCKET)
	{
		perror("socket_tcp_bind: p2p_socket");
		return 0;
	}

	fdwatch_add_fd(main_fdw, tcp_socket, NULL, FDW_READ, false);
#ifndef __UDP_BLOCK__
	fdwatch_add_fd(main_fdw, udp_socket, NULL, FDW_READ, false);
#endif
	fdwatch_add_fd(main_fdw, p2p_socket, NULL, FDW_READ, false);

	db_clientdesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, db_addr, db_port, PHASE_DBCLIENT, true);
	if (!g_bAuthServer) {
		db_clientdesc->UpdateChannelStatus(0, true);
	}

	if (g_bAuthServer)
	{
		if (g_stAuthMasterIP.length() != 0)
		{
			fprintf(stderr, "SlaveAuth");
			g_pkAuthMasterDesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, g_stAuthMasterIP.c_str(), g_wAuthMasterPort, PHASE_P2P, true); 
			P2P_MANAGER::instance().RegisterConnector(g_pkAuthMasterDesc);
			g_pkAuthMasterDesc->SetP2P(g_stAuthMasterIP.c_str(), g_wAuthMasterPort, g_bChannel);

		}
		else
		{
			fprintf(stderr, "MasterAuth %d", LC_GetLocalType());
		}
	}
	else
	{
		extern unsigned int g_uiSpamBlockDuration;
		extern unsigned int g_uiSpamBlockScore;
		extern unsigned int g_uiSpamReloadCycle;

		sys_log(0, "SPAM_CONFIG: duration %u score %u reload cycle %u\n",
			g_uiSpamBlockDuration, g_uiSpamBlockScore, g_uiSpamReloadCycle);

		extern void LoadSpamDB();
		LoadSpamDB();
	}

	signal_timer_enable(30);
	return 1;
}

 

 

libthecore/fdwatch.cpp

  Reveal hidden contents
void fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void * client_data, int rw, int oneshot)
{
	int flag;

	if (fd >= fdw->nfiles)
	{
		sys_err("fd overflow %d", fd);
		return;
	}

	if (fdw->fd_rw[fd] & rw)
		return;

	fdw->fd_rw[fd] |= rw;
	sys_log(2, "FDWATCH_fdw %p fd %d rw %d data %p", fdw, fd, rw, client_data);

	if (!oneshot)
		flag = EV_ADD;
	else
	{
		sys_log(2, "ADD ONESHOT fd_rw %d", fdw->fd_rw[fd]);
		flag = EV_ADD | EV_ONESHOT;
		fdw->fd_rw[fd] |= FDW_WRITE_ONESHOT;
	}

	fdw->fd_data[fd] = client_data;
	fdwatch_register(fdw, flag, fd, rw);
}

 

void fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void* client_data, int rw, int oneshot)
{
	int idx = fdwatch_get_fdidx(fdw, fd);
	if (idx < 0) {
		if (fdw->nselect_fds >= fdw->nfiles) {
			return;
		}
		idx = fdw->nselect_fds;
		fdw->select_fds[fdw->nselect_fds++] = fd;
		fdw->fd_rw[idx] = rw;
	} else {
		fdw->fd_rw[idx] |= rw;
	}
	fdw->fd_data[idx] = client_data;

    if (rw & FDW_READ)
	FD_SET(fd, &fdw->rfd_set);

    if (rw & FDW_WRITE)
	FD_SET(fd, &fdw->wfd_set);
}

 

** No idea as to why it exists twice but these are 2 different functions

 

libthecore/fdwatch.h

  Reveal hidden contents
void		fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void* client_data, int rw, int oneshot);

 

 

In the end the character is created in the database but no updates inside player_index.

Can you share bt full from gdb?

Also, is that the syserr from db after during the crash?

Edited by tw1x1
  • Active+ Member
13 hours ago, tw1x1 said:

Can you share bt full from gdb?

Also, is that the syserr from db after during the crash?

Hey thanks for replying! The syserrs are from channel1 cores db syserr is clear.

Here is a bt full

Spoiler
Reading symbols from db...
[New LWP 100416]
[New LWP 100435]
[New LWP 100436]
[New LWP 100438]
[New LWP 100439]
[New LWP 100443]
[New LWP 100444]
--Type <RET> for more, q to quit, c to continue without paging--c
[New LWP 100448]
[New LWP 100449]
[New LWP 100453]
[New LWP 100454]
Core was generated by `./db'.
Program terminated with signal SIGBUS, Bus error.
Object-specific hardware error.
#0  0x0000000000391ab4 in fdwatch_add_fd (fdw=0x305c305c305c305c, fd=19,
    client_data=0x22c96a243c0, rw=2, oneshot=1)
    at /usr/home/src/src/libthecore/fdwatch.cpp:129
129             if (fd >= fdw->nfiles)
[Current thread is 1 (LWP 100416)]
(gdb) bt full
#0  0x0000000000391ab4 in fdwatch_add_fd (fdw=0x305c305c305c305c, fd=19,
    client_data=0x22c96a243c0, rw=2, oneshot=1)
    at /usr/home/src/src/libthecore/fdwatch.cpp:129
        flag = 0
#1  0x0000000000370d80 in CPeerBase::Encode (this=0x22c96a243c0,
    data=0x821012903, size=9) at /usr/home/src/src/db/PeerBase.cpp:143
No locals.
#2  0x00000000003701ab in CPeer::EncodeHeader (this=0x22c96a243c0,
    header=37 '%', dwHandle=2, dwSize=64) at /usr/home/src/src/db/Peer.cpp:109
        h = {bHeader = 37 '%', dwHandle = 2, dwSize = 64}
#3  0x000000000032e0b4 in CClientManager::__QUERY_PLAYER_CREATE (
    this=0x821015aa8, peer=0x22c96a243c0, dwHandle=2, packet=0x22c9b3effc9)
    at /usr/home/src/src/db/ClientManagerPlayer.cpp:952
        text = "\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\0000\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"...
        queryStr = "UPDATE player_index0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"...
        queryLen = 5571
--Type <RET> for more, q to quit, c to continue without paging--
        player_id = 7
        it = {__i_ = {__ptr_ = 0x4708f0 <s_createTimeByAccountID+8>}}
        pMsg0 = std::unique_ptr<_SQLMsg> = 0x22c98481140
        pMsg1 = std::unique_ptr<_SQLMsg> = 0x22c98481260
        pMsg2 = std::unique_ptr<_SQLMsg> = 0x22c984811a0
        pMsg3 = std::unique_ptr<_SQLMsg> = 0x22c98481200
        pack = {bAccountCharacterIndex = 3 '\003', player = {dwID = 7,
            szName = "test55", '\000' <repeats 18 times>, byJob = 0 '\000',
            byLevel = 1 '\001', dwPlayMinutes = 0, byST = 6 '\006',
            byHT = 4 '\004', byDX = 3 '\003', byIQ = 3 '\003', wMainPart = 0,
            bChangeName = 0 '\000', wHairPart = 0, bDummy = "\000\000\000",
            x = 957405, y = 255412, lAddr = 0, wPort = 0,
            skill_group = 0 '\000'}}
#4  0x00000000002dea32 in CClientManager::ProcessPackets (this=0x821015aa8,
    peer=0x22c96a243c0) at /usr/home/src/src/db/ClientManager.cpp:2143
        header = 5 '\005'
        dwHandle = 2
        dwLength = 2899
        data = 0x22c9b3effc9 "admin2"
        i = 2908
        iCount = 1
#5  0x00000000002d5390 in CClientManager::Process (this=0x821015aa8)
    at /usr/home/src/src/db/ClientManager.cpp:2898
--Type <RET> for more, q to quit, c to continue without paging--
        pulses = -1
        num_events = 1
        idx = 0
        peer = 0x22c96a243c0
#6  0x00000000002d45d4 in CClientManager::MainLoop (this=0x821015aa8)
    at /usr/home/src/src/db/ClientManager.cpp:189
        tmp = 0x0
        it = end()
        it2 = <error reading variable: Cannot access memory at address 0x200215d                                                                                                                                                             4f>
#7  0x000000000035ffd5 in main () at /usr/home/src/src/db/Main.cpp:92
        Config = {<singleton<CConfig>> = {
            _vptr$singleton = 0x21a1f0 <vtable for CConfig+16>,
            static ms_singleton = 0x821015e88}, m_valueMap = {__tree_ = {
              __begin_node_ = 0x22c96a5c2d0,
              __pair1_ = {<std::__1::__compressed_pair_elem<std::__1::__tree_end                                                                                                                                                             _node<std::__1::__tree_node_base<void*>*>, 0, false>> = {__value_ = {
                    __left_ = 0x22c96a5c0f0}}, <std::__1::__compressed_pair_elem                                                                                                                                                             <std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basi                                                                                                                                                             c_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__                                                                                                                                                             1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >                                                                                                                                                             , void*> >, 1, true>> = {<std::__1::allocator<std::__1::__tree_node<std::__1::__                                                                                                                                                             value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::a                                                                                                                                                             --Type <RET> for more, q to quit, c to continue without paging--
llocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void*> >> = {<std::__1::__non_trivial_if<true, std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void*> > >> = {<No data fields>}, <No data fields>}, <No data fields>}, <No data fields>}, __pair3_ = {<std::__1::__compressed_pair_elem<unsigned long, 0, false>> = {
                  __value_ = 16}, <std::__1::__compressed_pair_elem<std::__1::__map_value_compare<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, 1, true>> = {<std::__1::__map_value_compare<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>> = {<std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >> = {<std::__1::__binary_function_keep_layout_base<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool>> = {<No data fields>}, <No data fields>}, <No data fields>}, <No data fields>}, <No data fields>}}}}
        poller = {<CNetBase> = {_vptr$CNetBase = 0x21ad28 <vtable for CNetPoller+16>, static m_fdWatcher = 0x305c305c305c305c}, <singleton<CNetPoller>> = {_vptr$singleton = 0x21ad48 <vtable for CNetPoller+48>,
            static ms_singleton = 0x305c305c305c305c}, <No data fields>}
        DBManager = {<singleton<CDBManager>> = {_vptr$singleton = 0x21a340 <vtable for CDBManager+16>, static ms_singleton = 0x821015df8}, m_mainSQL = {0x22c96a69e00, 0x22c96a6b300, 0x22c96a6c800, 0x22c96a6dd00}, m_directSQL = {
            0x22c96a69000, 0x22c96a6ac00, 0x22c96a6c100, 0x22c96a6d600}, m_asyncSQL = {0x22c96a6a500, 0x22c96a6ba00, 0x22c96a6cf00, 0x22c96a6e400}, m_quit = 553738056}
        ClientManager = {<CNetBase> = {_vptr$CNetBase = 0x219920 <vtable for CClientManager+16>, static m_fdWatcher = 0x305c305c305c305c}, <singleton<CClientManager>> = {_vptr$singleton = 0x219940 <vtable for CClientManager+48>,
            static ms_singleton = 0x821015aa8}, m_looping = 1, m_fdAccept = 18, m_peerList = Python Exception <class 'gdb.error'>: No type named CClientManager::TPeerList::__node_pointer.
{<std::__1::__list_imp<CPeer*, std::__1::allocator<CPeer*> >> = {__end_ = {__prev_ = 0x22c984000a0, __next_ = 0x22c984000c0},
              __size_alloc_ = {<std::__1::__compressed_pair_elem<unsigned long, 0, false>> = {
                  __value_ = 4}, <std::__1::__compressed_pair_elem<std::__1::allocator<std::__1::__list_node<CPeer*, void*> >, 1, true>> = {<std::__1::allocator<std::__1::__list_node<CPeer*, void*> >> = {<std::__1::__non_trivial_if<true, std::__1::allocator<std::__1::__list_node<CPeer*, void*> > >> = {<No data fields>}, <No data fields>}, <No data fields>}, <No data fields>}}, <No data fields>}, m_pkAuthPeer = 0x22c96a24780,
          m_map_pkLoginData = std::unordered_map with 1 element = {[776244856] = 0x22c96a55a80}, m_map_pkLoginDataByLogin = std::unordered_map with 1 element = {["admin2"] = 0x22c96a55a80},
          m_map_pkLoginDataByAID = std::unordered_map with 1 element = {[3] = 0x22c96a55a80}, m_map_kLogonAccount = std::unordered_map with 1 element = {["admin2"] = 0x22c96a55a80}, m_iPlayerIDStart = 100,
          m_iPlayerDeleteLevelLimit = 70, m_iPlayerDeleteLevelLimitLower = 0, m_bChinaEventServer = false, m_vec_mobTable = std::vector of length 1334 = {{<SEntityTable> = {dwVnum = 101}, szName = "??", '\000' <repeats 22 times>,
              szLocaleName = "Wild Dog", '\000' <repeats 16 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 0 '\000', bLevel = 1 '\001', bSize = 0 '\000', dwGoldMin = 18, dwGoldMax = 27, dwExp = 15, dwMaxHP = 126,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 4, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 3 '\003', bDex = 6 '\006', bCon = 5 '\005', bInt = 2 '\002', dwDamageRange = {20, 24}, sAttackSpeed = 100,
              sMovingSpeed = 100, bAggresiveHPPct = 0 '\000', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 0, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "stray_dog", '\000' <repeats 55 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 102}, szName = "??", '\000' <repeats 22 times>,
              szLocaleName = "Wolf", '\000' <repeats 20 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 0 '\000', bLevel = 3 '\003', bSize = 0 '\000', dwGoldMin = 23, dwGoldMax = 34, dwExp = 39, dwMaxHP = 162,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 6, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 4 '\004', bDex = 9 '\t', bCon = 7 '\a', bInt = 2 '\002', dwDamageRange = {23, 28}, sAttackSpeed = 100,
              sMovingSpeed = 100, bAggresiveHPPct = 25 '\031', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30028, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 103}, szName = "????", '\000' <repeats 20 times>,
              szLocaleName = "Alpha Wolf", '\000' <repeats 14 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 0 '\000', bLevel = 4 '\004', bSize = 0 '\000', dwGoldMin = 25, dwGoldMax = 38, dwExp = 51, dwMaxHP = 182,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 7, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 8 '\b', bDex = 5 '\005', bCon = 10 '\n', bInt = 3 '\003', dwDamageRange = {25, 30}, sAttackSpeed = 100,
              sMovingSpeed = 130, bAggresiveHPPct = 25 '\031', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30069, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 104}, szName = "????", '\000' <repeats 20 times>,
              szLocaleName = "Blue Wolf", '\000' <repeats 15 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 0 '\000', bLevel = 6 '\006', bSize = 0 '\000', dwGoldMin = 30, dwGoldMax = 45, dwExp = 75, dwMaxHP = 225,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 9, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 9 '\t', bDex = 12 '\f', bCon = 6 '\006', bInt = 3 '\003', dwDamageRange = {25, 38}, sAttackSpeed = 100,
              sMovingSpeed = 100, bAggresiveHPPct = 25 '\031', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 0, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 105}, szName = "?? ????", '\000' <repeats 17 times>,
              szLocaleName = "Alpha Blue Wolf\000\000\000\000\000\000\000\000\000", bType = 0 '\000', bRank = 0 '\000', bBattleType = 0 '\000', bLevel = 9 '\t', bSize = 0 '\000', dwGoldMin = 37, dwGoldMax = 56, dwExp = 111,
              dwMaxHP = 297, bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 13, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 14 '\016', bDex = 8 '\b', bCon = 16 '\020', bInt = 4 '\004', dwDamageRange = {33, 41},
              sAttackSpeed = 80, sMovingSpeed = 100, bAggresiveHPPct = 25 '\031', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000",
              dwResurrectionVnum = 0, dwDropItemVnum = 30027, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0,
              dwMobColor = 0, dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 106}, szName = "????", '\000' <repeats 20 times>,
              szLocaleName = "Grey Wolf", '\000' <repeats 15 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 0 '\000', bLevel = 13 '\r', bSize = 0 '\000', dwGoldMin = 47, dwGoldMax = 70, dwExp = 159, dwMaxHP = 412,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 17, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 21 '\025', bDex = 21 '\025', bCon = 10 '\n', bInt = 5 '\005', dwDamageRange = {40, 49}, sAttackSpeed = 100,
              sMovingSpeed = 100, bAggresiveHPPct = 25 '\031', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30070, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 107}, szName = "?? ????", '\000' <repeats 17 times>,
              szLocaleName = "Alpha Grey Wolf\000\000\000\000\000\000\000\000\000", bType = 0 '\000', bRank = 1 '\001', bBattleType = 0 '\000', bLevel = 16 '\020', bSize = 0 '\000', dwGoldMin = 80, dwGoldMax = 120, dwExp = 234,
              dwMaxHP = 614, bRegenCycle = 6 '\006', bRegenPercent = 12 '\f', wDef = 20, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 23 '\027', bDex = 24 '\030', bCon = 12 '\f', bInt = 6 '\006', dwDamageRange = {45, 55},
              sAttackSpeed = 80, sMovingSpeed = 130, bAggresiveHPPct = 25 '\031', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\005", cResists = "\000\000\000\000\000\000\000\000\000\000",
              dwResurrectionVnum = 0, dwDropItemVnum = 0, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>, fDamMultiply = 1.39999998, dwSummonVnum = 0, dwDrainSP = 0,
--Type <RET> for more, q to quit, c to continue without paging--
              dwMobColor = 0, dwPolymorphItemVnum = 70105, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 108}, szName = "???", '\000' <repeats 21 times>,
              szLocaleName = "Wild Boar", '\000' <repeats 15 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 0 '\000', bLevel = 7 '\a', bSize = 0 '\000', dwGoldMin = 32, dwGoldMax = 49, dwExp = 87, dwMaxHP = 248,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 11, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 14 '\016', bDex = 7 '\a', bCon = 10 '\n', bInt = 3 '\003', dwDamageRange = {30, 37}, sAttackSpeed = 80,
              sMovingSpeed = 100, bAggresiveHPPct = 30 '\036', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\005", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30004, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wild_boar", '\000' <repeats 55 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 109}, szName = "?? ???", '\000' <repeats 18 times>,
              szLocaleName = "Red Wild Boar", '\000' <repeats 11 times>, bType = 0 '\000', bRank = 1 '\001', bBattleType = 0 '\000', bLevel = 10 '\n', bSize = 0 '\000', dwGoldMin = 56, dwGoldMax = 84, dwExp = 148, dwMaxHP = 389,
              bRegenCycle = 3 '\003', bRegenPercent = 7 '\a', wDef = 14, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 22 '\026', bDex = 9 '\t', bCon = 13 '\r', bInt = 4 '\004', dwDamageRange = {35, 43}, sAttackSpeed = 80,
              sMovingSpeed = 100, bAggresiveHPPct = 30 '\036', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\005", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30003, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wild_boar", '\000' <repeats 55 times>, fDamMultiply = 1.39999998, dwSummonVnum = 0, dwDrainSP = 0,
              dwMobColor = 0, dwPolymorphItemVnum = 70105, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 110}, szName = "?", '\000' <repeats 23 times>,
              szLocaleName = "Bear", '\000' <repeats 20 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 4 '\004', bLevel = 12 '\f', bSize = 0 '\000', dwGoldMin = 44, dwGoldMax = 67, dwExp = 147, dwMaxHP = 381,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 16, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 20 '\024', bDex = 10 '\n', bCon = 20 '\024', bInt = 5 '\005', dwDamageRange = {39, 47}, sAttackSpeed = 100,
              sMovingSpeed = 70, bAggresiveHPPct = 40 '(', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30010, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "bear", '\000' <repeats 60 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 111}, szName = "???", '\000' <repeats 21 times>,
              szLocaleName = "Grizzly Bear", '\000' <repeats 12 times>, bType = 0 '\000', bRank = 1 '\001', bBattleType = 5 '\005', bLevel = 15 '\017', bSize = 0 '\000', dwGoldMin = 76, dwGoldMax = 114, dwExp = 220, dwMaxHP = 572,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 19, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 14 '\016', bDex = 17 '\021', bCon = 34 '"', bInt = 6 '\006', dwDamageRange = {44, 53}, sAttackSpeed = 100,
              sMovingSpeed = 100, bAggresiveHPPct = 40 '(', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30071, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "bear", '\000' <repeats 60 times>, fDamMultiply = 1.39999998, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70105, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 112}, szName = "???", '\000' <repeats 21 times>,
              szLocaleName = "Black Bear", '\000' <repeats 14 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 4 '\004', bLevel = 19 '\023', bSize = 0 '\000', dwGoldMin = 61, dwGoldMax = 92, dwExp = 385, dwMaxHP = 624,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 24, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 36 '$', bDex = 14 '\016', bCon = 21 '\025', bInt = 7 '\a', dwDamageRange = {50, 62}, sAttackSpeed = 100,
              sMovingSpeed = 100, bAggresiveHPPct = 40 '(', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30053, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "bear", '\000' <repeats 60 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 113}, szName = "??", '\000' <repeats 22 times>,
              szLocaleName = "Brown Bear", '\000' <repeats 14 times>, bType = 0 '\000', bRank = 1 '\001', bBattleType = 4 '\004', bLevel = 21 '\025', bSize = 0 '\000', dwGoldMin = 100, dwGoldMax = 150, dwExp = 510, dwMaxHP = 845,
              bRegenCycle = 6 '\006', bRegenPercent = 12 '\f', wDef = 26, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 35 '#', bDex = 15 '\017', bCon = 23 '\027', bInt = 8 '\b', dwDamageRange = {54, 66}, sAttackSpeed = 100,
              sMovingSpeed = 100, bAggresiveHPPct = 40 '(', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30072, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "bear", '\000' <repeats 60 times>, fDamMultiply = 1.39999998, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70105, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 114}, szName = "???", '\000' <repeats 21 times>,
              szLocaleName = "Tiger", '\000' <repeats 19 times>, bType = 0 '\000', bRank = 0 '\000', bBattleType = 4 '\004', bLevel = 18 '\022', bSize = 0 '\000', dwGoldMin = 59, dwGoldMax = 88, dwExp = 365, dwMaxHP = 585,
              bRegenCycle = 6 '\006', bRegenPercent = 12 '\f', wDef = 22, dwAIFlag = 0, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 18 '\022', bDex = 20 '\024', bCon = 27 '\033', bInt = 7 '\a', dwDamageRange = {49, 60},
              sAttackSpeed = 100, sMovingSpeed = 100, bAggresiveHPPct = 50 '2', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000",
              dwResurrectionVnum = 0, dwDropItemVnum = 30038, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "tiger", '\000' <repeats 59 times>, fDamMultiply = 1, dwSummonVnum = 0, dwDrainSP = 0,
              dwMobColor = 0, dwPolymorphItemVnum = 70104, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 115}, szName = "??", '\000' <repeats 22 times>,
              szLocaleName = "White Tiger", '\000' <repeats 13 times>, bType = 0 '\000', bRank = 1 '\001', bBattleType = 4 '\004', bLevel = 24 '\030', bSize = 0 '\000', dwGoldMin = 112, dwGoldMax = 168, dwExp = 582, dwMaxHP = 1007,
              bRegenCycle = 10 '\n', bRegenPercent = 22 '\026', wDef = 29, dwAIFlag = 1, dwRaceFlag = 1, dwImmuneFlag = 0, bStr = 25 '\031', bDex = 17 '\021', bCon = 45 '-', bInt = 9 '\t', dwDamageRange = {59, 72}, sAttackSpeed = 100,
              sMovingSpeed = 130, bAggresiveHPPct = 50 '2', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\000\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30023, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "tiger", '\000' <repeats 59 times>, fDamMultiply = 1.39999998, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 0,
              dwPolymorphItemVnum = 70105, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}},
              bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 131}, szName = "???? ??", '\000' <repeats 17 times>,
              szLocaleName = "Cursed Wolf", '\000' <repeats 13 times>, bType = 0 '\000', bRank = 2 '\002', bBattleType = 0 '\000', bLevel = 8 '\b', bSize = 0 '\000', dwGoldMin = 60, dwGoldMax = 91, dwExp = 198, dwMaxHP = 435,
              bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 12, dwAIFlag = 1, dwRaceFlag = 1, dwImmuneFlag = 8, bStr = 16 '\020', bDex = 16 '\020', bCon = 31 '\037', bInt = 8 '\b', dwDamageRange = {32, 39}, sAttackSpeed = 100,
              sMovingSpeed = 120, bAggresiveHPPct = 100 'd', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\n\000\000\000\000", cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0,
              dwDropItemVnum = 30028, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>, fDamMultiply = 1.79999995, dwSummonVnum = 0, dwDrainSP = 0,
              dwMobColor = 16764159, dwPolymorphItemVnum = 70106, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0,
                  bLevel = 0 '\000'}}, bBerserkPoint = 0 '\000', bStoneSkinPoint = 0 '\000', bGodSpeedPoint = 0 '\000', bDeathBlowPoint = 0 '\000', bRevivePoint = 0 '\000'}, {<SEntityTable> = {dwVnum = 132},
              szName = "???? ????", '\000' <repeats 15 times>, szLocaleName = "Cursed Alpha Wolf\000\000\000\000\000\000\000", bType = 0 '\000', bRank = 3 '\003', bBattleType = 0 '\000', bLevel = 9 '\t', bSize = 0 '\000',
              dwGoldMin = 80, dwGoldMax = 121, dwExp = 444, dwMaxHP = 743, bRegenCycle = 6 '\006', bRegenPercent = 7 '\a', wDef = 13, dwAIFlag = 1, dwRaceFlag = 1, dwImmuneFlag = 8, bStr = 23 '\027', bDex = 24 '\030', bCon = 31 '\037',
              bInt = 8 '\b', dwDamageRange = {33, 41}, sAttackSpeed = 100, sMovingSpeed = 120, bAggresiveHPPct = 100 'd', wAggressiveSight = 2000, wAttackRange = 175, cEnchants = "\n\000\000\000\000",
              cResists = "\000\000\000\000\000\000\000\000\000\000", dwResurrectionVnum = 0, dwDropItemVnum = 30069, bMountCapacity = 0 '\000', bOnClickType = 0 '\000', bEmpire = 0 '\000', szFolder = "wolf", '\000' <repeats 60 times>,
              fDamMultiply = 2, dwSummonVnum = 0, dwDrainSP = 0, dwMobColor = 16764159, dwPolymorphItemVnum = 70107, Skills = {{dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {dwVnum = 0, bLevel = 0 '\000'}, {
--Type <RET> for more, q to quit, c to continue without paging--
...

 

Let me know if you need me to try and get the entire thing cause this output is normally huge and cannot fit into the terminal from start to end.

In db/ClientManagerPlayer.cpp - CClientManager::__QUERY_PLAYER_CREATE

 

replace 

 

static char text[4096 + 1];

 

with 

 

static char text[8192 + 1];

It is somewhere at the bottom. It must be a buffer overflow in __QUERY_PLAYER_CREATE

Compile and let me know if it did the trick for you.

Edited by tw1x1
  • Metin2 Dev 1
  • Active+ Member
16 hours ago, tw1x1 said:

In db/ClientManagerPlayer.cpp - CClientManager::__QUERY_PLAYER_CREATE

 

replace 

 

static char text[4096 + 1];

 

with 

 

static char text[8192 + 1];

It is somewhere at the bottom. It must be a buffer overflow in __QUERY_PLAYER_CREATE

Compile and let me know if it did the trick for you.

That was the solution thank you and thanks for everyone's help so far 🙏

These files have a lot of bugs so far but I really like the way @ Distraught has structured and updated them so I'm gonna do my best in improving them.

I have already PR'ed an initial batch of fixes for all repos in my Github under a custom branch (not main) and they are all available for download and testing.

The query length fix will be included in my next batch of updates along with some more stuff that I have/intend to fix such as

  • Negative HP when dying
  • Motion not found for the Bodyguard in Cape map
  • A tool to extract untranslated strings from the source compared against locale_string.txt along with the missing values added and translated by me (English only)
  • Messenger not auto-updating for companion when getting deleted by someone in their friends list
  • Other stuff that I find

And yeah I know some of that stuff used to exist in Ymir's files when it was on that stage, but some people may find these useful.

If yall wanna test these files together please download them and install them (either the official main branch from the initial post of this topic or my custom branches) and perform any kind of test you want. If you find something please let us know here with as much information as possible such as:

  • Client syserr/ErrorLog
  • Channel cores syserr (check all 3 cores each time)
  • DB syserr
  • GDB results from core files
  • Screenshots, gifs, short videos, anything to display a visual (upload to https://metin2.download as a media and share the link in your reply here)

Please do not include files or issues with other system implemented. Adding custom systems is beyond the scope of these files and anyone can do it in their own private systems. Plus if we can fix these files adding systems later will be a lot easier for everyone

Let's make these files the most kick ass starting system in here!

  • muscle 1
  • Premium
On 9/23/2025 at 9:28 PM, Helia01 said:

Hidden Content

 

 Here's a guide for those who want to automatically set up a ready-to-use MariaDB for development with all the necessary data.
Create a directory structure:

\---m2dev-db
    |   docker-compose.yml
    |
    +---config
    |       my.cnf
    |
    \---initdb
        |   00-create-user.sql
        |   01-create-dbs.sql
        |   02-import.sh
        |
        \---sql
                account.sql
                common.sql
                hotbackup.sql
                log.sql
                player.sql


db sql files you can currently take from m2dev-server\sql 
Here are the remaining files you don't have yet. Simply create them according to the directory structure description.

m2dev-db\config\my.cnf

[mysqld]
bind-address          = *
sql_mode              = NO_ENGINE_SUBSTITUTION


m2dev-db\initdb\00-create-user.sql

CREATE USER IF NOT EXISTS 'mt2'@'%' IDENTIFIED BY 'mt2@pw';
GRANT ALL PRIVILEGES ON *.* TO 'mt2'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

 

m2dev-db\initdb\01-create-dbs.sql

CREATE DATABASE IF NOT EXISTS account;
CREATE DATABASE IF NOT EXISTS common;
CREATE DATABASE IF NOT EXISTS player;
CREATE DATABASE IF NOT EXISTS log;
CREATE DATABASE IF NOT EXISTS hotbackup;

 

m2dev-db\initdb\02-import.sh

#!/bin/bash
set -euo pipefail

mariadb -uroot -p"${MARIADB_ROOT_PASSWORD}" account < /docker-entrypoint-initdb.d/sql/account.sql
mariadb -uroot -p"${MARIADB_ROOT_PASSWORD}" common  < /docker-entrypoint-initdb.d/sql/common.sql
mariadb -uroot -p"${MARIADB_ROOT_PASSWORD}" player  < /docker-entrypoint-initdb.d/sql/player.sql
mariadb -uroot -p"${MARIADB_ROOT_PASSWORD}" log     < /docker-entrypoint-initdb.d/sql/log.sql
mariadb -uroot -p"${MARIADB_ROOT_PASSWORD}" hotbackup < /docker-entrypoint-initdb.d/sql/hotbackup.sql

 

m2dev-db\docker-compose.yml

services:
  mariadb:
    image: mariadb:10.6
    container_name: mariadb-10_6
    restart: unless-stopped
    ports:
      - "3306:3306"
    environment:
      MARIADB_ROOT_PASSWORD: m2dev
    volumes:
      - ./db_data:/var/lib/mysql
      - ./config/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
      - ./initdb:/docker-entrypoint-initdb.d:ro


Once the directory structure is ready and all the files are in place, you can simply run:
 

cd m2dev-db && docker compose up -d


Para ler os registros dos contêineres, você pode usar:
 

docker compose logs -f mariadb

 

 

Sorry for asking. It might sound funny. Isn't this tutorial for Linux/Docker? Does this font run on Linux?

I’m not sure what I’m doing wrong. The server is running properly, the client isn’t connecting, and there are no errors in the syserr log(Server).

 

#Edit 

[2025-11-16 18:11:09.202] [error] [int pid_init()()] 
Start of pid: 4514

[2025-11-16 18:11:09.208] [error] [int main(int, char **)()] Failed to Load ClientPackageCryptInfo File(package/)
 

Edited by hitwydhitl3r

That error is not the reason why your client wont connect. Make sure you have compiled the source with latest pr’s merged from repo, client / server.

  • Active+ Member
2 hours ago, hitwydhitl3r said:

I’m not sure what I’m doing wrong. The server is running properly, the client isn’t connecting, and there are no errors in the syserr log(Server).

 

#Edit 

[2025-11-16 18:11:09.202] [error] [int pid_init()()] 
Start of pid: 4514

[2025-11-16 18:11:09.208] [error] [int main(int, char **)()] Failed to Load ClientPackageCryptInfo File(package/)
 

Had the same issue you're missing the package folder inside share/data.
Create it manually and then create a sym link in each of the channel cores and auth (all except channels/db) or use my custom install.py script to automate this process.

I've shared the script in a previous comments and it is also available in my custom Github repo branch

1 hour ago, Mind Rapist said:

Had the same issue you're missing the package folder inside share/data.
Create it manually and then create a sym link in each of the channel cores and auth (all except channels/db) or use my custom install.py script to automate this process.

I've shared the script in a previous comments and it is also available in my custom Github repo branch

Thank you! It worked 😄

  • Metin2 Dev 1

Does anyone else have this issue with loading the maps? And there’s another problem with creating characters. When you create one, the database crashes.spacer.pngspacer.png

17 minutes ago, hitwydhitl3r said:

Does anyone else have this issue with loading the maps? And there’s another problem with creating characters. When you create one, the database crashes.spacer.pngspacer.png

Fix for db crash is above and pr’ed on github, the other problem’s fix, is work in progress 😂

 

Edited by tw1x1

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • 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.