I have not written such systems before, but I do have some thoughts and ideas I’d like to share.
Assuming that there is one global economy within the game, one problem you would have to find a way around is that you would need some cross-server communication or data storage at the least, because players might hop between servers. Or maybe you have some cross-server trading system. In my approach down below I’ll dive into some options that use one global database for the whole game.
Your approach of using a UUID sounds very feasible, especially when the chances of two UUID’s having the same value is close enough to zero to be negligible. I believe this shoud also work on a large scale very well as you can compare UUIDs on a local level. If a user is able to duplicate an item in their inventory, you could check upon adding an item to a user’s inventory if they already have such an item with the same UUID.
However, if a user can trick the game into generating an item multiple times, then the UUID approach might fail as those items will likely have different identifiers. In that case you’ll need additional approaches to solving item duplication.
Another approach to consider is to track for each item some additional metadata (such as the creation timestamp).
Let’s assume that some user is a bad actor who manages to duplicate a crown object. Depending on your code’s implementation, there is a good chance that on duplication either:
- The crown’s metadata is duplicated as well.
- The crown’s metadata is empty.
- The crown’s metadata is corrupt or invalid.
In all 3 cases, there are some options to identify duplication now by comparing items in your global database, for example upon storing or adding a new item to the database:
- If there are multiple items of the same type in your database with the same (or similar) creation timestamp, that item is likely to be duplicated. Especially if there are items in your game that can only be obtained once per user or per time period, the chances of a user having multiple of those items with the same timestamps is very slim. And if items are sorted in your database by creation time, look-ups should be very fast as well (n log(n)).
- If the metadata of an item is empty, there is a very good chance the item was not obtained in a legitimate way. (or your code has bugs. But if you have unit tests, you can eliminate that option with a high certainty). In the case of empty data, such as empty creation timestamps, the same method as the previous point can be applied.
- If the metadata of an item is corrupt or invalid, you could most likely identify this on a local level, such as on the server side within a game instance. For example if an item has been generated by some mob that shouldn’t drop such items, you can assume that someone in the server at that moment used some sort of exploit.
I would not recommend moderating users automatically when such conditions are met however, but if you have some sort of system that sends you a message whenever fraudulent activity has been recorded, you could do some manual verification and moderation afterwards.