Пример #1
0
    def copyEntitiesFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint, entities):
        chunkCount = sourceBox.chunkCount
        i = 0
        copyOffset = map(lambda x, y: x - y, destinationPoint, sourceBox.origin)
        e = t = 0

        for (chunk, slices, point) in sourceLevel.getChunkSlices(sourceBox):
            yield (i, chunkCount)
            i += 1

            if entities:
                e += len(chunk.Entities)
                for entityTag in chunk.Entities:
                    x, y, z = Entity.pos(entityTag)
                    if (x, y, z) not in sourceBox:
                        continue

                    eTag = Entity.copyWithOffset(entityTag, copyOffset)

                    self.addEntity(eTag)

            t += len(chunk.TileEntities)
            for tileEntityTag in chunk.TileEntities:
                x, y, z = TileEntity.pos(tileEntityTag)
                if (x, y, z) not in sourceBox:
                    continue

                eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)

                self.addTileEntity(eTag)

        info("Copied {0} entities, {1} tile entities".format(e, t))
Пример #2
0
    def copyEntitiesFromInfiniteIter(self, sourceLevel, sourceBox,
                                     destinationPoint, entities):
        chunkCount = sourceBox.chunkCount
        i = 0
        copyOffset = map(lambda x, y: x - y, destinationPoint,
                         sourceBox.origin)
        e = t = 0

        for (chunk, slices, point) in sourceLevel.getChunkSlices(sourceBox):
            yield (i, chunkCount)
            i += 1

            if entities:
                e += len(chunk.Entities)
                for entityTag in chunk.Entities:
                    x, y, z = Entity.pos(entityTag)
                    if (x, y, z) not in sourceBox:
                        continue

                    eTag = Entity.copyWithOffset(entityTag, copyOffset)

                    self.addEntity(eTag)

            t += len(chunk.TileEntities)
            for tileEntityTag in chunk.TileEntities:
                x, y, z = TileEntity.pos(tileEntityTag)
                if (x, y, z) not in sourceBox:
                    continue

                eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)

                self.addTileEntity(eTag)

        info("Copied {0} entities, {1} tile entities".format(e, t))
Пример #3
0
    def tileEntityAt(self, x, y, z, print_stuff=False):
        entities = []
        if print_stuff: print "len(self.TileEntities)", len(self.TileEntities)
        for entityTag in self.TileEntities:
            if print_stuff:
                print entityTag["id"].value, TileEntity.pos(entityTag), x, y, z
            if TileEntity.pos(entityTag) == [x, y, z]:
                entities.append(entityTag)

        if len(entities) > 1:
            log.info("Multiple tile entities found: {0}".format(entities))
        if len(entities) == 0:
            return None

        return entities[0]
Пример #4
0
    def tileEntityAt(self, x, y, z, print_stuff=False):
        entities = []
        if print_stuff:
            print "len(self.TileEntities)", len(self.TileEntities)
        for entityTag in self.TileEntities:
            if print_stuff:
                print entityTag["id"].value, TileEntity.pos(entityTag), x, y, z
            if TileEntity.pos(entityTag) == [x, y, z]:
                entities.append(entityTag)

        if len(entities) > 1:
            log.info("Multiple tile entities found: {0}".format(entities))
        if len(entities) == 0:
            return None

        return entities[0]
Пример #5
0
 def testEntities(self):
     level = self.indevlevel.level
     entityTag = Entity.Create("Zombie")
     tileEntityTag = TileEntity.Create("Painting")
     level.addEntity(entityTag)
     level.addTileEntity(tileEntityTag)
     schem = level.extractSchematic(level.bounds)
     level.copyBlocksFrom(schem, schem.bounds, (0, 0, 0))
Пример #6
0
    def tileEntityAt(self, x, y, z):
        entities = []
        for entityTag in self.TileEntities:
            if TileEntity.pos(entityTag) == [x, y, z]:
                entities.append(entityTag)

        if len(entities) > 1:
            log.info("Multiple tile entities found: {0}".format(entities))
        if len(entities) == 0:
            return None

        return entities[0]
Пример #7
0
    def tileEntityAt(self, x, y, z):
        entities = []
        for entityTag in self.TileEntities:
            if TileEntity.pos(entityTag) == [x, y, z]:
                entities.append(entityTag)

        if len(entities) > 1:
            log.info("Multiple tile entities found: {0}".format(entities))
        if len(entities) == 0:
            return None

        return entities[0]
Пример #8
0
    def removeTileEntities(self, func):
        if not hasattr(self, "TileEntities"):
            return
        newEnts = []
        for ent in self.TileEntities:
            if func(TileEntity.pos(ent)):
                continue
            newEnts.append(ent)

        entsRemoved = len(self.TileEntities) - len(newEnts)
        log.debug("Removed {0} tile entities".format(entsRemoved))

        self.TileEntities.value[:] = newEnts

        return entsRemoved
Пример #9
0
    def removeTileEntities(self, func):
        if not hasattr(self, "TileEntities"):
            return
        newEnts = []
        for ent in self.TileEntities:
            if func(TileEntity.pos(ent)):
                continue
            newEnts.append(ent)

        entsRemoved = len(self.TileEntities) - len(newEnts)
        log.debug("Removed {0} tile entities".format(entsRemoved))

        self.TileEntities.value[:] = newEnts

        return entsRemoved
Пример #10
0
    def removeTileEntitiesInBox(self, box):

        if not hasattr(self, "TileEntities"):
            return
        newEnts = []
        for ent in self.TileEntities:
            if TileEntity.pos(ent) in box:
                continue
            newEnts.append(ent)

        entsRemoved = len(self.TileEntities) - len(newEnts)
        debug("Removed {0} tile entities".format(entsRemoved))

        self.TileEntities.value[:] = newEnts

        return entsRemoved
Пример #11
0
    def removeTileEntitiesInBox(self, box):

        if not hasattr(self, "TileEntities"):
            return
        newEnts = []
        for ent in self.TileEntities:
            if TileEntity.pos(ent) in box:
                continue
            newEnts.append(ent)

        entsRemoved = len(self.TileEntities) - len(newEnts)
        debug("Removed {0} tile entities".format(entsRemoved))

        self.TileEntities.value[:] = newEnts

        return entsRemoved
