The library defines several different types of objects:
Component Sources
A component source is any object that provides a method named
nextComponent. This method returns a finite sequence of zero or more
game components. Each time it is called, the next component in the
sequence is returned. Once the sequence runs out, subsequent calls to the
method must return null.
Component Factories
A component factory is a component source that creates new game
components. Typically, the components are created using data taken from
some external source.
For example, instead of maintaining a bunch of .eon files
yourself, you can create a spreadsheet that describes
an entire deck. Using a component factory, you can then produce actual
game components from the spreadsheet data by running them through a
factory. These can be saved to disk, printed, or otherwise batch processed.
The following example script creates two Neighbourhood components by reading data from an array:
uselibrary( "factory" ); var array = [ [ "neighbourhood" ], [ $_file", "name", "_tint", "tinted", "comment" ], [ "park", "Circle Park", ":gc.setTint(0,0.7,0.6)", ":true", "Watch for squirrels." ], [ "dark", "The Darkness", ":gc.setTint(0,0,0)", "", " Dangerous. Very dangerous." ] ]; var factory = new RecordReaderFactory( new ArrayRecordReader( array ) ); var comp = factory.nextComponent(); while( comp != null ) { var ed = comp.createDefaultEditor(); ed.replaceEditedComponent( comp ); Eons.addEditor( ed ); comp = factory.nextComponent(); }
Component Filters A component filter is a component source that modifies the components produced by another component source. For example, a component source might change the expansion of every card that passes through it.
Component Handlers A component handler does some processing on each of the components produced by a component source, but it differs from a component filter because it is not itself a component source. Typically, a component handler does the "finishing steps" needed to do something useful with the components produced a factory or other component source. For example, the component handler might save the components to files, print them, open editors for them, or build a deck from them.
When implementing a factory, if your implementation does not or cannot suggest a file name, you may call this.createDefaultFileName() to generate a default name automatically.
Private setting fields are set according to the usual rules for $-notation in scripts. (The name of the private setting is determined by removing the leading $ and treating any _ characters as -.
Object properties are set as if by calling an appropriate setter method. For example, if field were name and value were "Jim", then calling this method would have the same result as executing the following Java code:
component.setName( "Jim" ); The type of value will be coerced according to the usual rules for
calling from JavaScript into Java. No other special processing of value is
performed.
| component | the game component to modify |
| field | the name of a field, or, if the first character is $, a private setting name |
| value | the object to set the field's value to |
The sequence of records returned by the reader must follow a few simple rules in order to be processed correctly. The first record, called the prototype record, must identify the type of component being created. The second record, called the header record, identifies attributes of the created component (such as name, comments, stamina, etc.). The third and subsequent records will each be converted into a component by setting its attributes from the field values. These three record types are described in detail below:
Prototype Record
The first field of the prototype record identifies the type of component
to be created. The prototype component is created as if by executing the code
PluginContext.createEditor( fieldValue ).gameComponent, where
fieldValue is the string value of the first field in the
record. Basically, this means that fieldValue is a
class map key in one of the active class maps.
Alternatively, the field can consist of script code (see below) that
evaluates to the prototype to be used.
Header Record
The header record consists of one or more attribute names. These are basically
the names of setter methods on the component of interest, without the
"set" prefix and starting with a lowercase letter. A setter method is a method
that takes a single parameter and starts with set.
(The View Component plug-in can be used to identify setter methods.)
If the name starts with a dollar sign ($), then it is treated as the
name of a private setting (without the $) to be set on the component
instead.
If the name starts with an underscore (_), then it is treated as
a placeholder name. Placeholder names are ignored when filling in fields,
but they can contain script code to be executed when the field is processed.
This can be used to modify aspects of the component that cannot be accessed
through setters.
Component Record(s)
Each component record will be converted into a game component by setting
the setter method identified by the field at this field's index in the
header record with the value in this field. (Setters that take
a parameter with a type other than string or a numeric type will generally
need to define script code that evaluates to the value to be set.)
If a field consists of a blank string, its value is taken from the last
non-blank value in that column. (If the blank field occurs in the first
component record, then it is treated as an empty string.) To specify a
truly blank field, you can use the embedded code (see below): :""
or :''.
The factory will skip any records that are empty (contain no fields) or that are commented out. A record is commented out if the first character of the first field is a number sign (hash): #. Skipped records have no effect on processing (so, for example, there may be empty records between the prototype record and the header record).
Fields may contain embedded script code. This is indicated by starting the field value with a colon (:). When a field contains embedded script code, the actual value used by the field is determined by evaluating the embedded code. This can be used to set an attribute using a computed value, or to call setter functions that require more than one parameter. Because fields that start with a colon are treated as scripts, you cannot begin a normal field value with a colon. To get around this, write a snippet of script code that evaluates to the string you want to use for the field. For example, if you want the value of a field to be : this!, use the following embedded script: :': this!'. The same technique can be used if the first field of a record starts with a number sign.
Some processing tools will recognize the special private setting $_file to suggest file names for generated components. (If absent, the tools will use default file names.)
| record | the record to process scripts in |
| gc | a component to be provided to scripts |
:f('portrait.jpg');
| file | the absolute path to the base folder |
| record | the prototype row record |
| record | the header row record |
| record | the record to use to fill in the component |
| gc | the component to modify |
| header | the header row record |
| prevRecord | a record to use to fill in missing values, or null if no other rows have been processed |
| fieldName | the name of the column to look up in record |
| record | the record to be searched |
| gc | the game component to be filtered |
Returns a game component (possibly gc) created by applying the filter.
Returns the next filtered component, or null if there are no more.
A set of records can be thought of as a table of data similar to that provided by a spreadsheet application. Each record describes one row of the table, and each field describes one column in that row. A Factory can use the data provided by a record reader to generate components automatically. For example, you could describe the properties of an entire deck of cards in a spreadsheet, and then use a CSVRecordReader to convert the spreadsheet into a matching set of .eon files.
In order to function, a reader subclass must override the nextRecord() function to return the next record from the source.
The input object can be any one of the following types of object (or a subclass): String (JavaScript), java.lang.String (Java), java.net.URL, java.io.File, java.io.InputStream, java.io.Reader.
| input | an object of one of the above types |
| encoding | an optional encoding that will be used for input streams |
Returns a java.io.BufferedReader capable of reading text from input. If input is not one of the types that can be converted, returns null.
CSV files are plain text files that normally store one record per line. Commas are used to separate fields, and whitespace around commas is ignored. If a field contains a comma, newline, or quote, or if whitespace at the start or end of the field is significant, then the field must be surrounded by quote (") characters. To include a quote inside the field, it must be doubled (""). (Otherwise, the quote will end the field.)
For example, the following input:
Name, Gold, "Starting Location"
Biff, 7, Nirvana
Cuddles, 3, "A bar, ""The Silver Donkey"""
Would produce these records:
| Field 1 | Field 2 | Field 3 | |
|---|---|---|---|
| Record 1 | Name | Gold | Starting Location |
| Record 2 | Biff | 7 | Nirvana |
| Record 3 | Cuddles | 3 | A bar, "The Silver Donkey" |
Example:
var array = [ [ "Name", "Gold", "Starting Location" ], [ "Biff", 7, "Nirvana" ], [ "Cuddles", 3, 'A bar, "The Silver Donkey"' ] ]; new ArrayRecordReader( array ).debugPrint();