Author - sapu


This will be a very technical blog post which provides a look into the new class library which has been added to the TSM codebase with TSM4. This is an internal code library which makes it easier for us to implement new features in TSM4. This new class library is the base for many other internal code libraries in TSM4 such as our UI Builder, Database, and FSM libraries. We will go into more detail on the other libraries in future blog posts.

What is a class?

A common feature of a programming language is being “Object-Oriented”. This means that the structure of the code is based around complex data structures called objects. The type of these objects is generally referred to as their class. The class describes the structure and features of the objects.

Let’s take a TSM group as an example of how utilizing classes can be beneficial (note: in practice, TSM doesn’t use classes for this purpose). A TSM group, at its core, consists of four things: the name of the group, some sort of reference to the parent group, a list of items which are in the group, and a list of operations which are applied to the group. A user may have hundreds of different groups, but they all have these exact same attributes.

A class allows us to easily represent this structure in code and anything which is defined as part of this class will automatically be shared among all instances of the class (all groups). Having this structure also allows us to easily enforce restrictions such as not allowing specific characters in the name of a group, or only allowing a single Crafting operation to be applied to a group. This is generally done by prohibiting outside code from modifying the attributes of objects directly, but instead providing class methods which can perform this validation. For example, if I have a group object `x`, rather than changing the name via ` = “foo”`, I would instead call a class method such as `x:SetName(“Foo”)`. This means that there is a polished set of APIs for interacting with the objects of each class defined by the class methods. Below is an example of how this might look in pseudo-code:

` ` `

define class TSMGroup {

   string name;

   class parentGroup;

   list items;

   list operations;


   function SetName(string newName) {

       if (newName.contains(SOME_INVALID_CHARACTER)) {

           return false;

       } = newName;

       return true;




// create a new group

group = new TSMGroup();

group:Setname(“My Group”);

` ` `

As you can see, we can use classes to define exactly what a TSMGroup is and what methods it supports, and then create objects of that class (aka. instances of the class) which behave according to the class definition.

TSM’s Class Library

Lua, the programming language used for WoW addons, is not generally considered an object-oriented language in that it doesn’t natively support classes. However, through something called metatables and metamethods (which I won’t go into great detail on here), we can extend the language to support them. The class system implemented by the class library in TSM4 does not support every feature that traditional object-oriented languages support, but it does allow for enough of them to allow us to use classes effectively in TSM.

Specifically, the TSM class library supports inheritance and polymorphism. The former means that classes can be subclassed to extend the functionality. For example, a TSMImportedGroup class could be a subclass of the TSMGroup class and could be used as part of the import process to represent a group which came from an import string that has additional methods ontop of those defined by the base TSMGroup class. With support for polymorphism, code can be written in a way which it can operate on an object which may belong to either a class or subclass without needing to explicitly know which is the case. For example, the `SetName()` method may be called on a TSMGroup object or a TSMImportGroup object without the calling code needing to know the type of the object is calling the method on. The TSMImportGroup object can even override the implementation of SetName() if it wants to impose additional restrictions on the name of the group for example.

In the future, I’d like to add support for access restriction to the class library so that the use of proper APIs when interacting with objects can be enforced.

Digging Deeper

There is a lot more to the TSM class library. If you want to see the code, you can check out the implementation and some unit tests here.

Deployment System

In this blog post, I will be giving a behind-the-scenes overview of the new deployment system we have created and been using throughout the development of TSM4.

Why did we create this new deployment system?

The primary goal of all this was to make it quicker and easier for us to get new changes into the hands of our users, and give us the ability to control which sets of users get which changes. Let’s talk about the latter goal first. We currently split our users into 4 separate release channels: Internal, TSM4 Alpha, TSM4 Beta, and TSM3 Release. The ‘Internal’ channel is used primarily for TSM team members for testing the very latest changes. The ‘TSM4 Alpha’ channel was used during the invite-only alpha phase of TSM4. The ‘TSM4 Beta’ channel is currently being used for everybody who has access to the TSM4 beta. The ‘TSM3 Release’ channel is one which all of our users have access to, and gives all of our users access to the latest version (of TSM3) we push to Curse. These release channels can easily be changed and adapted as our needs change (i.e. as TSM4 goes from internal-only to alpha to beta to release). So, the goal of our deployment system is to make it as easy as possible to release new versions to the proper channel.