Пример #12
0
    def copyEntitiesFromIter(self,
                             sourceLevel,
                             sourceBox,
                             destinationPoint,
                             entities=True):
        # assume coords have already been adjusted by copyBlocks
        # if not self.hasEntities or not sourceLevel.hasEntities:
        #    return
        sourcePoint0 = sourceBox.origin

        if sourceLevel.isInfinite:
            for i in self.copyEntitiesFromInfiniteIter(sourceLevel, sourceBox,
                                                       destinationPoint,
                                                       entities):
                yield i
        else:
            entsCopied = 0
            tileEntsCopied = 0
            copyOffset = map(lambda x, y: x - y, destinationPoint,
                             sourcePoint0)
            if entities:
                for entity in sourceLevel.getEntitiesInBox(sourceBox):
                    eTag = Entity.copyWithOffset(entity, copyOffset)

                    self.addEntity(eTag)
                    entsCopied += 1

            i = 0
            for entity in sourceLevel.getTileEntitiesInBox(sourceBox):
                i += 1
                if i % 100 == 0:
                    yield

                if not 'x' in entity:
                    continue
                eTag = TileEntity.copyWithOffset(entity, copyOffset)

                try:
                    self.addTileEntity(eTag)
                    tileEntsCopied += 1
                except ChunkNotPresent:
                    pass

            yield
            info(u"Copied {0} entities, {1} tile entities".format(
                entsCopied, tileEntsCopied))
Пример #13
0
    def _add_block(self, position, block):
        if position in self:
            self._remove_block(position, sync=True)
        if hasattr(block, 'entity_type'):
            # in world_server we have to create its entity to handle some tasks(growing, etc.)
            # but in client's world, we only create a TileEntity that contains the position
            # and the world to allow the block update itself and server will handle the task
            # and tell us
            self[position] = type(block)()
            self[position].entity = TileEntity(self, position)
        elif block.sub_id_as_metadata:
            self[position] = type(block)()
            self[position].set_metadata(block.get_metadata())
        else:
            self[position] = block

        self.sectors[sectorize(position)].append(position)
        if self.is_exposed(position):
            self.show_block(position)
        self.inform_neighbors_of_block_change(position)
Пример #14
0
    def copyEntitiesFromIter(self, sourceLevel, sourceBox, destinationPoint, entities=True):
        # assume coords have already been adjusted by copyBlocks
        # if not self.hasEntities or not sourceLevel.hasEntities:
        #    return
        sourcePoint0 = sourceBox.origin

        if sourceLevel.isInfinite:
            for i in self.copyEntitiesFromInfiniteIter(sourceLevel, sourceBox, destinationPoint, entities):
                yield i
        else:
            entsCopied = 0
            tileEntsCopied = 0
            copyOffset = map(lambda x, y: x - y, destinationPoint, sourcePoint0)
            if entities:
                for entity in sourceLevel.getEntitiesInBox(sourceBox):
                    eTag = Entity.copyWithOffset(entity, copyOffset)

                    self.addEntity(eTag)
                    entsCopied += 1

            i = 0
            for entity in sourceLevel.getTileEntitiesInBox(sourceBox):
                i += 1
                if i % 100 == 0:
                    yield

                if not 'x' in entity:
                    continue
                eTag = TileEntity.copyWithOffset(entity, copyOffset)

                try:
                    self.addTileEntity(eTag)
                    tileEntsCopied += 1
                except ChunkNotPresent:
                    pass

            yield
            info(u"Copied {0} entities, {1} tile entities".format(entsCopied, tileEntsCopied))
