roncli.com blog
The blog of roncli
roncli.com blog
roncli.com
blog
Profile
Ronald M. Clifford
Houston, Texas, United States
Labels
Coding
CTG Music
Editorials
Games
Miscellaneous
Music
Servers
Silliness
Software
Sports
Trax in Space Beta
Weather
Recent Posts
The Finished Product
Deja vu
LibWowArmory 0.1
I just don't keep up with this like I used to
LibWowArmory 0.1
Using the WoW Armory to determine class talents
LibBeImba 0.1 beta released
All's well
Sleepful in San Antonio
San Antonio
Archives
February 2005
March 2005
April 2005
May 2005
June 2005
July 2005
August 2005
September 2005
October 2005
November 2005
December 2005
January 2006
February 2006
March 2006
April 2006
May 2006
June 2006
July 2006
August 2006
September 2006
October 2006
November 2006
December 2006
February 2007
March 2007
April 2007
May 2007
June 2007
July 2007
August 2007
September 2007
October 2007
November 2007
December 2007
January 2008
February 2008
March 2008
April 2008
June 2008
July 2008
September 2008
December 2008
February 2009
Tuesday, February 10, 2009
The Finished Product
Posted: 10:58:00 AM 0 comments
It's hard to finish something a year after you intended to be finished with it. It makes you feel like you've got nothing done over that period of time. But with as little as I've been able to work on projects in my free time, the Six Minutes To Release website is finally in a somewhat finished state.

The last week has seen me make various bug fixes and LINQ optimizations to allow the site to run faster, but nothing new has gone in, and I think it'll stay that way for a while. The Equipment Planner's been a big hit with the guild members so far, and I've always thought in the back of my mind about taking that a step further and spinning it off into its own website. Indeed, it may be something I eventually do, but for now I think I'm content with admiring the finished product, and perhaps work on something else for a while.

The biggest thing for me is that I've finished a project. For those that have been following this blog, you may know that it is difficult for me to finish things I start, but I managed to see this one through despite the long time from development to final release. Sure, I'll add things here and there, but the original plans I made were followed. That's a boost to my confidence, and hopefully something I can draw off of for wherever my next project lands.

Labels:

Friday, February 06, 2009
Deja vu
Posted: 10:44:00 AM 0 comments
Hmm. Apparently, I did post on LibWowArmory, but when I looked at my blog page the other day, it never got published. WTF?

Labels:

Tuesday, February 03, 2009
LibWowArmory 0.1
Posted: 5:25:00 PM 0 comments
I totally forgot to post this. Not so long ago, I released LibWowArmory on CodePlex. It's a .NET library for interfacing with the World of Warcraft Armory.

It's not complete, but I have it looking up important stuff, like items and characters. You can also extensively search as if you were searching from the Armory itself. Well, you are searching from the Armory itself, really, using the same queries available on their website.

I want to add lots of stuff to this, such as Achievements and Arena Teams, but right now this will do, because that's all I need for the Six Minutes website. I'm hoping at some point I'll be able to revisit this library and complete it, because it's pretty nice to be able to just call this stuff from code and not have to worry about the implementation of HTTP.

Labels:

I just don't keep up with this like I used to
Posted: 4:51:00 PM 0 comments
I am mildly annoyed at myself. I used to do a real good job at keeping up with what I'm doing as a way to keep contact with people out in the real world. And yet here I am, realizing yet again that it's been more than a month since my last post. Hmph.

Anyway, a lot has happened lately. First and foremost, if you don't know that I've gotten engaged, you've been out of the loop! I proposed to Kathy on the 16th at Ruth's Chris Steakhouse. It's been over 7 1/2 years since we've been together. The only explanation I can gather is that I like outdoing my brother, who's got this thing he calls the "five year rule". Well, I did 50% better than ya, bro. Heh.

Anyway, the date we're looking at is June 20, 2009, which would be 8 years exactly since we met at the Seabrook Beach Club. Which is closed. Would've made for a great reception.

So the plans have begun. The bands are bought, and all of the fun of planning is on the way. Finding a ceremony and reception site, getting a planner, booking catering and a DJ, and all the other extras that go into setting up that special day. Admittedly, I feel I'm going really slow, but we're making progress.

I did take a trip to Buffalo this year, although it was a lot shorter than usual due to me mismanaging my days off at work. I promised myself I won't do that again this year, but with the wedding, I may have little choice. Anyway, the trip was out of the ordinary, as the day before I was supposed to leave it was 60 degrees! The backyard flooded some with all the melting snow from Christmas eve and Christmas day, it was nuts. Then the next day the airport was closed because of high wind and power outages. Ugly stuff, I had to miss a day from work I couldn't afford to take.

