Jump to content

Get Total Users Online


Recommended Posts

  • VIP

This is a simple (and probably unwanted) tutorial that will give you all the online players for each core, including the auth
We might argue about whether being in the select character phase is really in-game, but we will include it anyway

 

Why?

The /u and /w commands only provide data from the channel where the player is
Since I needed absolute values - as soon as someone logs in - I went searching in the source and came across the GetUserCount() function

mlGc5jM.png

I had 3 players in separated channels (auth, 1 and 99 respectively)
I used the commands above and lastly the new one we are going to create

 

Explanation?

The function returns (in type DWORD) the size of m_map_kLogonAccount
It is a map that stores the login values with class CLoginData
It is also responsible for storing the values of the players online every 1h in usage.txt
It is given an insert in the map every login a player makes through the boolean function InsertLogonAccount()

What we're going to do is requesting the data from GetUserCount() and show it.

 

Installing

 

DB

 

ClientManager.cpp:

Search for:

				//RELOAD_ADMIN
			case HEADER_GD_RELOAD_ADMIN:
				ReloadAdmin(peer, (TPacketReloadAdmin*)data);
				break;
				//END_RELOAD_ADMIN

Add below:

			case HEADER_GD_REQ_USER_COUNT:
				RequestUserCount(dwHandle);
				break;

Search for:

void CClientManager::ReloadAdmin(CPeer*, TPacketReloadAdmin* p)
{
  ....
}

Add below:

void CClientManager::RequestUserCount(DWORD dwHandle)
{
	for (TPeerList::const_iterator it = m_peerList.begin(); it != m_peerList.end(); ++it)
	{
		CPeer* peer = *it;

		if (!peer->GetChannel())
			continue;

		TPacketDGUserCount Info;
		peer->EncodeHeader(HEADER_DG_RET_USER_COUNT, dwHandle, sizeof(TPacketDGUserCount));
		Info.user = GetUserCount();
		peer->Encode(&Info, sizeof(TPacketDGUserCount));
	}
}

 

ClientManager.h:

Search for:

	//RELOAD_ADMIN
	void ReloadAdmin(CPeer * peer, TPacketReloadAdmin * p);
	//END_RELOAD_ADMIN

Add below:

	void RequestUserCount(DWORD dwHandle);

 

Common

tables.h:

Search for:

	HEADER_DG_RESPOND_CHANNELSTATUS		= 181,

Add below:

	HEADER_GD_REQ_USER_COUNT = 141,
	HEADER_DG_RET_USER_COUNT = 182,

Search for:

typedef struct SPacketDGChangeEmpirePriv
{
	BYTE type;
	int value;
	BYTE empire;
	BYTE bLog;
	time_t end_time_sec;
} TPacketDGChangeEmpirePriv;

Add below:

typedef struct SPacketDGUserCount
{
	DWORD user;
} TPacketDGUserCount;

 

Game

cmd_gm.cpp:

Search for:

				//RELOAD_ADMIN
			case 'a':
				ch->ChatPacket(CHAT_TYPE_INFO, "Reloading Admin infomation.");
				db_clientdesc->DBPacket(HEADER_GD_RELOAD_ADMIN, 0, NULL, 0);
				sys_log(0, "Reloading admin infomation.");
				break;
				//END_RELOAD_ADMIN

Add below:

			case 'y':
				ch->ChatPacket(CHAT_TYPE_INFO, "Requesting total users.");
				db_clientdesc->DBPacket(HEADER_GD_REQ_USER_COUNT, ch->GetDesc()->GetHandle(), NULL, 0);
				break;

 

input.cpp:

Search for:

							case 'a':
								db_clientdesc->DBPacket(HEADER_GD_RELOAD_ADMIN, 0, NULL, 0);
								sys_log(0, "Reloading admin infomation.");
								break;

Add below:

							case 'y':
								db_clientdesc->DBPacket(HEADER_GD_REQ_USER_COUNT, d->GetHandle(), NULL, 0);
								sys_log(0, "Reloading user count.");
								break;

 

input.h:

Search for:

	//RELOAD_ADMIN
	void ReloadAdmin( const char * c_pData );
	//END_RELOAD_ADMIN

Add below:

	void		UserCount(LPDESC d, const TPacketDGUserCount* p);

 

input_db.cpp:

Search for:

// MYSHOP_PRICE_LIST
void CInputDB::MyshopPricelistRes(LPDESC d, const TPacketMyshopPricelistHeader* p )
{
	LPCHARACTER ch;

	if (!d || !(ch = d->GetCharacter()) )
		return;

	sys_log(0, "RecvMyshopPricelistRes name[%s]", ch->GetName());
	ch->UseSilkBotaryReal(p );

}
// END_OF_MYSHOP_PRICE_LIST

Add below:

void CInputDB::UserCount(LPDESC d, const TPacketDGUserCount* p)
{
	sys_err("ADMIN WHISPER: USERCOUNT");

	LPCHARACTER ch;

	if (!d || !(ch = d->GetCharacter()))
		return;

	ch->ChatPacket(CHAT_TYPE_PARTY, "PLAYERS: %d", p->user);
}

