< / >

This is a blog by about coding and web development.

WoW deprecates its own content

Posted on in

I started playing World of Warcraft again recently to check out the expansions. Coming back to it again after so long away was an interesting experience. I realized some things after playing it, and talking to people at work about it.

The areas in WoW are so level segmented that, once you’ve moved on to a higher level, you have almost no incentive to visit the lower level areas again. Whole continents of content are lost to you.

I’m guessing they did this to avoid the problem of a new player wandering too far up a mountain and getting eviscerated by some foul, high level beast he had no way of knowing was there. (I hear this happened a lot in EQ?) You definitely feel safe wandering around in an area your level in WoW. Dumb.

One of my favorite things in WoW is the early Silverpine area. As a new player, you’ll be putzing around, doing some mind-numbing collect quest, when all of a sudden this massive wolfman charges out of nowhere and smashes you in the face. You run away blindly screaming, wondering what the hell is going on. You usually get away safely, if a little worse for wear.

These Sons of Arugal are definitely higher level than most of the players leveling in the area, and are an awesome harassment. They create stories for people. When you’re higher level, you’ll be riding up the road and see a pack of low level people running screaming out of the forest, with a worgen loping after them a few seconds later. It creates stories for people tell each other, and these are stories that evolve naturally through gameplay.

It was also one of the few storylines in WoW that I actually had a personal emotional investment in. After getting killed by these things a few times during leveling, you want nothing more than to be able to kill them.

Throughout a series of area quests as you get higher level, you learn the back story behind these creatures. The worgen were accidentally brought into the world during a summoning intended to strengthen the ranks of the mages defending against the undead scourge. After slaughtering the scourge, they turned on the mages themselves. The mage, Arugal, was driven mad with guilt, and adopted the worgen as his children. The quest chain culminates in you fighting your way through his ruined castle, ultimately destroying him, his pets, and the vengeful ghosts haunting the castle.

It’s an amazing quest chain, but wouldn’t have been nearly as interesting if it hadn’t hooked you early on with the lowbie harassment.

This is great storytelling through gameplay… unfortunately, this is one of only a few instances of it that I’ve seen in WoW. I wish they did more of it. An old dragon in a deep cave, occasionally coming down to harass a village; an evil wizard, hidden in a mountaintop retreat, sending out minions to harvest unsuspecting lowbies from nearby areas for dark spells; these things would allow for better re-use of areas and make the game far more interesting.

AS3 and Proxy

Posted on in

In ActionScript 3, you can extend a class from the Proxy class to override the behavior of many language level operations, making it a valuable tool for advanced development. However, they are much slower than sealed classes, so be careful with their use when high performance is necessary.

Proxy allows you to override:

// function calls
foo.bar(1, 2)
=>
foo.callProperty('bar', 1, 2)

// property get
foo.bar
foo['bar']
=>
foo.getProperty('bar')

// property set
foo.bar = 123
foo['bar'] = 123
=>
foo.setProperty('bar', 123)

// property delete
delete foo.bar
delete foo['bar']
=>
foo.deleteProperty('bar')

// in operator
'bar' in foo
=>
foo.hasProperty('bar')

// descendant operator
foo..bar
=>
foo.getDescendants('bar')

Proxy also allows you to override the handling of for..in and for each..in loops, using the nextNameIndex, nextName, and nextValue methods. This for..in loop:

for (var key:String in foo) {
    trace(key);
}

on a proxy, is equivalent to:

var i:int = 0;
while (true) {
    var index:int = foo.nextNameIndex(i);
    if (index == 0)
        break;
    var key:String = foo.nextName(index);
    trace(key);
    i++;
}

Similarly, this for each..in loop:

for each (var value:* in foo) {
    trace(value);
}

on a proxy, is equivalent to:

var i:int = 0;
while (true) {
    var index:int = foo.nextNameIndex(i);
    if (index == 0)
        break;
    var value:* = foo.nextValue(index);
    trace(value);
    i++;
}

Here is an example stub class implementing these methods:

package {
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;

    public class ExampleProxy extends Proxy {
        private var items:Array;

        public function ExampleProxy():void {
            items = [];
        }

        override flash_proxy function deleteProperty(name:*):Boolean {
            return delete items[name];
        }

        override flash_proxy function getProperty(name:*):* {
            return items[name];
        }

        override flash_proxy function hasProperty(name:*):Boolean {
            return name in items;
        }

        override flash_proxy function nextNameIndex(index:int):int {
            if (index > items.length)
                return 0;
            return index + 1;
        }

        override flash_proxy function nextName(index:int):String {
            return String(index - 1);
        }

        override flash_proxy function nextValue(index:int):* {
            return items[index - 1];
        }
    }
}

