aboutsummaryrefslogtreecommitdiff
path: root/doc/menu_lua_api.txt
blob: 9bc0c46bd555bb17a16ec2125ace70b03b7b09d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
Minetest Lua Mainmenu API Reference 5.5.0
=========================================

Introduction
-------------

The main menu is defined as a formspec by Lua in builtin/mainmenu/
Description of formspec language to show your menu is in lua_api.txt


Callbacks
---------

core.button_handler(fields): called when a button is pressed.
^ fields = {name1 = value1, name2 = value2, ...}
core.event_handler(event)
^ event: "MenuQuit", "KeyEnter", "ExitButton" or "EditBoxEnter"


Gamedata
--------

The "gamedata" table is read when calling core.start(). It should contain:
{
    playername     = <name>,
    password       = <password>,
    address        = <IP/adress>,
    port           = <port>,
    selected_world = <index>, -- 0 for client mode
    singleplayer   = <true/false>,
}


Functions
---------

core.start()
core.close()
core.get_min_supp_proto()
^ returns the minimum supported network protocol version
core.get_max_supp_proto()
^ returns the maximum supported network protocol version
core.open_url(url)
^ opens the URL in a web browser, returns false on failure.
^ Must begin with http:// or https://
core.open_dir(path)
^ opens the path in the system file browser/explorer, returns false on failure.
^ Must be an existing directory.
core.get_version() (possible in async calls)
^ returns current core version



Filesystem
----------

core.get_builtin_path()
^ returns path to builtin root
core.create_dir(absolute_path) (possible in async calls)
^ absolute_path to directory to create (needs to be absolute)
^ returns true/false
core.delete_dir(absolute_path) (possible in async calls)
^ absolute_path to directory to delete (needs to be absolute)
^ returns true/false
core.copy_dir(source,destination,keep_soure) (possible in async calls)
^ source folder
^ destination folder
^ keep_source DEFAULT true --> if set to false source is deleted after copying
^ returns true/false
core.is_dir(path) (possible in async calls)
^ returns true if path is a valid dir
core.extract_zip(zipfile,destination) [unzip within path required]
^ zipfile to extract
^ destination folder to extract to
^ returns true/false
core.sound_play(spec, looped) -> handle
^ spec = SimpleSoundSpec (see lua-api.txt)
^ looped = bool
core.sound_stop(handle)
core.get_video_drivers()
^ get list of video drivers supported by engine (not all modes are guaranteed to work)
^ returns list of available video drivers' settings name and 'friendly' display name
^ e.g. { {name="opengl", friendly_name="OpenGL"}, {name="software", friendly_name="Software Renderer"} }
^ first element of returned list is guaranteed to be the NULL driver
core.get_mapgen_names([include_hidden=false]) -> table of map generator algorithms
    registered in the core (possible in async calls)
core.get_cache_path() -> path of cache
core.get_temp_path([param]) (possible in async calls)
^ param=true: returns path to a temporary file
^ otherwise: returns path to the temporary folder


HTTP Requests
-------------

* core.download_file(url, target) (possible in async calls)
    * url to download, and target to store to
    * returns true/false
* `minetest.get_http_api()` (possible in async calls)
    * returns `HTTPApiTable` containing http functions.
    * The returned table contains the functions `fetch_sync`, `fetch_async` and
      `fetch_async_get` described below.
    * Function only exists if minetest server was built with cURL support.
* `HTTPApiTable.fetch_sync(HTTPRequest req)`: returns HTTPRequestResult
    * Performs given request synchronously
* `HTTPApiTable.fetch_async(HTTPRequest req)`: returns handle
    * Performs given request asynchronously and returns handle for
      `HTTPApiTable.fetch_async_get`
* `HTTPApiTable.fetch_async_get(handle)`: returns HTTPRequestResult
    * Return response data for given asynchronous HTTP request

