Exemple #1
0
    def testCreate(self):
        # log.info("Schematic from indev")

        size = (64, 64, 64)
        temp = mktemp("testcreate.schematic")
        editor = createSchematic(shape=size, blocktypes='Classic')
        editor.filename = temp
        dim = editor.getDimension()
        level = self.schematicLevel

        dim.importSchematic(level, (0, 0, 0))
        assert((schematic.Blocks[0:64, 0:64, 0:64] == level.adapter.Blocks[0:64, 0:64, 0:64]).all())

        dim.importSchematic(level, (-32, -32, -32))
        assert((schematic.Blocks[0:32, 0:32, 0:32] == level.adapter.Blocks[32:64, 32:64, 32:64]).all())

        schematic.saveChanges()

        schem = WorldEditor("test_files/Station.schematic")
        tempEditor = createSchematic(shape=(1, 1, 3))
        tempDim = tempEditor.getDimension()
        tempDim.copyBlocks(schem, BoundingBox((0, 0, 0), (1, 1, 3)), (0, 0, 0))

        level = self.anvilLevel
        for cx, cz in itertools.product(xrange(0, 4), xrange(0, 4)):
            try:
                level.createChunk(cx, cz)
            except ValueError:
                pass
        dim.copyBlocks(level.getDimension(), BoundingBox((0, 0, 0), (64, 64, 64,)), (0, 0, 0))
        os.remove(temp)
Exemple #2
0
    def __init__(self, pos, commandObj):
        """

        Parameters
        ----------
        commandObj : ExecuteCommand

        Returns
        -------

        """
        super(ExecuteVisuals, self).__init__()

        selector = commandObj.targetSelector
        if selector.playerName is not None:
            return

        selectorPos = [selector.getArg(a) for a in 'xyz']

        if None in (selectorPos):
            log.warn("No selector coordinates for command %s", commandObj)
            targetPos = commandObj.resolvePosition((0, 0, 0))
        else:
            targetPos = commandObj.resolvePosition(selectorPos)

        # Draw box at selector pos and draw line from command block to selector pos
        # xxxx selector pos is a sphere of radius `selector.getArg('r')`

        boxNode = SelectionBoxNode()
        boxNode.filled = False
        boxNode.wireColor = (0.9, 0.2, 0.2, 0.6)
        boxNode.selectionBox = BoundingBox(selectorPos, (1, 1, 1))

        lineNode = LineArcNode(
            Vector(*pos) + (0.5, 0.5, 0.5),
            Vector(*selectorPos) + (.5, .5, .5), (0.9, 0.2, 0.2, 0.6))
        self.addChild(boxNode)
        self.addChild(lineNode)

        if selectorPos != targetPos:
            # Command block's own coordinates are different from the selected pos,
            # either relative or absolute.
            # Draw a box at the target coordinates and a line from
            # the selected pos to the target

            boxNode = SelectionBoxNode()
            boxNode.filled = False
            boxNode.wireColor = (0.9, 0.2, 0.2, 0.6)
            boxNode.selectionBox = BoundingBox(targetPos, (1, 1, 1))

            lineNode = LineArcNode(
                Vector(*selectorPos) + (0.5, 0.5, 0.5),
                Vector(*targetPos) + (.5, .5, .5), (0.9, 0.2, 0.2, 0.6))

            self.addChild(boxNode)
            self.addChild(lineNode)

        if not isinstance(commandObj.subcommand, UnknownCommand):
            subvisuals = CommandVisuals(targetPos, commandObj.subcommand)
            self.addChild(subvisuals)
Exemple #3
0
def test_difference():
    box1 = BoundingBox((0, 0, 0), (10, 10, 10))
    box2 = BoundingBox((0, 5, 0), (10, 10, 10))

    diff = box1 - box2

    mask = diff.box_mask(box1)
    assert not mask[5:, :, :].any()
Exemple #4
0
 def updateBoxHandle(self):
     if self.transformedWorldScene is None:
         bounds = BoundingBox(self.basePosition,
                              self.pendingImport.bounds.size)
     else:
         origin = self.transformedPosition
         bounds = BoundingBox(origin, self.pendingImport.importBounds.size)
     #if self.handleNode.bounds.size != bounds.size:
     self.handleNode.bounds = bounds
Exemple #5
0
    def __init__(self, box=None, **kw):
        Symbol.__init__(self, **kw)
        if box is None:
            origin = kw['minx'], kw['miny'], kw['minz']
            size = kw['width'], kw['height'], kw['length']
        else:
            origin = box.origin
            size = box.size

        BoundingBox.__init__(self, origin, size)