Gmail IMAP and Thunderbird

Posted on

Google gives great instructions on how to get IMAP access setup in Thunderbird. But it can take some searching to work out all the kinks. Here are some tips to save you the digging I had to do:

Fixing the IMAP folders

Thunderbird tries to create its own folders for Sent Items, Drafts, and Trash, but it’s a bit cleaner if we just use Gmail’s.

To change Sent Items and Drafts, go to Tools -> Account Settings and go to Copies & Folders under your Gmail account. Choose Other for both, and browse to the appropriate [Gmail]/ folder.

To change Trash, go to Tools -> Options -> Advanced -> General and click Config Editor in the bottom right. Filter for mail.server.server. You’ll see mail.server.server1, mail.server.server2, etc. – one for each account you have.

Find the account you want to change, then right click and go to New -> String. Enter mail.server.server1.trash\_folder\_name where server1 is the server for your account. Press Ok and enter [Gmail]/Trash for the value.

Once you’ve setup your folders, you can log into Gmail and delete the [IMAP]/ filters that Thunderbird created.

Sorting emails by date and thread

If you want messages to be sorted like they are in Gmail, go to Tool -> Options -> Advanced -> General. Click Config Editor (bottom right) and filter for mailnews.thread_pane_column_unthreads. Double click the row to change it to false.

Then, back in the main window, go to the View -> Sort by menu and make sure Date, Descending, and Threaded are all selected.

Adding multiple Gmail accounts

Adding another Thunderbird account for each Gmail account you have works as expected except for one problem: by default, all of the accounts use a single SMTP server.

To add SMTP servers for additional Gmail accounts:

  1. Tools -> Account Settings
  2. Choose Outgoing Server (SMTP) (bottom of account list on the left)
  3. Click Add (right side)
  4. Enter a description (e.g. youremail@gmail.com)
  5. Enter smtp.gmail.com for Server Name
  6. Enter 587 for Port
  7. Check User name and Password
  8. Enter youremail@gmail.com for User Name (or youremail@yourdomain.com for Google Apps)
  9. Choose TLS for Use secure connection
  10. Click OK
  11. Choose the your Gmail account from the account list
  12. Select the new SMTP server from the Outgoing Server (SMTP) drop down list.

Reordering accounts

I added my accounts in a somewhat random order, and wanted to resort the way they appeared in my folder list. To do this go to Tools -> Options -> Advanced -> General. Click Config Editor (bottom right) and filter for mail.accountmanager.accounts. Double click the row to edit it.

You can swap the values to adjust the order. If you had:

account1,account2,account3

and wanted account 2 to be first, change it to:

account2,account1,account3

Then click OK and restart Thunderbird.

Game Objects library

Posted on in

Game Objects is a collection of 2D and 3D maths classes, and algorithms for helping in the creation of games with Python.

Will McGugan’s Game Objects library has been invaluable for my dabblings in Python game development. It provides optimized objects for common graphics math (3D vector class, matrix class, etc.). The objects are flexible and framework independent, so you can use them with the platform of your choice, be it pygame, PyOpenGL, or DirectPython.

It’s a somewhat new project, and the documentation a bit sparse, but the library is pretty straightforward and he’s been updating it regularly.

Relevant links:

Vertex buffer objects in PyOpenGL

Posted on in

Decided to move some of my vertex array code over to ARB_vertex_buffer_object, to see if I could get a bit of a speed boost out of PyOpenGL. Much to my dismay, these functions don’t have the sexy extension wrappers I talked about before, so it was a bit of a chore to get it all working.

Here’s a little wrapper class I wrote to make things easier:

from OpenGL.GL import *
from OpenGL.raw import GL
from OpenGL.arrays import ArrayDatatype as ADT

class VertexBuffer(object):

    def __init__(self, data, usage):
        self.buffer = GL.GLuint(0)
        glGenBuffers(1, self.buffer)
        self.buffer = self.buffer.value
        glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)
        glBufferData(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(data),
                     ADT.voidDataPointer(data), usage)

    def __del__(self):
        glDeleteBuffers(1, GL.GLuint(self.buffer))

    def bind(self):
        glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)

    def bind_vertexes(self, size, type, stride=0):
        self.bind()
        glVertexPointer(size, type, stride, None)

    ... snipped for length ...

Download buffers.py.

So, how to use it? Let’s say you have a Python list with a bunch of vertexes with float x, y, and z components:

