Introduction
Duplication glitches can be detrimental to a game’s economy if it is player based. If a duplication glitch breaks out it can do a great deal of damage to the economy.
Consider this:
You have just finished working on this great new mob for your game. It drops the single most rare item in the game. You go to bed satisfied with this week’s update. You wake up in the morning, eager to check how the update did only to find out that there’s an edge case where resetting your character during trading duplicates your inventory! You quickly fix this bug, push a patch update but by now, the damage has already been delt. That once rare item has now been duplicated hundreds of times, sold/traded to other players more times than you can count. You revert everyone’s data back to what it was before the update, upsetting a lot of the players who made a lot of progress during that time. The update ends up doing more bad to your game than good.
all of this could’ve been prevented had every item beared a UUID.
What is a UUID?
UUID stands for Universally Unique IDentifier. It is a randomly generated unique string used for identification purposes. A UUID can be used to tell apart from two objects of the same class having the exact same characteristics. The chance of two UUIDs generated ever being the same is mathematically negligible.
Okay, but how does using a UUID play out in game development?
Say you have a game which has an economy run by the players. Duplication glitches in such games can be detrimental as they can crash the economy of the game over night. Sure, testing a lot of edge cases can (and should be!) done before any major update is released but things can slip out of the testing phases. If every item ingame has a UUID then UUIDs of two objects can be compared before they’re traded, sold or added to the player’s inventory. Like I said, two objects having the same UUID is incredibly unlikely. If two items are ever found to have the same UUID, you can safely assume that they’ve been duplicated. You can then delete the item, and perhaps log the incident for future evaluation
How can I implement this?
there are several ways to implement such systems. For this post, I will be utilizing httpservice and attributes.
firstly we need to generate a UUID. You can create or your own system, pull from an external api or use the functions provided by roblox.
There’s a function provided by roblox called GenerateGUID()
(GUID stands for globally unique identifier which is basically the same thing as UUID)
local HttpService = game:GetService("HttpService")
local UUID = HttpService:GenerateGUID()
-- our unique string has been generated!
now that a UUID has been generated, we need to attach it to an object so that we can refer to it later on in other scripts. I will be using Attributes to accomplish this.
local HttpService = game:GetService("HttpService")
local function AttachUUID(object)
local UUID = HttpService:GenerateGUID() -- generate a unique ID...
object:SetAttribute("UUID",UUID) -- we've attached the UUID to the object!
end
AttachUUID(workspace.MySword)
print(workspace.MySword:GetAttribute("UUID")) -- prints {2B0FA56A-C1DF-43D1-8443-8D566ACDC13A}
Great! Now MySword
has a unique id. It can now be differentiated from YourSword
despite them both being Swords
Note: AttachUUID should only be called ONCE when the item is created. The UUID should then be saved to a datastore and pulled from there when we need to load that item again. You should NOT reattach a new UUID when loading the item!
Another way of indentification: Creation Timestamp
Apart from UUIDs, we can also assign a Creation Time
to objects which refers to the time at which that particular object was created. This can be useful if older items in your game cost more than newer ones of the same class. This is also just as simple to do. For this, we will also be using Attributes and os.time()
function
local function AttachCreationTime(object)
local CreationTime = os.time()
object:SetAttribute("CreationTime",CreationTime) -- we've attached the CreationTime to the object!
end
AttachCreationTime(workspace.MySword)
print(workspace.MySword:GetAttribute("CreationTime")) -- prints 1625737115 (unix time)
the unix time
can then be easily converted to months,days,hours etc. by dividing.
Note: AttachCreationTime should only be called ONCE when the item is created. The CreationTime should then be saved to a datastore and pulled from there when we need to load that item again. You should NOT reattach a new CreationTime when loading the item!
Example Usage
- UUID in a trading system
local function GiveItem(player,item)
--assuming that an UUID was attached to the item when it was created..
for _,object in pairs(player.Inventory) do
if object:GetAttribute("UUID") == item:GetAttribute("UUID") then
print("Duplicated item detected!")
-- dont give the item to the player since it's a dupe
else
player.Inventory:Add(item) -- proceed to give the item if the UUIDs were different
end
end
end
- Creation time for item worth evaluation
local function CalculateWorth(item)
local oneYear = 365*24*60*60 -- 31536000 seconds in a year
if item:GetAttribute("CreationTime") <= (os.time()-oneYear) then
item.Price *= 2 --double the price if item is a year or older
end
end
I hope that this post was useful. This is my first tutorial on the devforum so feedback & (constructive) criticism is greatly appreciated!