It was there that I got the idea to get proposal plans going when my mom commented, "Maybe I should take you out to look at rings." She was surprised when I took her seriously.

Also while I was there, I got to see my brother play live again. It wasn't his usual band, but they still sounded pretty good. But the place he played out, yikes. It reminded me of when I saw my sister at a similar place the year before, except this one seemed smaller and seemed like it had four times as many people in it. We were packed wall to wall.

I also extended my luck at casinos, as I posted a $200 profit from Casino Niagara. But this time it was off of a near straight flush in Let It Ride. The last card needed to be the five of diamonds for me to walk out with some awesome five digit figure. Instead it was the queen of diamonds, which was good enough for a flush. Now, what gets me is that I don't really understand why I sat down to play that game, because I normally go exclusively for Blackjack. Not only did I win on the flush, but I kept even for the rest of my time at that table. Yet the brief time I played Blackjack, I actually lost a bit. I have to wonder what kind of uncanny sixth sense I have when it comes to gambling, because I have only really lost badly once. I figure I'm up on casinos by well over $1,000 by now. Thank goodness I don't have a casino nearby in Houston, because I would be very tempted to play frequently.

Hmm. A straight flush... that would've made for a nice wedding.

Anyway, I got a lot to talk about, so I'll try to play catchup.

Labels:

Thursday, December 18, 2008
LibWowArmory 0.1
Posted: 1:50:00 PM 0 comments
I've finished up the first release of the .Net library I've been working on that queries the WoW Armory. You can grab LibWowArmory from Codeplex. There's still a lot of work I want to do on it, but for now it does what I need it to do, and I can go back and complete the rest of the functionality later.

Labels:

Friday, December 12, 2008
Using the WoW Armory to determine class talents
Posted: 5:11:00 PM 0 comments
First of all, my apologies for not posting in over two months. My main focus has been working on the Six Minutes To Release website and related functions. Believe me when I say I've poured a lot of time into this.

On the heels of my LibBeImba project, I needed a more robust way to access the World of Warcraft Armory than I have been on the website. My research led me to the fact that they are using XML and XLT files to create their web pages, thus leaving the XML data exposed. In addition, using Fiddler, I have been able to find additional files behind the scenes that allow me to mine even more XML data. Serializing the XML in lieu of an XSD and then presenting the information in a developer-friendly format has led me to create the LibWowArmory project, still in development.

So today I went to take a look at the talents, figuring they were in XML as well. Well, this:


<talentTree value="503501523201322531025012511400200000000000000000000050000000000000000000000000"/>


isn't exact useful data. Turns out that string is parsed via JavaScript, and the talent calculator, instead of being created by XML and XLT, is generated on the client side via JavaScript. This included all of the static data, including the names of the talent trees, the individual talents, and the actual tooltip text you get when you mouse over the talents on the page. Very unArmorylike. And very inaccessable from VB.Net. At least, initially.

A while back I had done a bit of work with compiling .Net assemblies on the fly, and had began to wonder if I could somehow take the JavaScript that Blizzard was using, convert it to some .Net-equivalent language, and mine the data through reflection. After looking into JScript.Net and doing a refresher on Reflection, it only took me a couple of hours to come up with this code:


    Public Sub Talents(ByVal strClass As String)
' Gather the source code
Dim lstSource As New List(Of String)
lstSource.Add("var jsLoaded; var document; var pointsTier = new Array(); var templateString; var reqTalentID; var reqTalentPoints; var variableIsSite; var maxRank; var theUpdatedRank; var showTip; var hideTip; var textNextRank; var textPoint; var textPoints;")
Using wcClient As New System.Net.WebClient
lstSource.Add(wcClient.DownloadString("http://www.wowarmory.com/shared/global/talents/includes/variables-live.js"))
lstSource.Add(wcClient.DownloadString("http://www.wowarmory.com/shared/global/talents/includes/functions.js"))
lstSource.Add(wcClient.DownloadString(String.Format("http://www.wowarmory.com/shared/global/talents/{0}/data.js", strClass.ToLower.Replace(" ", ""))))
lstSource.Add(wcClient.DownloadString(String.Format("http://www.wowarmory.com/shared/global/talents/{0}/donotlocalize.js", strClass.ToLower.Replace(" ", ""))))
End Using

' Compile the code
Dim cdpProvider As CodeDomProvider = CodeDomProvider.CreateProvider("JScript")
Dim cpParams As New CompilerParameters()
cpParams.GenerateInMemory = True
cpParams.GenerateExecutable = True
Dim crResults As CompilerResults = cdpProvider.CompileAssemblyFromSource(cpParams, lstSource.ToArray())

