Commands explaination

Would someone be able to give me a brief description of the workings of commands and how they work. Specifically, I am a bit confused on the sendtodeck function in the deck.java. I searched for where it is called and couldn’t find it…
(I still don’t have debug functionality… otherwise I think I would figure this out)
So how does the context menu cause the command to actually get called?

Second any help with being able to debug, (create break points that actually break) would be appreciated!

Thus spake “vbbartlett”:

One reason this might be failing for you is if you’re using the wrong
entry point for what you’re trying to debug. Are you using
VASSAL.launch.Player when trying to debug the Player?


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Hi,

What’s your name?

Can I get you to have a look at

RFE [2818259] Cannot report Save/Load Deck commands

also while you are in the Deck code? The Save/Load commands are hard-coded with no report format attached. You need to make them similiar to the way ‘Reversible?’ works.

If you can get this committed to your 3.1 branch, I will merge it into the TRUNK.

First of all, Deck’s are actually made up of two parts - a DrawPile which is the AbstractConfigurable part that is defined in the module and a Deck which is a GamePiece and actually exists when the game is running. DrawPile is just an Editable shell that doesn’t really do anything, all the action takes place in Deck.

In Deck, the ‘Send To Deck’ functionality is confusing called ‘Reshuffle’, so look for varables named ‘reshuffleXXXX’.

The SendToDeck functionality is implemented in

Deck.sendToDeck() at line Deck:1152

This is called from one of two places, depending on whether the player hits the SendToDeck Hotkey, or right-clicks and select the Send To Deck command.

The Hot Key Listener is set up in Deck:354-363 where a global KeyListener is registered with the module. If the key is hit, the actionPerformed() method is called at Deck:356.

The Menu Command is set up at Deck:935-945 in getKeyCommands(). The menu is actually built by the generic map menubuilder VASSAL.build.module.map.MenuDisplayer.

Commands are the most vitally important part of VASSAL to understand. Commands are the objects that are stored in log files and/or sent accross the network to other clients attached to a multi-player room. Anything you do that affects any aspect of VASSAL that you need to send to other clients MUST be encoded as a Command.

You will see this sort of construct often:

Command c = new DoSomethingCommands(…);
c.execute(); // Execute the Command on my client;
GameModule.getGameModule().sendAndLog(c); // Send Command to log file and other clients

When another client receives the Command, it will call the execute() method to do the same work on it as occured on the generating client.

This is the best way to use commands as exactly the same code will be exeucted at both ends.

You also see another way where a Generic command is used to capture the change of state of something, especially GamePieces.

ChangeTracker change = new ChangeTracker(gamePiece)
// Do some stuff that changes gamePiece
Command c = change.getChangeCommand();
GameModule.getGameModule().sendAndLog(c);

c.execute() is NOT called on our client because the changes have already happened. ChangeTracker returns a generic ChangePiece command that just updates the ‘state’ of the GamePiece to reflect the accumulated changes to the gamePiece. The same code is NOT executed at both ends.

The ‘type’ of a gamepiece is an accumulated string that represents the structure of all trait levels in a GamePiece. It is built up from all of the myGetType() calls of the individual Decorators.

The ‘state’ of a gamepiece is an accumulated string that represents the current state of all trait levels in a GamePiece. It is built up from all of the myGetState() calls of the individual Decorators.

Hope this helps, Keep asking questions…

I’m very keen to get you going. Your productivity is much diminished without debug capability.

Did Joel suggestion work? Sounds like you are debugging the ModuleManager and not the Player or Editor to me. The best entrypoint to use is:

VASSAL.launch.Editor

with the program arguments

–edit “D:\Vassal\Modules\A Most Dangerous Time\updater_test.vmod.zip”

If you are still having trouble, please post screnshots of the different tabs of the Debug Configuration you are trying to use.

Regards,
Brent.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Name = Carl
So my work box is up and running! :smiley: Not sure what all I did to get it running. It just kept giving me the cannot connect to VM. Did some searching reinstalls… moving dlls… adding path variables… and after a while it worked.
(It might have been my firewall, i opened ports in it)

Anyway im up and running and debugging!!! Starting to understand a lot more once i followed the code source down to my areas of concern. Your description of the commands now makes a lot more sense after seeing them in action. Thx for the details.
As for the RFE - I will take a look at it but I don’t have a lot of time and I really need to look at how to get the commands working for allowing a deck to be sent to multiple locations. In the process I will look into that bug.

thx for the help.

Hi Carl,

Excellent!

Don’t be afraid to ask questions. It took me a good year of tracing execution through the debugger to build a workable knowledge of about half of the major components of the code!

You need to create the SendToDeck components as AbstractConfigurables that allowable Children components of DrawPile. In your new Component. Follow the pattern of the DeckGlobalKeyCommand closely, it is very similiar.

Rgds,
B.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Ok after looking some more the load save report should be easy enough.

can you explain the getKeyCommands() in deck.java
what confuses me is the following code

if (reshuffleCommand.length() > 0) {
        c = new KeyCommand(reshuffleCommand, getReshuffleKey(), this) {
          private static final long serialVersionUID = 1L; 

          public void actionPerformed(ActionEvent evt) {
            GameModule.getGameModule().sendAndLog(sendToDeck());
            repaintMap();
          }
        };
        l.add(c);
      }

specifically the actionPerformed() function that is declared there. How does it work. Seems like when that context menu is hit if fires that chunk of code but I am missing how Java works in this respect. (Not how it is done in C++)