Пример #15
0
def copyBlocksFromIter(destLevel, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True,
                       create=False, biomes=False, tileTicks=True, staticCommands=False, moveSpawnerPos=False, regenerateUUID=False, first=False, cancelCommandBlockOffset=False):
    """ copy blocks between two infinite levels by looping through the
    destination's chunks. make a sub-box of the source level for each chunk
    and copy block and entities in the sub box to the dest chunk."""

    (lx, ly, lz) = sourceBox.size

    sourceBox, destinationPoint = adjustCopyParameters(destLevel, sourceLevel, sourceBox, destinationPoint)
    # needs work xxx
    log.info(u"Copying {0} blocks from {1} to {2}".format(ly * lz * lx, sourceBox, destinationPoint))
    startTime = datetime.now()

    destBox = BoundingBox(destinationPoint, sourceBox.size)
    chunkCount = destBox.chunkCount
    i = 0
    e = 0
    t = 0
    tt = 0
    sourceMask = sourceMaskFunc(blocksToCopy)

    copyOffset = [d - s for s, d in zip(sourceBox.origin, destinationPoint)]

    # Visit each chunk in the destination area.
    # Get the region of the source area corresponding to that chunk
    #   Visit each chunk of the region of the source area
    #     Get the slices of the destination chunk
    #     Get the slices of the source chunk
    #     Copy blocks and data

    for destCpos in destBox.chunkPositions:
        cx, cz = destCpos

        destChunkBox = BoundingBox((cx << 4, 0, cz << 4), (16, destLevel.Height, 16)).intersect(destBox)
        destChunkBoxInSourceLevel = BoundingBox([d - o for o, d in zip(copyOffset, destChunkBox.origin)],
                                                destChunkBox.size)

        if not destLevel.containsChunk(*destCpos):
            if create and any(sourceLevel.containsChunk(*c) for c in destChunkBoxInSourceLevel.chunkPositions):
                # Only create chunks in the destination level if the source level has chunks covering them.
                destLevel.createChunk(*destCpos)
            else:
                continue

        destChunk = destLevel.getChunk(*destCpos)

        i += 1
        yield (i, chunkCount)
        if i % 100 == 0:
            log.info("Chunk {0}...".format(i))

        for srcCpos in destChunkBoxInSourceLevel.chunkPositions:
            if not sourceLevel.containsChunk(*srcCpos):
                continue

            sourceChunk = sourceLevel.getChunk(*srcCpos)

            sourceChunkBox, sourceSlices = sourceChunk.getChunkSlicesForBox(destChunkBoxInSourceLevel)
            if sourceChunkBox.volume == 0:
                continue

            sourceChunkBoxInDestLevel = BoundingBox([d + o for o, d in zip(copyOffset, sourceChunkBox.origin)],
                                                    sourceChunkBox.size)

            _, destSlices = destChunk.getChunkSlicesForBox(sourceChunkBoxInDestLevel)

            sourceBlocks = sourceChunk.Blocks[sourceSlices]
            sourceData = sourceChunk.Data[sourceSlices]

            mask = sourceMask(sourceBlocks)
            convertedSourceBlocks, convertedSourceData = convertBlocks(destLevel, sourceLevel, sourceBlocks, sourceData)

            destChunk.Blocks[destSlices][mask] = convertedSourceBlocks[mask]
            if convertedSourceData is not None:
                destChunk.Data[destSlices][mask] = convertedSourceData[mask]

            def copy(p):
                return p in sourceChunkBoxInDestLevel and (blocksToCopy is None or mask[
                    int(p[0] - sourceChunkBoxInDestLevel.minx),
                    int(p[2] - sourceChunkBoxInDestLevel.minz),
                    int(p[1] - sourceChunkBoxInDestLevel.miny),
                ])

            if entities:
                destChunk.removeEntities(copy)

                ents = sourceChunk.getEntitiesInBox(destChunkBoxInSourceLevel)
                e += len(ents)
                for entityTag in ents:
                    eTag = Entity.copyWithOffset(entityTag, copyOffset, regenerateUUID)
                    destLevel.addEntity(eTag)

            destChunk.removeTileEntities(copy)

            tileEntities = sourceChunk.getTileEntitiesInBox(destChunkBoxInSourceLevel)
            t += len(tileEntities)
            for tileEntityTag in tileEntities:
                eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset, staticCommands, moveSpawnerPos, first, cancelCommandBlockOffset)
                destLevel.addTileEntity(eTag)

            destChunk.removeTileTicks(copy)

            tileTicksList = sourceChunk.getTileTicksInBox(destChunkBoxInSourceLevel)
            tt += len(tileTicksList)
            for tileTick in tileTicksList:
                eTag = deepcopy(tileTick)
                eTag['x'].value = tileTick['x'].value + copyOffset[0]
                eTag['y'].value = tileTick['y'].value + copyOffset[1]
                eTag['z'].value = tileTick['z'].value + copyOffset[2]
                destLevel.addTileTick(eTag)

            if biomes and hasattr(destChunk, 'Biomes') and hasattr(sourceChunk, 'Biomes'):
                destChunk.Biomes[destSlices[:2]] = sourceChunk.Biomes[sourceSlices[:2]]

        destChunk.chunkChanged()

    log.info("Duration: {0}".format(datetime.now() - startTime))
    log.info("Copied {0} entities and {1} tile entities and {2} tile ticks".format(e, t, tt))
Пример #16
0
    def __init__(self, root_tag=None, filename=""):
        self.Width = 0
        self.Height = 0
        self.Length = 0
        self.Blocks = array([], "uint8")
        self.Data = array([], "uint8")
        self.Spawn = (0, 0, 0)
        self.filename = filename

        if root_tag:

            self.root_tag = root_tag
            mapTag = root_tag["Map"]
            self.Width = mapTag["Width"].value
            self.Length = mapTag["Length"].value
            self.Height = mapTag["Height"].value

            mapTag["Blocks"].value.shape = (self.Height, self.Length, self.Width)

            self.Blocks = swapaxes(mapTag["Blocks"].value, 0, 2)

            mapTag["Data"].value.shape = (self.Height, self.Length, self.Width)

            self.Data = swapaxes(mapTag["Data"].value, 0, 2)

            self.BlockLight = self.Data & 0xf

            self.Data >>= 4

            self.Spawn = [mapTag[Spawn][i].value for i in range(3)]

            if "Entities" not in root_tag:
                root_tag["Entities"] = nbt.TAG_List()
            self.Entities = root_tag["Entities"]

            # xxx fixup Motion and Pos to match infdev format
            def numbersToDoubles(ent):
                for attr in "Motion", "Pos":
                    if attr in ent:
                        ent[attr] = nbt.TAG_List([nbt.TAG_Double(t.value) for t in ent[attr]])

            for ent in self.Entities:
                numbersToDoubles(ent)

            if "TileEntities" not in root_tag:
                root_tag["TileEntities"] = nbt.TAG_List()
            self.TileEntities = root_tag["TileEntities"]
            # xxx fixup TileEntities positions to match infdev format
            for te in self.TileEntities:
                pos = te["Pos"].value

                (x, y, z) = self.decodePos(pos)

                TileEntity.setpos(te, (x, y, z))

            localPlayerList = [tag for tag in root_tag["Entities"] if tag['id'].value == 'LocalPlayer']
            if len(localPlayerList) == 0:  # omen doesn't make a player entity
                playerTag = nbt.TAG_Compound()
                playerTag['id'] = nbt.TAG_String('LocalPlayer')
                playerTag['Pos'] = nbt.TAG_List([nbt.TAG_Float(0.), nbt.TAG_Float(64.), nbt.TAG_Float(0.)])
                playerTag['Rotation'] = nbt.TAG_List([nbt.TAG_Float(0.), nbt.TAG_Float(45.)])
                self.LocalPlayer = playerTag

            else:
                self.LocalPlayer = localPlayerList[0]

        else:
            log.info(u"Creating new Indev levels is not yet implemented.!")
            raise ValueError("Can't do that yet")