' Run the main module of the assembly
Dim lstArgs = New List(Of Object)
lstArgs.Add(Nothing)
Dim objReturn As Object = crResults.CompiledAssembly.EntryPoint.Invoke(Nothing, BindingFlags.Static, Nothing, lstArgs.ToArray(), Nothing)

' Get the type in the assembly that contains the data we want
Dim tType As Type = (From t In crResults.CompiledAssembly.GetTypes() Where t.Name = "JScript 0").First()

' Get the tree names
Dim fiTrees As FieldInfo = (From f In tType.GetFields() Where f.Name = "tree").First()
Dim lstTrees As List(Of Object) = CType(Unbox(fiTrees.GetValue(Nothing)), List(Of Object))

' Get the talents
Dim fiTalents As FieldInfo = (From f In tType.GetFields() Where f.Name = "talent").First()
Dim lstTalents As List(Of Object) = CType(Unbox(fiTalents.GetValue(Nothing)), List(Of Object))

' Get the rank descriptions (some of these are in HTML format)
Dim fiRanks As FieldInfo = (From f In tType.GetFields() Where f.Name = "rank").First()
Dim lstRanks As List(Of Object) = CType(Unbox(fiRanks.GetValue(Nothing)), List(Of Object))

' Get the non localizable tree names... used to mine images like so:
' String.Format("http://www.wowarmory.com/shared/global/talents/{0}/images/armory/{1}/background.jpg", strClass.ToLower().Replace(" ", ""), strTree.ToLower().Replace(" ", ""))
Dim fiNLTrees As FieldInfo = (From f In tType.GetFields() Where f.Name = "nltree").First()
Dim lstNLTrees As List(Of Object) = CType(Unbox(fiNLTrees.GetValue(Nothing)), List(Of Object))

' Get the non localizable talents... used to mine images like so:
' String.Format("http://www.wowarmory.com/shared/global/talents/{0}/images/armory/{1}/{2}.jpg", strClass.ToLower().Replace(" ", ""), strTree.ToLower().Replace(" ", ""), strTalent.ToLower().Replace(" ", ""))
' String.Format("http://www.wowarmory.com/shared/global/talents/{0}/images/armory/{1}/{2}-off.jpg", strClass.ToLower().Replace(" ", ""), strTree.ToLower().Replace(" ", ""), strTalent.ToLower().Replace(" ", "").Replace(":", ""))
Dim fiNLTalents As FieldInfo = (From f In tType.GetFields() Where f.Name = "nltalent").First()
Dim lstNLTalents As List(Of Object) = CType(Unbox(fiNLTalents.GetValue(Nothing)), List(Of Object))

' TODO: Cache lists here for future use
End Sub

Private Function Unbox(ByVal obj As Object) As Object
If TypeOf obj Is ArrayObject Then
Dim aoObj = CType(obj, ArrayObject)
If CInt(aoObj.length) = 0 Then
Return New List(Of Object)
Else
Dim arr As Array = CType(Microsoft.JScript.Convert.ToNativeArray(aoObj, Type.GetTypeHandle(New Object)), Array)
Dim lstReturn As New List(Of Object)
For Each o As Object In arr
lstReturn.Add(Unbox(o))
Next
Return lstReturn
End If
Else
Return obj
End If
End Function


There's a bit to talk about in here, so I'll go ahead and explain the code.

First, JScript.Net differs from JavaScript in that all variables must be defined. That's essentially what I'm doing with that big long line just after declaring lstSource. All of those variables need to be declared, otherwise the code will not compile. Interesting to note that "document" needs to be declared, since we're not running from within the scope of a web page. Fortunately, I'm not doing anything with the document object, so I'm not going to run into any runtime errors accessing the document.

Next, I download all of the necessary code from Blizzard. The second one has a lot of useless functions, but it does have a couple functions that are used in the last two. Those two files contain all of the talents for the specified class.

The next section compiles the code using the JScript CodeDomProvider. The following section actually runs the main module of the assembly, instantiating all the variables and allowing the functions to run. Most of Blizzard's code is written in the global scope, so most of that code runs. This is where the data from the data.js and donotlocalize.js files are put into memory.

Now we have to use reflection to get the type. After some debugging, I found that the type named "JScript 0" is the one with the data I'm interested in. So, using LINQ, I grab that type from the assembly.