How do we do this?

We currently use Bitbucket to host our source code repositories. In the past year, they added a new Bitbucket Pipelines feature, which is a build and deployment system. Because we already use Bitbucket tools so extensively, and Bitbucket Pipelines integrates nicely with the features we already use, we decided to utilize it for our deployment system.

Whenever there is a new change made to our TSM4 code branch and we want to release a new version to our beta testers, we simply hit a few buttons within our Bitbucket repository to start a deployment. The details of what happens as part of this deployment is entirely custom. In the case of the TSM addon, this involves taking a snapshot of the current code, removing our internal files which we don’t want to be included in the release, writing the version to the correct addon files, and packing it up into a .zip. This .zip file is then stored on our server for the app to download and marked as the latest version for the appropriate channels.

Future Plans

Once TSM4 is released, this deployment system potentially allows us to do more regular, staged releases. For example, we can release new version to a smaller set of beta testers to ensure there are no critical errors before releasing it to our entire user-base. In the end, this means that we can get more high-quality releases out to our users on a regular basis with less administrative effort on our end.

TSM4 Deep Dive: Sniper

Sniper has long been a very popular feature of TradeSkillMaster, with many goblins even setting up a second, dedicated sniper account. The Sniper feature allows for snatching up deals as quickly as possible once they are posted on the auction house by constantly scanning the most recently-posted auctions and comparing the buyout price with user-configured maximum prices at either a global or operation level.

In TSM4, we’re making Sniper a first class feature by adding new Sniper operations and a top-level Sniper tab to the Auction House frame. We’re also adding an entirely new type of sniping in the form of a new Bid Sniper.

Sniper Operations

In TSM3, Sniper configuration is done at either a global level or within Shopping operations. Our reason for putting the configuration in Shopping operations in TSM3 was that we felt users would likely have the same max price for Shopping as they would for Sniper. However, this has traditionally led to some confusion, and is a bit limiting. Now that Sniper is a first class feature, we’ve created an entirely new type of operation for Sniper.


As shown by the screenshot above, there is just a single “Below custom price” option for specifying your max price while sniping within Sniper operations. This max price will apply to any items within groups with this operation applied, or, if you have a Sniper operation applied to the new Base Group, it’ll apply to any items which aren’t in any group at all. TSM4 will ship with a default Sniper operation which will come pre-loaded and applied to the Base Group to allow new users to take advantage of the Sniper feature immediately upon installing TSM4.

Sniper Auction House Tab

Upon switching to the new Sniper tab in the TSM4 Auction House UI, you’ll be prompted with the option of starting either a Bid Sniper or Buyout Sniper. The Bid Sniper is a new type of sniper which, instead of looking for recently posted auctions, looks for auctions which are about to expire which have a bid price below the max price you have set in your Sniper operation. If you click on the “Run Buyout Sniper” button, the Buyout Sniper scan will start.


There are a ton of new features in the TSM4 Sniper. For example, the progress indicator at the bottom will animate to indicate that the scan is in progress. One common issue people run into with Sniper is phasing. This is a bug on Blizzard’s end where the AH freezes when you phase between servers without giving any indication of what has happened. TSM4 is able to detect this and will warn you when it happens so you can re-open the AH to resume your scan. Also, the results are now sorted by how recently they were posted so the newest results will always be on the top, ready for you to buy as quickly as possible. One common piece of feedback we’ve gotten from users is that some items show up in the results which they don’t want to buy, so in TSM4, we’ve added an easy way to clear an entry from the results table as well as a way to quickly restart the scan to clear all the results.

Join the Beta

As you can see, Sniper is better than ever in TSM4 and we’re super excited for you to try it out for yourself. If you want to ensure you get into the beta as soon as possible, you can go ahead and sign up for an invite here. If you like what we do and want to support the continued development of TradeSkillMaster and also get priority access to all of our betas, please consider becoming a TSM Premium user.