Пример #17
0
def fillBlocksIter(level, box, blockInfo, blocksToReplace=(), noData=False):
    if box is None:
        chunkIterator = level.getAllChunkSlices()
        box = level.bounds
    else:
        chunkIterator = level.getChunkSlices(box)

    log.info("Replacing {0} with {1}".format(blocksToReplace, blockInfo))

    changesLighting = True
    blocktable = None
    if len(blocksToReplace):
        blocktable = blockReplaceTable(blocksToReplace)

        newAbsorption = level.materials.lightAbsorption[blockInfo.ID]
        oldAbsorptions = [level.materials.lightAbsorption[b.ID] for b in blocksToReplace]
        changesLighting = False
        for a in oldAbsorptions:
            if a != newAbsorption:
                changesLighting = True

        newEmission = level.materials.lightEmission[blockInfo.ID]
        oldEmissions = [level.materials.lightEmission[b.ID] for b in blocksToReplace]
        for a in oldEmissions:
            if a != newEmission:
                changesLighting = True

    tileEntity = None
    if blockInfo.stringID in TileEntity.stringNames.keys():
        split_ver = level.gameVersion.split('.')
        if 'Unknown' not in split_ver and "PE" not in split_ver and int(split_ver[0]) >= 1 and int(split_ver[1]) >= 11:
            tileEntity = "minecraft:{}".format(blockInfo.stringID)
        else:
            tileEntity = TileEntity.stringNames[blockInfo.stringID]

    blocksIdToReplace = [block.ID for block in blocksToReplace]

    blocksList = []
    append = blocksList.append
    defsIds = level.defsIds
    if tileEntity and box is not None:
        for (boxX, boxY, boxZ) in box.positions:
            if blocktable is None or level.blockAt(boxX, boxY, boxZ) in blocksIdToReplace:
                tileEntityObject = TileEntity.Create(tileEntity, defsIds=defsIds)
                TileEntity.setpos(tileEntityObject, (boxX, boxY, boxZ))
                append(tileEntityObject)

    i = 0
    skipped = 0
    replaced = 0

    for (chunk, slices, point) in chunkIterator:
        i += 1
        if i % 100 == 0:
            log.info(u"Chunk {0}...".format(i))
        yield i, box.chunkCount

        blocks = chunk.Blocks[slices]
        data = chunk.Data[slices]
        mask = slice(None)

        needsLighting = changesLighting

        if blocktable is not None:
            mask = blocktable[blocks, data]

            blockCount = mask.sum()
            replaced += blockCount

            # don't waste time relighting and copying if the mask is empty
            if blockCount:
                blocks[:][mask] = blockInfo.ID
                if not noData:
                    data[mask] = blockInfo.blockData
            else:
                skipped += 1
                needsLighting = False

            def include(tileEntity):
                p = TileEntity.pos(tileEntity)
                x, y, z = map(lambda a, b, c: (a - b) - c, p, point, box.origin)
                return not ((p in box) and mask[x, z, y])

            chunk.TileEntities[:] = filter(include, chunk.TileEntities)

        else:
            blocks[:] = blockInfo.ID
            if not noData:
                data[:] = blockInfo.blockData
            chunk.removeTileEntitiesInBox(box)

        chunkBounds = chunk.bounds
        smallBoxSize = (1, 1, 1)
        tileEntitiesToEdit = [t for t in blocksList if chunkBounds.intersect(BoundingBox(TileEntity.pos(t), smallBoxSize)).volume > 0]

        for tileEntityObject in tileEntitiesToEdit:
            chunk.addTileEntity(tileEntityObject)
            blocksList.remove(tileEntityObject)
        
        chunk.chunkChanged(needsLighting)

    if len(blocksToReplace):
        log.info(u"Replace: Skipped {0} chunks, replaced {1} blocks".format(skipped, replaced))
Пример #18
0
 def include(tileEntity):
     p = TileEntity.pos(tileEntity)
     x, y, z = map(lambda a, b, c: (a - b) - c, p, point, box.origin)
     return not ((p in box) and mask[x, z, y])
Пример #19
0
    def __init__(self, root_tag=None, filename=""):
        self.Width = 0
        self.Height = 0
        self.Length = 0
        self.Blocks = array([], uint8)
        self.Data = array([], uint8)
        self.Spawn = (0, 0, 0)
        self.filename = filename

        if root_tag:

            self.root_tag = root_tag
            mapTag = root_tag[Map]
            self.Width = mapTag[Width].value
            self.Length = mapTag[Length].value
            self.Height = mapTag[Height].value

            mapTag[Blocks].value.shape = (self.Height, self.Length, self.Width)

            self.Blocks = swapaxes(mapTag[Blocks].value, 0, 2)

            mapTag[Data].value.shape = (self.Height, self.Length, self.Width)

            self.Data = swapaxes(mapTag[Data].value, 0, 2)

            self.BlockLight = self.Data & 0xf

            self.Data >>= 4

            self.Spawn = [mapTag[Spawn][i].value for i in range(3)]

            if not Entities in root_tag:
                root_tag[Entities] = nbt.TAG_List()
            self.Entities = root_tag[Entities]

            # xxx fixup Motion and Pos to match infdev format
            def numbersToDoubles(ent):
                for attr in "Motion", "Pos":
                    if attr in ent:
                        ent[attr] = nbt.TAG_List(
                            [nbt.TAG_Double(t.value) for t in ent[attr]])

            for ent in self.Entities:
                numbersToDoubles(ent)

            if not TileEntities in root_tag:
                root_tag[TileEntities] = nbt.TAG_List()
            self.TileEntities = root_tag[TileEntities]
            # xxx fixup TileEntities positions to match infdev format
            for te in self.TileEntities:
                pos = te["Pos"].value

                (x, y, z) = self.decodePos(pos)

                TileEntity.setpos(te, (x, y, z))

            if len(
                    filter(lambda x: x['id'].value == 'LocalPlayer',
                           root_tag[Entities])
            ) == 0:  # omen doesn't make a player entity
                p = nbt.TAG_Compound()
                p['id'] = nbt.TAG_String('LocalPlayer')
                p['Pos'] = nbt.TAG_List(
                    [nbt.TAG_Float(0.),
                     nbt.TAG_Float(64.),
                     nbt.TAG_Float(0.)])
                p['Rotation'] = nbt.TAG_List(
                    [nbt.TAG_Float(0.), nbt.TAG_Float(45.)])

                root_tag[Entities].append(p)
                # self.saveInPlace()

        else:
            info(u"Creating new Indev levels is not yet implemented.!")
            raise ValueError("Can't do that yet")
