Thursday, July 19, 2012

How to use sys.meta_path with Python

Update: See this article for a Python 3 take on import hooks.  

I was asked on Reddit a short while ago as to how to use sys.meta_path, which is an extremely valuable tool that can be used to implement import hooks. Since it seems there's little documentation as to how to use it properly, I decided to write an example that shows basic usage of sys.meta_path. I posted the example on Reddit in the thread I linked to, but I've put it here for posterity - enjoy. :)

import sys


class VirtualModule(object):

   def hello(self):
      return 'Hello World!'


class CustomImporter(object):

   virtual_name = 'my_virtual_module'

   def find_module(self, fullname, path=None):
      """This method is called by Python if this class
         is on sys.path. fullname is the fully-qualified
         name of the module to look for, and path is either
         __path__ (for submodules and subpackages) or None (for
         a top-level module/package).

         Note that this method will be called every time an import
         statement is detected (or __import__ is called), before
         Python's built-in package/module-finding code kicks in.
         Also note that if this method is called via pkgutil, it is possible
         that path will not be passed as an argument, hence the default value.
         Thanks to Damien Ayers for pointing this out!"""

      if fullname ==  self.virtual_name:
      
         # As per PEP #302 (which implemented the sys.meta_path protocol),
         # if fullname is the name of a module/package that we want to
         # report as found, then we need to return a loader object.
         # In this simple example, that will just be self.

         return self

      # If we don't provide the requested module, return None, as per
      # PEP #302.

      return None

   def load_module(self, fullname):
      """This method is called by Python if CustomImporter.find_module
         does not return None. fullname is the fully-qualified name
         of the module/package that was requested."""

      if fullname != self.virtual_name:
         # Raise ImportError as per PEP #302 if the requested module/package
         # couldn't be loaded. This should never be reached in this
         # simple example, but it's included here for completeness. :)
         raise ImportError(fullname)

      # PEP#302 says to return the module if the loader object (i.e,
      # this class) successfully loaded the module.
      # Note that a regular class works just fine as a module.
      return VirtualModule()


if __name__ == '__main__':

   # Add our import hook to sys.meta_path
   sys.meta_path.append(CustomImporter())

   # Let's use our import hook
   import my_virtual_module
   print my_virtual_module.hello()

Note: The original PEP that defined the sys.meta_path protocol is PEP #302, which you can read here.

Saturday, July 14, 2012

Reverse-engineering LEGO Racers 1 - part 1

First off, a brief description of LEGO Racers 1: It basically was a racing game released back in 1999 (and then re-released in 2001) where you could make your own car (and driver) out of LEGO bricks and then race it against half-a-dozen or so AI cars or a friend, on one of about two dozen tracks. Sounds fun, right? It is.



Sadly, since the game was released so long ago, it can be difficult to run it on a modern OS - the 1999 release of the game had DRM that required the disk, for example - not to mention there's quite a bit of dummied-out content (several shortcuts are missing, most famously from the Knightmare-athon track) that I and probably several others would love to play around with and modify. And that's why I've decided to write a drop-in replacement for the LEGO Racers 1 game engine.

It's not a new idea - I can bring up forum threads from up to 2 years ago of people attempting to mod LEGO Racers 1. That being said, these people are trying to mod the game itself, not create a replacement for LEGO Racers 1's game engine. I want to create a game engine instead of attempting to mod the game itself for several reasons:
  • A mod of the game still would have issues with the DRM and compatibility issues I previously mentioned; one would still need the original game to play the mod.
  • A mod of the game would not be able to add new content without removing existing content; I doubt, for instance, you could add new circuits, bricks, chassis, or piece sets (you unlocked the pieces of each bosses car when you beat them) without removing existing content.
  • A mod of the game would still be subject to the limitations of the original game engine - AI cars still wouldn't follow shortcuts, the AI behavior itself couldn't be changed, no new racing modes could be added, racing with more than 2 human players wouldn't be possible (and even then, you'd need a joystick), etc. In other words, only content would be moddable, not game logic.
There would be many advantages to making a game engine as well:
  • Not only would only the data files from the original game be required to play, but it would be feasible to create a replacement for the original data files as well, so you wouldn't even need the original game to play (ala PrBoom + freedoom).
  • A replacement for LEGO Racers 1's game engine would allow everything to be moddable - powerups, tracks, circuits, AI behavior (imagine the AI being a script the game engine runs instead of being part of the engine itself), bricks, piece sets, cutscenes, animations - everything.
  • Making a replacement game engine instead of modding the original game makes modding much easier and more approachable to a new modder.
Right now, I intend to make the engine open-source (under the Apache License 2.0, probably), and host it on GitHub, to make it more accessible to potential developers. If you'd like to help out (that said, I haven't started yet), let me know. :) I'll try to keep updating my blog as progress on reverse-engineering LEGO Racers 1's data formats is made.

Friday, July 13, 2012

Minetest Triforce

In case you're not familiar with it, Minetest is basically a free, open-source clone of Minecraft, plus some new stuff like Lua mod support. Anyway, I made a very large Triforce on gameboom's mt1.gameboom.net (port 30000) Minetest server some time ago, and this is the result:

Daytime


Nighttime


Monday, July 9, 2012

Evo 2012 - one hype event!

In case you're not familiar with it, Evo is a international fighting game tournament (though Mario Kart was on the roster one year a few years back) held every year in Las Vegas, Nevada. It attracts thousands (if not tens of thousands) of participants and spectators every year from places like Taiwan, Japan, and South Korea. Indeed, many of the top players come from those countries. The live video stream of the tournament attracted almost a hundred thousand viewers from all over the world at its peak, which is an amazing thing.


I wasn't able to watch the tournament in person, but I was able to watch the livestream for the entirety of the Super Street Fighter IV AE 2012 and Ultimate Marvel vs. Capcom 3 events. There were quite a few exciting matches - for me, here are the highlights of the tournament:






Hopefully, I'll be able to watch Evo in person next year, and possibly compete in the Super Street Fighter IV AE 2012 section if I ever buy the game.

Switching to Blogger

I exported my WordPress blog to Blogger - I think I'm going to enjoy the change. We'll see about that in the coming months, though. :)