Exemple #6
0
    def __init__(self, box=None, **kw):
        Symbol.__init__(self, **kw)
        if box is None:
            origin = kw['minx'], kw['miny'], kw['minz']
            size = kw['width'], kw['height'], kw['length']
        else:
            origin = box.origin
            size = box.size

        BoundingBox.__init__(self, origin, size)
Exemple #7
0
    def getWorldBounds(self):
        chunkPositions = list(self.chunkPositions())
        if len(chunkPositions) == 0:
            return BoundingBox((0, 0, 0), (0, 0, 0))

        chunkPositions = numpy.array(chunkPositions)
        mincx = (chunkPositions[:, 0]).min()
        maxcx = (chunkPositions[:, 0]).max()
        mincz = (chunkPositions[:, 1]).min()
        maxcz = (chunkPositions[:, 1]).max()

        origin = (mincx << 4, 0, mincz << 4)
        size = ((maxcx - mincx + 1) << 4, self.worldEditor.maxHeight, (maxcz - mincz + 1) << 4)

        return BoundingBox(origin, size)
Exemple #8
0
 def getEntity(self, dim):
     assert self.resultType == self.EntityResult
     box = BoundingBox(self.position, (1, 1, 1)).chunkBox(dim)
     entities = dim.getEntities(box, UUID=self.uuid)
     for entity in entities:
         return entity
     return None
Exemple #9
0
    def continueMove(self, event):
        if self.dragStartFace is None:
            return

        delta = self.dragMovePoint(event.ray) - self.dragStartPoint
        movePosition = self.dragStartMovePosition + map(int, delta)
        self.bounds = BoundingBox(movePosition, self.bounds.size)
Exemple #10
0
def transformBounds(bounds, matrix):
    # matrix goes from dest to source; we need source to dest here, so get inverse
    matrix = np.linalg.inv(matrix)
    corners = np.array(boundsCorners(bounds))
    corners = np.hstack([corners, ([1], ) * 8])
    corners = corners * matrix

    minx = math.floor(min(corners[:, 0]))
    miny = math.floor(min(corners[:, 1]))
    minz = math.floor(min(corners[:, 2]))
    maxx = math.ceil(max(corners[:, 0]))
    maxy = math.ceil(max(corners[:, 1]))
    maxz = math.ceil(max(corners[:, 2]))

    # Why? Weird hacks for rotation?

    # if maxx % 1:
    #     maxx += 1
    # if maxy % 1:
    #     maxy += 1
    # if maxz % 1:
    #     maxz += 1

    newbox = BoundingBox(origin=Vector(minx, miny, minz).intfloor(),
                         maximum=Vector(maxx, maxy, maxz).intfloor())
    return newbox
Exemple #11
0
    def __init__(self, pos, commandObj):
        super(CloneVisuals, self).__init__()

        sourceBox = commandObj.resolveBoundingBox(pos)

        dest = commandObj.resolveDestination(pos)
        destBox = BoundingBox(dest, sourceBox.size)

        sourceColor = (0.3, 0.5, 0.9, 0.6)
        destColor = (0.0, 0.0, 0.9, 0.6)

        sourceBoxNode = SelectionBoxNode()
        sourceBoxNode.filled = False
        sourceBoxNode.wireColor = sourceColor
        sourceBoxNode.selectionBox = sourceBox

        destBoxNode = SelectionBoxNode()
        destBoxNode.filled = False
        destBoxNode.wireColor = destColor
        destBoxNode.selectionBox = destBox

        lineToSourceNode = LineArcNode(
            Vector(*pos) + (0.5, 0.5, 0.5), sourceBox.center, sourceColor)
        lineToDestNode = LineArcNode(sourceBox.center, destBox.center,
                                     destColor)

        self.addChild(sourceBoxNode)
        self.addChild(destBoxNode)

        self.addChild(lineToSourceNode)
        self.addChild(lineToDestNode)
Exemple #12
0
    def boxFromDragResize(self, box, ray):
        point = self.dragResizePoint(ray)

        side = self.dragResizeFace & 1
        dragdim = self.dragResizeFace >> 1

        origin, size = list(box.origin), list(box.size)
        if side:
            origin[dragdim] += size[dragdim]
        size[dragdim] = 0

        otherSide = BoundingBox(origin, size)
        origin[dragdim] = int(numpy.floor(point[dragdim] + 0.5))
        thisSide = BoundingBox(origin, size)

        return thisSide.union(otherSide)
