• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

How to detect which items are cloned

LucasFerraz

Systems Analyst
Joined
Jun 10, 2010
Messages
2,857
Reaction score
96
Location
Brazil
Hello guys,
I would like to announce that I am working on a system of anti duplication.

Why do I have to work with him if there are any free forum?
I'm trying to do something with highest performance.

How?
Using Trigger and/or Procedure.

As most of you know, I'm not good with advanced things but I'm studying to conclude this project successfully.
I suggest you to join this project and contribute to our community.

I will use Darkhaos' Anti-Dupe as base.


- - - Known Anti-Dupe System - - -

function generateSerial() made by Darkhaos (This function should be rewritten select * sucks.)
LUA:
function generateSerial()
	local strings = "AaBbCcDdEeFfGgHhIiJjKkLlMmOoPpQqRrSsTtUuVvWwXxYyZz"
	local newSerialStr, newSerialInt = "", 0
	local newSerial = ""
	local query, query2, query3
	repeat
		for k = 1, math.random(1, 10) do
			local l = math.random(1, string.len(strings))
			newSerialStr = newSerialStr .. string.sub(strings, l, l)
		end
		newSerialInt = math.random(999999)
		newSerial = newSerialStr .. "-" .. newSerialInt
		query = db.getResult("select * from player_items where substring(convert(attributes using latin1) from 18) = " .. db.escapeString(newSerial))
		query2 = db.getResult("select * from player_depotitems where substring(convert(attributes using latin1) from 18) = " .. db.escapeString(newSerial))
		query3 = db.getResult("select * from tile_items where substring(convert(attributes using latin1) from 18) = " .. db.escapeString(newSerial))
	until query:getID() == -1 and query2:getID() == -1 and query3:getID() == -1
	return "!" .. newSerial
end
LUA:
doItemSetAttribute(uid, "serial", generateSerial())