### `HTTPRequest` definition

Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`.

    {
        url = "http://example.org",

        timeout = 10,
        -- Timeout for connection in seconds. Default is 3 seconds.

        post_data = "Raw POST request data string" OR {field1 = "data1", field2 = "data2"},
        -- Optional, if specified a POST request with post_data is performed.
        -- Accepts both a string and a table. If a table is specified, encodes
        -- table as x-www-form-urlencoded key-value pairs.
        -- If post_data is not specified, a GET request is performed instead.

        user_agent = "ExampleUserAgent",
        -- Optional, if specified replaces the default minetest user agent with
        -- given string

        extra_headers = { "Accept-Language: en-us", "Accept-Charset: utf-8" },
        -- Optional, if specified adds additional headers to the HTTP request.
        -- You must make sure that the header strings follow HTTP specification
        -- ("Key: Value").

        multipart = boolean
        -- Optional, if true performs a multipart HTTP request.
        -- Default is false.
    }

### `HTTPRequestResult` definition

Passed to `HTTPApiTable.fetch` callback. Returned by
`HTTPApiTable.fetch_async_get`.

    {
        completed = true,
        -- If true, the request has finished (either succeeded, failed or timed
        -- out)

        succeeded = true,
        -- If true, the request was successful

        timeout = false,
        -- If true, the request timed out

        code = 200,
        -- HTTP status code

        data = "response"
    }


Formspec
--------

core.update_formspec(formspec)
core.get_table_index(tablename) -> index
^ can also handle textlists
core.formspec_escape(string) -> string
^ escapes characters [ ] \ , ; that can not be used in formspecs
core.explode_table_event(string) -> table
^ returns e.g. {type="CHG", row=1, column=2}
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
core.explode_textlist_event(string) -> table
^ returns e.g. {type="CHG", index=1}
^ type: "INV" (no row selected), "CHG" (selected) or "DCL" (double-click)
core.set_formspec_prepend(formspec)
^ string to be added to every mainmenu formspec, to be used for theming.


GUI
---

core.set_background(type, texturepath,[tile],[minsize])
^ type: "background", "overlay", "header" or "footer"
^ tile: tile the image instead of scaling (background only)
^ minsize: minimum tile size, images are scaled to at least this size prior
^   doing tiling (background only)
core.set_clouds(<true/false>)
core.set_topleft_text(text)
core.show_keys_menu()
core.show_path_select_dialog(formname, caption, is_file_select)
^ shows a path select dialog
^ formname is base name of dialog response returned in fields
^     -if dialog was accepted "_accepted"
^        will be added to fieldname containing the path
^     -if dialog was canceled "_cancelled"
^        will be added to fieldname value is set to formname itself
^ if `is_file_select` is `true`, a file and not a folder will be selected
^ returns nil or selected file/folder
core.get_screen_info()
^ returns {
    density         = <screen density 0.75,1.0,2.0,3.0 ... (dpi)>,
    display_width   = <width of display>,
    display_height  = <height of display>,
    window_width    = <current window width>,
    window_height   = <current window height>,
    render_info     = <active render information>
    }


Content and Packages
--------------------

Content - an installed mod, modpack, game, or texture pack (txt)
Package - content which is downloadable from the content db, may or may not be installed.

* core.get_user_path() (possible in async calls)
    * returns path to global user data,
      the directory that contains user-provided mods, worlds, games, and texture packs.
* core.get_modpath() (possible in async calls)
    * returns path to global modpath, where mods can be installed
* core.get_modpaths() (possible in async calls)
    * returns list of paths to global modpaths, where mods have been installed

      The difference with "core.get_modpath" is that no mods should be installed in these
      directories by Minetest -- they might be read-only.

* core.get_clientmodpath() (possible in async calls)
    * returns path to global client-side modpath
* core.get_gamepath() (possible in async calls)
    * returns path to global gamepath
* core.get_texturepath() (possible in async calls)
    * returns path to default textures
* core.get_game(index)
    * returns:

        {
            id               = <id>,
            path             = <full path to game>,
            gamemods_path    = <path>,
            name             = <name of game>,
            menuicon_path    = <full path to menuicon>,
            author           = "author",
            DEPRECATED:
            addon_mods_paths = {[1] = <path>,},
        }

* core.get_games() -> table of all games in upper format (possible in async calls)
* core.get_content_info(path)
    * returns

        {
            name             = "name of content",
            type             = "mod" or "modpack" or "game" or "txp",
            description      = "description",
            author           = "author",
            path             = "path/to/content",
            depends          = {"mod", "names"}, -- mods only
            optional_depends = {"mod", "names"}, -- mods only
        }


Logging
-------

core.debug(line) (possible in async calls)
^ Always printed to stderr and logfile (print() is redirected here)
core.log(line) (possible in async calls)
core.log(loglevel, line) (possible in async calls)
^ loglevel one of "error", "action", "info", "verbose"


Settings
--------

core.settings:set(name, value)
core.settings:get(name) -> string or nil (possible in async calls)
core.settings:set_bool(name, value)
core.settings:get_bool(name) -> bool or nil (possible in async calls)
core.settings:save() -> nil, save all settings to config file

For a complete list of methods of the Settings object see
[lua_api.txt](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt)


Worlds
------

core.get_worlds() -> list of worlds (possible in async calls)
^ returns {
    [1] = {
    path   = <full path to world>,
    name   = <name of world>,
    gameid = <gameid of world>,
    },
}
core.create_world(worldname, gameid)
core.delete_world(index)


Helpers
-------

core.get_us_time()
^ returns time with microsecond precision
core.gettext(string) -> string
^ look up the translation of a string in the gettext message catalog
fgettext_ne(string, ...)
^ call core.gettext(string), replace "$1"..."$9" with the given
^ extra arguments and return the result
fgettext(string, ...) -> string
^ same as fgettext_ne(), but calls core.formspec_escape before returning result
core.parse_json(string[, nullvalue]) -> something (possible in async calls)
^ see core.parse_json (lua_api.txt)
dump(obj, dumped={})
^ Return object serialized as a string
string:split(separator)
^ eg. string:split("a,b", ",") == {"a","b"}
string:trim()
^ eg. string.trim("\n \t\tfoo bar\t ") == "foo bar"
core.is_yes(arg) (possible in async calls)
^ returns whether arg can be interpreted as yes
minetest.encode_base64(string) (possible in async calls)
^ Encodes a string in base64.
minetest.decode_base64(string) (possible in async calls)
^ Decodes a string encoded in base64.


Async
-----

core.handle_async(async_job,parameters,finished)
^ execute a function asynchronously
^ async_job is a function receiving one parameter and returning one parameter
^ parameters parameter table passed to async_job
^ finished function to be called once async_job has finished
^    the result of async_job is passed to this function

Limitations of Async operations
 -No access to global lua variables, don't even try
 -Limited set of available functions
    e.g. No access to functions modifying menu like core.start,core.close,
    core.show_path_select_dialog


Background music
----------------

The main menu supports background music.
It looks for a `main_menu` sound in `$USER_PATH/sounds`. The same naming
conventions as for normal sounds apply.
This means the player can add a custom sound.
It will be played in the main menu (gain = 1.0), looped.
ialization.h" #include "tile.h" /* Initializes all kind of stuff in here. Many things depend on this. This accesses g_texturesource; if it is non-NULL, textures are set. Client first calls this with g_texturesource=NULL to run some unit tests and stuff, then it runs this again with g_texturesource defined to get the textures. Server only calls this once with g_texturesource=NULL. */ void init_mapnode(); // Initializes g_content_inventory_texture_paths void init_content_inventory_texture_paths(); // NOTE: This is not used appropriately everywhere. #define MATERIALS_COUNT 256 /* Ignored node. Anything that stores MapNodes doesn't have to preserve parameters associated with this material. Doesn't create faces with anything and is considered being out-of-map in the game map. */ #define CONTENT_IGNORE 255 #define CONTENT_IGNORE_DEFAULT_PARAM 0 /* The common material through which the player can walk and which is transparent to light */ #define CONTENT_AIR 254 /* Suggested materials: - Gravel - Sand New naming scheme: - Material = irrlicht's Material class - Content = (u8) content of a node - Tile = (u16) Material ID at some side of a node */ #define CONTENT_STONE 0 #define CONTENT_GRASS 1 #define CONTENT_WATER 2 #define CONTENT_TORCH 3 #define CONTENT_TREE 4 #define CONTENT_LEAVES 5 #define CONTENT_GRASS_FOOTSTEPS 6 #define CONTENT_MESE 7 #define CONTENT_MUD 8 #define CONTENT_WATERSOURCE 9 // Pretty much useless, clouds won't be drawn this way #define CONTENT_CLOUD 10 #define CONTENT_COALSTONE 11 #define CONTENT_WOOD 12 #define CONTENT_SAND 13 #define CONTENT_SIGN_WALL 14 #define CONTENT_CHEST 15 #define CONTENT_FURNACE 16 //#define CONTENT_WORKBENCH 17 #define CONTENT_COBBLE 18 #define CONTENT_STEEL 19 #define CONTENT_GLASS 20 /* Content feature list */ enum ContentParamType { CPT_NONE, CPT_LIGHT, CPT_MINERAL, // Direction for chests and furnaces and such CPT_FACEDIR_SIMPLE }; enum LiquidType { LIQUID_NONE, LIQUID_FLOWING, LIQUID_SOURCE }; class MapNode; class NodeMetadata; struct ContentFeatures { // If non-NULL, content is translated to this when deserialized MapNode *translate_to; // Type of MapNode::param ContentParamType param_type; /* 0: up 1: down 2: right 3: left 4: back 5: front */ TileSpec tiles[6]; video::ITexture *inventory_texture; bool is_ground_content; bool light_propagates; bool sunlight_propagates; u8 solidness; // Used when choosing which face is drawn bool walkable; bool pointable; bool diggable; bool buildable_to; enum LiquidType liquid_type; // If true, param2 is set to direction when placed // NOTE: the direction format is quite inefficient and should be changed bool wall_mounted; // Inventory item string as which the node appears in inventory when dug. // Mineral overrides this. std::string dug_item; // Initial metadata is cloned from this NodeMetadata *initial_metadata; //TODO: Move more properties here ContentFeatures() { translate_to = NULL; param_type = CPT_NONE; inventory_texture = NULL; is_ground_content = false; light_propagates = false; sunlight_propagates = false; solidness = 2; walkable = true; pointable = true; diggable = true; buildable_to = false; liquid_type = LIQUID_NONE; wall_mounted = false; dug_item = ""; initial_metadata = NULL; } ~ContentFeatures(); /* Quickhands for simple materials */ void setTexture(u16 i, std::string name, u8 alpha=255); void setAllTextures(std::string name, u8 alpha=255) { for(u16 i=0; i<6; i++) { setTexture(i, name, alpha); } } void setTile(u16 i, const TileSpec &tile) { tiles[i] = tile; } void setAllTiles(const TileSpec &tile) { for(u16 i=0; i<6; i++) { setTile(i, tile); } } void setInventoryTexture(std::string imgname); void setInventoryTextureCube(std::string top, std::string left, std::string right); }; /* Call this to access the ContentFeature list */ ContentFeatures & content_features(u8 i); /* If true, the material allows light propagation and brightness is stored in param. NOTE: Don't use, use "content_features(m).whatever" instead */ inline bool light_propagates_content(u8 m) { return content_features(m).light_propagates; //return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE); } /* If true, the material allows lossless sunlight propagation. NOTE: It doesn't seem to go through torches regardlessly of this NOTE: Don't use, use "content_features(m).whatever" instead */ inline bool sunlight_propagates_content(u8 m) { return content_features(m).sunlight_propagates; //return (m == CONTENT_AIR || m == CONTENT_TORCH); } /* On a node-node surface, the material of the node with higher solidness is used for drawing. 0: Invisible 1: Transparent 2: Opaque NOTE: Don't use, use "content_features(m).whatever" instead */ inline u8 content_solidness(u8 m) { return content_features(m).solidness; /*// As of now, every pseudo node like torches are added to this if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER) return 0; if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE) return 1; return 2;*/ } // Objects collide with walkable contents // NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_walkable(u8 m) { return content_features(m).walkable; //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH); } // NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_liquid(u8 m) { return content_features(m).liquid_type != LIQUID_NONE; //return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE); } // NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_flowing_liquid(u8 m) { return content_features(m).liquid_type == LIQUID_FLOWING; //return (m == CONTENT_WATER); } // NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_liquid_source(u8 m) { return content_features(m).liquid_type == LIQUID_SOURCE; //return (m == CONTENT_WATERSOURCE); } // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER // CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA inline u8 make_liquid_flowing(u8 m) { if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE) return CONTENT_WATER; assert(0); } // Pointable contents can be pointed to in the map // NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_pointable(u8 m) { return content_features(m).pointable; //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE); } // NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_diggable(u8 m) { return content_features(m).diggable; //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE); } // NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_buildable_to(u8 m) { return content_features(m).buildable_to; //return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE); } /* Returns true for contents that form the base ground that follows the main heightmap */ /*inline bool is_ground_content(u8 m) { return content_features(m).is_ground_content; }*/ /* Nodes make a face if contents differ and solidness differs. Return value: 0: No face 1: Face uses m1's content 2: Face uses m2's content */ inline u8 face_contents(u8 m1, u8 m2) { if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE) return 0; bool contents_differ = (m1 != m2); // Contents don't differ for different forms of same liquid if(content_liquid(m1) && content_liquid(m2) && make_liquid_flowing(m1) == make_liquid_flowing(m2)) contents_differ = false; bool solidness_differs = (content_solidness(m1) != content_solidness(m2)); bool makes_face = contents_differ && solidness_differs; if(makes_face == false) return 0; if(content_solidness(m1) > content_solidness(m2)) return 1; else return 2; } /* Packs directions like (1,0,0), (1,-1,0) */ inline u8 packDir(v3s16 dir) { u8 b = 0; if(dir.X > 0) b |= (1<<0); else if(dir.X < 0) b |= (1<<1); if(dir.Y > 0) b |= (1<<2); else if(dir.Y < 0) b |= (1<<3); if(dir.Z > 0) b |= (1<<4); else if(dir.Z < 0) b |= (1<<5); return b; } inline v3s16 unpackDir(u8 b) { v3s16 d(0,0,0); if(b & (1<<0)) d.X = 1; else if(b & (1<<1)) d.X = -1; if(b & (1<<2)) d.Y = 1; else if(b & (1<<3)) d.Y = -1; if(b & (1<<4)) d.Z = 1; else if(b & (1<<5)) d.Z = -1; return d; } /* facedir: CPT_FACEDIR_SIMPLE param1 value dir: The face for which stuff is wanted return value: The face from which the stuff is actually found */ v3s16 facedir_rotate(u8 facedir, v3s16 dir); enum LightBank { LIGHTBANK_DAY, LIGHTBANK_NIGHT }; /* This is the stuff what the whole world consists of. */ struct MapNode { // Content u8 d; /* Misc parameter. Initialized to 0. - For light_propagates() blocks, this is light intensity, stored logarithmically from 0 to LIGHT_MAX. Sunlight is LIGHT_SUN, which is LIGHT_MAX+1. - Contains 2 values, day- and night lighting. Each takes 4 bits. */ union { s8 param; u8 param1; }; /* The second parameter. Initialized to 0. E.g. direction for torches and flowing water. */ union { u8 param2; u8 dir; }; MapNode(const MapNode & n) { *this = n; } MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_param2=0) { d = data; param = a_param; param2 = a_param2; } /*MapNode & operator=(const MapNode &other) { d = other.d; param = other.param; param2 = other.param2; return *this; }*/ bool operator==(const MapNode &other) { return (d == other.d && param == other.param && param2 == other.param2); } bool light_propagates() { return light_propagates_content(d); } bool sunlight_propagates() { return sunlight_propagates_content(d); } u8 solidness() { return content_solidness(d); } u8 light_source() { /* Note that a block that isn't light_propagates() can be a light source. */ if(d == CONTENT_TORCH) return LIGHT_MAX; return 0; } u8 getLightBanksWithSource() { // Select the brightest of [light source, propagated light] u8 lightday = 0; u8 lightnight = 0; if(content_features(d).param_type == CPT_LIGHT) { lightday = param & 0x0f; lightnight = (param>>4)&0x0f; } if(light_source() > lightday) lightday = light_source(); if(light_source() > lightnight) lightnight = light_source(); return (lightday&0x0f) | ((lightnight<<4)&0xf0); } void setLightBanks(u8 a_light) { param = a_light; } u8 getLight(enum LightBank bank) { // Select the brightest of [light source, propagated light] u8 light = 0; if(content_features(d).param_type == CPT_LIGHT) { if(bank == LIGHTBANK_DAY) light = param & 0x0f; else if(bank == LIGHTBANK_NIGHT) light = (param>>4)&0x0f; else assert(0); } if(light_source() > light) light = light_source(); return light; } // 0 <= daylight_factor <= 1000 // 0 <= return value <= LIGHT_SUN u8 getLightBlend(u32 daylight_factor) { u8 l = ((daylight_factor * getLight(LIGHTBANK_DAY) + (1000-daylight_factor) * getLight(LIGHTBANK_NIGHT)) )/1000; u8 max = LIGHT_MAX; if(getLight(LIGHTBANK_DAY) == LIGHT_SUN) max = LIGHT_SUN; if(l > max) l = max; return l; } /*// 0 <= daylight_factor <= 1000 // 0 <= return value <= 255 u8 getLightBlend(u32 daylight_factor) { u8 daylight = decode_light(getLight(LIGHTBANK_DAY)); u8 nightlight = decode_light(getLight(LIGHTBANK_NIGHT)); u8 mix = ((daylight_factor * daylight + (1000-daylight_factor) * nightlight) )/1000; return mix; }*/ void setLight(enum LightBank bank, u8 a_light) { // If node doesn't contain light data, ignore this if(content_features(d).param_type != CPT_LIGHT) return; if(bank == LIGHTBANK_DAY) { param &= 0xf0; param |= a_light & 0x0f; } else if(bank == LIGHTBANK_NIGHT) { param &= 0x0f; param |= (a_light & 0x0f)<<4; } else assert(0); } // In mapnode.cpp TileSpec getTile(v3s16 dir); u8 getMineral(); /* These serialization functions are used when informing client of a single node add */ static u32 serializedLength(u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); if(version == 0) return 1; else if(version <= 9) return 2; else return 3; } void serialize(u8 *dest, u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); if(version == 0) { dest[0] = d; } else if(version <= 9) { dest[0] = d; dest[1] = param; } else { dest[0] = d; dest[1] = param; dest[2] = param2; } } void deSerialize(u8 *source, u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); if(version == 0) { d = source[0]; } else if(version == 1) { d = source[0]; // This version doesn't support saved lighting if(light_propagates() || light_source() > 0) param = 0; else param = source[1]; } else if(version <= 9) { d = source[0]; param = source[1]; } else { d = source[0]; param = source[1]; param2 = source[2]; } // Translate deprecated stuff // NOTE: This doesn't get used because MapBlock handles node // parameters directly MapNode *translate_to = content_features(d).translate_to; if(translate_to) { dstream<<"MapNode: WARNING: Translating "<<d<<" to " <<translate_to->d<<std::endl; *this = *translate_to; } } }; #endif