Exemple #13
0
    def inspectBlock(self, pos):
        self.clearVisuals()
        self.blockPos = pos
        self.entity = None
        self.entityPtr = None
        self.currentChunk = None
        self.chunkPos = None

        self.stackedWidget.setCurrentWidget(self.pageInspectBlock)
        x, y, z = pos
        self.blockXSpinBox.setValue(x)
        self.blockYSpinBox.setValue(y)
        self.blockZSpinBox.setValue(z)

        blockID = self.editorSession.currentDimension.getBlockID(x, y, z)
        blockData = self.editorSession.currentDimension.getBlockData(x, y, z)
        blockLight = self.editorSession.currentDimension.getBlockLight(x, y, z)
        skyLight = self.editorSession.currentDimension.getSkyLight(x, y, z)

        self.blockIDLabel.setText(str(blockID))
        self.blockDataLabel.setText(str(blockData))
        self.blockLightLabel.setText(str(blockLight))
        self.skyLightLabel.setText(str(skyLight))

        block = self.editorSession.currentDimension.getBlock(x, y, z)

        self.blockNameLabel.setText(block.displayName)
        self.blockInternalNameLabel.setText(block.internalName)
        self.blockStateLabel.setText(str(block.blockState))

        blockBox = BoundingBox((x, y, z), (1, 1, 1))

        self.selectionNode.selectionBox = blockBox

        self.updateTileEntity()
Exemple #14
0
    def drawSelf(self):
        point = self.sceneNode.point
        if point is None:
            return

        r, g, b, a = self.sceneNode.color
        box = BoundingBox(point, (1, 1, 1))

        with gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT | GL.GL_ENABLE_BIT
                             | GL.GL_POLYGON_BIT):
            GL.glDepthMask(False)
            GL.glEnable(GL.GL_BLEND)
            GL.glPolygonOffset(DepthOffsets.SelectionCursor,
                               DepthOffsets.SelectionCursor)

            # Highlighted face

            GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL)

            GL.glColor(r, g, b, a)
            cubes.drawFace(box, self.sceneNode.face)

            # Wire box
            GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE)

            GL.glLineWidth(3.0)
            GL.glColor(1., 1., 1., a)

            cubes.drawBox(box)

            GL.glLineWidth(1.0)
            GL.glColor(0.2, 0.2, 0.2, a)

            cubes.drawBox(box)
Exemple #15
0
 def brushBoundingBox(self, center, options={}):
     # Return a box of size options['brushSize'] centered around point.
     # also used to position the preview cursor
     size = options['brushSize']
     x, y, z = size
     origin = Vector(*center) - (Vector(x, y, z) / 2) + Vector((x % 2) * 0.5, (y % 2) * 0.5, (z % 2) * 0.5)
     return BoundingBox(origin, size)
Exemple #16
0
    def boxFromDragResize(self, box, ray):
        point = self.dragResizePoint(ray)

        side = self.dragResizeFace & 1
        dragdim = self.dragResizeFace >> 1

        origin, size = list(box.origin), list(box.size)
        if side:
            origin[dragdim] += size[dragdim]
        size[dragdim] = 0

        otherSide = BoundingBox(origin, size)
        origin[dragdim] = int(numpy.floor(point[dragdim] + 0.5))
        thisSide = BoundingBox(origin, size)

        return thisSide.union(otherSide)
Exemple #17
0
 def redo(self):
     super(MoveFinishCommand, self).redo()
     self.previousSelection = self.editorSession.currentSelection
     self.currentImport = self.moveTool.currentImport
     self.editorSession.currentSelection = BoundingBox(
         self.pendingImport.pos, self.previousSelection.size)
     self.moveTool.currentImport = None
     self.editorSession.removePendingImport(self.currentImport)
Exemple #18
0
 def setMinX(self, value):
     origin, size = self.boundingBox
     dx = value - origin[0]
     size = size[0] - dx, size[1], size[2]
     origin = value, origin[1], origin[2]
     box = BoundingBox(origin, size)
     self.boundingBox = box
     self.boxChanged.emit(box)
Exemple #19
0
 def setMinY(self, value):
     origin, size = self.boundingBox
     dy = value - origin[1]
     size = size[0], size[1] - dy, size[2]
     origin = origin[0], value, origin[2]
     box = BoundingBox(origin, size)
     self.boundingBox = box
     self.boxChanged.emit(box)
