Increase block limit to 4096. Change Schematic format slightly to store extended blockIDs.
InfdevOldWorld now allocates Blocks as a 16-bit array and reads Add into the top 8 bits if present. MCSchematic also allocates Blocks as uint16 and uses WorldEdit's extension to the schematic format to store the Add arrays. Conflicts: test/extended_id_test.py
This commit is contained in:
parent
3095eacaa3
commit
b824cfbfaf
@ -14,7 +14,7 @@ def convertBlocks(destLevel, sourceLevel, blocks, blockData):
|
|||||||
|
|
||||||
def sourceMaskFunc(blocksToCopy):
|
def sourceMaskFunc(blocksToCopy):
|
||||||
if blocksToCopy is not None:
|
if blocksToCopy is not None:
|
||||||
typemask = numpy.zeros(256, dtype='bool')
|
typemask = numpy.zeros(materials.id_limit, dtype='bool')
|
||||||
typemask[blocksToCopy] = 1
|
typemask[blocksToCopy] = 1
|
||||||
|
|
||||||
def maskedSourceMask(sourceBlocks):
|
def maskedSourceMask(sourceBlocks):
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
from pymclevel import materials
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
@ -8,7 +10,7 @@ import blockrotation
|
|||||||
from entity import TileEntity
|
from entity import TileEntity
|
||||||
|
|
||||||
def blockReplaceTable(blocksToReplace):
|
def blockReplaceTable(blocksToReplace):
|
||||||
blocktable = numpy.zeros((256, 16), dtype='bool')
|
blocktable = numpy.zeros((materials.id_limit, 16), dtype='bool')
|
||||||
for b in blocksToReplace:
|
for b in blocksToReplace:
|
||||||
if b.hasVariants:
|
if b.hasVariants:
|
||||||
blocktable[b.ID, b.blockData] = True
|
blocktable[b.ID, b.blockData] = True
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import materials
|
||||||
from materials import alphaMaterials
|
from materials import alphaMaterials
|
||||||
from numpy import arange, zeros
|
from numpy import arange, zeros
|
||||||
|
|
||||||
@ -474,9 +475,9 @@ rotationClasses.append(Vines)
|
|||||||
|
|
||||||
|
|
||||||
def masterRotationTable(attrname):
|
def masterRotationTable(attrname):
|
||||||
# compute a 256x16 table mapping each possible blocktype/data combination to
|
# compute a materials.id_limitx16 table mapping each possible blocktype/data combination to
|
||||||
# the resulting data when the block is rotated
|
# the resulting data when the block is rotated
|
||||||
table = zeros((256, 16), dtype='uint8')
|
table = zeros((materials.id_limit, 16), dtype='uint8')
|
||||||
table[:] = arange(16, dtype='uint8')
|
table[:] = arange(16, dtype='uint8')
|
||||||
for cls in rotationClasses:
|
for cls in rotationClasses:
|
||||||
if hasattr(cls, attrname):
|
if hasattr(cls, attrname):
|
||||||
|
@ -113,7 +113,7 @@ class AnvilChunkData(object):
|
|||||||
self.root_tag = root_tag
|
self.root_tag = root_tag
|
||||||
self.dirty = False
|
self.dirty = False
|
||||||
|
|
||||||
self.Blocks = zeros((16, 16, world.Height), 'uint8') # xxx uint16?
|
self.Blocks = zeros((16, 16, world.Height), 'uint16')
|
||||||
self.Data = zeros((16, 16, world.Height), 'uint8')
|
self.Data = zeros((16, 16, world.Height), 'uint8')
|
||||||
self.BlockLight = zeros((16, 16, world.Height), 'uint8')
|
self.BlockLight = zeros((16, 16, world.Height), 'uint8')
|
||||||
self.SkyLight = zeros((16, 16, world.Height), 'uint8')
|
self.SkyLight = zeros((16, 16, world.Height), 'uint8')
|
||||||
@ -152,6 +152,7 @@ class AnvilChunkData(object):
|
|||||||
|
|
||||||
for sec in self.root_tag["Level"].pop("Sections", []):
|
for sec in self.root_tag["Level"].pop("Sections", []):
|
||||||
y = sec["Y"].value * 16
|
y = sec["Y"].value * 16
|
||||||
|
|
||||||
for name in "Blocks", "Data", "SkyLight", "BlockLight":
|
for name in "Blocks", "Data", "SkyLight", "BlockLight":
|
||||||
arr = getattr(self, name)
|
arr = getattr(self, name)
|
||||||
secarray = sec[name].value
|
secarray = sec[name].value
|
||||||
@ -163,6 +164,11 @@ class AnvilChunkData(object):
|
|||||||
|
|
||||||
arr[..., y:y + 16] = secarray.swapaxes(0, 2)
|
arr[..., y:y + 16] = secarray.swapaxes(0, 2)
|
||||||
|
|
||||||
|
tag = sec.get("Add")
|
||||||
|
if tag is not None:
|
||||||
|
tag.value.shape = (16, 16, 8)
|
||||||
|
add = unpackNibbleArray(tag.value)
|
||||||
|
self.Blocks[...,y:y + 16] |= (array(add, 'uint16') << 8).swapaxes(0, 2)
|
||||||
|
|
||||||
def savedTagData(self):
|
def savedTagData(self):
|
||||||
""" does not recalculate any data or light """
|
""" does not recalculate any data or light """
|
||||||
@ -188,7 +194,11 @@ class AnvilChunkData(object):
|
|||||||
BlockLight = packNibbleArray(BlockLight)
|
BlockLight = packNibbleArray(BlockLight)
|
||||||
SkyLight = packNibbleArray(SkyLight)
|
SkyLight = packNibbleArray(SkyLight)
|
||||||
|
|
||||||
section['Blocks'] = nbt.TAG_Byte_Array(array(Blocks))
|
add = Blocks >> 8
|
||||||
|
if add.any():
|
||||||
|
section["Add"] = nbt.TAG_Byte_Array(packNibbleArray(add).astype('uint8'))
|
||||||
|
|
||||||
|
section['Blocks'] = nbt.TAG_Byte_Array(array(Blocks, 'uint8'))
|
||||||
section['Data'] = nbt.TAG_Byte_Array(array(Data))
|
section['Data'] = nbt.TAG_Byte_Array(array(Data))
|
||||||
section['BlockLight'] = nbt.TAG_Byte_Array(array(BlockLight))
|
section['BlockLight'] = nbt.TAG_Byte_Array(array(BlockLight))
|
||||||
section['SkyLight'] = nbt.TAG_Byte_Array(array(SkyLight))
|
section['SkyLight'] = nbt.TAG_Byte_Array(array(SkyLight))
|
||||||
|
28
materials.py
28
materials.py
@ -53,7 +53,7 @@ class Block(object):
|
|||||||
r = r[self.blockData]
|
r = r[self.blockData]
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
id_limit = 4096
|
||||||
class MCMaterials(object):
|
class MCMaterials(object):
|
||||||
defaultColor = (0xc9, 0x77, 0xf0, 0xff)
|
defaultColor = (0xc9, 0x77, 0xf0, 0xff)
|
||||||
defaultBrightness = 0
|
defaultBrightness = 0
|
||||||
@ -67,21 +67,22 @@ class MCMaterials(object):
|
|||||||
|
|
||||||
self.defaultName = defaultName
|
self.defaultName = defaultName
|
||||||
|
|
||||||
self.blockTextures = zeros((256, 16, 6, 2), dtype='uint8')
|
|
||||||
self.blockTextures[:] = self.defaultTexture
|
|
||||||
self.names = [[defaultName] * 16 for i in range(256)]
|
|
||||||
self.aka = [[""] * 16 for i in range(256)]
|
|
||||||
|
|
||||||
self.type = [["NORMAL"] * 16] * 256
|
self.blockTextures = zeros((id_limit, 16, 6, 2), dtype='uint8')
|
||||||
|
self.blockTextures[:] = self.defaultTexture
|
||||||
|
self.names = [[defaultName] * 16 for i in range(id_limit)]
|
||||||
|
self.aka = [[""] * 16 for i in range(id_limit)]
|
||||||
|
|
||||||
|
self.type = [["NORMAL"] * 16] * id_limit
|
||||||
self.blocksByType = defaultdict(list)
|
self.blocksByType = defaultdict(list)
|
||||||
self.allBlocks = []
|
self.allBlocks = []
|
||||||
self.blocksByID = {}
|
self.blocksByID = {}
|
||||||
|
|
||||||
self.lightEmission = zeros(256, dtype='uint8')
|
self.lightEmission = zeros(id_limit, dtype='uint8')
|
||||||
self.lightEmission[:] = self.defaultBrightness
|
self.lightEmission[:] = self.defaultBrightness
|
||||||
self.lightAbsorption = zeros(256, dtype='uint8')
|
self.lightAbsorption = zeros(id_limit, dtype='uint8')
|
||||||
self.lightAbsorption[:] = self.defaultOpacity
|
self.lightAbsorption[:] = self.defaultOpacity
|
||||||
self.flatColors = zeros((256, 16, 4), dtype='uint8')
|
self.flatColors = zeros((id_limit, 16, 4), dtype='uint8')
|
||||||
self.flatColors[:] = self.defaultColor
|
self.flatColors[:] = self.defaultColor
|
||||||
|
|
||||||
self.idStr = {}
|
self.idStr = {}
|
||||||
@ -153,7 +154,8 @@ class MCMaterials(object):
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
|
||||||
f = pkg_resources.resource_stream(__name__, filename)
|
f = pkg_resources.resource_stream(__name__, filename)
|
||||||
except (ImportError, IOError):
|
except (ImportError, IOError), e:
|
||||||
|
print "Cannot get resource_stream for ", filename, e
|
||||||
root = os.environ.get("PYMCLEVEL_YAML_ROOT", "pymclevel") # fall back to cwd as last resort
|
root = os.environ.get("PYMCLEVEL_YAML_ROOT", "pymclevel") # fall back to cwd as last resort
|
||||||
path = join(root, filename)
|
path = join(root, filename)
|
||||||
|
|
||||||
@ -752,12 +754,12 @@ pocketMaterials.NetherReactorUsed = pocketMaterials[247, 1]
|
|||||||
# b.ID, b.blockData)
|
# b.ID, b.blockData)
|
||||||
# for b in sorted(mats.pocketMaterials.allBlocks)])
|
# for b in sorted(mats.pocketMaterials.allBlocks)])
|
||||||
|
|
||||||
_indices = rollaxis(indices((256, 16)), 0, 3)
|
_indices = rollaxis(indices((id_limit, 16)), 0, 3)
|
||||||
|
|
||||||
|
|
||||||
def _filterTable(filters, unavailable, default=(0, 0)):
|
def _filterTable(filters, unavailable, default=(0, 0)):
|
||||||
# a filter table is a 256x16 table of (ID, data) pairs.
|
# a filter table is a id_limit table of (ID, data) pairs.
|
||||||
table = zeros((256, 16, 2), dtype='uint8')
|
table = zeros((id_limit, 16, 2), dtype='uint8')
|
||||||
table[:] = _indices
|
table[:] = _indices
|
||||||
for u in unavailable:
|
for u in unavailable:
|
||||||
try:
|
try:
|
||||||
|
5
mce.py
5
mce.py
@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import mclevelbase
|
import mclevelbase
|
||||||
import mclevel
|
import mclevel
|
||||||
|
import materials
|
||||||
import infiniteworld
|
import infiniteworld
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
@ -269,7 +270,7 @@ class mce(object):
|
|||||||
return blockInfo
|
return blockInfo
|
||||||
|
|
||||||
def readBlocksToCopy(self, command):
|
def readBlocksToCopy(self, command):
|
||||||
blocksToCopy = range(256)
|
blocksToCopy = range(materials.id_limit)
|
||||||
while len(command):
|
while len(command):
|
||||||
word = command.pop()
|
word = command.pop()
|
||||||
if word == "noair":
|
if word == "noair":
|
||||||
@ -460,7 +461,7 @@ class mce(object):
|
|||||||
if i % 100 == 0:
|
if i % 100 == 0:
|
||||||
logging.info("Chunk {0}...".format(i))
|
logging.info("Chunk {0}...".format(i))
|
||||||
|
|
||||||
for blockID in range(256):
|
for blockID in range(materials.id_limit):
|
||||||
block = self.level.materials.blockWithID(blockID, 0)
|
block = self.level.materials.blockWithID(blockID, 0)
|
||||||
if block.hasVariants:
|
if block.hasVariants:
|
||||||
for data in range(16):
|
for data in range(16):
|
||||||
|
117
schematic.py
117
schematic.py
@ -17,7 +17,7 @@ from level import MCLevel, EntityLevel
|
|||||||
from materials import alphaMaterials, MCMaterials, namedMaterials
|
from materials import alphaMaterials, MCMaterials, namedMaterials
|
||||||
from mclevelbase import exhaust
|
from mclevelbase import exhaust
|
||||||
import nbt
|
import nbt
|
||||||
from numpy import array, swapaxes, uint8, zeros
|
from numpy import array, swapaxes, uint8, zeros, resize
|
||||||
|
|
||||||
log = getLogger(__name__)
|
log = getLogger(__name__)
|
||||||
|
|
||||||
@ -46,9 +46,6 @@ class MCSchematic (EntityLevel):
|
|||||||
I'm not sure what happens when I try to re-save a rotated schematic.
|
I'm not sure what happens when I try to re-save a rotated schematic.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# if(shape != None):
|
|
||||||
# self.setShape(shape)
|
|
||||||
|
|
||||||
if filename:
|
if filename:
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
if None is root_tag and os.path.exists(filename):
|
if None is root_tag and os.path.exists(filename):
|
||||||
@ -68,7 +65,39 @@ class MCSchematic (EntityLevel):
|
|||||||
self.materials = namedMaterials[self.Materials]
|
self.materials = namedMaterials[self.Materials]
|
||||||
else:
|
else:
|
||||||
root_tag["Materials"] = nbt.TAG_String(self.materials.name)
|
root_tag["Materials"] = nbt.TAG_String(self.materials.name)
|
||||||
self.shapeChunkData()
|
|
||||||
|
w = self.root_tag["Width"].value
|
||||||
|
l = self.root_tag["Length"].value
|
||||||
|
h = self.root_tag["Height"].value
|
||||||
|
|
||||||
|
self._Blocks = self.root_tag["Blocks"].value.astype('uint16').reshape(h, l, w)
|
||||||
|
del self.root_tag["Blocks"]
|
||||||
|
if "AddBlocks" in self.root_tag:
|
||||||
|
# Use WorldEdit's "AddBlocks" array to load and store the 4 high bits of a block ID.
|
||||||
|
# Unlike Minecraft's NibbleArrays, this array stores the first block's bits in the
|
||||||
|
# 4 high bits of the first byte.
|
||||||
|
|
||||||
|
size = (h * l * w)
|
||||||
|
|
||||||
|
# If odd, add one to the size to make sure the adjacent slices line up.
|
||||||
|
add = zeros(size + (size & 1), 'uint16')
|
||||||
|
|
||||||
|
# Fill the even bytes with data
|
||||||
|
add[::2] = self.root_tag["AddBlocks"].value
|
||||||
|
|
||||||
|
# Copy the low 4 bits to the odd bytes
|
||||||
|
add[1::2] = add[::2] & 0xf
|
||||||
|
|
||||||
|
# Shift the even bytes down
|
||||||
|
add[::2] >>= 4
|
||||||
|
|
||||||
|
# Shift every byte up before merging it with Blocks
|
||||||
|
add <<= 8
|
||||||
|
self._Blocks |= add[:size].reshape(h, l, w)
|
||||||
|
del self.root_tag["AddBlocks"]
|
||||||
|
|
||||||
|
self.root_tag["Data"].value = self.root_tag["Data"].value.reshape(h, l, w)
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
assert shape is not None
|
assert shape is not None
|
||||||
@ -81,12 +110,11 @@ class MCSchematic (EntityLevel):
|
|||||||
root_tag["TileEntities"] = nbt.TAG_List()
|
root_tag["TileEntities"] = nbt.TAG_List()
|
||||||
root_tag["Materials"] = nbt.TAG_String(self.materials.name)
|
root_tag["Materials"] = nbt.TAG_String(self.materials.name)
|
||||||
|
|
||||||
root_tag["Blocks"] = nbt.TAG_Byte_Array(zeros((shape[1], shape[2], shape[0]), uint8))
|
self._Blocks = zeros((shape[1], shape[2], shape[0]), 'uint16')
|
||||||
root_tag["Data"] = nbt.TAG_Byte_Array(zeros((shape[1], shape[2], shape[0]), uint8))
|
root_tag["Data"] = nbt.TAG_Byte_Array(zeros((shape[1], shape[2], shape[0]), uint8))
|
||||||
|
|
||||||
self.root_tag = root_tag
|
self.root_tag = root_tag
|
||||||
|
|
||||||
self.packUnpack()
|
|
||||||
self.root_tag["Data"].value &= 0xF # discard high bits
|
self.root_tag["Data"].value &= 0xF # discard high bits
|
||||||
|
|
||||||
|
|
||||||
@ -99,11 +127,33 @@ class MCSchematic (EntityLevel):
|
|||||||
|
|
||||||
self.Materials = self.materials.name
|
self.Materials = self.materials.name
|
||||||
|
|
||||||
self.packUnpack()
|
self.root_tag["Blocks"] = nbt.TAG_Byte_Array(self._Blocks.astype('uint8'))
|
||||||
|
|
||||||
|
add = self._Blocks >> 8
|
||||||
|
if add.any():
|
||||||
|
# WorldEdit AddBlocks compatibility.
|
||||||
|
# The first 4-bit value is stored in the high bits of the first byte.
|
||||||
|
|
||||||
|
# Increase odd size by one to align slices.
|
||||||
|
packed_add = zeros(add.size + (add.size & 1), 'uint8')
|
||||||
|
packed_add[:-(add.size & 1)] = add.ravel()
|
||||||
|
|
||||||
|
# Shift even bytes to the left
|
||||||
|
packed_add[::2] <<= 4
|
||||||
|
|
||||||
|
# Merge odd bytes into even bytes
|
||||||
|
packed_add[::2] |= packed_add[1::2]
|
||||||
|
|
||||||
|
# Save only the even bytes, now that they contain the odd bytes in their lower bits.
|
||||||
|
packed_add = packed_add[0::2]
|
||||||
|
self.root_tag["AddBlocks"] = nbt.TAG_Byte_Array(packed_add)
|
||||||
|
|
||||||
with open(filename, 'wb') as chunkfh:
|
with open(filename, 'wb') as chunkfh:
|
||||||
self.root_tag.save(chunkfh)
|
self.root_tag.save(chunkfh)
|
||||||
|
|
||||||
self.packUnpack()
|
del self.root_tag["Blocks"]
|
||||||
|
self.root_tag.pop("AddBlocks", None)
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return u"MCSchematic(shape={0}, materials={2}, filename=\"{1}\")".format(self.size, self.filename or u"", self.Materials)
|
return u"MCSchematic(shape={0}, materials={2}, filename=\"{1}\")".format(self.size, self.filename or u"", self.Materials)
|
||||||
@ -124,11 +174,11 @@ class MCSchematic (EntityLevel):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def Blocks(self):
|
def Blocks(self):
|
||||||
return self.root_tag["Blocks"].value
|
return swapaxes(self._Blocks, 0, 2)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def Data(self):
|
def Data(self):
|
||||||
return self.root_tag["Data"].value
|
return swapaxes(self.root_tag["Data"].value, 0, 2)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def Entities(self):
|
def Entities(self):
|
||||||
@ -152,19 +202,6 @@ class MCSchematic (EntityLevel):
|
|||||||
def _isTagLevel(cls, root_tag):
|
def _isTagLevel(cls, root_tag):
|
||||||
return "Schematic" == root_tag.name
|
return "Schematic" == root_tag.name
|
||||||
|
|
||||||
def shapeChunkData(self):
|
|
||||||
w = self.root_tag["Width"].value
|
|
||||||
l = self.root_tag["Length"].value
|
|
||||||
h = self.root_tag["Height"].value
|
|
||||||
|
|
||||||
self.root_tag["Blocks"].value.shape = (h, l, w)
|
|
||||||
self.root_tag["Data"].value.shape = (h, l, w)
|
|
||||||
|
|
||||||
def packUnpack(self):
|
|
||||||
self.root_tag["Blocks"].value = swapaxes(self.root_tag["Blocks"].value, 0, 2) # yzx to xzy
|
|
||||||
self.root_tag["Data"].value = swapaxes(self.root_tag["Data"].value, 0, 2) # yzx to xzy
|
|
||||||
|
|
||||||
|
|
||||||
def _update_shape(self):
|
def _update_shape(self):
|
||||||
root_tag = self.root_tag
|
root_tag = self.root_tag
|
||||||
shape = self.Blocks.shape
|
shape = self.Blocks.shape
|
||||||
@ -174,8 +211,8 @@ class MCSchematic (EntityLevel):
|
|||||||
|
|
||||||
def rotateLeft(self):
|
def rotateLeft(self):
|
||||||
|
|
||||||
self.root_tag["Blocks"].value = swapaxes(self.Blocks, 1, 0)[:, ::-1, :] # x=z; z=-x
|
self._Blocks = swapaxes(self._Blocks, 1, 0)[:, ::-1, :] # x=z; z=-x
|
||||||
self.root_tag["Data"].value = swapaxes(self.Data, 1, 0)[:, ::-1, :] # x=z; z=-x
|
self.root_tag["Data"].value = swapaxes(self.root_tag["Data"].value, 1, 0)[:, ::-1, :] # x=z; z=-x
|
||||||
self._update_shape()
|
self._update_shape()
|
||||||
|
|
||||||
blockrotation.RotateLeft(self.Blocks, self.Data)
|
blockrotation.RotateLeft(self.Blocks, self.Data)
|
||||||
@ -213,20 +250,20 @@ class MCSchematic (EntityLevel):
|
|||||||
|
|
||||||
def roll(self):
|
def roll(self):
|
||||||
" xxx rotate stuff "
|
" xxx rotate stuff "
|
||||||
self.root_tag["Blocks"].value = swapaxes(self.Blocks, 2, 0)[:, :, ::-1] # x=z; z=-x
|
self._Blocks = swapaxes(self.Blocks, 2, 0)[:, :, ::-1] # x=z; z=-x
|
||||||
self.root_tag["Data"].value = swapaxes(self.Data, 2, 0)[:, :, ::-1]
|
self.root_tag["Data"].value = swapaxes(self.root_tag["Data"].value, 2, 0)[:, :, ::-1]
|
||||||
self._update_shape()
|
self._update_shape()
|
||||||
|
|
||||||
def flipVertical(self):
|
def flipVertical(self):
|
||||||
" xxx delete stuff "
|
" xxx delete stuff "
|
||||||
blockrotation.FlipVertical(self.Blocks, self.Data)
|
blockrotation.FlipVertical(self.Blocks, self.Data)
|
||||||
self.root_tag["Blocks"].value = self.Blocks[:, :, ::-1] # y=-y
|
self._Blocks = self.Blocks[:, :, ::-1] # y=-y
|
||||||
self.root_tag["Data"].value = self.Data[:, :, ::-1]
|
self.root_tag["Data"].value = self.root_tag["Data"].value[:, :, ::-1]
|
||||||
|
|
||||||
def flipNorthSouth(self):
|
def flipNorthSouth(self):
|
||||||
blockrotation.FlipNorthSouth(self.Blocks, self.Data)
|
blockrotation.FlipNorthSouth(self.Blocks, self.Data)
|
||||||
self.root_tag["Blocks"].value = self.Blocks[::-1, :, :] # x=-x
|
self._Blocks = self.Blocks[::-1, :, :] # x=-x
|
||||||
self.root_tag["Data"].value = self.Data[::-1, :, :]
|
self.root_tag["Data"].value = self.root_tag["Data"].value[::-1, :, :]
|
||||||
|
|
||||||
northSouthPaintingMap = [0, 3, 2, 1]
|
northSouthPaintingMap = [0, 3, 2, 1]
|
||||||
|
|
||||||
@ -249,10 +286,9 @@ class MCSchematic (EntityLevel):
|
|||||||
tileEntity["x"].value = self.Width - tileEntity["x"].value - 1
|
tileEntity["x"].value = self.Width - tileEntity["x"].value - 1
|
||||||
|
|
||||||
def flipEastWest(self):
|
def flipEastWest(self):
|
||||||
" xxx flip entities "
|
|
||||||
blockrotation.FlipEastWest(self.Blocks, self.Data)
|
blockrotation.FlipEastWest(self.Blocks, self.Data)
|
||||||
self.root_tag["Blocks"].value = self.Blocks[:, ::-1, :] # z=-z
|
self._Blocks = self._Blocks[:, ::-1, :] # z=-z
|
||||||
self.root_tag["Data"].value = self.Data[:, ::-1, :]
|
self.root_tag["Data"].value = self.root_tag["Data"].value[:, ::-1, :]
|
||||||
|
|
||||||
eastWestPaintingMap = [2, 1, 0, 3]
|
eastWestPaintingMap = [2, 1, 0, 3]
|
||||||
|
|
||||||
@ -271,17 +307,6 @@ class MCSchematic (EntityLevel):
|
|||||||
for tileEntity in self.TileEntities:
|
for tileEntity in self.TileEntities:
|
||||||
tileEntity["z"].value = self.Length - tileEntity["z"].value - 1
|
tileEntity["z"].value = self.Length - tileEntity["z"].value - 1
|
||||||
|
|
||||||
def setShape(self, shape):
|
|
||||||
"""shape is a tuple of (width, height, length). sets the
|
|
||||||
schematic's properties and clears the block and data arrays"""
|
|
||||||
|
|
||||||
x, y, z = shape
|
|
||||||
shape = (x, z, y)
|
|
||||||
|
|
||||||
self.root_tag["Blocks"].value = zeros(dtype='uint8', shape=shape)
|
|
||||||
self.root_tag["Data"].value = zeros(dtype='uint8', shape=shape)
|
|
||||||
self.shapeChunkData()
|
|
||||||
|
|
||||||
|
|
||||||
def setBlockDataAt(self, x, y, z, newdata):
|
def setBlockDataAt(self, x, y, z, newdata):
|
||||||
if x < 0 or y < 0 or z < 0:
|
if x < 0 or y < 0 or z < 0:
|
||||||
|
@ -1,8 +1,27 @@
|
|||||||
from pymclevel.schematic import MCSchematic
|
from pymclevel.schematic import MCSchematic
|
||||||
|
from pymclevel import MCInfdevOldLevel
|
||||||
|
from templevel import TempLevel
|
||||||
|
|
||||||
__author__ = 'Rio'
|
__author__ = 'Rio'
|
||||||
|
|
||||||
def test_schematic_extended_ids():
|
def test_schematic_extended_ids():
|
||||||
s = MCSchematic(shape=(3, 2, 2))
|
s = MCSchematic(shape=(1, 1, 5))
|
||||||
s.Blocks[0,0,0] = 2048
|
s.Blocks[0,0,0] = 2048
|
||||||
|
temp = TempLevel("schematic", createFunc=s.saveToFile)
|
||||||
|
s = temp.level
|
||||||
assert s.Blocks[0,0,0] == 2048
|
assert s.Blocks[0,0,0] == 2048
|
||||||
|
|
||||||
|
|
||||||
|
def test_alpha_extended_ids():
|
||||||
|
temp = TempLevel("alpha", createFunc=lambda f: MCInfdevOldLevel(f, create=True))
|
||||||
|
level = temp.level
|
||||||
|
level.createChunk(0, 0)
|
||||||
|
|
||||||
|
level.setBlockAt(0,2,5, 2048)
|
||||||
|
level.saveInPlace()
|
||||||
|
level.close()
|
||||||
|
|
||||||
|
level = MCInfdevOldLevel(filename=level.filename)
|
||||||
|
|
||||||
|
assert level.blockAt(0,2,5) == 2048
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user