[skycastle-commits] SF.net SVN: skycastle: [467] trunk/skycastle/modules

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Sat, 19 Apr 2008 03:01:55 -0700

Revision: 467
          http://skycastle.svn.sourceforge.net/skycastle/?rev=467&view=rev
Author:   zzorn
Date:     2008-04-19 03:01:55 -0700 (Sat, 19 Apr 2008)

Log Message:
-----------
Fixed issue related to server side game context referenced without a managed 
reference.  Now it compiles, runs, and works after restart.

Modified Paths:
--------------
    
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/AbstractFacade.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameContext.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/MessagingFacadeImpl.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/ActionFacadeImpl.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/property/PropertyFacadeImpl.java
    
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectActionsTest.java
    
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectPropertiesTest.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/ButtonUi.java

Modified: 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
===================================================================
--- 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
 2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/client/src/main/java/org/skycastle/client/ClientObject.java
 2008-04-19 10:01:55 UTC (rev 467)
@@ -1,8 +1,6 @@
 package org.skycastle.client;
 
-import org.skycastle.core.DefaultGameObject;
-import org.skycastle.core.GameContext;
-import org.skycastle.core.GameObject;
+import org.skycastle.core.*;
 import org.skycastle.core.acting.ActionImpl;
 import org.skycastle.ui.*;
 import org.skycastle.util.parameters.ParameterSetMetadataImpl;
