This project is read-only.

Make Item class serializable?

Nov 2, 2012 at 6:19 PM

Hi, just to say I think this is a great library and thanks for providing it! :)


I have a request - would it be possible to make the WOWSharp.Community.Wow.Item class Serializable?


To explain:
I am have just written/am writing a program in C# which does some searching and functions that the game and remote program don't do very well


a) To be able to search Horde, Alliance and Neutral AH with several different search strings, all in one click and one result set. If I am searching for several pieces of transmog gear it can be a real bind to do several searches across several auction houses, one by one.


b) To be able to get a list for a particular char and AH (which will be one my chars) of all items which are selling for lower prices than my items (buyouts only). This is a lot faster than manually price checking 200+ auctions to see who has undercut me.


Yes there are probably in-game addons which do this but I wanted a way to do it out-of-game, and then I can re-price any undercutted items using the remote app for phone.
Other functions I have thought about is a Horde v Alliance price compare and then list items which vary by more than X% in price for the cheapest buyout. If X% is more than a certain amount may be worth investigating a bit of cross-faction economy exploitation ;)


Anyway, I got a basic thing up and running and it's working pretty well. The place I got a bit stuck was that obviously the auction dump only returns the ItemID of the item, no name or other information. I understand this is a restriction imposed by Blizzard in their API so not much we can do about it. However searching the string names of 50,000 auctions, and therefore hitting 50,000 GetItem method calls against the server, was obviously very slow.
So I wanted to build an item cache to file so for the vast majority of auctions I would already have the item in memory.


What I did was to was to download ItemDataCache addon from curse.com and then look at the item LUA file in there. It has a list of valid ItemIDs with sell prices. All I needed was the valid itemIDs so I parsed this to get a list of ItemIDs.


I wanted to get a dictionary of these items serialized to save to an XML file. Since the WOWSharp.Community.Wow.Item wasn't serializable I created my own GameItem class which has most of the obviously serializable properties in there (int, bool, string, nums etc). I can then create one of these from a WOWSharp.Community.Wow.Item class.


I used a SerializableDictionary (a third party custom class since standard Dictionary in .Net won't serialize) with the ItemID as the key and my GameItem object as the value. I have one routine which will generate the entire XML file (takes a good 1.5 hours since it has to do 60,000 server calls to get the item info 1 by 1). But once it's done it uses this, and probably you'd only want to regenerate the file occasionally, maybe once per month or so.


But then deserializing this into an object in memory on startup I can make very fast queries about items and their names/properties etc without having to make any server calls.


If WOWSharp.Community.Wow.Item class can be made serializable then I can capture ALL of the information into my item cache, rather than just the obviously serializable properties I have created in my custom class.


No biggie if it's going to be too much work to do this (other than adding [Serializable] on the class header may be some work getting the custom lists and object types serializable).
But thanks again for a very useful library! :)

Maplebunny

Nov 3, 2012 at 8:45 PM

Hello

Thanks a lot for the feedback.

The problem is not the amount of work but there is one problem with [Serializable] attribute is that it's available only in .NET framework. You see, this library is a portable class library that's compatible with .NET Framework, Silverlight, Windows Phone and .NET for Windows Store applications (Windows 8 Metro apps). So in order to make it compatible with all those platforms, I have to adhere to the classes common to all platforms and unfortunately [Serializable] attribute is not available in all the platforms (only .NET). 

However, the source code for the library is available, and you can use the source code to add the Serializable attribute and compile your own version. I am sorry for not being able to help more.

Best regards,

Grendizer

Nov 3, 2012 at 8:54 PM
Edited Nov 3, 2012 at 8:54 PM

Hello again

I also want to add that you can use DataContractSerializer, NetDataContractSerializer or JsonDataContractSerializer classes to serialize your data. All the classes have [DataContract] attribute and the properties have [DataMember] attribute. So it should be easy to use those classes instead of BinaryFormatter or SoapFormatter classes which require [Serializable] attribute. 

Best regards,

Grendizer

Nov 5, 2012 at 6:25 PM

Hi, thanks for the reply.

