Jump to content
Sign in to follow this  
Home

Anti Dupe Method

Recommended Posts

Hi Friends...

    I made this Anti Dupe method, for teleporting ways, let me explain how it works...

 

EXPLANATION

 

PLAYER teleports from Argent City(GS0) to Shaitan City ( GS1) ...

TELEPORTER gives him a GS1 "token"...

 

IF Player arrives to destination GS1 Token is deleted by destination map

ELSE if PLAYER tries to DUPE closing the game before teleporting,then when the player enter the map again the source map will check for the GS1 Token if it's there PLAYER will be automaticaly teleported to DESTINATION MAP, no having time to trade the itens or even droping

 

It worked here on my tests...

 

DEMO Resource with this method - ( ONLY BETWEEN Argent Teleporter and Shaitan Teleporter ) --

http://www.mediafire.com/download/p1u26j4a7vtdvo7/resource(2).rar

 

The modifications are in

GoToWhere function

garner.ctrl

magicsea.ctrl

variables

 

 

... I'll finish it after i take a bath

 

Edited by Home
  • Like 1

Share this post


Link to post
Share on other sites

This is harder than it should be. And a much better way when dealt with src.
If not, use lua. Took almost 1 hour to find this old thing.

Spoiler

	C_dupe = {}
	C_dupe.root = 'C:/PKO1.38/GameServer/'
	C_dupe.path = GetResPath('script/extension/antidupe/')
	C_dupe.hook = { tick = cha_timer }
	C_dupe.file = 'Gameserver.dat'
	C_dupe.db = 'PlayerGS.dat'

	file_exists = file_exists or function(name)
		local f = io.open(name, 'r')
		if(f ~= nil)then io.close(f) return true
		else return false
		end
	end
	
	split = split or function(str, delim, maxNb)
		if string.find(str, delim) == nil then return { str } end
		if maxNb == nil or maxNb < 1 then maxNb = 0 end
		local result = {}
		local pat = "(.-)" .. delim .. "()"
		local nb = 0
		local lastPos
		for part, pos in string.gfind(str, pat) do
			nb = nb + 1
			result[nb] = part
			lastPos = pos
			if nb == maxNb then break end
		end
		if nb ~= maxNb then result[nb + 1] = string.sub(str, lastPos) end
		return result
	end

	FileToArray = FileToArray or function(file)
		local f = io.open(file, "r")
		local arr = {}
		for line in f:lines() do
			table.insert(arr, line)
		end
		return arr
	end
	
	function GetChaKeyID(c)
		local hex,name = '', GetChaDefaultName(c)
		while string.len(name) > 0 do
		local hb = string.format("%X", string.byte(name, 1, 1))
		if string.len(hb) < 2 then 
			hb = '0' .. hb 
		end		
			hex = hex .. hb		
			name = string.sub(name, 2)	
		end	
		return hex
	end
	
	function C_dupe:GetChaKey(c)
		local n = GetChaKeyID(c);
		return n
	end

	function C_dupe:SortGS(j)
		local fp = assert(io.open(C_dupe.root..'Gameserver'..tostring(j)..'.cfg'))
		for line in fp:lines() do
			local p = string.find(line, 'map = ')
			if p == 1 then
				local d = split(line, 'map = ')
				if file_exists(C_dupe.path..C_dupe.file) == false then
					local f = io.open(C_dupe.path..C_dupe.file, 'a')
					table.save({},C_dupe.path..C_dupe.file, 'w')
					f:close()
				end
				local t = table.load(C_dupe.path..C_dupe.file, 'r')
				local rd = d[2]
				local q = string.find(d[2], ' ')
				if q ~= nil then
					q = q - 1
					rd = string.sub(d[2], 1, q)
				end
				if j == '' then j = 0 end
				if t[rd] == nil then
					t[rd] = j
				end
				table.save(t,C_dupe.path..C_dupe.file, 'w')
			end
		end
	end
	
	function C_dupe:StoreGS(n)
		for i = 0, n do
			local a = i
			if a == 0 then a = ''; end
			if file_exists(C_dupe.root..'Gameserver'..tostring(a)..'.cfg') == true then
				C_dupe:SortGS(a)
			end
		end
	end

	if file_exists(C_dupe.path..C_dupe.file) == true then
		os.remove(C_dupe.path..C_dupe.file)
	end
	C_dupe:StoreGS(5);

	function C_dupe:LG(f, text)
		local file = C_dupe.path..f..'.txt'
		if file_exists(file) == false then
			local c = io.open(file, 'a')
			c:close()
		end
		local lf = io.open(file, 'a')
		lf:write('['..os.date()..']\t'..text..'\n')
		lf:close()
	end
	
	function C_dupe.Kick(c)
		local pkt = GetPacket()
		WriteCmd(pkt,1505)
		SendPacket(c,pkt)
	end
	
	function C_dupe:GetChaGS(c)
		local t = table.load(C_dupe.path..C_dupe.file, 'r')
		return t[GetChaMapName(c)]
	end
	
	function C_dupe:GetChaCount()
		local t = table.load(C_dupe.path..C_dupe.db, 'r')
		local a = 0;
		for i,v in pairs(t) do
			a = a + 1;
		end
		return a
	end
	
	function C_dupe.Enter(i, c, m)
		if file_exists(C_dupe.path..C_dupe.db) == false then
			local f = io.open(C_dupe.path..C_dupe.db, 'a')
			table.save({},C_dupe.path..C_dupe.db, 'w')
			f:close()
		end
		local t = table.load(C_dupe.path..C_dupe.db, 'r')
		if t[GetChaKeyID(c)] ~= nil then
			C_dupe:LG('log', 'Player ['..GetChaDefaultName(c)..'] found in Gameserver'..t[GetChaKeyID(c)]..' (Entered map: '..GetChaMapName(c)..')')
			return
			-- C_dupe:Kick(c)
		end
		t[GetChaKeyID(c)] = C_dupe:GetChaGS(c)
		table.save(t, C_dupe.path..C_dupe.db, 'w')
	end
	
	function C_dupe.Leave(i, c)
		local t = table.load(C_dupe.path..C_dupe.db, 'r')
		t[GetChaKeyID(c)] = nil
		table.save(t, C_dupe.path..C_dupe.db, 'w')
	end

	cha_timer = function(r, f, t)
		C_dupe.hook['tick'](r, f, t)
		if IsPlayer(r) == 1 then
			local j = 'Player'
			if ChaIsBoat(r) == 1 then
				j = 'Boat'
				r = TurnToShip(r)
			end
			if file_exists(C_dupe.path..C_dupe.db) ~= false and
				file_exists(C_dupe.path..C_dupe.file) ~= false then
				local t = table.load(C_dupe.path..C_dupe.db, 'r')
				local gs = table.load(C_dupe.path..C_dupe.file, 'r')
				if t[GetChaKeyID(TurnToCha(r))] == nil then
					C_dupe:Kick(r)
				else
					if t[GetChaKeyID(TurnToCha(r))] ~= gs[GetChaMapName(TurnToCha(r))] then
						C_dupe:LG('log', ''..j..' ['..GetChaDefaultName(TurnToCha(cha))..'] found in 2 different Gameservers. (Gameserver'..t[GetChaKeyID(TurnToCha(r))]..' and Gameserver'..gs[GetChaMapName(TurnToCha(r))]..').')
						C_dupe:Kick(r)
					end
				end
			end
		end
	end
	
	function C_dupe:Initialize()
		Hook:SetHookPattern("^after_enter_.*$", "POST", C_dupe.Enter, 2)
		Hook:SetHookPattern("^before_leave_.*$", "POST", C_dupe.Leave, 2)
	end

	function C_dupe:SetHook()
		local gs = table.load(C_dupe.path..C_dupe.file, 'r')
		for i,v in pairs(gs) do
			if _G["after_enter_"..i] == nil then
				_G["after_enter_"..i] = function(role, map_copy)
				end
			end
			if _G["before_leave_"..i] == nil then
				_G["before_leave_"..i] = function(role) 
				end
			end
		end			
		C_dupe:Initialize()
	end
	
	function C_dupe:AddHook(func)
		local file = GetResPath('/script/help/AddHelpNPC.lua')
		local index = FileToArray(file)
		local r = 0
		for i = 1, table.getn(index) do
			if index[i] ~= tostring(func) then
				r = r + 1;
			end
		end
		if r == table.getn(index) then 
			local lf = io.open(file,'a')
			lf:write("\n")
			lf:write(tostring(func))
			lf:close()
		end
	end
	
	C_dupe:AddHook('C_dupe:SetHook()')
	C_dupe:Initialize()

 