Search for:

	// RELOAD_ADMIN
	case HEADER_DG_RELOAD_ADMIN:
		ReloadAdmin(c_pData );		
		break;
	//END_RELOAD_ADMIN

Add below:

	case HEADER_DG_RET_USER_COUNT:
		UserCount(DESC_MANAGER::instance().FindByHandle(m_dwHandle), (TPacketDGUserCount*)c_pData);
		break;

 

Usage
The usage is /reload y

 

  • Love 5
  • Think 1
Link to post
  • VIP
14 minutes ago, JinxTheLux said:

Don't you think it's okay when the number of players is high?

The system isn't requesting anything new, the GetUserCount() already exists and only returns the size from m_map_kLogonAccount, so I think it will be fine even if you have 30.000 players online.

Link to post
26 minutes ago, msnas said:

The system isn't requesting anything new, the GetUserCount() already exists and only returns the size from m_map_kLogonAccount, so I think it will be fine even if you have 30.000 players online.

Yes, I guess you are right, reload commands have always been a problem in active game, so I wanted to get your opinion. It shows +1 total players I can't understand about the system, do you know why?

Link to post
  • VIP
16 hours ago, JinxTheLux said:

Yes, I guess you are right, reload commands have always been a problem in active game, so I wanted to get your opinion. It shows +1 total players I can't understand about the system, do you know why?

mlGc5jM.png

 

  • Total [1] 0 / 0 / 1 (this server 1) -> /w command 
  • Testing Total 1 -> /u command
  • Requesting total users. PLAYERS: 3 -> /reload y command, this is what the system is all about.
Link to post
9 minutes ago, msnas said:

mlGc5jM.png

 

  • Total [1] 0 / 0 / 1 (this server 1) -> /w command 
  • Testing Total 1 -> /u command
  • Requesting total users. PLAYERS: 3 -> /reload y command, this is what the system is all about.

I understand, but it shows the total number of players over +1, for example if there is 1 player it shows 2 players, if there are 2 players it shows 3, do you know why? I did everything as in the narration

Link to post
  • VIP
Posted (edited)
(
//cmd.cpp
//Search
struct command_info cmd_info[] =

//Add Before
ACMD(do_online);

//Search	
	{ "\n", NULL, 0, POS_DEAD, GM_IMPLEMENTOR }
//Add Before
	{ "online", do_online, 0, POS_DEAD, GM_LOW_WIZARD },
)

(
//cmd_gm.cpp
//Search
ACMD(do_who)

//Add After
ACMD(do_online)
{
	/// Phase 1 - Count Local Core
	const DESC_MANAGER::DESC_SET& c_set_desc = DESC_MANAGER::instance().GetClientSet();
	DESC_MANAGER::DESC_SET::const_iterator it = c_set_desc.begin();

	DWORD dwLoginCount = 0;
	while (it != c_set_desc.end())
	{
		LPDESC d = *(it++);
		if (d->GetCharacter())
			++dwLoginCount; // count login count in core
	}
	/// Phase 2 - Count Peer PID Connections
	dwLoginCount = dwLoginCount + (int)P2P_MANAGER::instance().GetPIDCount();

	ch->ChatPacket(CHAT_TYPE_INFO, "Total Online: [%d] ", dwLoginCount);
}
)

(
//p2p.h
//Search
  	int GetCount();
//Add after
	int GetPIDCount() { return m_map_pkCCI.size(); };
)
 

 

252051BlueInfo.pngBetter than to involve a packet request..

 

 

Edited by ⚡FlasH⚡
Added missing function
  • Metin2 Dev 2
  • Love 1
  • Good 1
Link to post
27 minutes ago, ⚡FlasH⚡ said:
(
//cmd.cpp
//Search
struct command_info cmd_info[] =

//Add Before
ACMD(do_online);

//Search	
	{ "\n", NULL, 0, POS_DEAD, GM_IMPLEMENTOR }
//Add Before
	{ "online", do_online, 0, POS_DEAD, GM_LOW_WIZARD },
)

(
//cmd_gm.cpp
//Search
ACMD(do_who)

//Add After
ACMD(do_online)
{
	/// Phase 1 - Count Local Core
	const DESC_MANAGER::DESC_SET& c_set_desc = DESC_MANAGER::instance().GetClientSet();
	DESC_MANAGER::DESC_SET::const_iterator it = c_set_desc.begin();

	DWORD dwLoginCount = 0;
	while (it != c_set_desc.end())
	{
		LPDESC d = *(it++);
		if (d->GetCharacter())
			++dwLoginCount; // count login count in core
	}
	/// Phase 2 - Count Peer PID Connections
	dwLoginCount = dwLoginCount + (int)P2P_MANAGER::instance().GetPIDCount();

	ch->ChatPacket(CHAT_TYPE_INFO, "Total Online: [%d] ", dwLoginCount);
}
)
 

 

252051BlueInfo.pngBetter than to involve a packet request..

 

 

 

compiler fails
You must give the GetPIDCount function

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • 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.