Пример #20
0
def copyBlocksFromIter(destLevel,
                       sourceLevel,
                       sourceBox,
                       destinationPoint,
                       blocksToCopy=None,
                       entities=True,
                       create=False,
                       biomes=False,
                       tileTicks=True,
                       staticCommands=False,
                       moveSpawnerPos=False,
                       regenerateUUID=False,
                       first=False):
    """ copy blocks between two infinite levels by looping through the
    destination's chunks. make a sub-box of the source level for each chunk
    and copy block and entities in the sub box to the dest chunk."""

    (lx, ly, lz) = sourceBox.size

    sourceBox, destinationPoint = adjustCopyParameters(destLevel, sourceLevel,
                                                       sourceBox,
                                                       destinationPoint)
    # needs work xxx
    log.info(u"Copying {0} blocks from {1} to {2}".format(
        ly * lz * lx, sourceBox, destinationPoint))
    startTime = datetime.now()

    destBox = BoundingBox(destinationPoint, sourceBox.size)
    chunkCount = destBox.chunkCount
    i = 0
    e = 0
    t = 0
    tt = 0
    sourceMask = sourceMaskFunc(blocksToCopy)

    copyOffset = [d - s for s, d in zip(sourceBox.origin, destinationPoint)]

    # Visit each chunk in the destination area.
    # Get the region of the source area corresponding to that chunk
    #   Visit each chunk of the region of the source area
    #     Get the slices of the destination chunk
    #     Get the slices of the source chunk
    #     Copy blocks and data

    for destCpos in destBox.chunkPositions:
        cx, cz = destCpos

        destChunkBox = BoundingBox(
            (cx << 4, 0, cz << 4),
            (16, destLevel.Height, 16)).intersect(destBox)
        destChunkBoxInSourceLevel = BoundingBox(
            [d - o for o, d in zip(copyOffset, destChunkBox.origin)],
            destChunkBox.size)

        if not destLevel.containsChunk(*destCpos):
            if create and any(
                    sourceLevel.containsChunk(*c)
                    for c in destChunkBoxInSourceLevel.chunkPositions):
                # Only create chunks in the destination level if the source level has chunks covering them.
                destLevel.createChunk(*destCpos)
            else:
                continue

        destChunk = destLevel.getChunk(*destCpos)

        i += 1
        yield (i, chunkCount)
        if i % 100 == 0:
            log.info("Chunk {0}...".format(i))

        for srcCpos in destChunkBoxInSourceLevel.chunkPositions:
            if not sourceLevel.containsChunk(*srcCpos):
                continue

            sourceChunk = sourceLevel.getChunk(*srcCpos)

            sourceChunkBox, sourceSlices = sourceChunk.getChunkSlicesForBox(
                destChunkBoxInSourceLevel)
            if sourceChunkBox.volume == 0:
                continue

            sourceChunkBoxInDestLevel = BoundingBox(
                [d + o for o, d in zip(copyOffset, sourceChunkBox.origin)],
                sourceChunkBox.size)

            _, destSlices = destChunk.getChunkSlicesForBox(
                sourceChunkBoxInDestLevel)

            sourceBlocks = sourceChunk.Blocks[sourceSlices]
            sourceData = sourceChunk.Data[sourceSlices]

            mask = sourceMask(sourceBlocks)
            convertedSourceBlocks, convertedSourceData = convertBlocks(
                destLevel, sourceLevel, sourceBlocks, sourceData)

            destChunk.Blocks[destSlices][mask] = convertedSourceBlocks[mask]
            if convertedSourceData is not None:
                destChunk.Data[destSlices][mask] = convertedSourceData[mask]

            def copy(p):
                return p in sourceChunkBoxInDestLevel and (
                    blocksToCopy is None
                    or mask[p[0] - sourceChunkBoxInDestLevel.minx,
                            p[2] - sourceChunkBoxInDestLevel.minz,
                            p[1] - sourceChunkBoxInDestLevel.miny, ])

            if entities:
                destChunk.removeEntities(copy)

                ents = sourceChunk.getEntitiesInBox(destChunkBoxInSourceLevel)
                e += len(ents)
                for entityTag in ents:
                    eTag = Entity.copyWithOffset(entityTag, copyOffset,
                                                 regenerateUUID)
                    destLevel.addEntity(eTag)

            destChunk.removeTileEntities(copy)

            tileEntities = sourceChunk.getTileEntitiesInBox(
                destChunkBoxInSourceLevel)
            t += len(tileEntities)
            for tileEntityTag in tileEntities:
                eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset,
                                                 staticCommands,
                                                 moveSpawnerPos, first)
                destLevel.addTileEntity(eTag)

            destChunk.removeTileTicks(copy)

            tileTicksList = sourceChunk.getTileTicksInBox(
                destChunkBoxInSourceLevel)
            tt += len(tileTicksList)
            for tileTick in tileTicksList:
                eTag = deepcopy(tileTick)
                eTag['x'].value = tileTick['x'].value + copyOffset[0]
                eTag['y'].value = tileTick['y'].value + copyOffset[1]
                eTag['z'].value = tileTick['z'].value + copyOffset[2]
                destLevel.addTileTick(eTag)

            if biomes and hasattr(destChunk, 'Biomes') and hasattr(
                    sourceChunk, 'Biomes'):
                destChunk.Biomes[destSlices[:2]] = sourceChunk.Biomes[
                    sourceSlices[:2]]

        destChunk.chunkChanged()

    log.info("Duration: {0}".format(datetime.now() - startTime))
    log.info(
        "Copied {0} entities and {1} tile entities and {2} tile ticks".format(
            e, t, tt))
