Item Instances?
by Max · in Game Design and Creative Issues · 02/09/2012 (2:25 pm) · 7 replies
Hi! I'm having trouble with the item instancing system in my online RPG.
My current system will store a variable ($IID::mods[%id]) that contains the item the instance is based off of, and then a list of mods on the base statistics of that item. So the variable might be defined as something like:
So each instance can simulate an item. I can give the player an "inst12" and when I do, it'll send them all of the info when it is added to their inventory.
This all works, but I've got a problem. Since I've added this system, I'm the only person who has been online, and the file I store the variables in is nearly a megabyte in size. This is entirely too large to be executed and altered on the fly. I foresee huge performance issues in the future. Most of the item instances were created by NPC's spawning, but if I ever have more than 20 or so players crafting swords, that file will inflate even further.
I don't like this system. Not one bit. It's crude and hacked together. I've tried and tried to think of a classier and more elegant system for unique item stats, but I can not.
Basically what I need is to be able to have players create or find items that have varying statistics. The way my crafting system works, each Iron Sword you create becomes slightly better than the last. I need a way for the client to differentiate between one iron sword and the next.
What I'm looking for is an item instancing system that works like Minecraft, or World of Warcraft. If you drop a weapon in Minecraft, it retains the amount damage that weapon currently has sustained. And in World of Warcraft, you can have two identical swords, and sharpen one. Then the swords are no longer identical.
I don't need any code, I just need ideas. I'd appreciate any help the community could lend me.
Thank you!
My current system will store a variable ($IID::mods[%id]) that contains the item the instance is based off of, and then a list of mods on the base statistics of that item. So the variable might be defined as something like:
$IID::mods[12] = "IronSword prefix Crude integrity 56 weight 5.5 durable 56 value 0 hard 50";
So each instance can simulate an item. I can give the player an "inst12" and when I do, it'll send them all of the info when it is added to their inventory.
This all works, but I've got a problem. Since I've added this system, I'm the only person who has been online, and the file I store the variables in is nearly a megabyte in size. This is entirely too large to be executed and altered on the fly. I foresee huge performance issues in the future. Most of the item instances were created by NPC's spawning, but if I ever have more than 20 or so players crafting swords, that file will inflate even further.
I don't like this system. Not one bit. It's crude and hacked together. I've tried and tried to think of a classier and more elegant system for unique item stats, but I can not.
Basically what I need is to be able to have players create or find items that have varying statistics. The way my crafting system works, each Iron Sword you create becomes slightly better than the last. I need a way for the client to differentiate between one iron sword and the next.
What I'm looking for is an item instancing system that works like Minecraft, or World of Warcraft. If you drop a weapon in Minecraft, it retains the amount damage that weapon currently has sustained. And in World of Warcraft, you can have two identical swords, and sharpen one. Then the swords are no longer identical.
I don't need any code, I just need ideas. I'd appreciate any help the community could lend me.
Thank you!
About the author
#2
02/10/2012 (12:16 pm)
Global script variables is a bad route to take. Try breaking this up into XML files or a true SQL database. I worked on a crafting system and that's the route I took.
#3
What if I turned item instances into ScriptObjects, and I saved the objects themselves into the player save files? So the unique items owned by players aren't even considered by the server when that player isn't online. I think this is a moderately efficient way of storing the instance data.
But a problem still remains, how do I get the instance data to the client? I need to think of a way to send an entire ScriptObject from server to client.
02/10/2012 (12:18 pm)
I was thinking about this this morning. What if I turned item instances into ScriptObjects, and I saved the objects themselves into the player save files? So the unique items owned by players aren't even considered by the server when that player isn't online. I think this is a moderately efficient way of storing the instance data.
But a problem still remains, how do I get the instance data to the client? I need to think of a way to send an entire ScriptObject from server to client.
#4
Database. Seriously. All of your data is then securely stored on your server and the player can't simply invent crazy items at home and then log into your server with Thor's Hammer or a lightsaber.
02/10/2012 (12:30 pm)
And another issue is that you're trusting players in a multiplayer game to hold their own item data.Database. Seriously. All of your data is then securely stored on your server and the player can't simply invent crazy items at home and then log into your server with Thor's Hammer or a lightsaber.
#5
02/10/2012 (12:39 pm)
Oh, no, all of the player files are stored on the server. I've considered using the SQL Lite plugin, but then I still have the issue of exposing the client to what items they have. I'd like the client to open their inventory, and see that they have two different Iron Swords, and one is sharper than the other.
#6
When a player logs in, the file gets executed, and these values are applied to the new player object.
02/10/2012 (12:44 pm)
Here's an example of a player save file. The file is exported when a player logs out (and an autosave every 20 minutes).$playerData["Braveskin",EXP] = "215"; $playerData["Braveskin",Faction] = "Humans"; $playerData["Braveskin",Items] = "ArrowItem 159 Wood 2 IronOre 172 Coal 84 NomFruit 29 Gold 16102 SpiderVenom 7 GoblinClanLogo 130 FlaxFibers 3 inst33 1 inst35 1 inst36 1 inst236 1 inst259 1 inst2606 2 inst3852 1 "; $playerData["Braveskin",Level] = "4"; $playerData["Braveskin",mountedItem0] = "inst236"; $playerData["Braveskin",mountedItem1] = "inst3852"; $playerData["Braveskin",mountedItem2] = ""; $playerData["Braveskin",mountedItem3] = ""; $playerData["Braveskin",mountedItem4] = ""; $playerData["Braveskin",mountedItem5] = ""; $playerData["Braveskin",mountedItem6] = ""; $playerData["Braveskin",mountedItem7] = ""; $playerData["Braveskin",Skill,0] = "8"; $playerData["Braveskin",Skill,1] = "5"; $playerData["Braveskin",Skill,2] = "5"; $playerData["Braveskin",Skill,3] = "1"; $playerData["Braveskin",Skill,4] = "1"; $playerData["Braveskin",Skill,5] = "1"; $playerData["Braveskin",Skill,6] = "1"; $playerData["Braveskin",Skill,7] = "5"; $playerData["Braveskin",SkillExp,0] = "48"; $playerData["Braveskin",SkillExp,1] = "510.803"; $playerData["Braveskin",SkillExp,2] = "310"; $playerData["Braveskin",SkillExp,3] = ""; $playerData["Braveskin",SkillExp,4] = ""; $playerData["Braveskin",SkillExp,5] = ""; $playerData["Braveskin",SkillExp,6] = ""; $playerData["Braveskin",SkillExp,7] = "450"; $playerData["Braveskin",Transform] = "-42.819 -34.5401 0.0214791 0 0 1 0.973739";
When a player logs in, the file gets executed, and these values are applied to the new player object.
#7
- All player data files are stored on a server.
- The client requests information from the server via an HTTP request.
- The server does some validation and then returns the data.
Both the request and client is encrypted using a public/private key method and the encryption sits in the exe.
I used a special message format that works similarly to what I explained above, the main difference is that if the client doesn't know what to do with a new item (for example) it then sends a request for further instructions from the server and stores this in a local cache on the client.
I also have a version in my message that is compared to the client cache at decrypt time ... if the version is different, the client once again requests further instructions.
The only information stored on the client cache is the enum explanations for the client gui and not the calculations or anything that can effect game play.
I have given a sample game client to some friends whom I requested to try and hack the game scripts ... I even made it easy by giving them the raw .cs files ... they tried various things and were always redirected to the game client update utility to fix any issues.
I still have a ways to go ... but I am quite confident in my approach and it scales very well because of the standard http requests ... which I can load balance using software like haproxy.
02/11/2012 (9:28 pm)
Well the way I am approaching it on my project is as follows.- All player data files are stored on a server.
- The client requests information from the server via an HTTP request.
- The server does some validation and then returns the data.
Both the request and client is encrypted using a public/private key method and the encryption sits in the exe.
I used a special message format that works similarly to what I explained above, the main difference is that if the client doesn't know what to do with a new item (for example) it then sends a request for further instructions from the server and stores this in a local cache on the client.
I also have a version in my message that is compared to the client cache at decrypt time ... if the version is different, the client once again requests further instructions.
The only information stored on the client cache is the enum explanations for the client gui and not the calculations or anything that can effect game play.
I have given a sample game client to some friends whom I requested to try and hack the game scripts ... I even made it easy by giving them the raw .cs files ... they tried various things and were always redirected to the game client update utility to fix any issues.
I still have a ways to go ... but I am quite confident in my approach and it scales very well because of the standard http requests ... which I can load balance using software like haproxy.
Torque Owner Quinton Delpeche
Gobbo Games
I don't know much about how your system works or what the values mean ... so I am just going to go for it.
e.g. (I have added the pipe sign "|" for differentiation indicators)
|IronSword|prefix Crude|integrity 56|weight 5.5|durable 56|value 0|hard 50|
Would map to something like |xxx|y|##|#.#|##|#|##|
- First mapping (xxx) would be a unique numeric number for the item (e.g. 325 = Iron Sword, 001 = Club).
- Second mapping (y) would be a unique identifier for the prefix (e.g. 1 = crude, 5 = master worked).
- The rest of the mapping would be numeric values (i.e. # = number) for the various options.
You will however have to ensure that the rest of the mappings always follow in the same order and if one doesn't exist just pass a null value (i.e. ||).
Not sure if this will make the file smaller or any easier to use ... sorry, late on a Friday afternoon and I am about to head home.