@@ -94,27 +92,61 @@
 
     private static UiObject createClientUi()
     {
-        // TODO: Later maybe read this from config file or a persistent 
storage?
+        try
+        {
+// TODO: Later maybe read this from config file or a persistent storage?
 
-        final GameObject client = 
GameContext.getGameObjectContext().getGameObjectBoundToName( "client" );
+            final GameObjectContext context = 
GameContext.getGameObjectContext();
+            final GameObject client = context.getGameObjectBoundToName( 
"client" );
 
-        final SplitPanelUi splitPanelUi = new SplitPanelUi();
+            final SplitPanelUi splitPanelUi = context.createGameObject( 
SplitPanelUi.class );
 
-        final PanelUi clientBar = new PanelUi();
-        clientBar.addUi( new LabelUi( "This is the client bar" ) );
-        clientBar.addUi( new LabelUi( "<Connected server address goes here>" ) 
);
-        clientBar.addUi( new ButtonUi( client.getId(), "exit" ) );
-        //clientBar.addUi( new ButtonUi( ) ); // TODO: Create some named 
object that represents the client, that has methods like quit, logon to server, 
etc.
+            final PanelUi clientBar = context.createGameObject( PanelUi.class 
);
+            clientBar.addUi( createLabel( "This is the client bar" ) );
+            clientBar.addUi( createLabel( "<Connected server address goes 
here>" ) );
+            clientBar.addUi( createButton( client.getId(), "exit" ) );
+            //clientBar.addUi( new ButtonUi( ) ); // TODO: Create some named 
object that represents the client, that has methods like quit, logon to server, 
etc.
 
-        final PanelUi loginWindow = new PanelUi();
-        loginWindow.addUi( new LabelUi( "Server address:" ) );
-        loginWindow.addUi( new LabelUi( "<Input text field goes here>" ) );
-        loginWindow.addUi( new ButtonUi( client.getId(), "login" ) );
+            final PanelUi loginWindow = context.createGameObject( 
PanelUi.class );
+            loginWindow.addUi( createLabel( "Server address:" ) );
+            loginWindow.addUi( createLabel( "<Input text field goes here>" ) );
+            loginWindow.addUi( createButton( client.getId(), "login" ) );
 
-        splitPanelUi.setFirstUi( clientBar );
-        splitPanelUi.setSecondUi( loginWindow );
+            splitPanelUi.setFirstUi( clientBar );
+            splitPanelUi.setSecondUi( loginWindow );
 
-        return splitPanelUi;
+            return splitPanelUi;
+        }
+        catch ( InstantiationException e )
+        {
+            e.printStackTrace();  //To change body of catch statement use File 
| Settings | File Templates.
+        }
+        catch ( IllegalAccessException e )
+        {
+            e.printStackTrace();  //To change body of catch statement use File 
| Settings | File Templates.
+        }
+        return null;
     }
 
+    private static LabelUi createLabel( final String text )
+            throws IllegalAccessException, InstantiationException
+    {
+        final GameObjectContext context = GameContext.getGameObjectContext();
+        final LabelUi labelUi = context.createGameObject( LabelUi.class );
+        labelUi.setText( text );
+
+        return labelUi;
+    }
+
+    private static ButtonUi createButton( GameObjectId gameObjectId, final 
String actionId )
+            throws IllegalAccessException, InstantiationException
+    {
+        final GameObjectContext context = GameContext.getGameObjectContext();
+        final ButtonUi ui = context.createGameObject( ButtonUi.class );
+        ui.getActionReference().setReference( gameObjectId, actionId );
+
+        return ui;
+    }
+
+
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/AbstractFacade.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/AbstractFacade.java
   2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/AbstractFacade.java
   2008-04-19 10:01:55 UTC (rev 467)
@@ -16,7 +16,6 @@
     //======================================================================
     // Private Fields
 
-    private final GameObjectContext myGameObjectContext;
     private final GameObject myGameObject;
 
     //======================================================================
@@ -32,17 +31,16 @@
 
     /**
      * Creates a new {@link org.skycastle.core.AbstractFacade}.
+     *
+     * @param gameObject the {@link GameObject} that this facade is for.
      */
-    protected AbstractFacade( final GameObject gameObject, final 
GameObjectContext gameObjectContext )
+    protected AbstractFacade( final GameObject gameObject )
     {
         ParameterChecker.checkNotNull( gameObject, "gameObject" );
-        ParameterChecker.checkNotNull( gameObjectContext, "gameObjectContext" 
);
 
         myGameObject = gameObject;
-        myGameObjectContext = gameObjectContext;
     }
 
-
     /**
      * @return the {@link GameObject} that this {@link AbstractFacade} is part 
of.
      */
@@ -68,7 +66,7 @@
      */
     protected final GameObjectContext getContext()
     {
-        return myGameObjectContext;
+        return GameContext.getGameObjectContext();
     }
 
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
    2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ClientContext.java
    2008-04-19 10:01:55 UTC (rev 467)
@@ -73,7 +73,7 @@
     //----------------------------------------------------------------------
     // GameObjectContext Implementation
 
-    public final GameObjectId createGameObjectId( final GameObject gameObject )
+    private final GameObjectId createGameObjectId( final GameObject gameObject 
)
     {
         // IMPLEMENT: TODO: How should we create the ID?  For client side 
GameObjects, we need some specific prefix...
         // DEBUG
@@ -101,29 +101,24 @@
 
     public GameObject createGameObject()
     {
-        final DefaultGameObject gameObject = new DefaultGameObject();
-        setupGameObject( gameObject );
-
-        return gameObject;
+        return setupGameObject( GameObject.class, new DefaultGameObject() );
     }
 
-    private void setupGameObject( final GameObject gameObject )
-    {
-        // NOTE: Casting to default game object so we can set the id.  Might 
not work in all cases, maybe come up with better solution for the id setting?
-        ( (DefaultGameObject) gameObject ).setId( createGameObjectId( 
gameObject ) );
-
-        addGameObject( gameObject );
-    }
-
     public <T extends GameObject> T createGameObject( final Class<T> 
gameObjectType )
             throws InstantiationException, IllegalAccessException
     {
         ParameterChecker.checkNotNull( gameObjectType, "gameObjectType" );
 
-        final T gameObject = gameObjectType.newInstance();
+        return setupGameObject( gameObjectType, gameObjectType.newInstance() );
+    }
 
-        setupGameObject( gameObject );
+    private <T extends GameObject> T setupGameObject( final Class<T> 
gameObjectType, final T gameObject )
+    {
+        // NOTE: Casting to default game object so we can set the id.  Might 
not work in all cases, maybe come up with better solution for the id setting?
+        ( (DefaultGameObject) gameObject ).setId( createGameObjectId( 
gameObject ) );
 
+        addGameObject( gameObject );
+
         return gameObject;
     }
 

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
        2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
        2008-04-19 10:01:55 UTC (rev 467)
@@ -38,7 +38,7 @@
     private final ActionFacadeImpl myActionFacade;
     private final MessagingFacade myMessagingFacade;
 
-    private GameObjectId myId;
+    private GameObjectId myId = null;
 
     //======================================================================
     // Private Constants
@@ -51,11 +51,15 @@
     //----------------------------------------------------------------------
     // Constructors
 
-    public DefaultGameObject()
+    /**
+     * The constructor is protected, as GameObjects should only be created by 
the {@link GameObjectContext}s.
+     */
+    @SuppressWarnings( { "ThisEscapedInObjectConstruction" } )
+    protected DefaultGameObject()
     {
-        myPropertyFacade = new PropertyFacadeImpl( this, 
getGameObjectContext() );
-        myActionFacade = new ActionFacadeImpl( this, getGameObjectContext() );
-        myMessagingFacade = new MessagingFacadeImpl( this, 
getGameObjectContext() );
+        myPropertyFacade = new PropertyFacadeImpl( this );
+        myActionFacade = new ActionFacadeImpl( this );
+        myMessagingFacade = new MessagingFacadeImpl( this );
     }
 
     //----------------------------------------------------------------------
@@ -121,10 +125,9 @@
 
     public final GameObjectId getId()
     {
-        // Lazy init
         if ( myId == null )
         {
-            myId = getGameObjectContext().createGameObjectId( this );
+            throw new IllegalStateException( "The ID of this object has not 
been initialized during construction" );
         }
 
         return myId;

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameContext.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameContext.java  
    2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameContext.java  
    2008-04-19 10:01:55 UTC (rev 467)
@@ -53,13 +53,13 @@
             }
             catch ( NameNotBoundException e )
             {
-                final ServerSideContext serverSideContext = new 
ServerSideContext();
 
-                final ManagedReference reference = 
dataManager.createReference( serverSideContext );
+                final ServerSideContext context = new ServerSideContext();
+                final ManagedReference reference = 
dataManager.createReference( context );
 
-                dataManager.setBinding( SERVER_SIDE_GAME_CONTEXT_BINDING_NAME, 
serverSideContext );
+                dataManager.setBinding( SERVER_SIDE_GAME_CONTEXT_BINDING_NAME, 
context );
 
-                return serverSideContext;
+                return reference.get( ServerSideContext.class );
             }
         }
         else

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
        2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/GameObjectContext.java
        2008-04-19 10:01:55 UTC (rev 467)
@@ -9,10 +9,6 @@
 public interface GameObjectContext
 {
 
-    /**
-     * @return the id of the specified {@link GameObject}.
-     */
-    GameObjectId createGameObjectId( GameObject gameObject );
 
     /**
      * Requests that the run method of the specified gameObject is called 
after the specified amount of

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/MessagingFacadeImpl.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/MessagingFacadeImpl.java
      2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/MessagingFacadeImpl.java
      2008-04-19 10:01:55 UTC (rev 467)
@@ -35,9 +35,9 @@
     /**
      * Creates a new {@link org.skycastle.core.MessagingFacadeImpl}.
      */
-    public MessagingFacadeImpl( final GameObject gameObject, final 
GameObjectContext gameObjectContext )
+    public MessagingFacadeImpl( final GameObject gameObject )
     {
-        super( gameObject, gameObjectContext );
+        super( gameObject );
     }
 
     //----------------------------------------------------------------------

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
        2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideContext.java
        2008-04-19 10:01:55 UTC (rev 467)
@@ -27,21 +27,6 @@
 
     // TODO: Change to reflect that the GameContext internally manages all 
game objs.
 
-    public GameObjectId createGameObjectId( final GameObject gameObject )
-    {
-        ParameterChecker.checkNotNull( gameObject, "gameObject" );
-        checkImplementsManagedObject( gameObject );
-
-        final DataManager dataManager = AppContext.getDataManager();
-
-        // Assign unique ID, and bind it, so that we can access this object 
easily in the future
-        final ManagedReference reference = dataManager.createReference( 
(ManagedObject) gameObject );
-        final GameObjectId id = new GameObjectId( 
GameObjectId.GAME_OBJECT_BINDING_PREFIX + reference.getId().toString() );
-        dataManager.setBinding( id.toString(), (ManagedObject) gameObject );
-        return id;
-    }
-
-
     public void addTaskCallback( final long timeOfCallback_ms, final 
GameObject gameObject )
     {
         throw new UnsupportedOperationException( "This method has not yet been 
implemented." ); // IMPLEMENT
@@ -71,31 +56,16 @@
 
     public GameObject createGameObject()
     {
-        final GameObject serverSideGameObject = new ServerSideGameObject();
-
-        // Assign ID and register the object.
-        createGameObjectId( serverSideGameObject );
-
-        return serverSideGameObject;
+        return registerGameObject( ServerSideGameObject.class, new 
ServerSideGameObject() );
     }
 
     public <T extends GameObject> T createGameObject( final Class<T> 
gameObjectType )
             throws InstantiationException, IllegalAccessException
     {
-        ParameterChecker.checkNotNull( gameObjectType, "gameObjectType" );
-        if ( !gameObjectType.isAssignableFrom( ServerSideGameObject.class ) )
-        {
-            throw new IllegalArgumentException( "The type of the object has to 
be a subtype of ServerSideGameObject on the server, but it was '" + 
gameObjectType + "' ." );
-        }
-
-        final T serverSideGameObject = gameObjectType.newInstance();
-
-        // Assign ID and register the object.
-        createGameObjectId( serverSideGameObject );
-
-        return serverSideGameObject;
+        return registerGameObject( gameObjectType, (ServerSideGameObject) 
gameObjectType.newInstance() );
     }
 
+
     public void bindGameObjectToName( final String name, final GameObject 
gameObject )
     {
         ParameterChecker.checkNotNull( gameObject, "gameObject" );
@@ -126,6 +96,27 @@
     //======================================================================
     // Private Methods
 
+    private <T extends GameObject> T registerGameObject( final Class<T> 
gameObjectType, ServerSideGameObject createdGameObject )
+    {
+        ParameterChecker.checkNotNull( gameObjectType, "gameObjectType" );
+        if ( !gameObjectType.isAssignableFrom( ServerSideGameObject.class ) )
+        {
+            throw new IllegalArgumentException( "The type of the object has to 
be a subtype of ServerSideGameObject on the server, but it was '" + 
gameObjectType + "' ." );
+        }
+
+        // Add to managed objects, and get reference
+        final DataManager dataManager = AppContext.getDataManager();
+        final ManagedReference reference = dataManager.createReference( 
(ManagedObject) createdGameObject );
+        final T serverSideGameObject = reference.getForUpdate( gameObjectType 
);
+
+        // Assign unique ID, and bind it, so that we can access this object 
easily in the future
+        final GameObjectId id = new GameObjectId( 
GameObjectId.GAME_OBJECT_BINDING_PREFIX + reference.getId().toString() );
+        dataManager.setBinding( id.toString(), (ManagedObject) 
serverSideGameObject );
+        ( (ServerSideGameObject) serverSideGameObject ).setId( id );
+
+        return serverSideGameObject;
+    }
+
     private void checkImplementsManagedObject( final GameObject gameObject )
     {
         if ( !( gameObject instanceof ManagedObject ) )

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
     2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/ServerSideGameObject.java
     2008-04-19 10:01:55 UTC (rev 467)
@@ -23,6 +23,9 @@
     //----------------------------------------------------------------------
     // Constructors
 
+    /**
+     * Package protected constructor, should only be created with {@link 
ServerSideContext}.
+     */
     ServerSideGameObject()
     {
     }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/ActionFacadeImpl.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/ActionFacadeImpl.java
  2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/acting/ActionFacadeImpl.java
  2008-04-19 10:01:55 UTC (rev 467)
@@ -47,9 +47,9 @@
     /**
      * Creates a new {@link ActionFacadeImpl}.
      */
-    public ActionFacadeImpl( final GameObject gameObject, final 
GameObjectContext gameObjectContext )
+    public ActionFacadeImpl( final GameObject gameObject )
     {
-        super( gameObject, gameObjectContext );
+        super( gameObject );
     }
 
     //----------------------------------------------------------------------

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/property/PropertyFacadeImpl.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/property/PropertyFacadeImpl.java
      2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/property/PropertyFacadeImpl.java
      2008-04-19 10:01:55 UTC (rev 467)
@@ -2,7 +2,6 @@
 
 import org.skycastle.core.AbstractFacade;
 import org.skycastle.core.GameObject;
-import org.skycastle.core.GameObjectContext;
 import org.skycastle.messaging.updates.property.*;
 import org.skycastle.util.ParameterChecker;
 import org.skycastle.util.StringUtilities;
@@ -55,9 +54,9 @@
     /**
      * Creates a new {@link PropertyFacadeImpl}.
      */
-    public PropertyFacadeImpl( final GameObject gameObject, final 
GameObjectContext gameObjectContext )
+    public PropertyFacadeImpl( final GameObject gameObject )
     {
-        super( gameObject, gameObjectContext );
+        super( gameObject );
     }
 
     //----------------------------------------------------------------------

Modified: 
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectActionsTest.java
===================================================================
--- 
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectActionsTest.java
    2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectActionsTest.java
    2008-04-19 10:01:55 UTC (rev 467)
@@ -124,7 +124,7 @@
         myUnitTestingContext = new UnitTestingContext();
         GameContext.setGameObjectContextOnClient( myUnitTestingContext );
 
-        myGameObject = new DefaultGameObject();
+        myGameObject = myUnitTestingContext.createGameObject();
 
         myGameObject.addProperty( ACTION_INVOKED, false );
         myGameObject.addProperty( REPEAT_INTERVALL, -1 );

Modified: 
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectPropertiesTest.java
===================================================================
--- 
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectPropertiesTest.java
 2008-04-19 01:37:07 UTC (rev 466)
+++ 
trunk/skycastle/modules/core/src/test/java/org/skycastle/core/AbstractGameObjectPropertiesTest.java
 2008-04-19 10:01:55 UTC (rev 467)
@@ -302,9 +302,10 @@
     protected void setUp()
             throws Exception
     {
-        GameContext.setGameObjectContextOnClient( new UnitTestingContext() );
+        final UnitTestingContext unitTestingContext = new UnitTestingContext();
+        GameContext.setGameObjectContextOnClient( unitTestingContext );
 
-        myGameObject = new DefaultGameObject();
+        myGameObject = unitTestingContext.createGameObject();
 
         // Keep the messages sent by the game object
         mySentMessages = new ArrayList<Message>( 10 );

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/ButtonUi.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/ButtonUi.java     
2008-04-19 01:37:07 UTC (rev 466)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/ui/ButtonUi.java     
2008-04-19 10:01:55 UTC (rev 467)
@@ -39,6 +39,10 @@
     //----------------------------------------------------------------------
     // Constructors
 
+    public ButtonUi()
+    {
+    }
+
     public ButtonUi( GameObjectId gameObjectId, String actionIdentifier )
     {
         myActionReference.setReference( gameObjectId, actionIdentifier );


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

Other related posts:

  • » [skycastle-commits] SF.net SVN: skycastle: [467] trunk/skycastle/modules