on_death: Fix callback number of pushed arguments (Fixes #6451)
[oweals/minetest.git] / src / nodedef.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #include "nodedef.h"
21
22 #include "itemdef.h"
23 #ifndef SERVER
24 #include "mesh.h"
25 #include "shader.h"
26 #include "client.h"
27 #include "client/renderingengine.h"
28 #include "client/tile.h"
29 #include <IMeshManipulator.h>
30 #endif
31 #include "log.h"
32 #include "settings.h"
33 #include "nameidmapping.h"
34 #include "util/numeric.h"
35 #include "util/serialize.h"
36 #include "exceptions.h"
37 #include "debug.h"
38 #include "gamedef.h"
39 #include "mapnode.h"
40 #include <fstream> // Used in applyTextureOverrides()
41 #include <algorithm>
42
43 /*
44         NodeBox
45 */
46
47 void NodeBox::reset()
48 {
49         type = NODEBOX_REGULAR;
50         // default is empty
51         fixed.clear();
52         // default is sign/ladder-like
53         wall_top = aabb3f(-BS/2, BS/2-BS/16., -BS/2, BS/2, BS/2, BS/2);
54         wall_bottom = aabb3f(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2);
55         wall_side = aabb3f(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2);
56         // no default for other parts
57         connect_top.clear();
58         connect_bottom.clear();
59         connect_front.clear();
60         connect_left.clear();
61         connect_back.clear();
62         connect_right.clear();
63 }
64
65 void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
66 {
67         // Protocol >= 36
68         int version = 4;
69         writeU8(os, version);
70
71         switch (type) {
72         case NODEBOX_LEVELED:
73         case NODEBOX_FIXED:
74                 writeU8(os, type);
75
76                 writeU16(os, fixed.size());
77                 for (const aabb3f &nodebox : fixed) {
78                         writeV3F1000(os, nodebox.MinEdge);
79                         writeV3F1000(os, nodebox.MaxEdge);
80                 }
81                 break;
82         case NODEBOX_WALLMOUNTED:
83                 writeU8(os, type);
84
85                 writeV3F1000(os, wall_top.MinEdge);
86                 writeV3F1000(os, wall_top.MaxEdge);
87                 writeV3F1000(os, wall_bottom.MinEdge);
88                 writeV3F1000(os, wall_bottom.MaxEdge);
89                 writeV3F1000(os, wall_side.MinEdge);
90                 writeV3F1000(os, wall_side.MaxEdge);
91                 break;
92         case NODEBOX_CONNECTED:
93                 writeU8(os, type);
94
95 #define WRITEBOX(box) \
96                 writeU16(os, (box).size()); \
97                 for (const aabb3f &i: (box)) { \
98                         writeV3F1000(os, i.MinEdge); \
99                         writeV3F1000(os, i.MaxEdge); \
100                 };
101
102                 WRITEBOX(fixed);
103                 WRITEBOX(connect_top);
104                 WRITEBOX(connect_bottom);
105                 WRITEBOX(connect_front);
106                 WRITEBOX(connect_left);
107                 WRITEBOX(connect_back);
108                 WRITEBOX(connect_right);
109                 break;
110         default:
111                 writeU8(os, type);
112                 break;
113         }
114 }
115
116 void NodeBox::deSerialize(std::istream &is)
117 {
118         int version = readU8(is);
119         if (version < 4)
120                 throw SerializationError("unsupported NodeBox version");
121
122         reset();
123
124         type = (enum NodeBoxType)readU8(is);
125
126         if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED)
127         {
128                 u16 fixed_count = readU16(is);
129                 while(fixed_count--)
130                 {
131                         aabb3f box;
132                         box.MinEdge = readV3F1000(is);
133                         box.MaxEdge = readV3F1000(is);
134                         fixed.push_back(box);
135                 }
136         }
137         else if(type == NODEBOX_WALLMOUNTED)
138         {
139                 wall_top.MinEdge = readV3F1000(is);
140                 wall_top.MaxEdge = readV3F1000(is);
141                 wall_bottom.MinEdge = readV3F1000(is);
142                 wall_bottom.MaxEdge = readV3F1000(is);
143                 wall_side.MinEdge = readV3F1000(is);
144                 wall_side.MaxEdge = readV3F1000(is);
145         }
146         else if (type == NODEBOX_CONNECTED)
147         {
148 #define READBOXES(box) { \
149                 count = readU16(is); \
150                 (box).reserve(count); \
151                 while (count--) { \
152                         v3f min = readV3F1000(is); \
153                         v3f max = readV3F1000(is); \
154                         (box).emplace_back(min, max); }; }
155
156                 u16 count;
157
158                 READBOXES(fixed);
159                 READBOXES(connect_top);
160                 READBOXES(connect_bottom);
161                 READBOXES(connect_front);
162                 READBOXES(connect_left);
163                 READBOXES(connect_back);
164                 READBOXES(connect_right);
165         }
166 }
167
168 /*
169         TileDef
170 */
171
172 void TileDef::serialize(std::ostream &os, u16 protocol_version) const
173 {
174         // protocol_version >= 36
175         u8 version = 5;
176         writeU8(os, version);
177
178         os << serializeString(name);
179         animation.serialize(os, version);
180         writeU8(os, backface_culling);
181         writeU8(os, tileable_horizontal);
182         writeU8(os, tileable_vertical);
183         writeU8(os, has_color);
184         if (has_color) {
185                 writeU8(os, color.getRed());
186                 writeU8(os, color.getGreen());
187                 writeU8(os, color.getBlue());
188         }
189 }
190
191 void TileDef::deSerialize(std::istream &is, u8 contentfeatures_version,
192         NodeDrawType drawtype)
193 {
194         int version = readU8(is);
195         name = deSerializeString(is);
196         animation.deSerialize(is, version);
197         backface_culling = readU8(is);
198         tileable_horizontal = readU8(is);
199         tileable_vertical = readU8(is);
200         has_color = readU8(is);
201         if (has_color) {
202                 color.setRed(readU8(is));
203                 color.setGreen(readU8(is));
204                 color.setBlue(readU8(is));
205         }
206 }
207
208
209 /*
210         SimpleSoundSpec serialization
211 */
212
213 static void serializeSimpleSoundSpec(const SimpleSoundSpec &ss,
214                 std::ostream &os, u8 version)
215 {
216         os<<serializeString(ss.name);
217         writeF1000(os, ss.gain);
218         writeF1000(os, ss.pitch);
219 }
220 static void deSerializeSimpleSoundSpec(SimpleSoundSpec &ss,
221                 std::istream &is, u8 version)
222 {
223         ss.name = deSerializeString(is);
224         ss.gain = readF1000(is);
225         ss.pitch = readF1000(is);
226 }
227
228 void TextureSettings::readSettings()
229 {
230         connected_glass                = g_settings->getBool("connected_glass");
231         opaque_water                   = g_settings->getBool("opaque_water");
232         bool enable_shaders            = g_settings->getBool("enable_shaders");
233         bool enable_bumpmapping        = g_settings->getBool("enable_bumpmapping");
234         bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion");
235         bool smooth_lighting           = g_settings->getBool("smooth_lighting");
236         enable_mesh_cache              = g_settings->getBool("enable_mesh_cache");
237         enable_minimap                 = g_settings->getBool("enable_minimap");
238         std::string leaves_style_str   = g_settings->get("leaves_style");
239
240         // Mesh cache is not supported in combination with smooth lighting
241         if (smooth_lighting)
242                 enable_mesh_cache = false;
243
244         use_normal_texture = enable_shaders &&
245                 (enable_bumpmapping || enable_parallax_occlusion);
246         if (leaves_style_str == "fancy") {
247                 leaves_style = LEAVES_FANCY;
248         } else if (leaves_style_str == "simple") {
249                 leaves_style = LEAVES_SIMPLE;
250         } else {
251                 leaves_style = LEAVES_OPAQUE;
252         }
253 }
254
255 /*
256         ContentFeatures
257 */
258
259 ContentFeatures::ContentFeatures()
260 {
261         reset();
262 }
263
264 void ContentFeatures::reset()
265 {
266         /*
267                 Cached stuff
268         */
269 #ifndef SERVER
270         solidness = 2;
271         visual_solidness = 0;
272         backface_culling = true;
273
274 #endif
275         has_on_construct = false;
276         has_on_destruct = false;
277         has_after_destruct = false;
278         /*
279                 Actual data
280
281                 NOTE: Most of this is always overridden by the default values given
282                       in builtin.lua
283         */
284         name = "";
285         groups.clear();
286         // Unknown nodes can be dug
287         groups["dig_immediate"] = 2;
288         drawtype = NDT_NORMAL;
289         mesh = "";
290 #ifndef SERVER
291         for (auto &i : mesh_ptr)
292                 i = NULL;
293         minimap_color = video::SColor(0, 0, 0, 0);
294 #endif
295         visual_scale = 1.0;
296         for (auto &i : tiledef)
297                 i = TileDef();
298         for (auto &j : tiledef_special)
299                 j = TileDef();
300         alpha = 255;
301         post_effect_color = video::SColor(0, 0, 0, 0);
302         param_type = CPT_NONE;
303         param_type_2 = CPT2_NONE;
304         is_ground_content = false;
305         light_propagates = false;
306         sunlight_propagates = false;
307         walkable = true;
308         pointable = true;
309         diggable = true;
310         climbable = false;
311         buildable_to = false;
312         floodable = false;
313         rightclickable = true;
314         leveled = 0;
315         liquid_type = LIQUID_NONE;
316         liquid_alternative_flowing = "";
317         liquid_alternative_source = "";
318         liquid_viscosity = 0;
319         liquid_renewable = true;
320         liquid_range = LIQUID_LEVEL_MAX+1;
321         drowning = 0;
322         light_source = 0;
323         damage_per_second = 0;
324         node_box = NodeBox();
325         selection_box = NodeBox();
326         collision_box = NodeBox();
327         waving = 0;
328         legacy_facedir_simple = false;
329         legacy_wallmounted = false;
330         sound_footstep = SimpleSoundSpec();
331         sound_dig = SimpleSoundSpec("__group");
332         sound_dug = SimpleSoundSpec();
333         connects_to.clear();
334         connects_to_ids.clear();
335         connect_sides = 0;
336         color = video::SColor(0xFFFFFFFF);
337         palette_name = "";
338         palette = NULL;
339         node_dig_prediction = "air";
340 }
341
342 void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
343 {
344         // protocol_version >= 36
345         u8 version = 12;
346         writeU8(os, version);
347
348         // general
349         os << serializeString(name);
350         writeU16(os, groups.size());
351         for (const auto &group : groups) {
352                 os << serializeString(group.first);
353                 writeS16(os, group.second);
354         }
355         writeU8(os, param_type);
356         writeU8(os, param_type_2);
357
358         // visual
359         writeU8(os, drawtype);
360         os << serializeString(mesh);
361         writeF1000(os, visual_scale);
362         writeU8(os, 6);
363         for (const TileDef &td : tiledef)
364                 td.serialize(os, protocol_version);
365         for (const TileDef &td : tiledef_overlay)
366                 td.serialize(os, protocol_version);
367         writeU8(os, CF_SPECIAL_COUNT);
368         for (const TileDef &td : tiledef_special) {
369                 td.serialize(os, protocol_version);
370         }
371         writeU8(os, alpha);
372         writeU8(os, color.getRed());
373         writeU8(os, color.getGreen());
374         writeU8(os, color.getBlue());
375         os << serializeString(palette_name);
376         writeU8(os, waving);
377         writeU8(os, connect_sides);
378         writeU16(os, connects_to_ids.size());
379         for (u16 connects_to_id : connects_to_ids)
380                 writeU16(os, connects_to_id);
381         writeU8(os, post_effect_color.getAlpha());
382         writeU8(os, post_effect_color.getRed());
383         writeU8(os, post_effect_color.getGreen());
384         writeU8(os, post_effect_color.getBlue());
385         writeU8(os, leveled);
386
387         // lighting
388         writeU8(os, light_propagates);
389         writeU8(os, sunlight_propagates);
390         writeU8(os, light_source);
391
392         // map generation
393         writeU8(os, is_ground_content);
394
395         // interaction
396         writeU8(os, walkable);
397         writeU8(os, pointable);
398         writeU8(os, diggable);
399         writeU8(os, climbable);
400         writeU8(os, buildable_to);
401         writeU8(os, rightclickable);
402         writeU32(os, damage_per_second);
403
404         // liquid
405         writeU8(os, liquid_type);
406         os << serializeString(liquid_alternative_flowing);
407         os << serializeString(liquid_alternative_source);
408         writeU8(os, liquid_viscosity);
409         writeU8(os, liquid_renewable);
410         writeU8(os, liquid_range);
411         writeU8(os, drowning);
412         writeU8(os, floodable);
413
414         // node boxes
415         node_box.serialize(os, protocol_version);
416         selection_box.serialize(os, protocol_version);
417         collision_box.serialize(os, protocol_version);
418
419         // sound
420         serializeSimpleSoundSpec(sound_footstep, os, version);
421         serializeSimpleSoundSpec(sound_dig, os, version);
422         serializeSimpleSoundSpec(sound_dug, os, version);
423
424         // legacy
425         writeU8(os, legacy_facedir_simple);
426         writeU8(os, legacy_wallmounted);
427
428         os << serializeString(node_dig_prediction);
429 }
430
431 void ContentFeatures::correctAlpha(TileDef *tiles, int length)
432 {
433         // alpha == 0 means that the node is using texture alpha
434         if (alpha == 0 || alpha == 255)
435                 return;
436
437         for (int i = 0; i < length; i++) {
438                 if (tiles[i].name.empty())
439                         continue;
440                 std::stringstream s;
441                 s << tiles[i].name << "^[noalpha^[opacity:" << ((int)alpha);
442                 tiles[i].name = s.str();
443         }
444 }
445
446 void ContentFeatures::deSerialize(std::istream &is)
447 {
448         // version detection
449         int version = readU8(is);
450         if (version < 12)
451                 throw SerializationError("unsupported ContentFeatures version");
452
453         // general
454         name = deSerializeString(is);
455         groups.clear();
456         u32 groups_size = readU16(is);
457         for (u32 i = 0; i < groups_size; i++) {
458                 std::string name = deSerializeString(is);
459                 int value = readS16(is);
460                 groups[name] = value;
461         }
462         param_type = (enum ContentParamType) readU8(is);
463         param_type_2 = (enum ContentParamType2) readU8(is);
464
465         // visual
466         drawtype = (enum NodeDrawType) readU8(is);
467         mesh = deSerializeString(is);
468         visual_scale = readF1000(is);
469         if (readU8(is) != 6)
470                 throw SerializationError("unsupported tile count");
471         for (TileDef &td : tiledef)
472                 td.deSerialize(is, version, drawtype);
473         for (TileDef &td : tiledef_overlay)
474                 td.deSerialize(is, version, drawtype);
475         if (readU8(is) != CF_SPECIAL_COUNT)
476                 throw SerializationError("unsupported CF_SPECIAL_COUNT");
477         for (TileDef &td : tiledef_special)
478                 td.deSerialize(is, version, drawtype);
479         alpha = readU8(is);
480         color.setRed(readU8(is));
481         color.setGreen(readU8(is));
482         color.setBlue(readU8(is));
483         palette_name = deSerializeString(is);
484         waving = readU8(is);
485         connect_sides = readU8(is);
486         u16 connects_to_size = readU16(is);
487         connects_to_ids.clear();
488         for (u16 i = 0; i < connects_to_size; i++)
489                 connects_to_ids.push_back(readU16(is));
490         post_effect_color.setAlpha(readU8(is));
491         post_effect_color.setRed(readU8(is));
492         post_effect_color.setGreen(readU8(is));
493         post_effect_color.setBlue(readU8(is));
494         leveled = readU8(is);
495
496         // lighting-related
497         light_propagates = readU8(is);
498         sunlight_propagates = readU8(is);
499         light_source = readU8(is);
500         light_source = MYMIN(light_source, LIGHT_MAX);
501
502         // map generation
503         is_ground_content = readU8(is);
504
505         // interaction
506         walkable = readU8(is);
507         pointable = readU8(is);
508         diggable = readU8(is);
509         climbable = readU8(is);
510         buildable_to = readU8(is);
511         rightclickable = readU8(is);
512         damage_per_second = readU32(is);
513
514         // liquid
515         liquid_type = (enum LiquidType) readU8(is);
516         liquid_alternative_flowing = deSerializeString(is);
517         liquid_alternative_source = deSerializeString(is);
518         liquid_viscosity = readU8(is);
519         liquid_renewable = readU8(is);
520         liquid_range = readU8(is);
521         drowning = readU8(is);
522         floodable = readU8(is);
523
524         // node boxes
525         node_box.deSerialize(is);
526         selection_box.deSerialize(is);
527         collision_box.deSerialize(is);
528
529         // sounds
530         deSerializeSimpleSoundSpec(sound_footstep, is, version);
531         deSerializeSimpleSoundSpec(sound_dig, is, version);
532         deSerializeSimpleSoundSpec(sound_dug, is, version);
533
534         // read legacy properties
535         legacy_facedir_simple = readU8(is);
536         legacy_wallmounted = readU8(is);
537
538         try {
539                 node_dig_prediction = deSerializeString(is);
540         } catch(SerializationError &e) {};
541 }
542
543 #ifndef SERVER
544 void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileLayer *tile,
545                 TileDef *tiledef, u32 shader_id, bool use_normal_texture,
546                 bool backface_culling, u8 material_type)
547 {
548         tile->shader_id     = shader_id;
549         tile->texture       = tsrc->getTextureForMesh(tiledef->name, &tile->texture_id);
550         tile->material_type = material_type;
551
552         // Normal texture and shader flags texture
553         if (use_normal_texture) {
554                 tile->normal_texture = tsrc->getNormalTexture(tiledef->name);
555         }
556         tile->flags_texture = tsrc->getShaderFlagsTexture(tile->normal_texture ? true : false);
557
558         // Material flags
559         tile->material_flags = 0;
560         if (backface_culling)
561                 tile->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
562         if (tiledef->animation.type != TAT_NONE)
563                 tile->material_flags |= MATERIAL_FLAG_ANIMATION;
564         if (tiledef->tileable_horizontal)
565                 tile->material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL;
566         if (tiledef->tileable_vertical)
567                 tile->material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;
568
569         // Color
570         tile->has_color = tiledef->has_color;
571         if (tiledef->has_color)
572                 tile->color = tiledef->color;
573         else
574                 tile->color = color;
575
576         // Animation parameters
577         int frame_count = 1;
578         if (tile->material_flags & MATERIAL_FLAG_ANIMATION) {
579                 int frame_length_ms;
580                 tiledef->animation.determineParams(tile->texture->getOriginalSize(),
581                                 &frame_count, &frame_length_ms, NULL);
582                 tile->animation_frame_count = frame_count;
583                 tile->animation_frame_length_ms = frame_length_ms;
584         }
585
586         if (frame_count == 1) {
587                 tile->material_flags &= ~MATERIAL_FLAG_ANIMATION;
588         } else {
589                 std::ostringstream os(std::ios::binary);
590                 if (!tile->frames) {
591                         tile->frames = std::make_shared<std::vector<FrameSpec>>();
592                 }
593                 tile->frames->resize(frame_count);
594
595                 for (int i = 0; i < frame_count; i++) {
596
597                         FrameSpec frame;
598
599                         os.str("");
600                         os << tiledef->name;
601                         tiledef->animation.getTextureModifer(os,
602                                         tile->texture->getOriginalSize(), i);
603
604                         frame.texture = tsrc->getTextureForMesh(os.str(), &frame.texture_id);
605                         if (tile->normal_texture)
606                                 frame.normal_texture = tsrc->getNormalTexture(os.str());
607                         frame.flags_texture = tile->flags_texture;
608                         (*tile->frames)[i] = frame;
609                 }
610         }
611 }
612 #endif
613
614 #ifndef SERVER
615 void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
616         scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings)
617 {
618         // minimap pixel color - the average color of a texture
619         if (tsettings.enable_minimap && !tiledef[0].name.empty())
620                 minimap_color = tsrc->getTextureAverageColor(tiledef[0].name);
621
622         // Figure out the actual tiles to use
623         TileDef tdef[6];
624         for (u32 j = 0; j < 6; j++) {
625                 tdef[j] = tiledef[j];
626                 if (tdef[j].name.empty())
627                         tdef[j].name = "unknown_node.png";
628         }
629         // also the overlay tiles
630         TileDef tdef_overlay[6];
631         for (u32 j = 0; j < 6; j++)
632                 tdef_overlay[j] = tiledef_overlay[j];
633         // also the special tiles
634         TileDef tdef_spec[6];
635         for (u32 j = 0; j < CF_SPECIAL_COUNT; j++)
636                 tdef_spec[j] = tiledef_special[j];
637
638         bool is_liquid = false;
639
640         u8 material_type = (alpha == 255) ?
641                 TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
642
643         switch (drawtype) {
644         default:
645         case NDT_NORMAL:
646                 material_type = (alpha == 255) ?
647                         TILE_MATERIAL_OPAQUE : TILE_MATERIAL_ALPHA;
648                 solidness = 2;
649                 break;
650         case NDT_AIRLIKE:
651                 solidness = 0;
652                 break;
653         case NDT_LIQUID:
654                 assert(liquid_type == LIQUID_SOURCE);
655                 if (tsettings.opaque_water)
656                         alpha = 255;
657                 solidness = 1;
658                 is_liquid = true;
659                 break;
660         case NDT_FLOWINGLIQUID:
661                 assert(liquid_type == LIQUID_FLOWING);
662                 solidness = 0;
663                 if (tsettings.opaque_water)
664                         alpha = 255;
665                 is_liquid = true;
666                 break;
667         case NDT_GLASSLIKE:
668                 solidness = 0;
669                 visual_solidness = 1;
670                 break;
671         case NDT_GLASSLIKE_FRAMED:
672                 solidness = 0;
673                 visual_solidness = 1;
674                 break;
675         case NDT_GLASSLIKE_FRAMED_OPTIONAL:
676                 solidness = 0;
677                 visual_solidness = 1;
678                 drawtype = tsettings.connected_glass ? NDT_GLASSLIKE_FRAMED : NDT_GLASSLIKE;
679                 break;
680         case NDT_ALLFACES:
681                 solidness = 0;
682                 visual_solidness = 1;
683                 break;
684         case NDT_ALLFACES_OPTIONAL:
685                 if (tsettings.leaves_style == LEAVES_FANCY) {
686                         drawtype = NDT_ALLFACES;
687                         solidness = 0;
688                         visual_solidness = 1;
689                 } else if (tsettings.leaves_style == LEAVES_SIMPLE) {
690                         for (u32 j = 0; j < 6; j++) {
691                                 if (!tdef_spec[j].name.empty())
692                                         tdef[j].name = tdef_spec[j].name;
693                         }
694                         drawtype = NDT_GLASSLIKE;
695                         solidness = 0;
696                         visual_solidness = 1;
697                 } else {
698                         drawtype = NDT_NORMAL;
699                         solidness = 2;
700                         for (TileDef &td : tdef)
701                                 td.name += std::string("^[noalpha");
702                 }
703                 if (waving >= 1)
704                         material_type = TILE_MATERIAL_WAVING_LEAVES;
705                 break;
706         case NDT_PLANTLIKE:
707                 solidness = 0;
708                 if (waving >= 1)
709                         material_type = TILE_MATERIAL_WAVING_PLANTS;
710                 break;
711         case NDT_FIRELIKE:
712                 solidness = 0;
713                 break;
714         case NDT_MESH:
715         case NDT_NODEBOX:
716                 solidness = 0;
717                 if (waving == 1)
718                         material_type = TILE_MATERIAL_WAVING_PLANTS;
719                 else if (waving == 2)
720                         material_type = TILE_MATERIAL_WAVING_LEAVES;
721                 break;
722         case NDT_TORCHLIKE:
723         case NDT_SIGNLIKE:
724         case NDT_FENCELIKE:
725         case NDT_RAILLIKE:
726                 solidness = 0;
727                 break;
728         case NDT_PLANTLIKE_ROOTED:
729                 solidness = 2;
730                 break;
731         }
732
733         if (is_liquid) {
734                 // Vertex alpha is no longer supported, correct if necessary.
735                 correctAlpha(tdef, 6);
736                 correctAlpha(tdef_overlay, 6);
737                 correctAlpha(tdef_spec, CF_SPECIAL_COUNT);
738                 material_type = (alpha == 255) ?
739                         TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT;
740         }
741
742         u32 tile_shader = shdsrc->getShader("nodes_shader", material_type, drawtype);
743
744         u8 overlay_material = material_type;
745         if (overlay_material == TILE_MATERIAL_OPAQUE)
746                 overlay_material = TILE_MATERIAL_BASIC;
747         else if (overlay_material == TILE_MATERIAL_LIQUID_OPAQUE)
748                 overlay_material = TILE_MATERIAL_LIQUID_TRANSPARENT;
749
750         u32 overlay_shader = shdsrc->getShader("nodes_shader", overlay_material, drawtype);
751
752         // Tiles (fill in f->tiles[])
753         for (u16 j = 0; j < 6; j++) {
754                 fillTileAttribs(tsrc, &tiles[j].layers[0], &tdef[j], tile_shader,
755                         tsettings.use_normal_texture,
756                         tdef[j].backface_culling, material_type);
757                 if (!tdef_overlay[j].name.empty())
758                         fillTileAttribs(tsrc, &tiles[j].layers[1], &tdef_overlay[j],
759                                 overlay_shader, tsettings.use_normal_texture,
760                                 tdef[j].backface_culling, overlay_material);
761         }
762
763         u8 special_material = material_type;
764         if (drawtype == NDT_PLANTLIKE_ROOTED) {
765                 if (waving == 1)
766                         special_material = TILE_MATERIAL_WAVING_PLANTS;
767                 else if (waving == 2)
768                         special_material = TILE_MATERIAL_WAVING_LEAVES;
769         }
770         u32 special_shader = shdsrc->getShader("nodes_shader", special_material, drawtype);
771
772         // Special tiles (fill in f->special_tiles[])
773         for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) {
774                 fillTileAttribs(tsrc, &special_tiles[j].layers[0], &tdef_spec[j],
775                         special_shader, tsettings.use_normal_texture,
776                         tdef_spec[j].backface_culling, special_material);
777         }
778
779         if (param_type_2 == CPT2_COLOR ||
780                         param_type_2 == CPT2_COLORED_FACEDIR ||
781                         param_type_2 == CPT2_COLORED_WALLMOUNTED)
782                 palette = tsrc->getPalette(palette_name);
783
784         if (drawtype == NDT_MESH && !mesh.empty()) {
785                 // Meshnode drawtype
786                 // Read the mesh and apply scale
787                 mesh_ptr[0] = client->getMesh(mesh);
788                 if (mesh_ptr[0]){
789                         v3f scale = v3f(1.0, 1.0, 1.0) * BS * visual_scale;
790                         scaleMesh(mesh_ptr[0], scale);
791                         recalculateBoundingBox(mesh_ptr[0]);
792                         meshmanip->recalculateNormals(mesh_ptr[0], true, false);
793                 }
794         } else if ((drawtype == NDT_NODEBOX) &&
795                         ((node_box.type == NODEBOX_REGULAR) ||
796                         (node_box.type == NODEBOX_FIXED)) &&
797                         (!node_box.fixed.empty())) {
798                 //Convert regular nodebox nodes to meshnodes
799                 //Change the drawtype and apply scale
800                 drawtype = NDT_MESH;
801                 mesh_ptr[0] = convertNodeboxesToMesh(node_box.fixed);
802                 v3f scale = v3f(1.0, 1.0, 1.0) * visual_scale;
803                 scaleMesh(mesh_ptr[0], scale);
804                 recalculateBoundingBox(mesh_ptr[0]);
805                 meshmanip->recalculateNormals(mesh_ptr[0], true, false);
806         }
807
808         //Cache 6dfacedir and wallmounted rotated clones of meshes
809         if (tsettings.enable_mesh_cache && mesh_ptr[0] &&
810                         (param_type_2 == CPT2_FACEDIR
811                         || param_type_2 == CPT2_COLORED_FACEDIR)) {
812                 for (u16 j = 1; j < 24; j++) {
813                         mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
814                         rotateMeshBy6dFacedir(mesh_ptr[j], j);
815                         recalculateBoundingBox(mesh_ptr[j]);
816                         meshmanip->recalculateNormals(mesh_ptr[j], true, false);
817                 }
818         } else if (tsettings.enable_mesh_cache && mesh_ptr[0]
819                         && (param_type_2 == CPT2_WALLMOUNTED ||
820                         param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
821                 static const u8 wm_to_6d[6] = { 20, 0, 16 + 1, 12 + 3, 8, 4 + 2 };
822                 for (u16 j = 1; j < 6; j++) {
823                         mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
824                         rotateMeshBy6dFacedir(mesh_ptr[j], wm_to_6d[j]);
825                         recalculateBoundingBox(mesh_ptr[j]);
826                         meshmanip->recalculateNormals(mesh_ptr[j], true, false);
827                 }
828                 rotateMeshBy6dFacedir(mesh_ptr[0], wm_to_6d[0]);
829                 recalculateBoundingBox(mesh_ptr[0]);
830                 meshmanip->recalculateNormals(mesh_ptr[0], true, false);
831         }
832 }
833 #endif
834
835 /*
836         CNodeDefManager
837 */
838
839 class CNodeDefManager: public IWritableNodeDefManager {
840 public:
841         CNodeDefManager();
842         virtual ~CNodeDefManager();
843         void clear();
844
845         inline virtual const ContentFeatures& get(content_t c) const;
846         inline virtual const ContentFeatures& get(const MapNode &n) const;
847         virtual bool getId(const std::string &name, content_t &result) const;
848         virtual content_t getId(const std::string &name) const;
849         virtual bool getIds(const std::string &name, std::vector<content_t> &result) const;
850         virtual const ContentFeatures& get(const std::string &name) const;
851         content_t allocateId();
852         virtual content_t set(const std::string &name, const ContentFeatures &def);
853         virtual content_t allocateDummy(const std::string &name);
854         virtual void removeNode(const std::string &name);
855         virtual void updateAliases(IItemDefManager *idef);
856         virtual void applyTextureOverrides(const std::string &override_filepath);
857         virtual void updateTextures(IGameDef *gamedef,
858                 void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress),
859                 void *progress_cbk_args);
860         void serialize(std::ostream &os, u16 protocol_version) const;
861         void deSerialize(std::istream &is);
862
863         inline virtual void setNodeRegistrationStatus(bool completed);
864
865         virtual void pendNodeResolve(NodeResolver *nr);
866         virtual bool cancelNodeResolveCallback(NodeResolver *nr);
867         virtual void runNodeResolveCallbacks();
868         virtual void resetNodeResolveState();
869         virtual void mapNodeboxConnections();
870         virtual bool nodeboxConnects(MapNode from, MapNode to, u8 connect_face);
871         virtual core::aabbox3d<s16> getSelectionBoxIntUnion() const
872         {
873                 return m_selection_box_int_union;
874         }
875
876 private:
877         void addNameIdMapping(content_t i, std::string name);
878         /*!
879          * Recalculates m_selection_box_int_union based on
880          * m_selection_box_union.
881          */
882         void fixSelectionBoxIntUnion();
883
884         // Features indexed by id
885         std::vector<ContentFeatures> m_content_features;
886
887         // A mapping for fast converting back and forth between names and ids
888         NameIdMapping m_name_id_mapping;
889
890         // Like m_name_id_mapping, but only from names to ids, and includes
891         // item aliases too. Updated by updateAliases()
892         // Note: Not serialized.
893
894         std::unordered_map<std::string, content_t> m_name_id_mapping_with_aliases;
895
896         // A mapping from groups to a vector of content_ts that belong to it.
897         // Necessary for a direct lookup in getIds().
898         // Note: Not serialized.
899         std::unordered_map<std::string, std::vector<content_t>> m_group_to_items;
900
901         // Next possibly free id
902         content_t m_next_id;
903
904         // NodeResolvers to callback once node registration has ended
905         std::vector<NodeResolver *> m_pending_resolve_callbacks;
906
907         // True when all nodes have been registered
908         bool m_node_registration_complete;
909
910         //! The union of all nodes' selection boxes.
911         aabb3f m_selection_box_union;
912         /*!
913          * The smallest box in node coordinates that
914          * contains all nodes' selection boxes.
915          */
916         core::aabbox3d<s16> m_selection_box_int_union;
917 };
918
919
920 CNodeDefManager::CNodeDefManager()
921 {
922         clear();
923 }
924
925
926 CNodeDefManager::~CNodeDefManager()
927 {
928 #ifndef SERVER
929         for (ContentFeatures &f : m_content_features) {
930                 for (auto &j : f.mesh_ptr) {
931                         if (j)
932                                 j->drop();
933                 }
934         }
935 #endif
936 }
937
938
939 void CNodeDefManager::clear()
940 {
941         m_content_features.clear();
942         m_name_id_mapping.clear();
943         m_name_id_mapping_with_aliases.clear();
944         m_group_to_items.clear();
945         m_next_id = 0;
946         m_selection_box_union.reset(0,0,0);
947         m_selection_box_int_union.reset(0,0,0);
948
949         resetNodeResolveState();
950
951         u32 initial_length = 0;
952         initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1);
953         initial_length = MYMAX(initial_length, CONTENT_AIR + 1);
954         initial_length = MYMAX(initial_length, CONTENT_IGNORE + 1);
955         m_content_features.resize(initial_length);
956
957         // Set CONTENT_UNKNOWN
958         {
959                 ContentFeatures f;
960                 f.name = "unknown";
961                 // Insert directly into containers
962                 content_t c = CONTENT_UNKNOWN;
963                 m_content_features[c] = f;
964                 addNameIdMapping(c, f.name);
965         }
966
967         // Set CONTENT_AIR
968         {
969                 ContentFeatures f;
970                 f.name                = "air";
971                 f.drawtype            = NDT_AIRLIKE;
972                 f.param_type          = CPT_LIGHT;
973                 f.light_propagates    = true;
974                 f.sunlight_propagates = true;
975                 f.walkable            = false;
976                 f.pointable           = false;
977                 f.diggable            = false;
978                 f.buildable_to        = true;
979                 f.floodable           = true;
980                 f.is_ground_content   = true;
981                 // Insert directly into containers
982                 content_t c = CONTENT_AIR;
983                 m_content_features[c] = f;
984                 addNameIdMapping(c, f.name);
985         }
986
987         // Set CONTENT_IGNORE
988         {
989                 ContentFeatures f;
990                 f.name                = "ignore";
991                 f.drawtype            = NDT_AIRLIKE;
992                 f.param_type          = CPT_NONE;
993                 f.light_propagates    = false;
994                 f.sunlight_propagates = false;
995                 f.walkable            = false;
996                 f.pointable           = false;
997                 f.diggable            = false;
998                 f.buildable_to        = true; // A way to remove accidental CONTENT_IGNOREs
999                 f.is_ground_content   = true;
1000                 // Insert directly into containers
1001                 content_t c = CONTENT_IGNORE;
1002                 m_content_features[c] = f;
1003                 addNameIdMapping(c, f.name);
1004         }
1005 }
1006
1007
1008 inline const ContentFeatures& CNodeDefManager::get(content_t c) const
1009 {
1010         return c < m_content_features.size()
1011                         ? m_content_features[c] : m_content_features[CONTENT_UNKNOWN];
1012 }
1013
1014
1015 inline const ContentFeatures& CNodeDefManager::get(const MapNode &n) const
1016 {
1017         return get(n.getContent());
1018 }
1019
1020
1021 bool CNodeDefManager::getId(const std::string &name, content_t &result) const
1022 {
1023         std::unordered_map<std::string, content_t>::const_iterator
1024                 i = m_name_id_mapping_with_aliases.find(name);
1025         if(i == m_name_id_mapping_with_aliases.end())
1026                 return false;
1027         result = i->second;
1028         return true;
1029 }
1030
1031
1032 content_t CNodeDefManager::getId(const std::string &name) const
1033 {
1034         content_t id = CONTENT_IGNORE;
1035         getId(name, id);
1036         return id;
1037 }
1038
1039
1040 bool CNodeDefManager::getIds(const std::string &name,
1041                 std::vector<content_t> &result) const
1042 {
1043         //TimeTaker t("getIds", NULL, PRECISION_MICRO);
1044         if (name.substr(0,6) != "group:") {
1045                 content_t id = CONTENT_IGNORE;
1046                 bool exists = getId(name, id);
1047                 if (exists)
1048                         result.push_back(id);
1049                 return exists;
1050         }
1051         std::string group = name.substr(6);
1052
1053         std::unordered_map<std::string, std::vector<content_t>>::const_iterator
1054                 i = m_group_to_items.find(group);
1055         if (i == m_group_to_items.end())
1056                 return true;
1057
1058         const std::vector<content_t> &items = i->second;
1059         result.insert(result.end(), items.begin(), items.end());
1060         //printf("getIds: %dus\n", t.stop());
1061         return true;
1062 }
1063
1064
1065 const ContentFeatures& CNodeDefManager::get(const std::string &name) const
1066 {
1067         content_t id = CONTENT_UNKNOWN;
1068         getId(name, id);
1069         return get(id);
1070 }
1071
1072
1073 // returns CONTENT_IGNORE if no free ID found
1074 content_t CNodeDefManager::allocateId()
1075 {
1076         for (content_t id = m_next_id;
1077                         id >= m_next_id; // overflow?
1078                         ++id) {
1079                 while (id >= m_content_features.size()) {
1080                         m_content_features.emplace_back();
1081                 }
1082                 const ContentFeatures &f = m_content_features[id];
1083                 if (f.name.empty()) {
1084                         m_next_id = id + 1;
1085                         return id;
1086                 }
1087         }
1088         // If we arrive here, an overflow occurred in id.
1089         // That means no ID was found
1090         return CONTENT_IGNORE;
1091 }
1092
1093
1094 /*!
1095  * Returns the smallest box that contains all boxes
1096  * in the vector. Box_union is expanded.
1097  * @param[in]      boxes     the vector containing the boxes
1098  * @param[in, out] box_union the union of the arguments
1099  */
1100 void boxVectorUnion(const std::vector<aabb3f> &boxes, aabb3f *box_union)
1101 {
1102         for (const aabb3f &box : boxes) {
1103                 box_union->addInternalBox(box);
1104         }
1105 }
1106
1107
1108 /*!
1109  * Returns a box that contains the nodebox in every case.
1110  * The argument node_union is expanded.
1111  * @param[in]      nodebox  the nodebox to be measured
1112  * @param[in]      features  used to decide whether the nodebox
1113  * can be rotated
1114  * @param[in, out] box_union the union of the arguments
1115  */
1116 void getNodeBoxUnion(const NodeBox &nodebox, const ContentFeatures &features,
1117         aabb3f *box_union)
1118 {
1119         switch(nodebox.type) {
1120                 case NODEBOX_FIXED:
1121                 case NODEBOX_LEVELED: {
1122                         // Raw union
1123                         aabb3f half_processed(0, 0, 0, 0, 0, 0);
1124                         boxVectorUnion(nodebox.fixed, &half_processed);
1125                         // Set leveled boxes to maximal
1126                         if (nodebox.type == NODEBOX_LEVELED) {
1127                                 half_processed.MaxEdge.Y = +BS / 2;
1128                         }
1129                         if (features.param_type_2 == CPT2_FACEDIR ||
1130                                         features.param_type_2 == CPT2_COLORED_FACEDIR) {
1131                                 // Get maximal coordinate
1132                                 f32 coords[] = {
1133                                         fabsf(half_processed.MinEdge.X),
1134                                         fabsf(half_processed.MinEdge.Y),
1135                                         fabsf(half_processed.MinEdge.Z),
1136                                         fabsf(half_processed.MaxEdge.X),
1137                                         fabsf(half_processed.MaxEdge.Y),
1138                                         fabsf(half_processed.MaxEdge.Z) };
1139                                 f32 max = 0;
1140                                 for (float coord : coords) {
1141                                         if (max < coord) {
1142                                                 max = coord;
1143                                         }
1144                                 }
1145                                 // Add the union of all possible rotated boxes
1146                                 box_union->addInternalPoint(-max, -max, -max);
1147                                 box_union->addInternalPoint(+max, +max, +max);
1148                         } else {
1149                                 box_union->addInternalBox(half_processed);
1150                         }
1151                         break;
1152                 }
1153                 case NODEBOX_WALLMOUNTED: {
1154                         // Add fix boxes
1155                         box_union->addInternalBox(nodebox.wall_top);
1156                         box_union->addInternalBox(nodebox.wall_bottom);
1157                         // Find maximal coordinate in the X-Z plane
1158                         f32 coords[] = {
1159                                 fabsf(nodebox.wall_side.MinEdge.X),
1160                                 fabsf(nodebox.wall_side.MinEdge.Z),
1161                                 fabsf(nodebox.wall_side.MaxEdge.X),
1162                                 fabsf(nodebox.wall_side.MaxEdge.Z) };
1163                         f32 max = 0;
1164                         for (float coord : coords) {
1165                                 if (max < coord) {
1166                                         max = coord;
1167                                 }
1168                         }
1169                         // Add the union of all possible rotated boxes
1170                         box_union->addInternalPoint(-max, nodebox.wall_side.MinEdge.Y, -max);
1171                         box_union->addInternalPoint(max, nodebox.wall_side.MaxEdge.Y, max);
1172                         break;
1173                 }
1174                 case NODEBOX_CONNECTED: {
1175                         // Add all possible connected boxes
1176                         boxVectorUnion(nodebox.fixed,          box_union);
1177                         boxVectorUnion(nodebox.connect_top,    box_union);
1178                         boxVectorUnion(nodebox.connect_bottom, box_union);
1179                         boxVectorUnion(nodebox.connect_front,  box_union);
1180                         boxVectorUnion(nodebox.connect_left,   box_union);
1181                         boxVectorUnion(nodebox.connect_back,   box_union);
1182                         boxVectorUnion(nodebox.connect_right,  box_union);
1183                         break;
1184                 }
1185                 default: {
1186                         // NODEBOX_REGULAR
1187                         box_union->addInternalPoint(-BS / 2, -BS / 2, -BS / 2);
1188                         box_union->addInternalPoint(+BS / 2, +BS / 2, +BS / 2);
1189                 }
1190         }
1191 }
1192
1193
1194 inline void CNodeDefManager::fixSelectionBoxIntUnion()
1195 {
1196         m_selection_box_int_union.MinEdge.X = floorf(
1197                 m_selection_box_union.MinEdge.X / BS + 0.5f);
1198         m_selection_box_int_union.MinEdge.Y = floorf(
1199                 m_selection_box_union.MinEdge.Y / BS + 0.5f);
1200         m_selection_box_int_union.MinEdge.Z = floorf(
1201                 m_selection_box_union.MinEdge.Z / BS + 0.5f);
1202         m_selection_box_int_union.MaxEdge.X = ceilf(
1203                 m_selection_box_union.MaxEdge.X / BS - 0.5f);
1204         m_selection_box_int_union.MaxEdge.Y = ceilf(
1205                 m_selection_box_union.MaxEdge.Y / BS - 0.5f);
1206         m_selection_box_int_union.MaxEdge.Z = ceilf(
1207                 m_selection_box_union.MaxEdge.Z / BS - 0.5f);
1208 }
1209
1210
1211 // IWritableNodeDefManager
1212 content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &def)
1213 {
1214         // Pre-conditions
1215         assert(name != "");
1216         assert(name == def.name);
1217
1218         // Don't allow redefining ignore (but allow air and unknown)
1219         if (name == "ignore") {
1220                 warningstream << "NodeDefManager: Ignoring "
1221                         "CONTENT_IGNORE redefinition"<<std::endl;
1222                 return CONTENT_IGNORE;
1223         }
1224
1225         content_t id = CONTENT_IGNORE;
1226         if (!m_name_id_mapping.getId(name, id)) { // ignore aliases
1227                 // Get new id
1228                 id = allocateId();
1229                 if (id == CONTENT_IGNORE) {
1230                         warningstream << "NodeDefManager: Absolute "
1231                                 "limit reached" << std::endl;
1232                         return CONTENT_IGNORE;
1233                 }
1234                 assert(id != CONTENT_IGNORE);
1235                 addNameIdMapping(id, name);
1236         }
1237         m_content_features[id] = def;
1238         verbosestream << "NodeDefManager: registering content id \"" << id
1239                 << "\": name=\"" << def.name << "\""<<std::endl;
1240
1241         getNodeBoxUnion(def.selection_box, def, &m_selection_box_union);
1242         fixSelectionBoxIntUnion();
1243         // Add this content to the list of all groups it belongs to
1244         // FIXME: This should remove a node from groups it no longer
1245         // belongs to when a node is re-registered
1246         for (const auto &group : def.groups) {
1247                 const std::string &group_name = group.first;
1248                 m_group_to_items[group_name].push_back(id);
1249         }
1250         return id;
1251 }
1252
1253
1254 content_t CNodeDefManager::allocateDummy(const std::string &name)
1255 {
1256         assert(name != "");     // Pre-condition
1257         ContentFeatures f;
1258         f.name = name;
1259         return set(name, f);
1260 }
1261
1262
1263 void CNodeDefManager::removeNode(const std::string &name)
1264 {
1265         // Pre-condition
1266         assert(name != "");
1267
1268         // Erase name from name ID mapping
1269         content_t id = CONTENT_IGNORE;
1270         if (m_name_id_mapping.getId(name, id)) {
1271                 m_name_id_mapping.eraseName(name);
1272                 m_name_id_mapping_with_aliases.erase(name);
1273         }
1274
1275         // Erase node content from all groups it belongs to
1276         for (std::unordered_map<std::string, std::vector<content_t>>::iterator iter_groups =
1277                         m_group_to_items.begin(); iter_groups != m_group_to_items.end();) {
1278                 std::vector<content_t> &items = iter_groups->second;
1279                 items.erase(std::remove(items.begin(), items.end(), id), items.end());
1280
1281                 // Check if group is empty
1282                 if (items.empty())
1283                         m_group_to_items.erase(iter_groups++);
1284                 else
1285                         ++iter_groups;
1286         }
1287 }
1288
1289
1290 void CNodeDefManager::updateAliases(IItemDefManager *idef)
1291 {
1292         std::set<std::string> all;
1293         idef->getAll(all);
1294         m_name_id_mapping_with_aliases.clear();
1295         for (const std::string &name : all) {
1296                 const std::string &convert_to = idef->getAlias(name);
1297                 content_t id;
1298                 if (m_name_id_mapping.getId(convert_to, id)) {
1299                         m_name_id_mapping_with_aliases.insert(
1300                                 std::make_pair(name, id));
1301                 }
1302         }
1303 }
1304
1305 void CNodeDefManager::applyTextureOverrides(const std::string &override_filepath)
1306 {
1307         infostream << "CNodeDefManager::applyTextureOverrides(): Applying "
1308                 "overrides to textures from " << override_filepath << std::endl;
1309
1310         std::ifstream infile(override_filepath.c_str());
1311         std::string line;
1312         int line_c = 0;
1313         while (std::getline(infile, line)) {
1314                 line_c++;
1315                 if (trim(line).empty())
1316                         continue;
1317                 std::vector<std::string> splitted = str_split(line, ' ');
1318                 if (splitted.size() != 3) {
1319                         errorstream << override_filepath
1320                                 << ":" << line_c << " Could not apply texture override \""
1321                                 << line << "\": Syntax error" << std::endl;
1322                         continue;
1323                 }
1324
1325                 content_t id;
1326                 if (!getId(splitted[0], id))
1327                         continue; // Ignore unknown node
1328
1329                 ContentFeatures &nodedef = m_content_features[id];
1330
1331                 if (splitted[1] == "top")
1332                         nodedef.tiledef[0].name = splitted[2];
1333                 else if (splitted[1] == "bottom")
1334                         nodedef.tiledef[1].name = splitted[2];
1335                 else if (splitted[1] == "right")
1336                         nodedef.tiledef[2].name = splitted[2];
1337                 else if (splitted[1] == "left")
1338                         nodedef.tiledef[3].name = splitted[2];
1339                 else if (splitted[1] == "back")
1340                         nodedef.tiledef[4].name = splitted[2];
1341                 else if (splitted[1] == "front")
1342                         nodedef.tiledef[5].name = splitted[2];
1343                 else if (splitted[1] == "all" || splitted[1] == "*")
1344                         for (TileDef &i : nodedef.tiledef)
1345                                 i.name = splitted[2];
1346                 else if (splitted[1] == "sides")
1347                         for (int i = 2; i < 6; i++)
1348                                 nodedef.tiledef[i].name = splitted[2];
1349                 else {
1350                         errorstream << override_filepath
1351                                 << ":" << line_c << " Could not apply texture override \""
1352                                 << line << "\": Unknown node side \""
1353                                 << splitted[1] << "\"" << std::endl;
1354                         continue;
1355                 }
1356         }
1357 }
1358
1359 void CNodeDefManager::updateTextures(IGameDef *gamedef,
1360         void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
1361         void *progress_callback_args)
1362 {
1363 #ifndef SERVER
1364         infostream << "CNodeDefManager::updateTextures(): Updating "
1365                 "textures in node definitions" << std::endl;
1366
1367         Client *client = (Client *)gamedef;
1368         ITextureSource *tsrc = client->tsrc();
1369         IShaderSource *shdsrc = client->getShaderSource();
1370         scene::IMeshManipulator *meshmanip =
1371                 RenderingEngine::get_scene_manager()->getMeshManipulator();
1372         TextureSettings tsettings;
1373         tsettings.readSettings();
1374
1375         u32 size = m_content_features.size();
1376
1377         for (u32 i = 0; i < size; i++) {
1378                 ContentFeatures *f = &(m_content_features[i]);
1379                 f->updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
1380                 progress_callback(progress_callback_args, i, size);
1381         }
1382 #endif
1383 }
1384
1385 void CNodeDefManager::serialize(std::ostream &os, u16 protocol_version) const
1386 {
1387         writeU8(os, 1); // version
1388         u16 count = 0;
1389         std::ostringstream os2(std::ios::binary);
1390         for (u32 i = 0; i < m_content_features.size(); i++) {
1391                 if (i == CONTENT_IGNORE || i == CONTENT_AIR
1392                                 || i == CONTENT_UNKNOWN)
1393                         continue;
1394                 const ContentFeatures *f = &m_content_features[i];
1395                 if (f->name.empty())
1396                         continue;
1397                 writeU16(os2, i);
1398                 // Wrap it in a string to allow different lengths without
1399                 // strict version incompatibilities
1400                 std::ostringstream wrapper_os(std::ios::binary);
1401                 f->serialize(wrapper_os, protocol_version);
1402                 os2<<serializeString(wrapper_os.str());
1403
1404                 // must not overflow
1405                 u16 next = count + 1;
1406                 FATAL_ERROR_IF(next < count, "Overflow");
1407                 count++;
1408         }
1409         writeU16(os, count);
1410         os << serializeLongString(os2.str());
1411 }
1412
1413
1414 void CNodeDefManager::deSerialize(std::istream &is)
1415 {
1416         clear();
1417         int version = readU8(is);
1418         if (version != 1)
1419                 throw SerializationError("unsupported NodeDefinitionManager version");
1420         u16 count = readU16(is);
1421         std::istringstream is2(deSerializeLongString(is), std::ios::binary);
1422         ContentFeatures f;
1423         for (u16 n = 0; n < count; n++) {
1424                 u16 i = readU16(is2);
1425
1426                 // Read it from the string wrapper
1427                 std::string wrapper = deSerializeString(is2);
1428                 std::istringstream wrapper_is(wrapper, std::ios::binary);
1429                 f.deSerialize(wrapper_is);
1430
1431                 // Check error conditions
1432                 if (i == CONTENT_IGNORE || i == CONTENT_AIR || i == CONTENT_UNKNOWN) {
1433                         warningstream << "NodeDefManager::deSerialize(): "
1434                                 "not changing builtin node " << i << std::endl;
1435                         continue;
1436                 }
1437                 if (f.name.empty()) {
1438                         warningstream << "NodeDefManager::deSerialize(): "
1439                                 "received empty name" << std::endl;
1440                         continue;
1441                 }
1442
1443                 // Ignore aliases
1444                 u16 existing_id;
1445                 if (m_name_id_mapping.getId(f.name, existing_id) && i != existing_id) {
1446                         warningstream << "NodeDefManager::deSerialize(): "
1447                                 "already defined with different ID: " << f.name << std::endl;
1448                         continue;
1449                 }
1450
1451                 // All is ok, add node definition with the requested ID
1452                 if (i >= m_content_features.size())
1453                         m_content_features.resize((u32)(i) + 1);
1454                 m_content_features[i] = f;
1455                 addNameIdMapping(i, f.name);
1456                 verbosestream << "deserialized " << f.name << std::endl;
1457
1458                 getNodeBoxUnion(f.selection_box, f, &m_selection_box_union);
1459                 fixSelectionBoxIntUnion();
1460         }
1461 }
1462
1463
1464 void CNodeDefManager::addNameIdMapping(content_t i, std::string name)
1465 {
1466         m_name_id_mapping.set(i, name);
1467         m_name_id_mapping_with_aliases.insert(std::make_pair(name, i));
1468 }
1469
1470
1471 IWritableNodeDefManager *createNodeDefManager()
1472 {
1473         return new CNodeDefManager();
1474 }
1475
1476 inline void CNodeDefManager::setNodeRegistrationStatus(bool completed)
1477 {
1478         m_node_registration_complete = completed;
1479 }
1480
1481
1482 void CNodeDefManager::pendNodeResolve(NodeResolver *nr)
1483 {
1484         nr->m_ndef = this;
1485         if (m_node_registration_complete)
1486                 nr->nodeResolveInternal();
1487         else
1488                 m_pending_resolve_callbacks.push_back(nr);
1489 }
1490
1491
1492 bool CNodeDefManager::cancelNodeResolveCallback(NodeResolver *nr)
1493 {
1494         size_t len = m_pending_resolve_callbacks.size();
1495         for (size_t i = 0; i != len; i++) {
1496                 if (nr != m_pending_resolve_callbacks[i])
1497                         continue;
1498
1499                 len--;
1500                 m_pending_resolve_callbacks[i] = m_pending_resolve_callbacks[len];
1501                 m_pending_resolve_callbacks.resize(len);
1502                 return true;
1503         }
1504
1505         return false;
1506 }
1507
1508
1509 void CNodeDefManager::runNodeResolveCallbacks()
1510 {
1511         for (size_t i = 0; i != m_pending_resolve_callbacks.size(); i++) {
1512                 NodeResolver *nr = m_pending_resolve_callbacks[i];
1513                 nr->nodeResolveInternal();
1514         }
1515
1516         m_pending_resolve_callbacks.clear();
1517 }
1518
1519
1520 void CNodeDefManager::resetNodeResolveState()
1521 {
1522         m_node_registration_complete = false;
1523         m_pending_resolve_callbacks.clear();
1524 }
1525
1526 void CNodeDefManager::mapNodeboxConnections()
1527 {
1528         for (ContentFeatures &f : m_content_features) {
1529                 if (f.drawtype != NDT_NODEBOX || f.node_box.type != NODEBOX_CONNECTED)
1530                         continue;
1531
1532                 for (const std::string &name : f.connects_to) {
1533                         getIds(name, f.connects_to_ids);
1534                 }
1535         }
1536 }
1537
1538 bool CNodeDefManager::nodeboxConnects(MapNode from, MapNode to, u8 connect_face)
1539 {
1540         const ContentFeatures &f1 = get(from);
1541
1542         if ((f1.drawtype != NDT_NODEBOX) || (f1.node_box.type != NODEBOX_CONNECTED))
1543                 return false;
1544
1545         // lookup target in connected set
1546         if (!CONTAINS(f1.connects_to_ids, to.param0))
1547                 return false;
1548
1549         const ContentFeatures &f2 = get(to);
1550
1551         if ((f2.drawtype == NDT_NODEBOX) && (f2.node_box.type == NODEBOX_CONNECTED))
1552                 // ignores actually looking if back connection exists
1553                 return CONTAINS(f2.connects_to_ids, from.param0);
1554
1555         // does to node declare usable faces?
1556         if (f2.connect_sides > 0) {
1557                 if ((f2.param_type_2 == CPT2_FACEDIR ||
1558                                 f2.param_type_2 == CPT2_COLORED_FACEDIR)
1559                                 && (connect_face >= 4)) {
1560                         static const u8 rot[33 * 4] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1561                                 0, 0, 0, 0, 4, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1562                                 0, // 4 - back
1563                                 8, 4, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1564                                 0, // 8 - right
1565                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 4, 32, 0,
1566                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1567                                 0, // 16 - front
1568                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1569                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1570                                 0, 0, 0, 0, 0, 0, 32, 16, 8, 4 // 32 - left
1571                                 };
1572                         return (f2.connect_sides
1573                                 & rot[(connect_face * 4) + (to.param2 & 0x1F)]);
1574                 }
1575                 return (f2.connect_sides & connect_face);
1576         }
1577         // the target is just a regular node, so connect no matter back connection
1578         return true;
1579 }
1580
1581 ////
1582 //// NodeResolver
1583 ////
1584
1585 NodeResolver::NodeResolver()
1586 {
1587         m_nodenames.reserve(16);
1588         m_nnlistsizes.reserve(4);
1589 }
1590
1591
1592 NodeResolver::~NodeResolver()
1593 {
1594         if (!m_resolve_done && m_ndef)
1595                 m_ndef->cancelNodeResolveCallback(this);
1596 }
1597
1598
1599 void NodeResolver::nodeResolveInternal()
1600 {
1601         m_nodenames_idx   = 0;
1602         m_nnlistsizes_idx = 0;
1603
1604         resolveNodeNames();
1605         m_resolve_done = true;
1606
1607         m_nodenames.clear();
1608         m_nnlistsizes.clear();
1609 }
1610
1611
1612 bool NodeResolver::getIdFromNrBacklog(content_t *result_out,
1613         const std::string &node_alt, content_t c_fallback)
1614 {
1615         if (m_nodenames_idx == m_nodenames.size()) {
1616                 *result_out = c_fallback;
1617                 errorstream << "NodeResolver: no more nodes in list" << std::endl;
1618                 return false;
1619         }
1620
1621         content_t c;
1622         std::string name = m_nodenames[m_nodenames_idx++];
1623
1624         bool success = m_ndef->getId(name, c);
1625         if (!success && !node_alt.empty()) {
1626                 name = node_alt;
1627                 success = m_ndef->getId(name, c);
1628         }
1629
1630         if (!success) {
1631                 errorstream << "NodeResolver: failed to resolve node name '" << name
1632                         << "'." << std::endl;
1633                 c = c_fallback;
1634         }
1635
1636         *result_out = c;
1637         return success;
1638 }
1639
1640
1641 bool NodeResolver::getIdsFromNrBacklog(std::vector<content_t> *result_out,
1642         bool all_required, content_t c_fallback)
1643 {
1644         bool success = true;
1645
1646         if (m_nnlistsizes_idx == m_nnlistsizes.size()) {
1647                 errorstream << "NodeResolver: no more node lists" << std::endl;
1648                 return false;
1649         }
1650
1651         size_t length = m_nnlistsizes[m_nnlistsizes_idx++];
1652
1653         while (length--) {
1654                 if (m_nodenames_idx == m_nodenames.size()) {
1655                         errorstream << "NodeResolver: no more nodes in list" << std::endl;
1656                         return false;
1657                 }
1658
1659                 content_t c;
1660                 std::string &name = m_nodenames[m_nodenames_idx++];
1661
1662                 if (name.substr(0,6) != "group:") {
1663                         if (m_ndef->getId(name, c)) {
1664                                 result_out->push_back(c);
1665                         } else if (all_required) {
1666                                 errorstream << "NodeResolver: failed to resolve node name '"
1667                                         << name << "'." << std::endl;
1668                                 result_out->push_back(c_fallback);
1669                                 success = false;
1670                         }
1671                 } else {
1672                         m_ndef->getIds(name, *result_out);
1673                 }
1674         }
1675
1676         return success;
1677 }