Exemple #20
0
 def setMinZ(self, value):
     origin, size = self.boundingBox
     dz = value - origin[2]
     size = size[0], size[1], size[2] - dz
     origin = origin[0], origin[1], value
     box = BoundingBox(origin, size)
     self.boundingBox = box
     self.boxChanged.emit(box)
Exemple #21
0
def testImport(world, sourceLevel):
    dim = world.getDimension()
    dim.copyBlocks(sourceLevel.getDimension(),
                   BoundingBox((0, 0, 0), (
                       32,
                       64,
                       32,
                   )), dim.bounds.origin)
    world.saveChanges()
Exemple #22
0
    def updateImportPos(self):
        if self.transformedDim is None:
            self.importPos = self.basePosition
            size = self.selection.size
        else:
            self.importPos = self.basePosition + self.transformOffset
            size = self.transformedDim.bounds.size

        self.importBounds = BoundingBox(self.importPos, size)
Exemple #23
0
    def getEntity(self):
        assert self.resultType == self.EntityResult
        dim = self.dimension

        box = BoundingBox(self.position.intfloor(), (1, 1, 1)).chunkBox(dim)
        entities = dim.getEntities(box, UUID=self.uuid)
        for entity in entities:
            return entity
        return None
Exemple #24
0
 def setMaxZ(self, value):
     origin, size = self.boundingBox
     if self.editSizeInput.checkState():
         size = size[0], size[1], value
     else:
         size = size[0], size[1], value - origin[2]
     box = BoundingBox(origin, size)
     self.boundingBox = box
     self.boxChanged.emit(box)
def do_copy(dim, station, relight):
    times = 1
    boxes = []
    for x in range(times):
        for z in range(times):
            origin = (x * station.bounds.width, 54, z * station.bounds.length)
            boxes.append(BoundingBox(origin, station.bounds.size))
            dim.copyBlocks(station, station.bounds, origin, create=True, updateLights=relight)
    return reduce(lambda a, b: a.union(b), boxes)
Exemple #26
0
def testImport(any_world, schematic_world):
    dim = any_world.getDimension()
    dim.copyBlocks(schematic_world.getDimension(),
                   BoundingBox((0, 0, 0), (
                       32,
                       64,
                       32,
                   )), dim.bounds.origin)
    any_world.saveChanges()
Exemple #27
0
def testCopyRelight(anvilLevel, sourceLevel):
    destDim = anvilLevel.getDimension()
    exhaust(
        destDim.copyBlocksIter(sourceLevel.getDimension(),
                               BoundingBox((0, 0, 0), (
                                   32,
                                   64,
                                   32,
                               )), destDim.bounds.origin))
    anvilLevel.saveChanges()
Exemple #28
0
def testCopyRelight(pc_world, schematic_world):
    destDim = pc_world.getDimension()
    exhaust(
        destDim.copyBlocksIter(schematic_world.getDimension(),
                               BoundingBox((0, 0, 0), (
                                   32,
                                   64,
                                   32,
                               )), destDim.bounds.origin))
    pc_world.saveChanges()
Exemple #29
0
 def updateNodes(self):
     box = self.currentSelection
     if box:
         self.boxHandleNode.bounds = BoundingBox(box.origin, box.size)
         self.selectionNode.visible = True
         self.selectionNode.selection = box
     else:
         self.boxHandleNode.bounds = None
         self.selectionNode.visible = False
         self.faceHoverNode.visible = False
Exemple #30
0
def main():
    app = QtGui.QApplication([])
    selection = ShapeFuncSelection(BoundingBox((0, 0, 0), (63, 63, 63)), SphereShape)
    scene = SelectionScene()
    def timeBuild():
        scene.selection = selection
        for _ in scene.loadSections():
            pass

    duration = timeit.timeit(timeBuild, number=1) * 1000
    print("timeBuild x1 in %0.2fms (%0.3fms per chunk)" % (duration, duration / selection.chunkCount))
Exemple #31
0
def timeFillCeiling():
    temp = bench_temp_level("AnvilWorld")
    editor = temp
    dim = editor.getDimension()
    bounds = dim.bounds
    x, y, z = bounds.center
    y = 254
    x -= size // 2
    z -= size // 2
    bounds = BoundingBox((x, y, z), (size, 1, size))
    exhaust(dim.fillBlocksIter(bounds, editor.blocktypes["planks"]))