verts = [[x, y, z], [x, y, z], [x, y, z], ...]

You’ll have to use NumPy or an equivalent to convert it to a PyOpenGL compatible array:

import numpy
numpy_verts = numpy.array(verts, dtype=numpy.float32)

Create the VertexBuffer object with it:

buffer = VertexBuffer(numpy_verts, GL_STATIC_DRAW)

Use it in your day to day rendering:

glEnableClientState(GL_VERTEX_ARRAY)
buffer.bind_vertexes(3, GL_FLOAT)
glDrawElementsui(GL_TRIANGLES, indexes)

They’re not shown in the snippet, but I’ve also defined bind_colors, bind_edgeflags, bind_indexes, bind_normals, and bind_texcoords, as shortcuts for the rest of the GL array functions.

DRY your views with middleware

Posted on in

When I have Django URL patterns like:

urlpatterns = patterns('',
    (r'^(?P<foo_id>\w+)/$', 'myproject.myapp.views.show'),
    (r'^(?P<foo_id>\w+)/edit/$', 'myproject.myapp.views.edit'),
    (r'^(?P<foo_id>\w+)/delete/$', 'myproject.myapp.views.delete'),
)

I always end up with views like:

def show(self, foo_id):
    foo = get_object_or_404(Foo, id=foo_id)
    ...

def edit(self, foo_id):
    foo = get_object_or_404(Foo, id=foo_id)
    ...

def delete(self, foo_id):
    foo = get_object_or_404(Foo, id=foo_id)
    ...

Having the same few lines at the top of every function in makes me feel dirty. You can clean this up with a Middleware class, replacing foo_id with the actual object before calling the view.

myproject/myapp/middleware.py looks like this:

from django.shortcuts import get_object_or_404
from someapp.models import Foo

class FindObjects:
    def process_view(self, request, view_func, view_args, view_kwargs):
        if 'foo_id' in view_kwargs:
            foo_id = view_kwargs['foo_id']
            view_kwargs['foo'] = get_object_or_404(Foo, id=foo_id)
            del view_kwargs['foo_id']

I include it in settings.py:

MIDDLEWARE_CLASSES = (
    ...
    'myproject.myapp.middleware.FindObjects',
)

And now my views look like this:

def show(request, foo):
    ... yay, do stuff with foo ...

Very useful for views with many parameters, or views with multiple optional parameters. In one project, I have views which process data for three different situations: data in a metropolitan area, data in a city, or data in a city within a metro. My middleware for that looks like this:

from django.shortcuts import get_object_or_404
from phuce.metros.models import City, Metro

class FindObjects:
    def process_view(self, request, view_func, view_args, view_kwargs):
        city = metro = None
        if 'metro_link' in view_kwargs:
            metro_link = view_kwargs['metro_link']
            metro = get_object_or_404(Metro, link=metro_link)
            del view_kwargs['metro_link']
            view_kwargs['metro'] = metro
        if 'city_link' in view_kwargs:
            city_link = view_kwargs['city_link']
            if metro:
                city = get_object_or_404(City, metro=metro,
                                         metro_link=city_link)
            else:
                city = get_object_or_404(City, link=city_link)
            del view_kwargs['city_link']
            view_kwargs['city'] = city

It’s much tidier without that monster in my views.

PyOpenGL's extension wrappers

Posted on in

Normally if you wanted to get access to an OpenGL extension, you’d have to do something like:

from ctypes import *
from OpenGL import platform
gl = platform.OpenGL
glGetShaderiv = gl.glGetShaderiv
glGetShaderiv.argtypes = [c_int, c_int, POINTER(c_int)]

Gross. Luckily, PyOpenGL version 3.0.0a5 and later will automatically map ARB standard functions for you when they are available. Now all you have to do is:

from OpenGL.GL import *

And everything will be magically available to you, wrapped so you don’t have to use ctypes to create c_char_p or c_int variables to pass them.

Watch out, though! The functions won’t be mapped correctly if your display context hasn’t been created yet. Always make sure to import OpenGL after the pygame display has been initialized.

# first initialize pygame
import pygame
from pygame.locals import *
pygame.init()
pygame.display.set_mode((800, 600), OPENGL | DOUBLEBUF)

# now you can import it
from OpenGL.GL import *

I would love to know how to manually tell PyOpenGL to re-map everything after initializing pygame, though. I don’t like having to reposition the import like that. Nathan Gray has a deep reload replacement for the reload builtin, which might work, but I’m not sure if that’s the best solution to this problem…