I think this script does the following...
> serialize maps and their respective gameserver by reading cfg files
> when player enters any map, serialize their map
> we can then retrieve their Gameserver by knowing their map
> If the player's map is not located in the GameServer they are supposely in, this is consider a clone.

This is the only way i can think of when dealing with lua but it was a very long ago.
I also remember that there is a logic error in cha_timer. 

  • Like 1

kong.png

a2.png

Share this post


Link to post
Share on other sites

A way to easily tell which GS you are on is too rename the system NPC in the .cfg off each GS to be differance (System1, System2 etc), then use 

local ret, npc = GetEudemon()
local GSName = GetChaDefaultName(npc)

to get the GS.

 

With your ( @Home ) method, you will have issues with players with a full inv, 

 

I had started trying to record a players inv/bank/temp/equips into a file when they leave a map, and then checking this against their current inv/bank/temp/equips when they enter a map, but idk if that would fully work due to order of disconnecting if they enter the same map as their clone. (and web based malls would need to be replaced with IGS)

  • Like 2

Share this post


Link to post
Share on other sites
9 hours ago, Home said:

@Billy @KONG @V3ct0r @Totoka @xSeth @Treuno86 How can i delete an character instance using lua?

 

Im not sure if you are able to do such stuff from lua.

I think an extension could be useful here.

 