Exemple #32
0
def testRotate(pc_world):
    dim = pc_world.getDimension()
    schematic = dim.exportSchematic(BoundingBox((0, 0, 0), (21, 11, 8)))

    schematic.rotateLeft()
    dim.importSchematic(schematic, dim.bounds.origin)

    schematic.flipEastWest()
    dim.importSchematic(schematic, dim.bounds.origin)

    schematic.flipVertical()
    dim.importSchematic(schematic, dim.bounds.origin)
Exemple #33
0
    def boxFromDragSelect(self, event):
        """
        Create a flat selection from dragging the mouse outside the selection.

        Parameters
        ----------

        ray: mcedit2.util.geometry.Ray

        Returns
        -------

        box: BoundingBox
        """
        point = self.dragStartPoint
        face = self.dragStartFace
        size = [1, 1, 1]

        if self.classicSelection:
            endPoint = event.blockPosition
        else:
            ray = event.ray
            dim = face >> 1
            size[dim] = 0
            s = [0,0,0]

            if face & 1 == 0:
                s[dim] = 1
                point = point + s

            endPoint = ray.intersectPlane(dim, point[dim])

        startBox = BoundingBox(point, size)
        endBox = BoundingBox(endPoint.intfloor(), size)

        return startBox.union(endBox)
Exemple #34
0
    def boxFromDragSelect(self, ray):
        """
        Create a flat selection from dragging the mouse outside the selection.

        :type ray: mcedit2.util.geometry.Ray
        :rtype: BoundingBox
        """
        point = self.dragStartPoint
        face = self.dragStartFace
        size = [1, 1, 1]

        dim = face >> 1
        size[dim] = 0
        s = [0,0,0]

        if face & 1 == 0:
            s[dim] = 1
            point = point + s

        startBox = BoundingBox(point, size)
        endPoint = ray.intersectPlane(dim, point[dim])
        endBox = BoundingBox(endPoint.intfloor(), size)

        return startBox.union(endBox)
