3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "scriptapi.h"
21 #include "scriptapi_content.h"
22 #include "scriptapi_types.h"
23 #include "scriptapi_common.h"
24 #include "scriptapi_node.h"
27 NodeBox read_nodebox(lua_State *L, int index)
30 if(lua_istable(L, -1)){
31 nodebox.type = (NodeBoxType)getenumfield(L, index, "type",
32 es_NodeBoxType, NODEBOX_REGULAR);
34 lua_getfield(L, index, "fixed");
35 if(lua_istable(L, -1))
36 nodebox.fixed = read_aabb3f_vector(L, -1, BS);
39 lua_getfield(L, index, "wall_top");
40 if(lua_istable(L, -1))
41 nodebox.wall_top = read_aabb3f(L, -1, BS);
44 lua_getfield(L, index, "wall_bottom");
45 if(lua_istable(L, -1))
46 nodebox.wall_bottom = read_aabb3f(L, -1, BS);
49 lua_getfield(L, index, "wall_side");
50 if(lua_istable(L, -1))
51 nodebox.wall_side = read_aabb3f(L, -1, BS);
61 void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec)
64 index = lua_gettop(L) + 1 + index;
65 if(lua_isnil(L, index)){
66 } else if(lua_istable(L, index)){
67 getstringfield(L, index, "name", spec.name);
68 getfloatfield(L, index, "gain", spec.gain);
69 } else if(lua_isstring(L, index)){
70 spec.name = lua_tostring(L, index);
74 struct EnumString es_TileAnimationType[] =
77 {TAT_VERTICAL_FRAMES, "vertical_frames"},
85 TileDef read_tiledef(lua_State *L, int index)
88 index = lua_gettop(L) + 1 + index;
92 // key at index -2 and value at index
93 if(lua_isstring(L, index)){
95 tiledef.name = lua_tostring(L, index);
97 else if(lua_istable(L, index))
99 // {name="default_lava.png", animation={}}
101 getstringfield(L, index, "name", tiledef.name);
102 getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
103 tiledef.backface_culling = getboolfield_default(
104 L, index, "backface_culling", true);
106 lua_getfield(L, index, "animation");
107 if(lua_istable(L, -1)){
108 // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
109 tiledef.animation.type = (TileAnimationType)
110 getenumfield(L, -1, "type", es_TileAnimationType,
112 tiledef.animation.aspect_w =
113 getintfield_default(L, -1, "aspect_w", 16);
114 tiledef.animation.aspect_h =
115 getintfield_default(L, -1, "aspect_h", 16);
116 tiledef.animation.length =
117 getfloatfield_default(L, -1, "length", 1.0);
129 ContentFeatures read_content_features(lua_State *L, int index)
132 index = lua_gettop(L) + 1 + index;
136 /* Cache existence of some callbacks */
137 lua_getfield(L, index, "on_construct");
138 if(!lua_isnil(L, -1)) f.has_on_construct = true;
140 lua_getfield(L, index, "on_destruct");
141 if(!lua_isnil(L, -1)) f.has_on_destruct = true;
143 lua_getfield(L, index, "after_destruct");
144 if(!lua_isnil(L, -1)) f.has_after_destruct = true;
147 lua_getfield(L, index, "on_rightclick");
148 f.rightclickable = lua_isfunction(L, -1);
152 getstringfield(L, index, "name", f.name);
155 lua_getfield(L, index, "groups");
156 read_groups(L, -1, f.groups);
159 /* Visual definition */
161 f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType,
163 getfloatfield(L, index, "visual_scale", f.visual_scale);
166 lua_getfield(L, index, "tiles");
167 // If nil, try the deprecated name "tile_images" instead
168 if(lua_isnil(L, -1)){
170 warn_if_field_exists(L, index, "tile_images",
171 "Deprecated; new name is \"tiles\".");
172 lua_getfield(L, index, "tile_images");
174 if(lua_istable(L, -1)){
175 int table = lua_gettop(L);
178 while(lua_next(L, table) != 0){
179 // Read tiledef from value
180 f.tiledef[i] = read_tiledef(L, -1);
181 // removes value, keeps key for next iteration
189 // Copy last value to all remaining textures
191 TileDef lasttile = f.tiledef[i-1];
193 f.tiledef[i] = lasttile;
200 // special_tiles = {}
201 lua_getfield(L, index, "special_tiles");
202 // If nil, try the deprecated name "special_materials" instead
203 if(lua_isnil(L, -1)){
205 warn_if_field_exists(L, index, "special_materials",
206 "Deprecated; new name is \"special_tiles\".");
207 lua_getfield(L, index, "special_materials");
209 if(lua_istable(L, -1)){
210 int table = lua_gettop(L);
213 while(lua_next(L, table) != 0){
214 // Read tiledef from value
215 f.tiledef_special[i] = read_tiledef(L, -1);
216 // removes value, keeps key for next iteration
227 f.alpha = getintfield_default(L, index, "alpha", 255);
229 bool usealpha = getboolfield_default(L, index,
230 "use_texture_alpha", false);
236 lua_getfield(L, index, "post_effect_color");
237 if(!lua_isnil(L, -1))
238 f.post_effect_color = readARGB8(L, -1);
241 f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
242 es_ContentParamType, CPT_NONE);
243 f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
244 es_ContentParamType2, CPT2_NONE);
246 // Warn about some deprecated fields
247 warn_if_field_exists(L, index, "wall_mounted",
248 "deprecated: use paramtype2 = 'wallmounted'");
249 warn_if_field_exists(L, index, "light_propagates",
250 "deprecated: determined from paramtype");
251 warn_if_field_exists(L, index, "dug_item",
252 "deprecated: use 'drop' field");
253 warn_if_field_exists(L, index, "extra_dug_item",
254 "deprecated: use 'drop' field");
255 warn_if_field_exists(L, index, "extra_dug_item_rarity",
256 "deprecated: use 'drop' field");
257 warn_if_field_exists(L, index, "metadata_name",
258 "deprecated: use on_add and metadata callbacks");
260 // True for all ground-like things like stone and mud, false for eg. trees
261 getboolfield(L, index, "is_ground_content", f.is_ground_content);
262 f.light_propagates = (f.param_type == CPT_LIGHT);
263 getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
264 // This is used for collision detection.
265 // Also for general solidness queries.
266 getboolfield(L, index, "walkable", f.walkable);
267 // Player can point to these
268 getboolfield(L, index, "pointable", f.pointable);
269 // Player can dig these
270 getboolfield(L, index, "diggable", f.diggable);
271 // Player can climb these
272 getboolfield(L, index, "climbable", f.climbable);
273 // Player can build on these
274 getboolfield(L, index, "buildable_to", f.buildable_to);
275 // Whether the node is non-liquid, source liquid or flowing liquid
276 f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
277 es_LiquidType, LIQUID_NONE);
278 // If the content is liquid, this is the flowing version of the liquid.
279 getstringfield(L, index, "liquid_alternative_flowing",
280 f.liquid_alternative_flowing);
281 // If the content is liquid, this is the source version of the liquid.
282 getstringfield(L, index, "liquid_alternative_source",
283 f.liquid_alternative_source);
284 // Viscosity for fluid flow, ranging from 1 to 7, with
285 // 1 giving almost instantaneous propagation and 7 being
286 // the slowest possible
287 f.liquid_viscosity = getintfield_default(L, index,
288 "liquid_viscosity", f.liquid_viscosity);
289 getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
290 // Amount of light the node emits
291 f.light_source = getintfield_default(L, index,
292 "light_source", f.light_source);
293 f.damage_per_second = getintfield_default(L, index,
294 "damage_per_second", f.damage_per_second);
296 lua_getfield(L, index, "node_box");
297 if(lua_istable(L, -1))
298 f.node_box = read_nodebox(L, -1);
301 lua_getfield(L, index, "selection_box");
302 if(lua_istable(L, -1))
303 f.selection_box = read_nodebox(L, -1);
306 // Set to true if paramtype used to be 'facedir_simple'
307 getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
308 // Set to true if wall_mounted used to be set to true
309 getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
312 lua_getfield(L, index, "sounds");
313 if(lua_istable(L, -1)){
314 lua_getfield(L, -1, "footstep");
315 read_soundspec(L, -1, f.sound_footstep);
317 lua_getfield(L, -1, "dig");
318 read_soundspec(L, -1, f.sound_dig);
320 lua_getfield(L, -1, "dug");
321 read_soundspec(L, -1, f.sound_dug);