Пример #21
0
def fillBlocksIter(level, box, blockInfo, blocksToReplace=(), noData=False):
    if box is None:
        chunkIterator = level.getAllChunkSlices()
        box = level.bounds
    else:
        chunkIterator = level.getChunkSlices(box)

    log.info("Replacing {0} with {1}".format(blocksToReplace, blockInfo))

    changesLighting = True
    blocktable = None
    if len(blocksToReplace):
        blocktable = blockReplaceTable(blocksToReplace)

        newAbsorption = level.materials.lightAbsorption[blockInfo.ID]
        oldAbsorptions = [
            level.materials.lightAbsorption[b.ID] for b in blocksToReplace
        ]
        changesLighting = False
        for a in oldAbsorptions:
            if a != newAbsorption:
                changesLighting = True

        newEmission = level.materials.lightEmission[blockInfo.ID]
        oldEmissions = [
            level.materials.lightEmission[b.ID] for b in blocksToReplace
        ]
        for a in oldEmissions:
            if a != newEmission:
                changesLighting = True

    tileEntity = None
    if blockInfo.stringID in TileEntity.stringNames.keys():
        split_ver = level.gameVersion.split('.')
        if 'Unknown' not in split_ver and int(split_ver[0]) >= 1 and int(
                split_ver[1]) >= 11:
            tileEntity = "minecraft:{}".format(blockInfo.stringID)
        else:
            tileEntity = TileEntity.stringNames[blockInfo.stringID]

    blocksIdToReplace = [block.ID for block in blocksToReplace]

    blocksList = []
    append = blocksList.append
    defsIds = level.defsIds
    if tileEntity and box is not None:
        for (boxX, boxY, boxZ) in box.positions:
            if blocktable is None or level.blockAt(boxX, boxY,
                                                   boxZ) in blocksIdToReplace:
                tileEntityObject = TileEntity.Create(tileEntity,
                                                     defsIds=defsIds)
                TileEntity.setpos(tileEntityObject, (boxX, boxY, boxZ))
                append(tileEntityObject)

    i = 0
    skipped = 0
    replaced = 0

    for (chunk, slices, point) in chunkIterator:
        i += 1
        if i % 100 == 0:
            log.info(u"Chunk {0}...".format(i))
        yield i, box.chunkCount

        blocks = chunk.Blocks[slices]
        data = chunk.Data[slices]
        mask = slice(None)

        needsLighting = changesLighting

        if blocktable is not None:
            mask = blocktable[blocks, data]

            blockCount = mask.sum()
            replaced += blockCount

            # don't waste time relighting and copying if the mask is empty
            if blockCount:
                blocks[:][mask] = blockInfo.ID
                if not noData:
                    data[mask] = blockInfo.blockData
            else:
                skipped += 1
                needsLighting = False

            def include(tileEntity):
                p = TileEntity.pos(tileEntity)
                x, y, z = map(lambda a, b, c: (a - b) - c, p, point,
                              box.origin)
                return not ((p in box) and mask[x, z, y])

            chunk.TileEntities[:] = filter(include, chunk.TileEntities)

        else:
            blocks[:] = blockInfo.ID
            if not noData:
                data[:] = blockInfo.blockData
            chunk.removeTileEntitiesInBox(box)

        chunkBounds = chunk.bounds
        smallBoxSize = (1, 1, 1)
        tileEntitiesToEdit = [
            t for t in blocksList if chunkBounds.intersect(
                BoundingBox(TileEntity.pos(t), smallBoxSize)).volume > 0
        ]

        for tileEntityObject in tileEntitiesToEdit:
            chunk.addTileEntity(tileEntityObject)
            blocksList.remove(tileEntityObject)

        chunk.chunkChanged(needsLighting)

    if len(blocksToReplace):
        log.info(u"Replace: Skipped {0} chunks, replaced {1} blocks".format(
            skipped, replaced))
Пример #22
0
 def getTileEntitiesInBox(self, box):
     """Returns a list of references to tile entities in this chunk, whose positions are within box"""
     return [ent for ent in self.TileEntities if TileEntity.pos(ent) in box]
Пример #23
0
    def __init__(self, root_tag=None, filename=""):
        self.Width = 0
        self.Height = 0
        self.Length = 0
        self.Blocks = array([], uint8)
        self.Data = array([], uint8)
        self.Spawn = (0, 0, 0)
        self.filename = filename

        if root_tag:

            self.root_tag = root_tag
            mapTag = root_tag[Map]
            self.Width = mapTag[Width].value
            self.Length = mapTag[Length].value
            self.Height = mapTag[Height].value

            mapTag[Blocks].value.shape = (self.Height, self.Length, self.Width)

            self.Blocks = swapaxes(mapTag[Blocks].value, 0, 2)

            mapTag[Data].value.shape = (self.Height, self.Length, self.Width)

            self.Data = swapaxes(mapTag[Data].value, 0, 2)

            self.BlockLight = self.Data & 0xf

            self.Data >>= 4

            self.Spawn = [mapTag[Spawn][i].value for i in range(3)]

            if not Entities in root_tag:
                root_tag[Entities] = nbt.TAG_List()
            self.Entities = root_tag[Entities]

            # xxx fixup Motion and Pos to match infdev format
            def numbersToDoubles(ent):
                for attr in "Motion", "Pos":
                    if attr in ent:
                        ent[attr] = nbt.TAG_List([nbt.TAG_Double(t.value) for t in ent[attr]])
            for ent in self.Entities:
                numbersToDoubles(ent)

            if not TileEntities in root_tag:
                root_tag[TileEntities] = nbt.TAG_List()
            self.TileEntities = root_tag[TileEntities]
            # xxx fixup TileEntities positions to match infdev format
            for te in self.TileEntities:
                pos = te["Pos"].value

                (x, y, z) = self.decodePos(pos)

                TileEntity.setpos(te, (x, y, z))

            if len(filter(lambda x: x['id'].value == 'LocalPlayer', root_tag[Entities])) == 0:  # omen doesn't make a player entity
                p = nbt.TAG_Compound()
                p['id'] = nbt.TAG_String('LocalPlayer')
                p['Pos'] = nbt.TAG_List([nbt.TAG_Float(0.), nbt.TAG_Float(64.), nbt.TAG_Float(0.)])
                p['Rotation'] = nbt.TAG_List([nbt.TAG_Float(0.), nbt.TAG_Float(45.)])

                root_tag[Entities].append(p)
                # self.saveInPlace()

        else:
            info(u"Creating new Indev levels is not yet implemented.!")
            raise ValueError("Can't do that yet")