Exemple #35
0
def copyBlocksIter(destDim, sourceDim, sourceSelection, destinationPoint, blocksToCopy=None, entities=True, create=False, biomes=False, updateLights=False):
    """
    Copy blocks and entities from the `sourceBox` area of `sourceDim` to `destDim` starting at `destinationPoint`.

    :param sourceDim: WorldEditorDimension
    :param destDim: WorldEditorDimension

    Optional parameters:
      - `blocksToCopy`: list of blockIDs to copy.
      - `entities`: True to copy Entities and TileEntities, False otherwise.
      - `create`: True to create new chunks in destLevel, False otherwise.
      - `biomes`: True to copy biome data, False otherwise.
    """

    (lx, ly, lz) = sourceSelection.size

    # needs work xxx
    log.info(u"Copying {0} blocks from {1} to {2}" .format(ly * lz * lx, sourceSelection, destinationPoint))
    startTime = time.time()

    destBox = BoundingBox(destinationPoint, sourceSelection.size)
    chunkCount = destBox.chunkCount
    i = 0
    entitiesCopied = 0
    tileEntitiesCopied = 0
    entitiesSeen = 0
    tileEntitiesSeen = 0

    if updateLights:
        allChangedX = []
        allChangedY = []
        allChangedZ = []

    makeSourceMask = sourceMaskFunc(blocksToCopy)

    copyOffset = destBox.origin - sourceSelection.origin

    # Visit each chunk in the source area
    #   Visit each section in this chunk
    #      Find the chunks and sections of the destination area corresponding to this section
    #          Compute slices for Blocks array and mask
    #          Use slices and mask to copy Blocks and Data
    #   Copy entities and tile entities from this chunk.
    sourceBiomeMask = None
    convertBlocks = blocktypes.blocktypeConverter(destDim.blocktypes, sourceDim.blocktypes)

    for sourceCpos in sourceSelection.chunkPositions():
        # Visit each chunk
        if not sourceDim.containsChunk(*sourceCpos):
            continue

        sourceChunk = sourceDim.getChunk(*sourceCpos)

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

        # Use sourceBiomeMask to accumulate a list of columns over all sections whose biomes should be copied.
        sourceBiomes = None
        if biomes and hasattr(sourceChunk, 'Biomes'):
            sourceBiomes = sourceChunk.Biomes
            sourceBiomeMask = numpy.zeros_like(sourceBiomes)

        for sourceCy in sourceChunk.sectionPositions():
            # Visit each section
            sourceSection = sourceChunk.getSection(sourceCy)
            if sourceSection is None:
                continue

            selectionMask = sourceSelection.section_mask(sourceCpos[0], sourceCy, sourceCpos[1])
            if selectionMask is None:
                continue

            typeMask = makeSourceMask(sourceSection.Blocks)
            sourceMask = selectionMask & typeMask

            # Update sourceBiomeMask
            if sourceBiomes is not None:
                sourceBiomeMask |= sourceMask.any(axis=0)

            # Find corresponding destination area(s)
            sectionBox = SectionBox(sourceCpos[0], sourceCy, sourceCpos[1])
            destBox = BoundingBox(sectionBox.origin + copyOffset, sectionBox.size)

            for destCpos in destBox.chunkPositions():
                if not create and not destDim.containsChunk(*destCpos):
                    continue
                destChunk = destDim.getChunk(*destCpos, create=True)

                for destCy in destBox.sectionPositions(*destCpos):
                    # Compute slices for source and dest arrays
                    destSectionBox = SectionBox(destCpos[0], destCy, destCpos[1])
                    intersect = destSectionBox.intersect(destBox)
                    if intersect.volume == 0:
                        continue

                    destSection = destChunk.getSection(destCy, create=True)
                    if destSection is None:
                        continue

                    destSlices = (
                        slice(intersect.miny - (destCy << 4), intersect.maxy - (destCy << 4)),
                        slice(intersect.minz - (destCpos[1] << 4), intersect.maxz - (destCpos[1] << 4)),
                        slice(intersect.minx - (destCpos[0] << 4), intersect.maxx - (destCpos[0] << 4)),
                    )

                    sourceIntersect = BoundingBox(intersect.origin - copyOffset, intersect.size)
                    sourceSlices = (
                        slice(sourceIntersect.miny - (sourceCy << 4), sourceIntersect.maxy - (sourceCy << 4)),
                        slice(sourceIntersect.minz - (sourceCpos[1] << 4), sourceIntersect.maxz - (sourceCpos[1] << 4)),
                        slice(sourceIntersect.minx - (sourceCpos[0] << 4), sourceIntersect.maxx - (sourceCpos[0] << 4)),
                    )
                    # Read blocks
                    sourceBlocks = sourceSection.Blocks[sourceSlices]
                    sourceData = sourceSection.Data[sourceSlices]
                    sourceMaskPart = sourceMask[sourceSlices]

                    # Convert blocks
                    convertedSourceBlocks, convertedSourceData = convertBlocks(sourceBlocks, sourceData)
                    convertedSourceBlocksMasked = convertedSourceBlocks[sourceMaskPart]

                    # Find blocks that need direct lighting update - block opacity or brightness changed

                    oldBrightness = destDim.blocktypes.brightness[destSection.Blocks[destSlices][sourceMaskPart]]
                    newBrightness = destDim.blocktypes.brightness[convertedSourceBlocksMasked]
                    oldOpacity = destDim.blocktypes.opacity[destSection.Blocks[destSlices][sourceMaskPart]]
                    newOpacity = destDim.blocktypes.opacity[convertedSourceBlocksMasked]
                    changedLight = (oldBrightness != newBrightness) | (oldOpacity != newOpacity)

                    # Write blocks
                    destSection.Blocks[destSlices][sourceMaskPart] = convertedSourceBlocks[sourceMaskPart]
                    destSection.Data[destSlices][sourceMaskPart] = convertedSourceData[sourceMaskPart]

                    if updateLights:
                        # Find coordinates of lighting updates
                        (changedFlat,) = changedLight.nonzero()
                        # Since convertedSourceBlocksMasked is a 1d array, changedFlat is an index
                        # into this array. Thus, changedFlat is also an index into the nonzero values
                        # of sourceMaskPart.

                        if len(changedFlat):
                            x, y, z = sourceMaskPart.nonzero()
                            changedX = x[changedFlat].astype('i4')
                            changedY = y[changedFlat].astype('i4')
                            changedZ = z[changedFlat].astype('i4')

                            changedX += intersect.minx
                            changedY += intersect.miny
                            changedZ += intersect.minz
                            if updateLights == "all":
                                allChangedX.append(changedX)
                                allChangedY.append(changedY)
                                allChangedZ.append(changedZ)
                            else:
                                # log.info("Updating section lights in %s blocks... (ob %s)",
                                #          changedFlat.shape,
                                #          oldBrightness.shape)
                                relight.updateLightsByCoord(destDim, changedX, changedY, changedZ)

                destChunk.dirty = True

        # Copy biomes
        if sourceBiomes is not None:
            bx, bz = sourceBiomeMask.nonzero()
            wbx = bx + (sourceCpos[0] << 4)
            wbz = bz + (sourceCpos[1] << 4)
            destDim.setBlocks(wbx, 1, wbz, Biomes=sourceBiomes[bx, bz])

        # Copy entities and tile entities
        if entities:
            entitiesSeen += len(sourceChunk.Entities)
            for entity in sourceChunk.Entities:
                if entity.Position in sourceSelection:
                    entitiesCopied += 1
                    newEntity = entity.copyWithOffset(copyOffset)
                    destDim.addEntity(newEntity)

        tileEntitiesSeen += len(sourceChunk.TileEntities)
        for tileEntity in sourceChunk.TileEntities:
            if tileEntity.Position in sourceSelection:
                tileEntitiesCopied += 1
                newEntity = tileEntity.copyWithOffset(copyOffset)
                destDim.addTileEntity(newEntity)

    duration = time.time() - startTime
    log.info("Duration: %0.3fs, %d/%d chunks, %0.2fms per chunk (%0.2f chunks per second)",
             duration, i, sourceSelection.chunkCount, 1000 * duration/i, i/duration)
    log.info("Copied %d/%d entities and %d/%d tile entities",
             entitiesCopied, entitiesSeen, tileEntitiesCopied, tileEntitiesSeen)

    if updateLights == "all":
        log.info("Updating all at once for %d sections (%d cells)", len(allChangedX), sum(len(a) for a in allChangedX))

        startTime = time.time()

        for i in range(len(allChangedX)):
            x = allChangedX[i]
            y = allChangedY[i]
            z = allChangedZ[i]
            relight.updateLightsByCoord(destDim, x, y, z)

        i = i or 1
        duration = time.time() - startTime
        duration = duration or 1

        log.info("Lighting complete.")
        log.info("Duration: %0.3fs, %d sections, %0.2fms per section (%0.2f sections per second)",
                 duration, i, 1000 * duration/i, i/duration)