Yes I did think about using a customized version of the source, but when I checked it looked like only version 1.0, and not version 1.3, of the source code was available? I also had trouble adding the project to my solution because of compatibility. Do I need to install and be targetting .Net 4.5 because I have Visual Studio 2010 which I think is currently targetting 4.0?

Anyway I can take a look at the other classes you mention.

Currently all the information I need to serialize can be done in my own object which is basically just strings, bools, ints etc so it serializes fine with just the [Serializable] tag. I am mainly looking at future development since it would obviously be nice to capture all the information in my item cache.

 

Anyway thanks once again for taking the time to reply, and for taking the time to provide us with this great library :)

Maplebunny.

Nov 6, 2012 at 5:53 PM

Hi

The source code issue may be a mistake on my part. The folder called WOWSharp1.0 should actually be called 1.x. It contains version 1.3. I wasn't thinking right when I named the folder. Sorry about that.

As for visual studio version, the project template used is portable library template in VS 2012. It will not open in VS 2010. However, you can create an empty project in VS 2010 targeting .NET 4.0 and add all the .cs files to the project it should compile. The source code does not use any new feature in .NET 4.5 that is not available in 4.0.

Best regards,

Grendizer

Nov 7, 2012 at 7:59 PM

Hi Grendizer :)

Thanks once again for the reply.

I have managed to create a project and add in the source code files as you suggested for .Net 4.0. There were just a couple of lines I had to comment out to get it to build.

Although now having thought about this, I'd like to avoid having my own customized version of the source code if possible. The main reason being that as versions 1.4, 1.5 etc are released if I had my own customised version I'd have to track all my changes, get the latest source, re-apply my changes and rebuild in order to use features in newer libraries.

Therefore if possible I'd prefer to work with the compiled DLL provided and just upgrade the DLL as each new version comes out.

So I thought I would try using the DataContractSerializer as you suggested which looked like a really good alternative. Unfortunately using this method seems to have a problem with enums:
"Enum value 'BindOnEquipped' is invalid for type'WOWSharp.Community.Wow.ItemBindType' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute."

Is it possible to mark these enums as it is suggesting so the object can be fully serialized (and presumably then deserialized)? 

Sorry if I am making work for you :) But I'd think a lot of people would be interested in generating and storing their own item cache in a file to minimize server calls at runtime. If you're going through an entire auction house, item caching is pretty much the only way to go.


Thanks for your time.

Maplebunny

Nov 7, 2012 at 8:31 PM

Cool! Ok I did a quick test just on a single item (a onehanded weapon) and it seems to be serializing ok using the DataContractSerializer if the EnumMember attributes are added to the values, e.g.: 

[DataContract]   

public enum ItemBindType   

{       

[EnumMember(Value = "Unbound")]       

Unbound = 0,       

[EnumMember(Value = "BindOnPickup")]       

BindOnPickup = 1,

 

Etc. Sorry the formatting is really screwy. 

Although in the test I did there were several nil entries which looked like enums (e.g. <allowableClasses i:nil="true"/>), also gemInfo, itemSet, socketInfo which other items might use - so I think probably further enums would need these attributes adding for all items to serialize in every case.

 

Would it be feasible to add these EnumMember attributes into the main source code for enum definitions? How much work would this be, and would it present any issues for the other platforms such as Silverlight / Windows Phone etc which you've mentioned?

If there will be problems I will ofc use my own customized version of the source, but as they say - if you don't ask, you don't get! :)

Best wishes,

Maplebunny.

Nov 8, 2012 at 8:08 AM

Hello,

Adding EnumMember attribute should not be a problem. I will do that later today when I am back home from work.

Best regards,

Sherif

Nov 8, 2012 at 5:17 PM

Excellent thank you.

As I said I am not entirely sure which enums will require it to serialize the Item class without doing a larger test of data.

If I get time this evening I can try this on a wider spread of data and see what happens.

Nov 8, 2012 at 8:04 PM

Hi.

I uploaded the change. The new release is 1.3.1

Best regards,

Sherif (aka Grendizer)