Пример #24
0
def fillBlocksIter(level, box, blockInfo, blocksToReplace=(), noData=False):
    if box is None:
        chunkIterator = level.getAllChunkSlices()
        box = level.bounds
    else:
        chunkIterator = level.getChunkSlices(box)

    log.info("Replacing {0} with {1}".format(blocksToReplace, blockInfo))

    changesLighting = True
    blocktable = None
    if len(blocksToReplace):
        blocktable = blockReplaceTable(blocksToReplace)

        newAbsorption = level.materials.lightAbsorption[blockInfo.ID]
        oldAbsorptions = [level.materials.lightAbsorption[b.ID] for b in blocksToReplace]
        changesLighting = False
        for a in oldAbsorptions:
            if a != newAbsorption:
                changesLighting = True

        newEmission = level.materials.lightEmission[blockInfo.ID]
        oldEmissions = [level.materials.lightEmission[b.ID] for b in blocksToReplace]
        for a in oldEmissions:
            if a != newEmission:
                changesLighting = True

    tileEntity = None
    for tileEntityName in TileEntity.otherNames.keys():
        if tileEntityName in blockInfo.name:
            tileEntity = TileEntity.otherNames[tileEntityName]

    blocksIdToReplace = [block.ID for block in blocksToReplace]

    blocksList = []
    if tileEntity and box is not None:
            for (boxX, boxY, boxZ) in box.positions:
                if blocktable is None or level.blockAt(boxX, boxY, boxZ) in blocksIdToReplace:
                    blocksList.append((boxX, boxY, boxZ))

    i = 0
    skipped = 0
    replaced = 0

    for (chunk, slices, point) in chunkIterator:
        i += 1
        if i % 100 == 0:
            log.info(u"Chunk {0}...".format(i))
        yield i, box.chunkCount

        blocks = chunk.Blocks[slices]
        data = chunk.Data[slices]
        mask = slice(None)

        needsLighting = changesLighting

        if blocktable is not None:
            mask = blocktable[blocks, data]

            blockCount = mask.sum()
            replaced += blockCount

            # don't waste time relighting and copying if the mask is empty
            if blockCount:
                blocks[:][mask] = blockInfo.ID
                if not noData:
                    data[mask] = blockInfo.blockData
            else:
                skipped += 1
                needsLighting = False

            def include(tileEntity):
                p = TileEntity.pos(tileEntity)
                x, y, z = map(lambda a, b, c: (a - b) - c, p, point, box.origin)
                return not ((p in box) and mask[x, z, y])

            chunk.TileEntities[:] = filter(include, chunk.TileEntities)

        else:
            blocks[:] = blockInfo.ID
            if not noData:
                data[:] = blockInfo.blockData
            chunk.removeTileEntitiesInBox(box)

        if blocksList:
            for position in blocksList:
                tileEntityObject = TileEntity.Create(tileEntity)
                TileEntity.setpos(tileEntityObject, position)
                chunk.addTileEntity(tileEntityObject)
        chunk.chunkChanged(needsLighting)

    if len(blocksToReplace):
        log.info(u"Replace: Skipped {0} chunks, replaced {1} blocks".format(skipped, replaced))
Пример #25
0
 def getTileEntitiesInBox(self, box):
     """Returns a list of references to tile entities in this chunk, whose positions are within box"""
     return [ent for ent in self.TileEntities if TileEntity.pos(ent) in box]
Пример #26
0
 def differentPosition(a):
     return not ((tileEntityTag is a) or TileEntity.pos(a) == TileEntity.pos(tileEntityTag))
Пример #27
0
def copyBlocksFromIter(destLevel,
                       sourceLevel,
                       sourceBox,
                       destinationPoint,
                       blocksToCopy=None,
                       entities=True,
                       create=False):
    """ copy blocks between two infinite levels by looping through the
    destination's chunks. make a sub-box of the source level for each chunk
    and copy block and entities in the sub box to the dest chunk."""

    (lx, ly, lz) = sourceBox.size

    sourceBox, destinationPoint = adjustCopyParameters(destLevel, sourceLevel,
                                                       sourceBox,
                                                       destinationPoint)
    # needs work xxx
    log.info(u"Copying {0} blocks from {1} to {2}".format(
        ly * lz * lx, sourceBox, destinationPoint))
    startTime = datetime.now()

    destBox = BoundingBox(destinationPoint, sourceBox.size)
    chunkCount = destBox.chunkCount
    i = 0
    e = 0
    t = 0

    sourceMask = sourceMaskFunc(blocksToCopy)

    copyOffset = [d - s for s, d in zip(sourceBox.origin, destinationPoint)]

    # Visit each chunk in the destination area.
    #   Get the region of the source area corresponding to that chunk
    #   Visit each chunk of the region of the source area
    #     Get the slices of the destination chunk
    #     Get the slices of the source chunk
    #     Copy blocks and data

    for destCpos in destBox.chunkPositions:
        cx, cz = destCpos

        destChunkBox = BoundingBox(
            (cx << 4, 0, cz << 4),
            (16, destLevel.Height, 16)).intersect(destBox)
        destChunkBoxInSourceLevel = BoundingBox(
            [d - o for o, d in zip(copyOffset, destChunkBox.origin)],
            destChunkBox.size)

        if not destLevel.containsChunk(*destCpos):
            if create and any(
                    sourceLevel.containsChunk(*c)
                    for c in destChunkBoxInSourceLevel.chunkPositions):
                # Only create chunks in the destination level if the source level has chunks covering them.
                destLevel.createChunk(*destCpos)
            else:
                continue

        destChunk = destLevel.getChunk(*destCpos)

        i += 1
        yield (i, chunkCount)
        if i % 100 == 0:
            log.info("Chunk {0}...".format(i))

        for srcCpos in destChunkBoxInSourceLevel.chunkPositions:
            if not sourceLevel.containsChunk(*srcCpos):
                continue

            sourceChunk = sourceLevel.getChunk(*srcCpos)

            sourceChunkBox, sourceSlices = sourceChunk.getChunkSlicesForBox(
                destChunkBoxInSourceLevel)
            sourceChunkBoxInDestLevel = BoundingBox(
                [d + o for o, d in zip(copyOffset, sourceChunkBox.origin)],
                sourceChunkBox.size)

            _, destSlices = destChunk.getChunkSlicesForBox(
                sourceChunkBoxInDestLevel)

            sourceBlocks = sourceChunk.Blocks[sourceSlices]
            sourceData = sourceChunk.Data[sourceSlices]

            mask = sourceMask(sourceBlocks)
            convertedSourceBlocks, convertedSourceData = convertBlocks(
                destLevel, sourceLevel, sourceBlocks, sourceData)

            destChunk.Blocks[destSlices][mask] = convertedSourceBlocks[mask]
            if convertedSourceData is not None:
                destChunk.Data[destSlices][mask] = convertedSourceData[mask]

            if entities:
                ents = sourceChunk.getEntitiesInBox(destChunkBoxInSourceLevel)
                e += len(ents)
                for entityTag in ents:
                    eTag = Entity.copyWithOffset(entityTag, copyOffset)
                    destLevel.addEntity(eTag)

            tileEntities = sourceChunk.getTileEntitiesInBox(
                destChunkBoxInSourceLevel)
            t += len(tileEntities)
            for tileEntityTag in tileEntities:
                eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)
                destLevel.addTileEntity(eTag)

        destChunk.chunkChanged()

    log.info("Duration: {0}".format(datetime.now() - startTime))
    log.info("Copied {0} entities and {1} tile entities".format(e, t))