(kop 2.4)-------------------------------------------------------------------

 

do some lua handler

// some prototypes and stuff to do pointers frowarding
struct T {
	template<typename TMember>
	static TMember F(unsigned int Ptr)
	{
		void *Address = reinterpret_cast<void*>(Ptr);
		return reinterpret_cast<TMember&>(Address);
	}
};
  
class CCharacter {
  public:
  	void *GetPlayer()// a forward to 0x41bb50 which is the function pointer of GetPlayer()
    {
		typedef void*(CCharacter::*m)(void);
        // be careful, didnt check if this is a pointer to a context, or pointer to pointer. must be debuged.
		return (this->*(T::F<m>(0x0041BB50)))();
    }
};

class GameServerApp {
  public:
	bool DelPlayer(void *player) // another forward.
	{
		typedef bool(GameServerApp::*m)(void*);
		return (this->*(T::F<m>(pDelPlayer)))(player);
	}
};


then register your new lua function

would be something like:

 

//////////////////////////////////////////////////////
// LUA POINTER/FUNCTIONS UTIL

#define lua_vm (void*)0x006F6768

#define lua_pushstring(S)\
  ((void(*)(void *, const char *))0x0062D320)(lua_vm, S)

#define lua_pushcclosure(F)\
  ((void(*)(void *, void *, int N))0x0062D3F0)(lua_vm, F, 0)

#define lua_pushcclosure(F)\
  ((void(*)(void *, void *, int N))0x0062D3F0)(lua_vm,F,0)

#define lua_settable()\
  ((void(*)(void *, int))0x0062D6B0)(lua_vm,0xFFFFD8EF)

#define lua_touserdata(L,N)\
  ((void*(*)(void*,int))0x0062D1C0)(L,N)

int lua_delplayer(void* L)
{
  CCharacter *c = (CCharacter*)lua_touserdata(L, 1);
  GameServerApp *s = GameServerApp::I();
  s->DelPlayer(c->GetPlayer());
  return 0;
}

//////////////////////////////////////////////////////
// Then finally, the one you should hook
// in order to get it working.
//  (it should be after the lua vm has been initialized)
extern "C" __declspec(dllexport) void __stdcall lua_extension()
{
  lua_pushstring("delrole");
  lua_pushcclosure(lua_delplayer);
  lua_settable();
}

 

i dont test it, don't have time. hope that helps.

 

Edit: --------------------------------------------------------------

after that whole stuff, call it from lua whenever you want.


delrole(role);

 

Edited by Totoka
code cleaning, macro redefinition, wrong returned type
  • Like 1

Discord: andresc

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

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.

Sign in to follow this  

×
×
  • Create New...