Changes between Initial Version and Version 1 of Scripting/API


Ignore:
Timestamp:
04/06/18 16:40:49 (6 years ago)
Author:
admin
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Scripting/API

    v1 v1  
     1= Scripting API =
     2
     3The way the script will interact with !WorldPainter is through a context object named `wp` which exports a number of operations in the form of functions or methods (depending on your scripting language). The operations follow the "builder pattern" or "method chaining", meaning that you chain one or more method invocations to set the parameters and then invoke "go()" to actually perform the operation, which may or may not return a value. For example, in !JavaScript:
     4
     5{{{
     6#!js
     7var world = wp.getWorld()
     8    .fromFile('path/to/world/worldname.world')
     9    .go();
     10}}}
     11
     12This single statement loads a !WorldPainter world from the specified file and stores it in a variable named "world", which you can then use in further operations to refer to the loaded world.
     13
     14== Don't Forget The Go! ==
     15
     16Once again: every operation ends with a call to `.go()`, which will actually perform the operation and return the result, if any. Don't forget it, or nothing will happen!
     17
     18== Commandline Arguments ==
     19
     20The script will have access to any commandline arguments specified by the user when invoking the script via the `arguments` or `argv` array (both are available; the first command line argument is in `arguments[0]` or `argv[1]`; `argv[0]` contains the name of the script; in the `arguments` array that is not available).
     21
     22== Variables Available Inside !WorldPainter ==
     23
     24When a script is executed inside !WorldPainter (Tools -> Run script...) it has the same `arguments` and `argv` arrays available as when run on the command line, in which the arguments entered by the user on the Run Script screen will be available.
     25
     26In addition it will have two global variables available: `world` and `dimension`, which point to the currently loaded world and the currently selected dimension respectively, and through which the script can modify the currently loaded world.
     27
     28== Loading a World ==
     29
     30Loading a !WorldPainter world from disk:
     31
     32{{{
     33#!js
     34var world = wp.getWorld()
     35    .fromFile('path/to/world/myworld.world') // The filename of the world to load; may be absolute or relative to the current directory
     36    .go();
     37}}}
     38
     39== Saving a World ==
     40
     41Saving a !WorldPainter world to disk:
     42
     43{{{
     44#!js
     45wp.saveWorld(world) // The world to save. See "Loading a World"
     46    .toFile('path/to/world/myworld.world') // The filename under which to save the world. If it already exists a backup will automatically be made using the backup settings stored in the !WorldPainter configuration of the user running the script
     47    .go();
     48}}}
     49
     50== Exporting a World ==
     51
     52Exporting a !WorldPainter world as a Minecraft map:
     53
     54{{{
     55#!js
     56wp.exportWorld(world) // The world to export. See "Loading a World"
     57    .toDirectory('path/to/saves') // The directory in which to export the world. Should NOT include the world name; a directory with the name of the world will automatically be created inside the specified directory. If a directory with that name already exists it will automatically be backed up
     58    .go();
     59}}}
     60
     61== Loading a Layer ==
     62
     63Getting a standard !WorldPainter layer:
     64
     65{{{
     66#!js
     67var layer = wp.getLayer()
     68    .withName('Frost') // The name of the standard layer
     69    .go();
     70}}}
     71
     72Getting a layer from a !WorldPainter world:
     73
     74{{{
     75#!js
     76var layer = wp.getLayer()
     77    .fromWorld(world) // See "Loading a World"
     78    .withName('My Layer') // The name of layer in the world
     79    .go();
     80}}}
     81
     82Loading a layer from a .layer file exported from !WorldPainter:
     83
     84{{{
     85#!js
     86var layer = wp.getLayer()
     87    .fromFile('path/to/layer/mylayer.layer') // The filename of the layer to load
     88    .go();
     89}}}
     90
     91== Loading a Custom Terrain ==
     92
     93Loading a Custom Terrain from a .terrain file exported from !WorldPainter:
     94
     95{{{
     96#!js
     97var terrain = wp.getTerrain()
     98    .fromFile('path/to/terrain/myterrain.terrain') // The filename of the terrain to load
     99    .go();
     100}}}
     101
     102Note that to actually ''use'' a Custom Terrain you must first install it on the world! See below for the "Installing a Custom Terrain" operation.
     103
     104== Installing a Custom Terrain ==
     105
     106Before you can actually use a Custom Terrain you must first install it on the world using the following operation:
     107
     108{{{
     109#!js
     110var customTerrainIndex = wp.installCustomTerrain(terrain) // The Custom Terrain to install on the world. See "Loading a Custom Terrain"
     111    .toWorld(world) // The world on which to install the Custom Terrain. See "Loading a World"
     112    .inSlot(1) // Optional. The Custom Terrain slot from 1 to 24 (inclusive) on which to install the terrain. When not specified the first free slot will be used. If there are no free slots an exception will be thrown
     113    .go(); // Returns the terrain index to use for actually placing this Custom Terrain using other operations
     114}}}
     115
     116== Loading a Height Map ==
     117
     118There are several operations which take a height map as input. Here is how to load one:
     119
     120{{{
     121#!js
     122var heightMap = wp.getHeightMap()
     123    .fromFile('path/to/heightmap/myheightmap.png') // The filename of the height map to load. Supported formats are dependent on the Java platform, but usually include at least PNG and TIFF
     124    .selectRedChannel() // Optional. If the image is not a grayscale image you may invoke ONE OF selectRedChannel(), selectGreenChannel() or selectBlueChannel() to indicate which channel should be used to read values from. This is the default for colour images
     125    .selectGreenChannel() // Optional. If the image is not a grayscale image you may invoke ONE OF selectRedChannel(), selectGreenChannel() or selectBlueChannel() to indicate which channel should be used to read values from. The default is to use the red channel for colour images.
     126    .selectBlueChannel() // Optional. If the image is not a grayscale image you may invoke ONE OF selectRedChannel(), selectGreenChannel() or selectBlueChannel() to indicate which channel should be used to read values from. The default is to use the red channel for colour images.
     127    .go(); // Returns the loaded height map for use in other operations
     128}}}
     129
     130== Creating a World from a Height Map ==
     131
     132Creating a new world from a height map:
     133
     134{{{
     135#!js
     136var world = wp.createWorld()
     137    .fromHeightMap(heightMap) // See "Loading a Height Map"
     138    .scale(100) // Optional. The % at which to scale the height map. Default value: 100%
     139    .shift(0, 0) // Optional. The number of blocks the height map should be shifted east and south respectively (negative numbers shift west and north). Default value: 0, 0
     140    .fromLevels(0, 255).toLevels(0, 255) // Optional. Specifies how image values should be mapped to surface heights. The first two values are the lower and upper bounds of the range of image values; the second pair of values if the corresponding range of surface heights those image values should be mapped to. The default is to map the values one on one
     141    .go(); // Returns the created world for exporting, saving or using in other operations
     142}}}
     143
     144'''Note''' that !WorldPainter supports 16-bit height maps! You can import them to create worlds with high resolution height information, which will make smooth snow look better and editing work more smoothly. You'll need to tell !WorldPainter to map the full range of the height map (or any other desired range) to the full range of the world height though, by setting fromLevels() and toLevels() like this:
     145
     146{{{
     147#!js
     148    .fromLevels(0, 65535).toLevels(0, 255)
     149}}}
     150
     151== Applying a Height Map as a Layer ==
     152
     153To apply a height map to a world as a layer:
     154
     155{{{
     156#!js
     157wp.applyHeightMap(heightMap) // See "Loading a Height Map"
     158    .toWorld(world) // See "Loading a World" or "Creating a World from a Height Map"
     159    .withFilter(filter) // Optional. Specifies conditions for where the layer will be applied. See below for details about creating a filter
     160    .applyToSurface() // Optional. Mutually exclusive with applyToNether() and applyToEnd(). Indicates that the layer should be applied to the Surface dimension. This is the default
     161    .applyToNether() // Optional. Mutually exclusive with applyToSurface() and applyToEnd(). Indicates that the layer should be applied to the Nether dimension
     162    .applyToEnd() // Optional. Mutually exclusive with applyToSurface() and applyToNether(). Indicates that the layer should be applied to the End dimension
     163    .scale(100) // Optional. The % at which to scale the height map. Default value: 100%
     164    .shift(0, 0) // Optional. The number of blocks the height map should be shifted east and south respectively (negative numbers shift west and north). Default value: 0, 0
     165    .applyToLayer(layer) // See "Loading a Layer"
     166    .fromLevel(0).toLevel(0) // Optional. Repeatable. Specifies that a single value from the image must be mapped to a single layer intensity (see below)
     167    .fromLevels(0, 255).toLevel(0) // Optional. Repeatable. Specifies that a range of values from the image must be mapped to a single layer intensity (see below)
     168    .fromLevels(0, 255).toLevels(0, 255) // Optional. Repeatable. Specifies that a range of values from the image must be mapped to a range of layer intensities (see below)
     169    .fromColour(0, 0, 0).toLevel(0) // Optional. Repeatable. Specificies that a single colour, in the form of red, green and blue components from 0 to 255 (inclusive), from the image must be mapped to a single layer intensity (see below). The alpha value is assumed to be 255 (fully opaque)
     170    .fromColour(0, 0, 0, 0).toLevel(0) // Optional. Repeatable. Specificies that a single colour, in the form of alpha, red, green and blue components from 0 to 255 (inclusive), from the image must be mapped to a single layer intensity (see below)
     171    .setAlways() // Optional. Mutually exclusive with setWhenLower() and setWhenHigher(). Indicates that the layer intensity must always be overridden, no matter what it was before. This is the default
     172    .setWhenLower() // Optional. Mutually exclusive with setAlways() and setWhenHigher(). Indicates that the layer intensity must only be overridden if the value from the image is lower than what was already there in the world
     173    .setWhenHigher() // Optional. Mutually exclusive with setAlways() and setWhenLower(). Indicates that the layer intensity must only be overridden if the value from the image is higher than what was already there in the world
     174    .go();
     175}}}
     176
     177About the mapping:
     178
     179You may map EITHER grey scale values (using fromLevel() and fromLevels()) OR colour values (using fromColour()), but you may not mix both. Mapping colour values obviously is only useful if the height map was derived from a colour image. '''Note''' that the colours are only matched exactly as specified. Slightly different colours don't match. Therefore you must make sure that your input image contains only solid areas of discrete colours and has no anti-aliasing, smoothing, mixing of colours, gradients, etc.
     180
     181You must specify a mapping by using the fromLevel(s)/fromColour(s)/toLevel(s) setters at least once. The value mapping specifies which layer intensities should be set for which input values. Any input values not mapped will be ignored, i.e. the existing layer intensity, if any, will remain unaltered in those locations. To correctly set the mapping you must know which target values to use for the type of layer you are mapping to. As of now there are three layer types:
     182
     183=== !On/Off Layers ===
     184
     185So-called on/off or true/false or 1-bit layers don't have an intensity. Instead they are either on or off for each coordinate. Examples of this type of layer are: the Frost layer, the Void layer, Custom Ground Cover layers and Custom !Cave/Tunnel layers.
     186
     187For these layers a target value of zero means "off" and any other value means "on". In other words, if you use the default mapping, any areas where the height map is not completely black will result in the layer being applied.
     188
     189=== Continuous Layers ===
     190
     191So-called continuous or 4-bit layers have an intensity. In the GUI the intensity is displayed as a percentage between 0% and 100%, but technically these layers only have 16 discrete intensities, from 0 to 15. Zero means the layer is absent; 1 corresponds to 1%, 8 to 50% and 15 to 100%. Examples of this type of layer are: the Caverns and Chasms layers, the standard tree layers, the Resources layer, Custom Object layers, Custom Underground Pockets layers and Combined layers.
     192
     193For these layers the target value must therefore lie between 0 and 15 (inclusive). If you use the default mapping, any areas where the height map is completely black will not have the layer set; where the height map value is between 1 and 14 (inclusive) will have the layer set to a percentage from 1% to 93% and where the value is 15 (which is still very dark) or higher the layer will be set to 100%.
     194
     195=== Direct Mapping Layers ===
     196
     197These are layers which don't have an intensity, but where the layer values correspond directly to arbitrary concepts such as colours or biomes. Examples of this type of layer are the Biomes layer and the Annotations layer.
     198
     199It depends on the type of height map what kind of mapping makes sense for these layers. If it is a genuine height map (i.e. it corresponds to surface heights) then you can use it to map different height ranges to different biomes, for instance, and it makes sense to use the ranged setters (fromLevels().toLevel() and fromLevels().toLevels()) to set up the mapping.
     200
     201If instead the "height map" is a value map or mask which directly indicates which biomes, for instance, must be used then using the ranged setters does not make sense and it would be better to use the one on one setter (fromLevel().toLevel()) repeatedly to set up each mapping of a "height map" value to a biome, or a colour.
     202
     203For the Biomes layer, the target values are the Minecraft biome IDs which you can find on the [http://minecraft.gamepedia.com/Data_values#Biome_IDs Minecraft wiki]. To reset the biome to "automatic", set the layer value to 255.
     204
     205For the Annotations layer, the target values must be between 0 and 15. 0 indicates that the layer should not be present; the other values indicate individual colours. See [Scripting/AnnotationColours this] page for an overview of the colour mapping.
     206
     207== Applying a Height Map to the Terrain Type ==
     208
     209To apply a height map to a world as the terrain type:
     210
     211{{{
     212#!js
     213wp.applyHeightMap(heightMap) // See "Loading a Height Map"
     214    .toWorld(world) // See "Loading a World" or "Creating a World from a Height Map"
     215    .withFilter(filter) // Optional. Specifies conditions for where the terrain will be applied. See below for details about creating a filter
     216    .applyToSurface() // Optional. Mutually exclusive with applyToNether() and applyToEnd(). Indicates that the terrain should be changed of the Surface dimension. This is the default
     217    .applyToNether() // Optional. Mutually exclusive with applyToSurface() and applyToEnd(). Indicates that the terrain should be changed of the Nether dimension
     218    .applyToEnd() // Optional. Mutually exclusive with applyToSurface() and applyToNether(). Indicates that the terrain should be changed of the End dimension
     219    .scale(100) // Optional. The % at which to scale the height map. Default value: 100%
     220    .shift(0, 0) // Optional. The number of blocks the height map should be shifted east and south respectively (negative numbers shift west and north). Default value: 0, 0
     221    .applyToTerrain()
     222    .fromLevel(0).toTerrain(0) // Optional. Repeatable. Specifies that a single value from the image must be mapped to a single terrain type (see below)
     223    .fromLevels(0, 255).toTerrain(0) // Optional. Repeatable. Specifies that a range of values from the image must be mapped to a single terrain type (see below)
     224    .fromColour(0, 0, 0).toTerrain(0) // Optional. Repeatable. Specificies that a single colour, in the form of red, green and blue components from 0 to 255 (inclusive), from the image must be mapped to a single terrain type (see below). The alpha value is assumed to be 255 (fully opaque)
     225    .fromColour(0, 0, 0, 0).toTerrain(0) // Optional. Repeatable. Specificies that a single colour, in the form of alpha, red, green and blue components from 0 to 255 (inclusive), from the image must be mapped to a single terrain type (see below)
     226    .go();
     227}}}
     228
     229About the mapping:
     230
     231You may map EITHER grey scale values (using fromLevel() and fromLevels()) OR colour values (using fromColour()), but you may not mix both. Mapping colour values obviously is only useful if the height map was derived from a colour image. '''Note''' that the colours are only matched exactly as specified. Slightly different colours don't match. Therefore you must make sure that your input image contains only solid areas of discrete colours and has no anti-aliasing, smoothing, mixing of colours, gradients, etc.
     232
     233For applying a height map to the terrain, the mapping is to arbitrary terrain type indices which correspond to different terrain types. It depends on the type of height map what kind of mapping makes sense. If it is a genuine height map (i.e. it corresponds to surface heights) then you can use it to map different height ranges to different terrain types, and it makes sense to use the ranged setter (fromLevels().toLevel()) to set up the mapping.
     234
     235If instead the "height map" is a value map or mask which directly indicates which terrain types must be used then using the ranged setter does not make sense and it would be better to use the one on one setter (fromLevel().toLevel() or fromColour().toLevel()) repeatedly to set up each mapping of a "height map" value or colour to a terrain type.
     236
     237For an overview of the actual terrain type indices to use and the terrain types to which they correspond, see [Scripting/TerrainTypeValues this] page. '''Note''' that if you want to include Custom Terrain types which aren't already present in the world, you must install the Custom Terrain type on the world first (see "Installing a Custom Terrain" above) and that operation will return the terrain index to use for that particular Custom Terrain.
     238
     239== Applying a Layer Directly ==
     240
     241A layer can also be applied to a world directly, without a height map but optionally with a filter:
     242
     243{{{
     244#!js
     245wp.applyLayer(layer) // See "Loading a Layer"
     246    .toWorld(world) // See "Loading a World" or "Creating a World from a Height Map"
     247    .toLevel(0) // Optional. The level to which to set the layer. The default is half the maximum for the layer type (or "on" for 1-bit layers such as Frost). See the discussion above under Applying a Height Map as a Layer
     248    .withFilter(filter) // Optional. Specifies conditions for where the layer will be applied. See below for details about creating a filter
     249    .applyToSurface() // Optional. Mutually exclusive with applyToNether() and applyToEnd(). Indicates that the layer should be applied to the Surface dimension. This is the default
     250    .applyToNether() // Optional. Mutually exclusive with applyToSurface() and applyToEnd(). Indicates that the layer should be applied to the Nether dimension
     251    .applyToEnd() // Optional. Mutually exclusive with applyToSurface() and applyToNether(). Indicates that the layer should be applied to the End dimension
     252    .setAlways() // Optional. Mutually exclusive with setWhenLower() and setWhenHigher(). Indicates that the layer intensity must always be overridden, no matter what it was before. This is the default
     253    .setWhenLower() // Optional. Mutually exclusive with setAlways() and setWhenHigher(). Indicates that the layer intensity must only be overridden if the value from the image is lower than what was already there in the world
     254    .setWhenHigher() // Optional. Mutually exclusive with setAlways() and setWhenLower(). Indicates that the layer intensity must only be overridden if the value from the image is higher than what was already there in the world
     255    .go();
     256}}}
     257
     258For the layer value to specify with toLevel(), see the discussion above under Applying a Height Map as a Layer
     259
     260== Applying a Terrain Type Directly ==
     261
     262A terrain type can also be applied to a world directly, without a height map but optionally with a filter:
     263
     264{{{
     265#!js
     266wp.applyTerrain(0) // The terrain type index to set
     267    .toWorld(world) // See "Loading a World" or "Creating a World from a Height Map"
     268    .withFilter(filter) // Optional. Specifies conditions for where the layer will be applied. See below for details about creating a filter
     269    .applyToSurface() // Optional. Mutually exclusive with applyToNether() and applyToEnd(). Indicates that the layer should be applied to the Surface dimension. This is the default
     270    .applyToNether() // Optional. Mutually exclusive with applyToSurface() and applyToEnd(). Indicates that the layer should be applied to the Nether dimension
     271    .applyToEnd() // Optional. Mutually exclusive with applyToSurface() and applyToNether(). Indicates that the layer should be applied to the End dimension
     272    .go();
     273}}}
     274
     275For an overview of the actual terrain type indices to use in applyTerrain() and the terrain types to which they correspond, see [Scripting/TerrainTypeValues this] page. '''Note''' that if you want to include Custom Terrain types which aren't already present in the world, you must install the Custom Terrain type on the world first (see "Installing a Custom Terrain" above) and that operation will return the terrain index to use for that particular Custom Terrain.
     276
     277== Creating a Filter ==
     278
     279The height map, layer and terrain application operations described above can take a filter. Here is how you create one:
     280
     281{{{
     282#!js
     283var filter = wp.createFilter()
     284    .aboveLevel(0) // Optional. Apply the operation only at and above the specified terrain level
     285    .belowLevel(255) // Optional. Apply the operation only at or below the specified terrain level
     286    .feather() // Optional. When applying a continuously-valued layer, let it fade out around the specified terrain levels, instead of being cut off sharply
     287    .aboveDegrees(0) // Optional. Mutuatlly exclusive with belowDegrees(). Specifies the slope in degrees above which the operation must be applied. PLEASE NOTE: only works well with worlds created from high res (16-bit) height maps or sculpted manually in WorldPainter!
     288    .belowDegrees(0) // Optional. Mutuatlly exclusive with aboveDegrees(). Specifies the slope in degrees below which the operation must be applied. PLEASE NOTE: only works well with worlds created from high res (16-bit) height maps or sculpted manually in WorldPainter!
     289    .onlyOnTerrain(0) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the terrain index of the terrain on which the operation should only be applied
     290    .onlyOnLayer(layer) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the layer which must be present for the operation to be applied
     291    .onlyOnBiome(0) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the biome ID of the manually painted biome on which the operation should only be applied
     292    .onlyOnAutoBiome(0) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the biome ID of the automatically set biome on which the operation should only be applied
     293    .onlyOnAutoBiomes() // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies that the operation must only be applied on automatically set biomes
     294    .onlyOnWater() // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies that the operation must only be applied on flooded areas
     295    .onlyOnLand() // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies that the operation must only be applied on dry areas
     296    .exceptOnTerrain(0) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the terrain index of the terrain on which the operation must NOT be applied
     297    .exceptOnLayer(layer) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the layer which must NOT be present for the operation to be applied
     298    .exceptOnBiome(0) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the biome ID of the manually painted biome on which the operation should NOT be applied
     299    .exceptOnAutoBiome(0) // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies the biome ID of the automatically set biome on which the operation should NOT be applied
     300    .exceptOnAutoBiomes() // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies that the operation must only be applied on manually painted biomes
     301    .exceptOnWater() // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies that the operation must only be applied on dry areas
     302    .exceptOnLand() // Optional. Mutually exclusive with all other onlyOn* and exceptOn* conditions. Specifies that the operation must only be applied on flooded areas
     303    .go();
     304}}}
     305
     306For an overview of the actual terrain type indices to use in onlyOnTerrain() or exceptOnTerrain() and the terrain types to which they correspond, see [Scripting/TerrainTypeValues this] page. For an overview of the biome IDs to use in onlyOnBiome(), onlyOnAutoBiome(), exceptOnBiome() or exceptOnAutoBiome() see [http://minecraft.gamepedia.com/Biome#Biome_IDs this] page.