- default:
- i_start = 0;
- i_step_x = xstride;
- i_step_z = zstride;
- }
-
- for (s16 z = 0; z != sz; z++)
- 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 (!force_placement) {
- content_t c = vm->m_data[vi].getContent();
- if (c != CONTENT_AIR && c != CONTENT_IGNORE)
- continue;
- }
-
- if (schematic[i].param1 && myrand_range(1, 256) > 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);
- }
- }
-}
-
-
-void DecoSchematic::placeStructure(Map *map, v3s16 p) {
- assert(schematic != NULL);
- ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
-
- Rotation rot = (rotation == ROTATE_RAND) ?
- (Rotation)myrand_range(ROTATE_0, ROTATE_270) : rotation;
-
- v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ?
- v3s16(size.Z, size.Y, size.X) : size;
-
- if (flags & DECO_PLACE_CENTER_X)
- p.X -= (s.X + 1) / 2;
- if (flags & DECO_PLACE_CENTER_Y)
- p.Y -= (s.Y + 1) / 2;
- if (flags & DECO_PLACE_CENTER_Z)
- p.Z -= (s.Z + 1) / 2;
-
- v3s16 bp1 = getNodeBlockPos(p);
- v3s16 bp2 = getNodeBlockPos(p + s - v3s16(1,1,1));
- vm->initialEmerge(bp1, bp2);
-
- blitToVManip(p, vm, rot, true);
-
- std::map<v3s16, MapBlock *> lighting_modified_blocks;
- std::map<v3s16, MapBlock *> modified_blocks;
- vm->blitBackAll(&modified_blocks);
-
- // TODO: Optimize this by using Mapgen::calcLighting() instead
- lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
- map->updateLighting(lighting_modified_blocks, modified_blocks);
-
- MapEditEvent event;
- event.type = MEET_OTHER;
- for (std::map<v3s16, MapBlock *>::iterator
- it = modified_blocks.begin();
- it != modified_blocks.end(); ++it)
- event.modified_blocks.insert(it->first);
-
- map->dispatchEvent(&event);
-}
-
-
-bool DecoSchematic::loadSchematicFile() {
- std::ifstream is(filename.c_str(), std::ios_base::binary);
-
- u32 signature = readU32(is);
- if (signature != MTSCHEM_FILE_SIGNATURE) {
- errorstream << "loadSchematicFile: invalid schematic "
- "file" << std::endl;
- return false;
- }
-
- u16 version = readU16(is);
- if (version != 1) {
- errorstream << "loadSchematicFile: unsupported schematic "
- "file version" << std::endl;
- return false;
- }
-
- size = readV3S16(is);
- int nodecount = size.X * size.Y * size.Z;
-
- u16 nidmapcount = readU16(is);
-
- node_names = new std::vector<std::string>;
- for (int i = 0; i != nidmapcount; i++) {
- std::string name = deSerializeString(is);
- node_names->push_back(name);
- }
-
- delete schematic;
- schematic = new MapNode[nodecount];
- MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schematic,
- nodecount, 2, 2, true);
-
- return true;
-}
-
-
-/*
- Minetest Schematic File Format
-
- All values are stored in big-endian byte order.
- [u32] signature: 'MTSM'
- [u16] version: 1
- [u16] size X
- [u16] size Y
- [u16] size Z
- [Name-ID table] Name ID Mapping Table
- [u16] name-id count
- For each name-id mapping:
- [u16] name length
- [u8[]] name
- ZLib deflated {
- For each node in schematic: (for z, y, x)
- [u16] content
- For each node in schematic:
- [u8] probability of occurance (param1)
- For each node in schematic:
- [u8] param2
- }
-*/
-void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) {
- std::ofstream os(filename.c_str(), std::ios_base::binary);
-
- writeU32(os, MTSCHEM_FILE_SIGNATURE); // signature
- writeU16(os, 1); // version
- writeV3S16(os, size); // schematic size
-
- std::vector<content_t> usednodes;
- int nodecount = size.X * size.Y * size.Z;
- build_nnlist_and_update_ids(schematic, nodecount, &usednodes);
-
- u16 numids = usednodes.size();
- writeU16(os, numids); // name count
- for (int i = 0; i != numids; i++)
- os << serializeString(ndef->get(usednodes[i]).name); // node names
-
- // compressed bulk node data
- MapNode::serializeBulk(os, SER_FMT_VER_HIGHEST_WRITE, schematic,
- nodecount, 2, 2, true);
-}
-
-
-void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
- std::vector<content_t> *usednodes) {
- std::map<content_t, content_t> nodeidmap;
- content_t numids = 0;
-
- for (u32 i = 0; i != nodecount; i++) {
- content_t id;
- content_t c = nodes[i].getContent();
-
- std::map<content_t, content_t>::const_iterator it = nodeidmap.find(c);
- if (it == nodeidmap.end()) {
- id = numids;
- numids++;
-
- usednodes->push_back(c);
- nodeidmap.insert(std::make_pair(c, id));
- } else {
- id = it->second;
- }
- nodes[i].setContent(id);
- }
-}
-
-
-bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2) {
- ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
-
- v3s16 bp1 = getNodeBlockPos(p1);
- v3s16 bp2 = getNodeBlockPos(p2);
- vm->initialEmerge(bp1, bp2);
-
- size = p2 - p1 + 1;
- schematic = new MapNode[size.X * size.Y * size.Z];
-
- u32 i = 0;
- for (s16 z = p1.Z; z <= p2.Z; z++)
- for (s16 y = p1.Y; y <= p2.Y; y++) {
- u32 vi = vm->m_area.index(p1.X, y, z);
- for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) {
- schematic[i] = vm->m_data[vi];
- schematic[i].param1 = 0;
- }
- }
-
- delete vm;
- return true;
-}
-