]> git.lizzy.rs Git - minetest.git/commitdiff
Decoration: Add schematic Y-slice probability support
authorkwolekr <kwolekr@minetest.net>
Sun, 1 Dec 2013 06:23:39 +0000 (01:23 -0500)
committerkwolekr <kwolekr@minetest.net>
Sun, 1 Dec 2013 06:24:59 +0000 (01:24 -0500)
doc/lua_api.txt
src/mapgen.cpp
src/mapgen.h
src/script/lua_api/l_mapgen.cpp

index 6c06d558fa76d4697f2892a7bad0eb747fcb04dc..f3240dd40d0ca60d9a6a698ec87e47abc53465c8 100644 (file)
@@ -1491,7 +1491,7 @@ minetest.delete_particlespawner(id, player)
 ^ otherwise on all clients
 
 Schematics:
-minetest.create_schematic(p1, p2, probability_list, filename)
+minetest.create_schematic(p1, p2, probability_list, filename, slice_prob_list)
 ^ Create a schematic from the volume of map specified by the box formed by p1 and p2.
 ^ Apply the specified probability values to the specified nodes in probability_list.
    ^ probability_list is an array of tables containing two fields, pos and prob.
@@ -1500,6 +1500,9 @@ minetest.create_schematic(p1, p2, probability_list, filename)
    ^ If there are two or more entries with the same pos value, the last occuring in the array is used.
    ^ If pos is not inside the box formed by p1 and p2, it is ignored.
    ^ If probability_list is nil, no probabilities are applied.
+   ^ Slice probability works in the same manner, except takes a field called ypos instead which indicates
+   ^ the y position of the slice with a probability applied.
+   ^ If slice probability list is nil, no slice probabilities are applied.
 ^ Saves schematic in the Minetest Schematic format to filename.
 
 minetest.place_schematic(pos, schematic, rotation, replacements)
index f6311849139ad9956cc99fa7f1da0d984cb3a14a..2be0c1dd2e8b75c2a204394c45a083023bb1327e 100644 (file)
@@ -482,16 +482,18 @@ std::string DecoSimple::getName() {
 
 
 DecoSchematic::DecoSchematic() {
-       node_names = NULL;
-       schematic  = NULL;
-       flags      = 0;
-       size       = v3s16(0, 0, 0);
+       node_names  = NULL;
+       schematic   = NULL;
+       slice_probs = NULL;
+       flags       = 0;
+       size        = v3s16(0, 0, 0);
 }
 
 
 DecoSchematic::~DecoSchematic() {
        delete node_names;
        delete []schematic;
+       delete []slice_probs;
 }
 
 
@@ -599,37 +601,44 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
                        i_step_x = xstride;
                        i_step_z = zstride;
        }