Exemple #36
0
def copyBlocksIter(destDim, sourceDim, sourceSelection, destinationPoint, blocksToCopy=None, entities=True, create=False, biomes=False):
    """
    Copy blocks and entities from the `sourceBox` area of `sourceDim` to `destDim` starting at `destinationPoint`.

    :param sourceDim: WorldEditorDimension
    :param destDim: WorldEditorDimension

    Optional parameters:
      - `blocksToCopy`: list of blockIDs to copy.
      - `entities`: True to copy Entities and TileEntities, False otherwise.
      - `create`: True to create new chunks in destLevel, False otherwise.
      - `biomes`: True to copy biome data, False otherwise.
    """

    (lx, ly, lz) = sourceSelection.size

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

    destBox = BoundingBox(destinationPoint, sourceSelection.size)
    chunkCount = destBox.chunkCount
    i = 0
    entitiesCopied = 0
    tileEntitiesCopied = 0
    entitiesSeen = 0
    tileEntitiesSeen = 0

    makeSourceMask = sourceMaskFunc(blocksToCopy)

    copyOffset = destBox.origin - sourceSelection.origin

    # Visit each chunk in the source area
    #   Visit each section in this chunk
    #      Find the chunks and sections of the destination area corresponding to this section
    #          Compute slices for Blocks array and mask
    #          Use slices and mask to copy Blocks and Data
    #   Copy entities and tile entities from this chunk.
    sourceBiomeMask = None
    convertBlocks = blocktypes.blocktypeConverter(destDim.blocktypes, sourceDim.blocktypes)

    for sourceCpos in sourceSelection.chunkPositions():
        # Visit each chunk
        if not sourceDim.containsChunk(*sourceCpos):
            continue

        sourceChunk = sourceDim.getChunk(*sourceCpos)

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

        # Use sourceBiomeMask to accumulate a list of columns over all sections whose biomes should be copied.
        sourceBiomes = None
        if biomes and hasattr(sourceChunk, 'Biomes'):
            sourceBiomes = sourceChunk.Biomes
            sourceBiomeMask = numpy.zeros_like(sourceBiomes)

        for sourceCy in sourceChunk.sectionPositions():
            # Visit each section
            sourceSection = sourceChunk.getSection(sourceCy)
            if sourceSection is None:
                continue

            selectionMask = sourceSelection.section_mask(sourceCpos[0], sourceCy, sourceCpos[1])
            if selectionMask is None:
                continue

            typeMask = makeSourceMask(sourceSection.Blocks)
            sourceMask = selectionMask & typeMask

            # Update sourceBiomeMask
            if sourceBiomes is not None:
                sourceBiomeMask |= sourceMask.any(axis=0)

            # Find corresponding destination area(s)
            sectionBox = SectionBox(sourceCpos[0], sourceCy, sourceCpos[1], sourceSection)
            destBox = BoundingBox(sectionBox.origin + copyOffset, sectionBox.size)

            for destCpos in destBox.chunkPositions():
                if not create and not destDim.containsChunk(*destCpos):
                    continue
                destChunk = destDim.getChunk(*destCpos, create=True)

                for destCy in destBox.sectionPositions(*destCpos):
                    # Compute slices for source and dest arrays
                    destSectionBox = SectionBox(destCpos[0], destCy, destCpos[1])
                    intersect = destSectionBox.intersect(destBox)
                    if intersect.volume == 0:
                        continue

                    destSection = destChunk.getSection(destCy, create=True)
                    if destSection is None:
                        continue

                    # Recompute destSectionBox and intersect using the shape of destSection.Blocks
                    # after destChunk is loaded to work with odd shaped FakeChunkDatas XXXXXXXXXXXX
                    destSectionBox = SectionBox(destCpos[0], destCy, destCpos[1], destSection)
                    intersect = destSectionBox.intersect(destBox)
                    if intersect.volume == 0:
                        continue

                    destSlices = (
                        slice(intersect.miny - (destCy << 4), intersect.maxy - (destCy << 4)),
                        slice(intersect.minz - (destCpos[1] << 4), intersect.maxz - (destCpos[1] << 4)),
                        slice(intersect.minx - (destCpos[0] << 4), intersect.maxx - (destCpos[0] << 4)),
                    )

                    sourceIntersect = BoundingBox(intersect.origin - copyOffset, intersect.size)
                    sourceSlices = (
                        slice(sourceIntersect.miny - (sourceCy << 4), sourceIntersect.maxy - (sourceCy << 4)),
                        slice(sourceIntersect.minz - (sourceCpos[1] << 4), sourceIntersect.maxz - (sourceCpos[1] << 4)),
                        slice(sourceIntersect.minx - (sourceCpos[0] << 4), sourceIntersect.maxx - (sourceCpos[0] << 4)),
                    )
                    # Read blocks
                    sourceBlocks = sourceSection.Blocks[sourceSlices]
                    sourceData = sourceSection.Data[sourceSlices]
                    sourceMaskPart = sourceMask[sourceSlices]

                    # Convert blocks
                    convertedSourceBlocks, convertedSourceData = convertBlocks(sourceBlocks, sourceData)

                    # Write blocks
                    destSection.Blocks[destSlices][sourceMaskPart] = convertedSourceBlocks[sourceMaskPart]
                    destSection.Data[destSlices][sourceMaskPart] = convertedSourceData[sourceMaskPart]

                destChunk.dirty = True

        # Copy biomes
        if sourceBiomes is not None:
            bx, bz = sourceBiomeMask.nonzero()
            wbx = bx + (sourceCpos[0] << 4)
            wbz = bz + (sourceCpos[1] << 4)
            destDim.setBlocks(wbx, 1, wbz, Biomes=sourceBiomes[bx, bz])

        # Copy entities and tile entities
        if entities:
            entitiesSeen += len(sourceChunk.Entities)
            for entity in sourceChunk.Entities:
                if entity.Position in sourceSelection:
                    entitiesCopied += 1
                    newEntity = entity.copyWithOffset(copyOffset)
                    destDim.addEntity(newEntity)

        tileEntitiesSeen += len(sourceChunk.TileEntities)
        for tileEntity in sourceChunk.TileEntities:
            if tileEntity.Position in sourceSelection:
                tileEntitiesCopied += 1
                newEntity = tileEntity.copyWithOffset(copyOffset)
                destDim.addTileEntity(newEntity)

    log.info("Duration: {0}".format(datetime.now() - startTime))
    log.info("Copied %d/%d entities and %d/%d tile entities", entitiesCopied, entitiesSeen, tileEntitiesCopied, tileEntitiesSeen)