Now we get to pull the data we want. I get the FieldInfo object from the type, again using reflection to make it easy to cherry pick the correct field. Then I can use FieldInfo.GetValue to grab my value and...

Not so fast.

Because the assembly I'm pulling from is in JScript.Net, arrays are not of type System.Array, but rather Microsoft.JScript.ArrayObject. This is a monolithic array type that really doesn't let you play around much with it. Trying to LINQ from it doesn't give you the data, you actually have to call the data through the Item property.

Fortunately, JScript.Net provides a way to change ArrayObjects to normal Arrays, via the ToNativeArray function. I packaged this all up into a recursive function called Unbox. This takes an object and spits the object back out if it's not an ArrayObject. However, if it is an ArrayObject, it converts it into a List(Of Object) using some trickery. Note that it tries to unbox each object that it inserts into the list. This is because Blizzard likes nesting arrays, so I needed to make sure that every ArrayObject inside is put into a more friendly list object.

The idea is to cache this data so I don't have to spam Blizzard for their JavaScript files every time I need to access a player's talents, something I already have a bit of a framework setup to do in LibWowArmory.

The result is I can now take that very ugly talentTree XML node, split the string up into individual characters, and assign each of those numbers to each of the character's talents to learn exactly what their build looks like in code.

All in all, I'm pretty happy with my work on this, and plan to release LibWowArmory soon with item search and lookup, as well as player search, lookup, and talent inspection. Further, I am now able to apply the power of the Armory to my own website in an easy-to-use library in what should be a write-and-forget library, much like LibBeImba turned out to be.

I would be doing this post an injustice if I didn't talk about how the guild is doing. So far, we've cleared about half of Naxxramas 10 as people are still working on leveling up. We've also taken out Sartharion 10 with no drakes, and are farming Archavon 10 when we can as well. Wrath of the Lich King brought some great content into the game, succeeding in many places where, in my opinion, Burning Crusade just failed miserably. I'm really happy with this expansion so far, as is Kathy, and it's something we continue to enjoy together, something that's more important to us than the game itself.

Labels:

Wednesday, September 24, 2008
LibBeImba 0.1 beta released
Posted: 4:18:00 PM 0 comments
With everything nearly back to normal in Houston, I'm back to working on my guild's website.

In the course of doing so, I recently added the ability to pull scores from the BeImba website for use on my website. The admin over there just recently opened up a SOAP API, which took me a matter of an hour or so to create something to interface with it.

Well, I took things a step further. I took out the portion of the code from the website and made it its own project called LibBeImba. After playing around and tweaking things, I got to the point where I thought the library should be available to the public.

The result? A CodePlex project for LibBeImba. It was pretty straightforward for me to create the project, upload the source via SVN, and create its first release.

Currently, I use it to capture all of my level 70 guild members' scores once a day and store the information in a database. Then the website can query that information and display it in any number of ways. I hope to get a graph up on individual users' pages, but that might be a while before I can get around to that.

In any case, if you're a .NET coder interested in getting BeImba scores for your World of Warcraft guild, this is the library you need. Check it out.

Labels:

Sunday, September 14, 2008
All's well
Posted: 4:16:00 PM 0 comments
Kathy and I are home after spending a relaxing night and morning in San Antonio, TX. The ride home was a bit rough, lots of traffic, and some getting off at rare exits along the way.

When we got home, we were excited to see the electricity in the Galleria area on, when it had been off in practically every other area we saw. Sure enough, we get home and electricity's up, and I fired up the computers to find working Internet as well. Can you believe that?

It sucks for the rest of the city, and especially Galveston, for they aren't so lucky, and may have up to three weeks without power. Kathy and I are very fortunate.

So now it's business as usual for us, safe and sound. I still don't know if I have work tomorrow, as the power may still be out and the servers there are down. I'm sure I'll find out soon enough, though.

Labels:

Saturday, September 13, 2008
Sleepful in San Antonio
Posted: 10:55:00 PM 1 comments
We just got into our hotel in San Antonio, away from the mess that is Houston. They're estimating over 4 million people without power in the Houston area, and some may not have power again for possibly a week to a month. If that's the case, this next week has the potential to be full of suck.

In any case, Kathy and I are going to get some much needed sleep. When we get home, I'll report on how Houston is doing.

Labels:

San Antonio
Posted: 6:12:00 PM 0 comments
So 90% of the Houston area is without power. Kathy is getting off work a day and a half sooner than expected, and does not want to deal with the apartment as it stands.

So we're spending the night in San Antonio to get a clean room, A/C, and a good night's sleep away from it all. We'll hopefully be leaving in an hour or so.

Posted with LifeCast

Labels: