Jump to content

One Player per IP in Certain Maps


Recommended Posts

  • Premium

M2 Download Center

This is the hidden content, please
( Internal )

This is the hidden content, please
( GitHub )

If you want to allow only one player per IP in certain maps you can use this :)

Example of usage:

when login with pc.is_pc_ip_in_map() begin
	chat("En este mapa solo puede entrar 1 personaje por IP, serás transportado en 5 segundos.")
	warp_to_village()
end

For add/remove maps, just edit:

		std::map<DWORD, std::map<DWORD, DWORD>> maps = {
			{ 181, {} },
			{ 182, {} },
			{ 183, {} }
		};

In map_manager.h

Implementation:

This is the hidden content, please

Enjoy :)

  • Metin2 Dev 41
  • Cry 1
  • Scream 1
  • Good 13
  • Love 1
  • Love 16
Link to comment
Share on other sites

  • Premium
4 hours ago, jeddawee said:

Thank you so much .. 

 

I which someone can do the same using HWID  

There are 2 players in one house. both with a different pc. One uses a proxy one doesn't. Your HWID check, even if used together with an IP check, becomes useless.

 

There is always a way to bypass the system, Hwid check is not even worth implementing.

  • Love 1

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Forum Moderator

The idea isn't bad (even if we're in 2019 and can be bypassed very easy and have no effects this), but there's some things which can be written in C++11 and a better structure, since your map have empty list initialization (since C++11).

Here's some advices which can help you in future, maybe.

  • Your map have as value type a another std::map, for what? Since you store in key and value the same thing (player id), you should use std::list / std::vector or anything you want, but not a another std::map for no-reason if your key is same as value and no possible changes.
  • You insert all time for each login in a x map the player id, you don't check if already exist and then insert it (you could use std::find/std::map::find), you use make_pair for map and that means the key can't be duplicated, but this isn't a good practice to trying to insert 1000 times and nothing happen.
  • You check if map size is smaller or equal than 0, how can be a map size < 0? 
  • You declared a another map for iterating in a for-loop, you don't need to do that. std::map<DWORD, DWORD> map_players = [....];
  • You use map.at(...), if you use this you should use the std::out_of_range too, otherwise have no sense, because you already did a check before if exist mapIndex by map.count(index), so you can use directly operator std::map::operator[] instead of std::map::at.
  • You declared a std::string with no-reason for GetHostName() -> return a const char *, which you can use strcmp(str1, str2) instead of string.compare(str2).
  • Your key of map should be as constant, because you don't want to change it.
  • You should use also #pragma once for your header file (including: less code, avoidance of name clashes, and sometimes improvement in compilation speed.)
  • You should remove the pid of player after disconnect of the map, have no sense to remain.

PS: If i were in your place, i didn't do the structure like this, it's a bit messed up.

Here's some of things what i said. (didn't tested)

 

  • map_manager.h
Spoiler

#pragma once

class MapManager: public singleton<MapManager>
{
	private:
		std::map<const DWORD, std::list<const DWORD>> m_map_manager = {
			{ 181, {} },
			{ 182, {} },
			{ 183, {} }
		};
		
	public:
		const bool      Initialize();
		void            Clear();
		void            Destroy();

		void            Enter(const LPCHARACTER ch);
		void            Disconnect(const LPCHARACTER ch);

		const size_t    GetIPMapCount(const DWORD dwMapIndex);
		const bool      IsPlayerIPInMap(const LPCHARACTER ch);
		const bool      IsUniqueIPMap(const DWORD dwMapIndex);
};

 

  • map_manager.cpp
Spoiler

#include "stdafx.h"
#include "buffer_manager.h"
#include "char.h"
#include "char_manager.h"
#include "map_manager.h"
#include "desc.h"

void MapManager::Initialize()
{
	Clear();
}

void MapManager::Destroy()
{
	Clear();
}

// Removes all elements from the map container (which are destroyed), leaving the container with a size of 0.
void MapManager::Clear()
{
	for (auto iter = m_map_manager.begin(); iter != m_map_manager.end(); ++iter)
		iter->second.clear();
}

// Count elements with a specific key, return 1 (if the element is found) or zero (otherwise).
const bool MapManager::IsUniqueIPMap(const DWORD dwMapIndex)
{
	return m_map_manager.count(dwMapIndex) != 0;
}

// Returns the number of elements in the map container.
const size_t MapManager::GetIPMapCount(const DWORD dwMapIndex)
{
	return (m_map_manager[dwMapIndex]).size();
}

/*
char.cpp : #include "map_manager.h"
	marriage::CManager::instance().Logout(this);
	+ MapManager::instance().Disconnect(this);
*/
void MapManager::Disconnect(const LPCHARACTER ch)
{
	if (!ch)
		return;

	const DWORD dwMapIndex = ch->GetMapIndex();	
	if (!IsUniqueIPMap(dwMapIndex))
		return;

	// Remove the player id from map list if exist.
	const auto it = std::find(m_map_manager[dwMapIndex].begin(), m_map_manager[dwMapIndex].end(), ch->GetPlayerID());
	if (it != m_map_manager[dwMapIndex].end())
		m_map_manager[dwMapIndex].erase(it);
}

void MapManager::Enter(const LPCHARACTER ch)
{
	if (!ch)
		return;
	
	const DWORD dwPID = ch->GetPlayerID();
	const DWORD dwMapIndex = ch->GetMapIndex();

	if (!IsUniqueIPMap(dwMapIndex))
		return;

	// Return iterator to the first element satisfying the condition or last if no such element is found.
	const auto it = std::find(m_map_manager[dwMapIndex].begin(), m_map_manager[dwMapIndex].end(), dwPID);

	// If no element is found in the map, find() returns map.end().
	if (it != m_map_manager[dwMapIndex].end())
		return;

	// Add the player id into map list.
	m_map_manager[dwMapIndex].emplace_back(dwPID);
}

const bool MapManager::IsPlayerIPInMap(const LPCHARACTER ch)
{	
	if (!ch)
		return false;

	if (!IsUniqueIPMap(ch->GetMapIndex()))
		return false;

	if (GetIPMapCount() == 0)
		return false;

	LPCHARACTER pkChar = NULL;
	// Range-based for loop, iterating the std::list with player pids.
	for (const auto dwPID : m_map_manager[ch->GetMapIndex()])
	{
		if (!(pkChar = CHARACTER_MANAGER::instance().FindByPID(dwPID)))
			continue;

		if (!strcmp(ch->GetDesc()->GetHostName(), pkChar->GetDesc()->GetHostName()) && ch->GetPlayerID() != pkChar->GetPlayerID())
			return true;
	}
	
	return false;
}

 

BTW: Sorry for my english skills.

  • Metin2 Dev 8
  • Angry 1
  • Smile Tear 1
  • Good 4
  • Love 8
Link to comment
Share on other sites

21 hours ago, Syreldar said:

There are 2 players in one house. both with a different pc. One uses a proxy one doesn't. Your HWID check, even if used together with an IP check, becomes useless.

 

There is always a way to bypass the system, Hwid check is not even worth implementing.

the ip check  can bypass easily using proxy as you said , but hwid is not familiar for normal players and i don't care if he used another pc :) 

 

Link to comment
Share on other sites

  • Premium
En 29/3/2019 a las 22:46, VegaS™ dijo:

The idea isn't bad (even if we're in 2019 and can be bypassed very easy and have no effects this), but there's some things which can be written in C++11 and a better structure, since your map have empty list initialization (since C++11).

Here's some advices which can help you in future, maybe.

  • Your map have as value type a another std::map, for what? Since you store in key and value the same thing (player id), you should use std::list / std::vector or anything you want, but not a another std::map for no-reason if your key is same as value and no possible changes.
  • You insert all time for each login in a x map the player id, you don't check if already exist and then insert it (you could use std::find/std::map::find), you use make_pair for map and that means the key can't be duplicated, but this isn't a good practice to trying to insert 1000 times and nothing happen.
  • You check if map size is smaller or equal than 0, how can be a map size < 0? 
  • You declared a another map for iterating in a for-loop, you don't need to do that. std::map<DWORD, DWORD> map_players = [....];
  • You use map.at(...), if you use this you should use the std::out_of_range too, otherwise have no sense, because you already did a check before if exist mapIndex by map.count(index), so you can use directly operator std::map::operator[] instead of std::map::at.
  • You declared a std::string with no-reason for GetHostName() -> return a const char *, which you can use strcmp(str1, str2) instead of string.compare(str2).
  • Your key of map should be as constant, because you don't want to change it.
  • You should use also #pragma once for your header file (including: less code, avoidance of name clashes, and sometimes improvement in compilation speed.)
  • You should remove the pid of player after disconnect of the map, have no sense to remain.

PS: If i were in your place, i didn't do the structure like this, it's a bit messed up.

Here's some of things what i said. (didn't tested)

 

  • map_manager.h
  Reveal hidden contents


#pragma once

class MapManager: public singleton<MapManager>
{
	private:
		std::map<const DWORD, std::list<const DWORD>> m_map_manager = {
			{ 181, {} },
			{ 182, {} },
			{ 183, {} }
		};
		
	public:
		const bool      Initialize();
		void            Clear();
		void            Destroy();

		void            Enter(const LPCHARACTER ch);
		void            Disconnect(const LPCHARACTER ch);

		const size_t    GetIPMapCount(const DWORD dwMapIndex);
		const bool      IsPlayerIPInMap(const LPCHARACTER ch);
		const bool      IsUniqueIPMap(const DWORD dwMapIndex);
};

 

  • map_manager.cpp
  Reveal hidden contents


#include "stdafx.h"
#include "buffer_manager.h"
#include "char.h"
#include "char_manager.h"
#include "map_manager.h"
#include "desc.h"

void MapManager::Initialize()
{
	Clear();
}

void MapManager::Destroy()
{
	Clear();
}

// Removes all elements from the map container (which are destroyed), leaving the container with a size of 0.
void MapManager::Clear()
{
	for (auto iter = m_map_manager.begin(); iter != m_map_manager.end(); ++iter)
		iter->second.clear();
}

// Count elements with a specific key, return 1 (if the element is found) or zero (otherwise).
const bool MapManager::IsUniqueIPMap(const DWORD dwMapIndex)
{
	return m_map_manager.count(dwMapIndex) != 0;
}

// Returns the number of elements in the map container.
const size_t MapManager::GetIPMapCount(const DWORD dwMapIndex)
{
	return (m_map_manager[dwMapIndex]).size();
}

/*
char.cpp : #include "map_manager.h"
	marriage::CManager::instance().Logout(this);
	+ MapManager::instance().Disconnect(this);
*/
void MapManager::Disconnect(const LPCHARACTER ch)
{
	if (!ch)
		return;

	const DWORD dwMapIndex = ch->GetMapIndex();	
	if (!IsUniqueIPMap(dwMapIndex))
		return;

	// Remove the player id from map list if exist.
	const auto it = std::find(m_map_manager[dwMapIndex].begin(), m_map_manager[dwMapIndex].end(), ch->GetPlayerID());
	if (it != m_map_manager[dwMapIndex].end())
		m_map_manager[dwMapIndex].erase(it);
}

void MapManager::Enter(const LPCHARACTER ch)
{
	if (!ch)
		return;
	
	const DWORD dwPID = ch->GetPlayerID();
	const DWORD dwMapIndex = ch->GetMapIndex();

	if (!IsUniqueIPMap(dwMapIndex))
		return;

	// Return iterator to the first element satisfying the condition or last if no such element is found.
	const auto it = std::find(m_map_manager[dwMapIndex].begin(), m_map_manager[dwMapIndex].end(), dwPID);

	// If no element is found in the map, find() returns map.end().
	if (it != m_map_manager[dwMapIndex].end())
		return;

	// Add the player id into map list.
	m_map_manager[dwMapIndex].emplace_back(dwPID);
}

const bool MapManager::IsPlayerIPInMap(const LPCHARACTER ch)
{	
	if (!ch)
		return false;

	if (!IsUniqueIPMap(ch->GetMapIndex()))
		return false;

	if (GetIPMapCount() == 0)
		return false;

	LPCHARACTER pkChar = NULL;
	// Range-based for loop, iterating the std::list with player pids.
	for (const auto dwPID : m_map_manager[ch->GetMapIndex()])
	{
		if (!(pkChar = CHARACTER_MANAGER::instance().FindByPID(dwPID)))
			continue;

		if (!strcmp(ch->GetDesc()->GetHostName(), pkChar->GetDesc()->GetHostName()) && ch->GetPlayerID() != pkChar->GetPlayerID())
			return true;
	}
	
	return false;
}

 

BTW: Sorry for my english skills.

Thanks for your tips, I will keep improving :)

  • Good 1
Link to comment
Share on other sites

  • 6 months later...

Announcements



×
×
  • Create New...

Important Information

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