This is function onStartup(GlobalEvent) made by Darkhaos and improved by BeniS.
LUA:
function onStartup()
 
	tablesToCheck = {"player_items", "player_depotitems", "tile_items", {"player_items", {"player_depotitems", "tile_items"}}, {"player_depotitems", "tile_items"}}
	local text, final = "", ""
	local filex = "data/logs/duplicated.txt"
	local f = io.open(filex, "a+")
	local delete, delete2, query, query_ = nil, nil, nil, nil
	local count, tmpCount = 0, 0
 
	for i = 1, table.maxn(tablesToCheck) do
		if type(tablesToCheck[i]) == "string" then
			query = db.getResult("SELECT *, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i] .. " WHERE CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 1)")
			if query:getID() ~= -1 then
				tmpCount = query:getRows()
				while(true) do
					delete = db.executeQuery("DELETE FROM " .. tablesToCheck[i] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
					count = (delete and count + 1 or count)
					text = "[!] -> Deleting items with duplicated serial from '" .. tablesToCheck[i] .. "': [Player: " .. getPlayerNameByGUID(query:getDataInt("player_id")) .. ", Item: " .. query:getDataInt("itemtype") .. ", Count: " .. query:getDataInt("count") .. ", Serial: " .. query:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!")
					final = final .. (final ~= "" and "\n" or "") .. text
					tmpCount = tmpCount - 1
					if (not query:next() or tmpCount <= 1) then break end
				end
				query:free()
			end
		else
			if type(tablesToCheck[i][2]) == "string" then
				query = db.getResult("SELECT *, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][1] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][2] .. " WHERE CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
				if query:getID() ~= -1 then
					tmpCount = query:getRows()
					while(true) do
						query_ = db.getResult("SELECT *, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][2] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][1] .. " WHERE CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
						delete = db.executeQuery("DELETE FROM" .. tablesToCheck[i][1] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
						count = (delete and count + 1 or count)
						delete2 = db.executeQuery("DELETE FROM " .. tablesToCheck[i][2] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
						count = (delete2 and count + 1 or count)
						text = "[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][1] .. "' [Player: " .. getPlayerNameByGUID(query:getDataInt("player_id")) .. ", Item: " .. query:getDataInt("itemtype") .. ", Count: " .. query:getDataInt("count") .. ", Serial: " .. query:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!") ..
						"\n[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][2] .. "' [Player: " .. getPlayerNameByGUID(query_:getDataInt("player_id")) .. ", Item: " .. query_:getDataInt("itemtype") .. ", Count: " .. query_:getDataInt("count") .. ", Serial: " .. query_:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!")
						final = final .. (final ~= "" and "\n" or "") .. text
						tmpCount = tmpCount - 1
						if (query_:getID() ~= -1) then query_:free() end
						if (not query:next() or tmpCount <= 1) then break end
					end
					query:free()
				end
			else
				for j = 1, #tablesToCheck[i][2] do
					query = db.getResult("SELECT *, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][1] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][2][j] .. " WHERE CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
					if query:getID() ~= -1 then
						tmpCount = query:getRows()
						while(true) do
							query_ = db.getResult("SELECT *, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][2][j] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][1] .. " WHERE CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
							delete = db.executeQuery("DELETE FROM " .. tablesToCheck[i][1] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
							count = (delete and count + 1 or count)
							delete2 = db.executeQuery("DELETE FROM " .. tablesToCheck[i][2][j] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
							count = (delete2 and count + 1 or count)
							text = "[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][1] .. "' [Player: " .. getPlayerNameByGUID(query:getDataInt("player_id")) .. ", Item: " .. query:getDataInt("itemtype") .. ", Count: " .. query:getDataInt("count") .. ", Serial: " .. query:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!") ..
							"\n[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][2][j] .. "' [Player: " .. getPlayerNameByGUID(query_:getDataInt("player_id")) .. ", Item: " .. query_:getDataInt("itemtype") .. ", Count: " .. query_:getDataInt("count") .. ", Serial: " .. query_:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!")
							final = final .. (final ~= "" and "\n" or "") .. text
							tmpCount = tmpCount - 1
							if (query_:getID() ~= -1) then query_:free() end
							if (not query:next() or tmpCount <= 1) then break end
						end
						query:free()
					end
				end
			end
		end
	end
	if f ~= nil then
		print("["..os.date("%X", os.time())..".TMI] >> Item Tracker: " .. count .. " duplicated items have been deleted...")
		f:write("[" .. os.date("%d %B %Y %X ", os.time()) .. "] >> [Item Tracker] " .. count .. " duplicated items have been deleted from the database.\n" .. (final == "" and "[!] -> No duplicated item was found in the database" or final) .. "\n\n")
		f:close()
	else
		print("[["..os.date("%X", os.time())..".TMI] >> [Item Tracker] Cannot save info to file!")
	end
	return true
end

The problem is: The code is bringing all pages of MySQL. This is not the best solution because it will f**k up the network.
The Solution: The correct way to do the procedure is to perform everything in MySQL. Doing this way the network will not be compromised and the connection will be stable/fine/ok.
Tips: The procedure should be as specific as possible to have better performance. A good idea would be to use as the filter itemtypes (pre-defined), so only the items 'vip' would be sought and only the items 'vip' with serial duplicate would be deleted.
The disadvantages of using this filter would be for items not 'vip' duplicate would not be deleted.
In a second stage a second 'scan' could fetch all the duplicate items that are not declared previously (vip items).
As you can see, so far I have all the theory, the practice is missing, if you know how to help, I'm counting on you :)

- - - New Anti-Dupe System - - -

LUA:
--Removed SELECT * because it sucks
--Added filter in select, ADD YOUR ITEM ID (VIP ITENS) THERE. (Search for itemtype = 2160 or itemtype = 2159)
function generateSerial()
	local strings = "AaBbCcDdEeFfGgHhIiJjKkLlMmOoPpQqRrSsTtUuVvWwXxYyZz"
	local newSerialStr, newSerialInt = "", 0
	local newSerial = ""
	local query, query2, query3
	repeat
		for k = 1, math.random(1, 10) do
			local l = math.random(1, string.len(strings))
			newSerialStr = newSerialStr .. string.sub(strings, l, l)
		end
		newSerialInt = math.random(999999)
		newSerial = newSerialStr .. "-" .. newSerialInt
		query = db.getResult("select attributes from player_items where substring(convert(attributes using latin1) from 18) = " .. db.escapeString(newSerial) .. " and itemtype = 2160 or itemtype = 2159")
		query2 = db.getResult("select attributes from player_depotitems where substring(convert(attributes using latin1) from 18) = " .. db.escapeString(newSerial) .. " and itemtype = 2160 or itemtype = 2159")
		query3 = db.getResult("select attributes from tile_items where substring(convert(attributes using latin1) from 18) = " .. db.escapeString(newSerial) .. " and itemtype = 2160 or itemtype = 2159")
	until query:getID() == -1 and query2:getID() == -1 and query3:getID() == -1
	return "!" .. newSerial
end
LUA:
doItemSetAttribute(uid, "serial", generateSerial())
SQL:
DELIMITER $$

DROP PROCEDURE IF EXISTS `anti_dupe` $$

CREATE PROCEDURE `anti_dupe`(IN _id INT)

BEGIN

-- All procedure here --
-- Until now, I don't know how to do that but I'm studying to --

END $$

DELIMITER ;

and then:

LUA:
function onStartup()
 
db.executeQuery("CALL anti_dupe ();")

return true
end

Also, here is a re-improved onStartUp()
LUA:
-- Removed SELECT *
--Added filter in select, ADD YOUR ITEM ID (VIP ITENS) THERE. (Search for itemtype = 2160 or itemtype = 2159)
function onStartup()
 
	tablesToCheck = {"player_items", "player_depotitems", "tile_items", {"player_items", {"player_depotitems", "tile_items"}}, {"player_depotitems", "tile_items"}}
	local text, final = "", ""
	local filex = "data/logs/duplicated.txt"
	local f = io.open(filex, "a+")
	local delete, delete2, query, query_ = nil, nil, nil, nil
	local count, tmpCount = 0, 0
 
	for i = 1, table.maxn(tablesToCheck) do
		if type(tablesToCheck[i]) == "string" then
			query = db.getResult("SELECT attributes, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i] .. " WHERE itemtype = 2160 or itemtype = 2159 and SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i] .. " WHERE itemtype = 2160 or itemtype = 2159 and CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 1)")
			if query:getID() ~= -1 then
				tmpCount = query:getRows()
				while(true) do
					delete = db.executeQuery("DELETE FROM " .. tablesToCheck[i] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
					count = (delete and count + 1 or count)
					text = "[!] -> Deleting items with duplicated serial from '" .. tablesToCheck[i] .. "': [Player: " .. getPlayerNameByGUID(query:getDataInt("player_id")) .. ", Item: " .. query:getDataInt("itemtype") .. ", Count: " .. query:getDataInt("count") .. ", Serial: " .. query:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!")
					final = final .. (final ~= "" and "\n" or "") .. text
					tmpCount = tmpCount - 1
					if (not query:next() or tmpCount <= 1) then break end
				end
				query:free()
			end
		else
			if type(tablesToCheck[i][2]) == "string" then
				query = db.getResult("SELECT attributes, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][1] .. " WHERE itemtype = 2160 or itemtype = 2159 and SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][2] .. " WHERE itemtype = 2160 or itemtype = 2159 and CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
				if query:getID() ~= -1 then
					tmpCount = query:getRows()
					while(true) do
						query_ = db.getResult("SELECT attributes, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][2] .. " WHERE itemtype = 2160 or itemtype = 2159 and SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][1] .. " WHERE itemtype = 2160 or itemtype = 2159 and CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
						delete = db.executeQuery("DELETE FROM" .. tablesToCheck[i][1] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
						count = (delete and count + 1 or count)
						delete2 = db.executeQuery("DELETE FROM " .. tablesToCheck[i][2] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
						count = (delete2 and count + 1 or count)
						text = "[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][1] .. "' [Player: " .. getPlayerNameByGUID(query:getDataInt("player_id")) .. ", Item: " .. query:getDataInt("itemtype") .. ", Count: " .. query:getDataInt("count") .. ", Serial: " .. query:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!") ..
						"\n[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][2] .. "' [Player: " .. getPlayerNameByGUID(query_:getDataInt("player_id")) .. ", Item: " .. query_:getDataInt("itemtype") .. ", Count: " .. query_:getDataInt("count") .. ", Serial: " .. query_:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!")
						final = final .. (final ~= "" and "\n" or "") .. text
						tmpCount = tmpCount - 1
						if (query_:getID() ~= -1) then query_:free() end
						if (not query:next() or tmpCount <= 1) then break end
					end
					query:free()
				end
			else
				for j = 1, #tablesToCheck[i][2] do
					query = db.getResult("SELECT attributes, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][1] .. " WHERE itemtype = 2160 or itemtype = 2159 and SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][2][j] .. " WHERE itemtype = 2160 or itemtype = 2159 and CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
					if query:getID() ~= -1 then
						tmpCount = query:getRows()
						while(true) do
							query_ = db.getResult("SELECT attributes, SUBSTRING(CONVERT(attributes USING latin1) FROM 18) AS 'track' FROM " .. tablesToCheck[i][2][j] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) IN (SELECT SUBSTRING(CONVERT(attributes USING latin1) FROM 18) FROM " .. tablesToCheck[i][1] .. " WHERE CONVERT(attributes USING latin1) LIKE '%serial%' GROUP BY SUBSTRING(CONVERT(attributes USING latin1) FROM 18) HAVING COUNT(*) > 0)")
							delete = db.executeQuery("DELETE FROM " .. tablesToCheck[i][1] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
							count = (delete and count + 1 or count)
							delete2 = db.executeQuery("DELETE FROM " .. tablesToCheck[i][2][j] .. " WHERE SUBSTRING(CONVERT(attributes USING latin1) FROM 18) = " .. db.escapeString(query:getDataString("track")) .. " LIMIT 1;")
							count = (delete2 and count + 1 or count)
							text = "[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][1] .. "' [Player: " .. getPlayerNameByGUID(query:getDataInt("player_id")) .. ", Item: " .. query:getDataInt("itemtype") .. ", Count: " .. query:getDataInt("count") .. ", Serial: " .. query:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!") ..
							"\n[!] -> Deleting item with duplicated serial from '" .. tablesToCheck[i][2][j] .. "' [Player: " .. getPlayerNameByGUID(query_:getDataInt("player_id")) .. ", Item: " .. query_:getDataInt("itemtype") .. ", Count: " .. query_:getDataInt("count") .. ", Serial: " .. query_:getDataString("track") .."]... " .. (delete and "Success!" or "Failed!")
							final = final .. (final ~= "" and "\n" or "") .. text
							tmpCount = tmpCount - 1
							if (query_:getID() ~= -1) then query_:free() end
							if (not query:next() or tmpCount <= 1) then break end
						end
						query:free()
					end
				end
			end
		end
	end
	if f ~= nil then
		print("["..os.date("%X", os.time())..".TMI] >> Item Tracker: " .. count .. " duplicated items have been deleted...")
		f:write("[" .. os.date("%d %B %Y %X ", os.time()) .. "] >> [Item Tracker] " .. count .. " duplicated items have been deleted from the database.\n" .. (final == "" and "[!] -> No duplicated item was found in the database" or final) .. "\n\n")
		f:close()
	else
		print("[["..os.date("%X", os.time())..".TMI] >> [Item Tracker] Cannot save info to file!")
	end
	return true
end
 
Last edited:
I would really want to help, but since i suck on lua. I cant help you.
 
Try to describe idea 'how to detect which items are cloned' and then we will think how to realize it by few quick SQL queries.
 
Why don't you use a serialKey which you just increase every time so you do not have to use a query for checking?
 
Is it anyway possible to track it with dissapearing items?
 
I think that most important is where you will store serial key and how to read/write/compare it fast with others.

edit:
Because if you try to compare 3.000.000 items, each of them with all others it will take ages (select and compare operation 9,000,000,000,000 times!).
---------------------------------
I think it's not possible to 'find duplicated items' for all items, even if you edit engine :( as there are many items stackable which lose all special attributes everytime you move them (40 bolts [with serial] to 2 x 20 bolts [not attributes]). Also I don't understand when you want add serial to items. To make it not possible to duplicate it, it should be added when OTS 'creates' item.

You can try to detect duplicated 'sms shop items' (except stackable) and check how much money got players (check if it grows normal or too fast and then check WHO has too much), but can't detect/remove all duplicated items by LUA script :(
 
Last edited:
Yes but no idea how to do it :S
 
I think that most important is where you will store serial key and how to read/write/compare it fast with others.

edit:
Because if you try to compare 3.000.000 items, each of them with all others it will take ages (select and compare operation 9,000,000,000,000 times!).
---------------------------------
I think it's not possible to 'find duplicated items' for all items, even if you edit engine :( as there are many items stackable which lose all special attributes everytime you move them (40 bolts [with serial] to 2 x 20 bolts [not attributes]). Also I don't understand when you want add serial to items. To make it not possible to duplicate it, it should be added when OTS 'creates' item.

You can try to detect duplicated 'sms shop items' (except stackable) and check how much money got players (check if it grows normal or too fast and then check WHO has too much), but can't detect/remove all duplicated items by LUA script :(

duplicated 'sms shop items' (except stackable)

thats what i mean with 'vip itens'
 
duplicated 'sms shop items' (except stackable)

thats what i mean with 'vip itens'
I mean that you can find (add special attribute when it's created) only items that you create by LUA script (edit script that add these items). You can also add attributes to items from NPCs, so if someone clone BP it will be easy to detect.


DO NOT LET PEOPLE CLONE ITEMS AND NO PROBLEMS LIKE THAT.
 
I get reports about items dissapearing, i wonder if its possible to make similar system. To check the serial of that item then search if the serial exsist ingame.
 
LUA:
local lettersUsedToGenerateHash = "AaBbCcDdEeFfGgHhIiJjKkLlMmOoPpQqRrSsTtUuVvWwXxYyZz"
math.randomseed(os.time()) -- required!
function generateSerial()
	local newSerial = "!"
	for k = 1, 10 do
		local l = math.random(1, string.len(lettersUsedToGenerateHash))
		newSerial = newSerial .. string.sub(lettersUsedToGenerateHash, l, l)
	end
	local newSerialInt  = math.random(899999) + 100000 -- this will return always same lenght
	newSerial = newSerial .. "-" .. os.time() .. "-" .. newSerialInt
	-- length: ![10 letters]-[10 numbers (unix date)]-[6 numbers]
	-- length = 29 [always!]
	return newSerial
end
This 'random' function will return one of 15.943.212.285.300.000.000.000 random letters-numbers combinations and it will be different (part of it is time in seconds) every second. You don't have to select anything from MySQL to get unique string.

@Lucas
Could you post dump of database with some items that got serials? Then I could try to make some MySQL queries to make it work faster.
 
How did you get to 15.943.212.285.300.000.000.000?
 
I think that is 8.065817517 x 10^67 = 52!
that is just with letters

with numbers and letters is 62!

idk
 
Back
Top