-       
-       for (s16 z = 0; z != sz; z++)
+
+       s16 y_map = p.Y;
        for (s16 y = 0; y != sy; y++) {
-               u32 i = z * i_step_z + y * ystride + i_start;
-               for (s16 x = 0; x != sx; x++, i += i_step_x) {
-                       u32 vi = vm->m_area.index(p.X + x, p.Y + y, p.Z + z);
-                       if (!vm->m_area.contains(vi))
-                               continue;
-                       
-                       if (schematic[i].getContent() == CONTENT_IGNORE)
-                               continue;
-                               
-                       if (schematic[i].param1 == MTSCHEM_PROB_NEVER)
-                               continue;
+               if (slice_probs[y] != MTSCHEM_PROB_ALWAYS &&
+                       myrand_range(1, 255) > slice_probs[y])
+                       continue;
 
-                       if (!force_placement) {
-                               content_t c = vm->m_data[vi].getContent();
-                               if (c != CONTENT_AIR && c != CONTENT_IGNORE)
+               for (s16 z = 0; z != sz; z++) {
+                       u32 i = z * i_step_z + y * ystride + i_start;
+                       for (s16 x = 0; x != sx; x++, i += i_step_x) {
+                               u32 vi = vm->m_area.index(p.X + x, y_map, p.Z + z);
+                               if (!vm->m_area.contains(vi))
                                        continue;
+
+                               if (schematic[i].getContent() == CONTENT_IGNORE)
+                                       continue;
+
+                               if (schematic[i].param1 == MTSCHEM_PROB_NEVER)
+                                       continue;
+
+                               if (!force_placement) {
+                                       content_t c = vm->m_data[vi].getContent();
+                                       if (c != CONTENT_AIR && c != CONTENT_IGNORE)
+                                               continue;
+                               }
+
+                               if (schematic[i].param1 != MTSCHEM_PROB_ALWAYS &&
+                                       myrand_range(1, 255) > schematic[i].param1)
+                                       continue;
+
+                               vm->m_data[vi] = schematic[i];
+                               vm->m_data[vi].param1 = 0;
+
+                               if (rot)
+                                       vm->m_data[vi].rotateAlongYAxis(ndef, rot);
                        }
-                       
-                       if (schematic[i].param1 != MTSCHEM_PROB_ALWAYS &&
-                               myrand_range(1, 255) > schematic[i].param1)
-                               continue;
-                       
-                       vm->m_data[vi] = schematic[i];
-                       vm->m_data[vi].param1 = 0;
-                       
-                       if (rot)
-                               vm->m_data[vi].rotateAlongYAxis(ndef, rot);
                }
+               y_map++;
        }
 }
 
@@ -690,13 +699,24 @@ bool DecoSchematic::loadSchematicFile() {
        }
        
        u16 version = readU16(is);
-       if (version > 2) {
+       if (version > MTSCHEM_FILE_VER_HIGHEST_READ) {
                errorstream << "loadSchematicFile: unsupported schematic "
                        "file version" << std::endl;
                return false;
        }
 
        size = readV3S16(is);
+
+       delete []slice_probs;
+       slice_probs = new u8[size.Y];
+       if (version >= 3) {
+               for (int y = 0; y != size.Y; y++)
+                       slice_probs[y] = readU8(is);
+       } else {
+               for (int y = 0; y != size.Y; y++)
+                       slice_probs[y] = MTSCHEM_PROB_ALWAYS;
+       }
+
        int nodecount = size.X * size.Y * size.Z;
        
        u16 nidmapcount = readU16(is);
@@ -712,7 +732,7 @@ bool DecoSchematic::loadSchematicFile() {
                node_names->push_back(name);
        }
 
-       delete schematic;
+       delete []schematic;
        schematic = new MapNode[nodecount];
        MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schematic,
                                nodecount, 2, 2, true);
@@ -735,10 +755,12 @@ bool DecoSchematic::loadSchematicFile() {
 
        All values are stored in big-endian byte order.
        [u32] signature: 'MTSM'
-       [u16] version: 2
+       [u16] version: 3
        [u16] size X
        [u16] size Y
        [u16] size Z
+       For each Y:
+               [u8] slice probability value
        [Name-ID table] Name ID Mapping Table
                [u16] name-id count
                For each name-id mapping:
@@ -760,10 +782,13 @@ bool DecoSchematic::loadSchematicFile() {
 void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) {
        std::ostringstream ss(std::ios_base::binary);
 
-       writeU32(ss, MTSCHEM_FILE_SIGNATURE); // signature
-       writeU16(ss, 2);      // version
-       writeV3S16(ss, size); // schematic size
-       
+       writeU32(ss, MTSCHEM_FILE_SIGNATURE);         // signature
+       writeU16(ss, MTSCHEM_FILE_VER_HIGHEST_WRITE); // version
+       writeV3S16(ss, size);                         // schematic size
+
+       for (int y = 0; y != size.Y; y++)             // Y slice probabilities
+               writeU8(ss, slice_probs[y]);
+
        std::vector<content_t> usednodes;
        int nodecount = size.X * size.Y * size.Z;
        build_nnlist_and_update_ids(schematic, nodecount, &usednodes);
@@ -813,6 +838,11 @@ bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) {
        vm->initialEmerge(bp1, bp2);
        
        size = p2 - p1 + 1;
+
+       slice_probs = new u8[size.Y];
+       for (s16 y = 0; y != size.Y; y++)
+               slice_probs[y] = MTSCHEM_PROB_ALWAYS;
+
        schematic = new MapNode[size.X * size.Y * size.Z];
        
        u32 i = 0;
@@ -830,8 +860,10 @@ bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) {
 }
 
 
-void DecoSchematic::applyProbabilities(std::vector<std::pair<v3s16, u8> > *plist,
-                                                                       v3s16 p0) {
+void DecoSchematic::applyProbabilities(v3s16 p0,
+       std::vector<std::pair<v3s16, u8> > *plist,
+       std::vector<std::pair<s16, u8> > *splist) {
+
        for (size_t i = 0; i != plist->size(); i++) {
                v3s16 p = (*plist)[i].first - p0;
                int index = p.Z * (size.Y * size.X) + p.Y * size.X + p.X;
@@ -844,6 +876,11 @@ void DecoSchematic::applyProbabilities(std::vector<std::pair<v3s16, u8> > *plist
                                schematic[index].setContent(CONTENT_AIR);
                }
        }
+
+       for (size_t i = 0; i != splist->size(); i++) {
+               s16 y = (*splist)[i].first - p0.Y;
+               slice_probs[y] = (*splist)[i].second;
+       }
 }
 
 
index 040320f27cf8f3155024ab462638b85f321f777e..46261a202410049ee9aa8f842e71959393de8e4d 100644 (file)
@@ -256,6 +256,9 @@ class DecoSimple : public Decoration {
 };
 
 #define MTSCHEM_FILE_SIGNATURE 0x4d54534d // 'MTSM'
+#define MTSCHEM_FILE_VER_HIGHEST_READ  3
+#define MTSCHEM_FILE_VER_HIGHEST_WRITE 3
+
 #define MTSCHEM_PROB_NEVER  0x00
 #define MTSCHEM_PROB_ALWAYS 0xFF
 
@@ -271,6 +274,7 @@ class DecoSchematic : public Decoration {
        Rotation rotation;
        v3s16 size;
        MapNode *schematic;
+       u8 *slice_probs;
 
        DecoSchematic();
        ~DecoSchematic();
@@ -288,7 +292,9 @@ class DecoSchematic : public Decoration {
        
        bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
        void placeStructure(Map *map, v3s16 p);
-       void applyProbabilities(std::vector<std::pair<v3s16, u8> > *plist, v3s16 p0);
+       void applyProbabilities(v3s16 p0,
+               std::vector<std::pair<v3s16, u8> > *plist,
+               std::vector<std::pair<s16, u8> > *splist);
 };
 
 void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
index b0ad202be043b65febc8975b8d01cea2d6b9b200..de9b5aba7406406e910e959f0cecfb9c8b1bac6c 100644 (file)
@@ -475,7 +475,7 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
        v3s16 p2 = read_v3s16(L, 2);
        sortBoxVerticies(p1, p2);
        
-       std::vector<std::pair<v3s16, u8> > probability_list;
+       std::vector<std::pair<v3s16, u8> > prob_list;
        if (lua_istable(L, 3)) {
                lua_pushnil(L);
                while (lua_next(L, 3)) {
@@ -485,22 +485,37 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
                                lua_pop(L, 1);
                                
                                u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS);
-                               probability_list.push_back(std::make_pair(pos, prob));
+                               prob_list.push_back(std::make_pair(pos, prob));
                        }
 
                        lua_pop(L, 1);
                }
        }
        
-       dschem.filename = std::string(lua_tostring(L, 4));
+       std::vector<std::pair<s16, u8> > slice_prob_list;
+       if (lua_istable(L, 5)) {
+               lua_pushnil(L);
+               while (lua_next(L, 5)) {
+                       if (lua_istable(L, -1)) {
+                               s16 ypos = getintfield_default(L, -1, "ypos", 0);
+                               u8 prob  = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS);
+                               slice_prob_list.push_back(std::make_pair(ypos, prob));
+                       }
+
+                       lua_pop(L, 1);
+               }
+       }
+
+       const char *s = lua_tostring(L, 4);
+       dschem.filename = std::string(s ? s : "");
 
        if (!dschem.getSchematicFromMap(map, p1, p2)) {
                errorstream << "create_schematic: failed to get schematic "
                        "from map" << std::endl;
                return 0;
        }
-       
-       dschem.applyProbabilities(&probability_list, p1);
+
+       dschem.applyProbabilities(p1, &prob_list, &slice_prob_list);
        
        dschem.saveSchematicFile(ndef);
        actionstream << "create_schematic: saved schematic file '"