Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
106 lines (81 sloc) 3.37 KB
import logging
import materials
log = logging.getLogger(__name__)
import numpy
from mclevelbase import exhaust
import blockrotation
from entity import TileEntity
def blockReplaceTable(blocksToReplace):
blocktable = numpy.zeros((materials.id_limit, 16), dtype='bool')
for b in blocksToReplace:
if b.hasVariants:
blocktable[b.ID, b.blockData] = True
else:
blocktable[b.ID] = True
return blocktable
def fillBlocks(level, box, blockInfo, blocksToReplace=()):
return exhaust(level.fillBlocksIter(box, blockInfo, blocksToReplace))
def fillBlocksIter(level, box, blockInfo, blocksToReplace=()):
if box is None:
chunkIterator = level.getAllChunkSlices()
box = level.bounds
else:
chunkIterator = level.getChunkSlices(box)
# shouldRetainData = (not blockInfo.hasVariants and not any([b.hasVariants for b in blocksToReplace]))
# if shouldRetainData:
# log.info( "Preserving data bytes" )
shouldRetainData = False # xxx old behavior overwrote blockdata with 0 when e.g. replacing water with lava
log.info("Replacing {0} with {1}".format(blocksToReplace, blockInfo))
changesLighting = True
blocktable = None
if len(blocksToReplace):
blocktable = blockReplaceTable(blocksToReplace)
shouldRetainData = all([blockrotation.SameRotationType(blockInfo, b) for b in 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
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 shouldRetainData:
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 shouldRetainData:
data[:] = blockInfo.blockData
chunk.removeTileEntitiesInBox(box)
chunk.chunkChanged(needsLighting)
if len(blocksToReplace):
log.info(u"Replace: Skipped {0} chunks, replaced {1} blocks".format(skipped, replaced))