Пример #28
0
def copyBlocksFromIter(destLevel, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True, create=False):
    """ copy blocks between two infinite levels by looping through the
    destination's chunks. make a sub-box of the source level for each chunk
    and copy block and entities in the sub box to the dest chunk."""

    (lx, ly, lz) = sourceBox.size

    sourceBox, destinationPoint = adjustCopyParameters(destLevel, sourceLevel, sourceBox, destinationPoint)
    # needs work xxx
    log.info(u"Copying {0} blocks from {1} to {2}" .format(ly * lz * lx, sourceBox, destinationPoint))
    startTime = datetime.now()

    destBox = BoundingBox(destinationPoint, sourceBox.size)
    chunkCount = destBox.chunkCount
    i = 0
    e = 0
    t = 0

    sourceMask = sourceMaskFunc(blocksToCopy)

    copyOffset = [d - s for s, d in zip(sourceBox.origin, destinationPoint)]

    # Visit each chunk in the destination area.
    #   Get the region of the source area corresponding to that chunk
    #   Visit each chunk of the region of the source area
    #     Get the slices of the destination chunk
    #     Get the slices of the source chunk
    #     Copy blocks and data

    for destCpos in destBox.chunkPositions:
        cx, cz = destCpos

        destChunkBox = BoundingBox((cx << 4, 0, cz << 4), (16, destLevel.Height, 16)).intersect(destBox)
        destChunkBoxInSourceLevel = BoundingBox([d - o for o, d in zip(copyOffset, destChunkBox.origin)], destChunkBox.size)

        if not destLevel.containsChunk(*destCpos):
            if create and any(sourceLevel.containsChunk(*c) for c in destChunkBoxInSourceLevel.chunkPositions):
                # Only create chunks in the destination level if the source level has chunks covering them.
                destLevel.createChunk(*destCpos)
            else:
                continue

        destChunk = destLevel.getChunk(*destCpos)


        i += 1
        yield (i, chunkCount)
        if i % 100 == 0:
            log.info("Chunk {0}...".format(i))

        for srcCpos in destChunkBoxInSourceLevel.chunkPositions:
            if not sourceLevel.containsChunk(*srcCpos):
                continue

            sourceChunk = sourceLevel.getChunk(*srcCpos)

            sourceChunkBox, sourceSlices = sourceChunk.getChunkSlicesForBox(destChunkBoxInSourceLevel)
            if sourceChunkBox.volume == 0:
                continue

            sourceChunkBoxInDestLevel = BoundingBox([d + o for o, d in zip(copyOffset, sourceChunkBox.origin)], sourceChunkBox.size)

            _, destSlices = destChunk.getChunkSlicesForBox(sourceChunkBoxInDestLevel)

            sourceBlocks = sourceChunk.Blocks[sourceSlices]
            sourceData = sourceChunk.Data[sourceSlices]

            mask = sourceMask(sourceBlocks)
            convertedSourceBlocks, convertedSourceData = convertBlocks(destLevel, sourceLevel, sourceBlocks, sourceData)

            destChunk.Blocks[destSlices][mask] = convertedSourceBlocks[mask]
            if convertedSourceData is not None:
                destChunk.Data[destSlices][mask] = convertedSourceData[mask]

            if entities:
                ents = sourceChunk.getEntitiesInBox(destChunkBoxInSourceLevel)
                e += len(ents)
                for entityTag in ents:
                    eTag = Entity.copyWithOffset(entityTag, copyOffset)
                    destLevel.addEntity(eTag)

            tileEntities = sourceChunk.getTileEntitiesInBox(destChunkBoxInSourceLevel)
            t += len(tileEntities)
            for tileEntityTag in tileEntities:
                eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)
                destLevel.addTileEntity(eTag)

        destChunk.chunkChanged()

    log.info("Duration: {0}".format(datetime.now() - startTime))
    log.info("Copied {0} entities and {1} tile entities".format(e, t))
Пример #29
0
 def differentPosition(a):
     return not ((tileEntityTag is a)
                 or TileEntity.pos(a) == TileEntity.pos(tileEntityTag))
Пример #30
0
 def include(tileEntity):
     p = TileEntity.pos(tileEntity)
     x, y, z = map(lambda a, b, c: (a - b) - c, p, point,
                   box.origin)
     return not ((p in box) and mask[x, z, y])