It is indeed a mess. I was experimenting and I left the code there.
Anyways, here's the implementation. I might need to get rid of the "id" property though. The code is as follows:
/*
IUID - is the hash code over every property of the object except for 'count', uid and iuid. This creates an IUID (Inventory UID) that is unique to the items inside the inventory by item type. It is used to identify items that have more or less the same properties. We use this information to merge items in the inventory that have the same uid. Meaning that they probably have the same values relevant to the game logic and therefore we merge them into one item and calculate their "count" property.
UID - it is supposed to be unique to all other uids in the game
*/
// standard Java 32 bit hash code that can be generated over any string
// we use it to calculate the hash code over the string provided by JSON.stringify()
String.prototype.hashCode = function()
{
var hash = 0;
if (this.length == 0) return hash;
for (var i = 0; i < this.length; i++) {
var character = this.charCodeAt(i);
hash = ((hash<<5)-hash)+character;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
}
setup.calculateInventoryUniqueId = function(obj)
{
obj.uid = JSON.stringify(obj).replace(/,\"uid\":\"item:[a-z0-9:-]+\"/g,"").replace(/,\"count\":[0-9-]+/g,"").replace(/,\"iuid\":\"[0-9-]+\"/g,"").hashCode().toString();
return obj.iuid;
}
// attempt to create a unique ID that is unique to all uids inside and outside of the current inventory
// it calculates the integrity over the count as well
// and adds a date as well as a random character string, which is going to be used as the salt
setup.calculateUniqueId = function(obj)
{
integrityHash = JSON.stringify(obj).replace(/,\"uid\":\"item:[a-z0-9:-]+\"/g,"").replace(/,\"iuid\":\"[0-9-]+\"/g,"").hashCode().toString();
var salt = Math.random().toString(36).substring(7);
obj.uid = ('item:' + integrityHash + ':' + Date.now() + ':' + salt);
return obj.uid;
}
I know the way this thing is implemented is very unusual, but it works very well in the game.
Here's an example of an item that I use in my game:
<<set $flower_dress =
{
id: "flower.dress",
name: "Flower Dress",
count: 4,
value: 70,
type: "top",
image: "images/Items/Wearables/flower_dress.png",
isEquipped: false,
attributes: [],
status: [{ name: "hotness", bonus: 12 }],
iuid:"-1186697761",
onEquip:
{
passages: {"bathroom":"PutOnTopBathroom"},
tags: ['bathroom']
},
onUnEquip:
{
passages: {"bathroom":"RemoveTopBedroom",
"home":"RemoveTopBedroom"},
tags: ['bathroom','home']
},
uid:"item:-887800947:1512698440234:th9gsl",
enhancements: [],
description: "This is a colorful dress with some flowers sewn into the fabric. It's very comfy."
}>>
<<set $flower_dress =
{
id: "flower.dress",
name: "Flower Dress",
count: 1,
value: 70,
type: "top",
image: "images/Items/Wearables/flower_dress.png",
isEquipped: false,
attributes: [],
status: [{ name: "hotness", bonus: 12 }],
iuid:"-1186697761",
onEquip:
{
passages: {"bathroom":"PutOnTopBathroom"},
tags: ['bathroom']
},
onUnEquip:
{
passages: {"bathroom":"RemoveTopBedroom",
"home":"RemoveTopBedroom"},
tags: ['bathroom','home']
},
uid:"item:476897104:1512698479412:hsdd0s",
enhancements: [],
description: "This is a colorful dress with some flowers sewn into the fabric. It's very comfy."
}>>
You can see that the 'uid' stays the same because both items are supposed to be seen by the game as the same item.All relevant properties that are important to the logic of the game are the same. Therefore, these items can be merged / stacked. When you do so, you get the same item with a new 'iuid' and the 'count' raised to 5.