[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Troll] Java Port -- Libraries



[Aside]
This is the first in what is probably a long series of messages about the 
Java Port and the decisions I made/am making about it.  I'm just generally 
looking for feedback here; any possible ideas anyone has are welcome.  This 
stuff is not game design stuff, BTW, but rather gory details of the Java 
implementation and the potential ramifications for the C++ 
version.  Without further ado...

Libraries
=========

Dennis and I had a long discussion about the desired goals of the libraries 
under the C++ version of TrollBridge.  The difficulty that arose was seeing 
how to implement the same general idea under Java, where I do not have 
function pointers.  Let me explain:

Typically under C++, the loading of libraries works as follows:

* TrollGame constructed
* TrollGame::loadLibrary("./troll.dll");
* loadLibrary calls TrollDllInit
* TrollDllInit makes callbacks to the TrollGame, adding the needed items as 
function pointers in the array of monsters, items, etc.

Java, of course, does not have function pointers.  Instead, I've decided to 
go with the use of Java "Method" objects from the Reflection API.  (Refer 
to the Java Tutorial on Reflection, if you care.)  I also need to add some 
interfaces to make the calls easier.  In Java the loading will work like this:

* TrollGame constructed
* TrollGame.loadLibrary("DefaultTrollLibrary");  // Or other library
* loadLibrary instantiates bootstrapper class, DefaultTrollLibrary
* DefaultTrollLibrary::init makes callbacks to the TrollGame, adding 
TrollMonsterConstructors, TrollItemConstructors, etc., which are wrappers 
for "Methods."

----

package com.identicalsoftware.trollbridge;

public interface TrollLibrary {
  static void init () throws TrollLibraryError;
}

----

Each library needs a "bootstrap class" to load the actual library.  This 
class basically holds the "TrollDllInit" method, now called "Init".

----

package com.identicalsoftware.trollbridge.gamedll;

import com.identicalsoftware.trollbridge.*;

public class DefaultTrollLibrary implements TrollLibrary
{
  public static void init () throws TrollLibraryError
  {
   try
   {
    Class temp;

    temp = Class.forName(
      "com.identicalsoftware.trollbridge.gamedll.TrollPerson");
    game.addMonsterType(0,
      new TrollMonsterConstructor(temp.getMethod("createGrayTroll", null)));

    temp = Class.forName(
      "com.identicalsoftware.trollbridge.gamedll.TrollDoor");
    game.addMonsterType(1,
      new TrollMonsterConstructor(temp.getMethod("createNorthDoor", null)));
    game.addMonsterType(2,
      new TrollMonsterConstructor(temp.getMethod("createSouthDoor", null)));
    game.addMonsterType(3,
      new TrollMonsterConstructor(temp.getMethod("createWestDoor", null)));
    game.addMonsterType(4,
      new TrollMonsterConstructor(temp.getMethod("createEastDoor", null)));

    /* ... */

    return;
   }
   catch (Exception e)
   {
    throw new TrollLibraryException(e.getMessage());
   }
  }
}

----

Here the bootstrapper simply uses Relection to create the "Method" objects 
which point to the static factory methods that create the actual objects in 
question.  ("Factory Methods" just mean methods that create a new object 
instance, and return that instance.)  It is important that these methods be 
static, BTW.

TrollMonsterConstructor is simply a wrapper for the Method which calls the 
method and casts the result to the appropriate type.  It is a array of 
these that is stored in the TrollGame class.  I won't bore you with the 
implementation.

The only thing that remains to be examined is the TrollGame::loadLibrary 
function, which looks like this:

----

  /** Loads a library and runs init. <P>
   *  @param bootstrap_name full name of the library bootstraping class
   *  @throws TrollLibraryError if there is a problem loading the library
   */
  protected void loadLibrary (String bootstrap_name) throws TrollLibraryError
  {
   try
   {
    TrollLibrary tl = (TrollLibrary) Class.forName(bootstrap_name)
                                          .newInstance();
    if (tl == null)
     throw new TrollLibraryError(bootstrap_name + " is not a library!");

    tl.init(this);
    return;
   }
   catch (InstantiationException ie)
   {
    throw new TrollLibraryError(ie.getMessage());
   }
   catch (IllegalAccessException iae)
   {
    throw new TrollLibraryError(iae.getMessage());
   }
  }

----

We use Reflection, again, to load the class file for the library, and then 
call init if everything works out.


The Bottom Line
===============

The basic frameworks for libraries under the Java port is presented 
above.  Currently, the code examines the arguments to the program, and 
interprets them as the names of bootstrap classes for various libraries, 
and attempts to load them; if no arguments are specified, the default 
library is loaded.  The payoff of using reflection is that the libraries 
can be passed as command line arguments to the program, which ideally, is 
what we want.

To implement a new library, follow these simple steps:

1) Write your monster classes, etc., as normal.

2) Decide on where they will be in the main arrays, and whether your 
library will require (or be compatible with) other libraries.

3) Implement the bootstrapper class ("implements TrollLibrary") as 
suggested above.

4) Pass the name of the bootstrapper class to the program when you run it.

The impact here is that for the implementor of the library, there is 
minimal extra work to do this in Java, even sans function pointers.  The 
Java code is in the same style as the C++ code, with the addition of the 
bootstrapper class.

Comments, questions, explosions?

:)

Thanks all,
Kenn


--------------------------------------------------------------
IMPORTANT: The below information has changed!  Please use the
email addresses below to contact me.
------------------------------+-------------------------------
Kenneth W. Flynn              | flynnk@astro.umd.edu
Graduate Fellow, Astronomy    | flynn@nrl.itd.navy.mil
UMD (College Park)            | And 10 or so others...
------------------------------+-------------------------------