[/code]

Sorry but that went right over my head! What I got was I need to create member array of decks to point to and like the globals, I add those decks to this one. Then when the command is fired, catch it and call a SendToDeckX () that determines the deck and moves the cards?

what does “AbstractConfigurables that allowable Children components of DrawPile” mean?
What are AbstractConfigurables ?
[/quote]

Hi Carl,

My bible to understanding what is going on with Swing is the Sun Java tutorial:

java.sun.com/docs/books/tutorial/

KeyCommands are a subclass of Action:

java.sun.com/docs/books/tutorial … ction.html

Deck.getKeyCommands() returns an arry of the KeyCommands that are currently applicable to this Deck in it’s current state. These KeyCommands are used by the MenuDisplayer to build and show a popupmenu. Each KeyCommand (Action) is attached to a menu entry. When the user selects a menu option, the actionPerformed(Event e) is called automatically.

B.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

[/quote]

A module is a tree structure, as visible in the module editor.

Each node on the tree is a subclass of AbstractConfigurable which provides all of the facilities to allow the component to be Automatically built, edited and saved based on the information retuned by the methods defined in AbstractConfigurable.

The top-level component in the tree is GameModule.

Each component specifies what components are allowed to be added to it as children in the getAllowableConfigureComponents() method. Here it is for DrawPile:

public Class<?>[] getAllowableConfigureComponents() { return new Class<?>{CardSlot.class, DeckGlobalKeyCommand.class};
}

Hence, when you right-click on a DrawPile (i.e. Deck) in the Editor, you are given the option to add a Card or a Deck Global Key Command.

You will need to change this to be

public Class<?>[] getAllowableConfigureComponents() { return new Class<?>{CardSlot.class, DeckGlobalKeyCommand.class, DeckSendToCommand.class};
}

Now you need to write your DeckSendToCommand class. DeckSendToCommand will be similar to, but different from DeckGlobalKeyCommand :slight_smile:

public class DeckSendToCommand extends AbstractConfigurable {
public void addTo(Buildable parent) {
((DrawPile) parent).addSendToKeyCommand(this);
}
public void removeFrom(Buildable parent) {
((DrawPile) parent).removeSendToKeyCommand(this);
}
public KeyCommand getKeyCommand(Deck deck) {
return new SendToCommand(…);
}

class SendToCommand extends KeyCommand {
private static final long serialVersionUID = 1L;
protected Deck deck;
public DeckKeyCommand(String name, KeyStroke key, Deck deck) {
super(name, key, deck);
this.deck = deck;
}
public void actionPerformed(ActionEvent e) {
// This is where yo do the actual sending.
}
}

}

That should get you started.

B.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

yep it is making more sense all the time! Thx

Thus spake “vbbartlett”:

Whate you’re seeing there is the declaration of an anonymous subclass.

By putting a block after a ‘new’, you can override or add members, just
as you would by declaring a named subclass someplace else. This comes in
handy for one-off subclasses, since then you can put the code which differs
near where it’s relevant.


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Ok after going back through it with a fine tooth comb, I now understand that the actionPerformed is part to the constructor args to the keystrokelisteners.

However in getKeyCommands, the syntax is a bit different. Could you explain it. (Sorry this is more java than anything) but the KeyCommand is in the form of
var = new KeyCommand(args){ code; function definition };
what is exactly happening?
I can understand if the function def is in the args and is passed along to be called later by function ptr but this way is not something I have seen or had experience with.

Thx
[/quote]

Side note, on the load/save format string, that needs to come at the end of the deck description(setType) so as to keep old decks compatible right?

On Jul 8, 2009, at 8:18 AM, vbbartlett wrote:

This is the definition of an anonymous sub-class.
AFAIK they don’t exist in C++. They are used like lambda expressions
in Lisp or Python [but I bet that doesn’t help].

Essentially what is being done by this code is that a new, unnamed
subclass of the KeyCommand class is being built, with the key part
being that the actionPerformed method is being overridden to provide a
specialized action for this particular KeyCommand.

Instead, one could write something like

class ANewKeyCommand extends KeyCommand {
// Constructor
ANewKeyCommand(args…) {
super(args…)
}

// Override method
public void actionPerformed (…) {
…function…
}
}

and then use

c = new ANewKeyCommand(args);
l.add(c);

but that way you have to come up with all sorts of new names for one-
off uses of classes. So the shortcut is to use anonymous subclasses
to do this all without generating a new and generally meaningless
name. In effect, this is the technique Java uses when there is
supposed to be a specialized function called. Instead of creating a
function (which you can’t do outside a class in Java), you create an
instance of a new subclass which has the function as a method with a
pre-negotiated name. That method is then invoked by the procedure
that uses it. [In C++ you would probably just pass a function
pointer].

For more details see:

j2ee.me/docs/books/tutorial/ … asses.html
java.sun.com/new2java/divelog/part5/page5.jsp
mindprod.com/jgloss/anonymousclasses.html
developer.com/java/other/article.php/3300881
tek-tips.com/faqs.cfm?fid=1849


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org
[/quote]


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Clear as shower glass. So that all actually made sense, but if you asked me to actually use it I think I would fall on my face. :slight_smile:

RFE [2818259] - I believe I have code done for this. I am trying to check it in. No luck. I can’t find the option to check it in.

Help plz.

NM, found the menu item Team in a different window

Carl,

What is your sourceforge user id?

B.

Thus spake “vbbartlett”:

It looks like you succeeded. Are you still having trouble?


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)