This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
pymclevel/javalevel.py
David Vierra 7aff12babf Rename java.py -> javalevel.py
java.py is not being picked up by setuptools for some reason
2013-11-23 20:45:37 -10:00

186 lines
5.7 KiB
Python

'''
Created on Jul 22, 2011
@author: Rio
'''
__all__ = ["MCJavaLevel"]
from cStringIO import StringIO
import gzip
from level import MCLevel
from logging import getLogger
from numpy import fromstring
import os
import re
log = getLogger(__name__)
class MCJavaLevel(MCLevel):
def setBlockDataAt(self, *args):
pass
def blockDataAt(self, *args):
return 0
@property
def Height(self):
return self.Blocks.shape[2]
@property
def Length(self):
return self.Blocks.shape[1]
@property
def Width(self):
return self.Blocks.shape[0]
def guessSize(self, data):
Width = 64
Length = 64
Height = 64
if data.shape[0] <= (32 * 32 * 64) * 2:
log.warn(u"Can't guess the size of a {0} byte level".format(data.shape[0]))
raise IOError("MCJavaLevel attempted for smaller than 64 blocks cubed")
if data.shape[0] > (64 * 64 * 64) * 2:
Width = 128
Length = 128
Height = 64
if data.shape[0] > (128 * 128 * 64) * 2:
Width = 256
Length = 256
Height = 64
if data.shape[0] > (256 * 256 * 64) * 2: # could also be 256*256*256
Width = 512
Length = 512
Height = 64
if data.shape[0] > 512 * 512 * 64 * 2: # just to load shadowmarch castle
Width = 512
Length = 512
Height = 256
return Width, Length, Height
@classmethod
def _isDataLevel(cls, data):
return (data[0] == 0x27 and
data[1] == 0x1B and
data[2] == 0xb7 and
data[3] == 0x88)
def __init__(self, filename, data):
self.filename = filename
if isinstance(data, basestring):
data = fromstring(data, dtype='uint8')
self.filedata = data
# try to take x,z,y from the filename
r = re.findall("\d+", os.path.basename(filename))
if r and len(r) >= 3:
(w, l, h) = map(int, r[-3:])
if w * l * h > data.shape[0]:
log.info("Not enough blocks for size " + str((w, l, h)))
w, l, h = self.guessSize(data)
else:
w, l, h = self.guessSize(data)
log.info(u"MCJavaLevel created for potential level of size " + str((w, l, h)))
blockCount = h * l * w
if blockCount > data.shape[0]:
raise ValueError("Level file does not contain enough blocks! (size {s}) Try putting the size into the filename, e.g. server_level_{w}_{l}_{h}.dat".format(w=w, l=l, h=h, s=data.shape))
blockOffset = data.shape[0] - blockCount
blocks = data[blockOffset:blockOffset + blockCount]
maxBlockType = 64 # maximum allowed in classic
while max(blocks[-4096:]) > maxBlockType:
# guess the block array by starting at the end of the file
# and sliding the blockCount-sized window back until it
# looks like every block has a valid blockNumber
blockOffset -= 1
blocks = data[blockOffset:blockOffset + blockCount]
if blockOffset <= -data.shape[0]:
raise IOError("Can't find a valid array of blocks <= #%d" % maxBlockType)
self.Blocks = blocks
self.blockOffset = blockOffset
blocks.shape = (w, l, h)
blocks.strides = (1, w, w * l)
def saveInPlace(self):
s = StringIO()
g = gzip.GzipFile(fileobj=s, mode='wb')
g.write(self.filedata.tostring())
g.flush()
g.close()
try:
os.rename(self.filename, self.filename + ".old")
except Exception, e:
pass
try:
with open(self.filename, 'wb') as f:
f.write(s.getvalue())
except Exception, e:
log.info(u"Error while saving java level in place: {0}".format(e))
try:
os.remove(self.filename)
except:
pass
os.rename(self.filename + ".old", self.filename)
try:
os.remove(self.filename + ".old")
except Exception, e:
pass
class MCSharpLevel(MCLevel):
""" int magic = convert(data.readShort())
logger.trace("Magic number: {}", magic)
if (magic != 1874)
throw new IOException("Only version 1 MCSharp levels supported (magic number was "+magic+")")
int width = convert(data.readShort())
int height = convert(data.readShort())
int depth = convert(data.readShort())
logger.trace("Width: {}", width)
logger.trace("Depth: {}", depth)
logger.trace("Height: {}", height)
int spawnX = convert(data.readShort())
int spawnY = convert(data.readShort())
int spawnZ = convert(data.readShort())
int spawnRotation = data.readUnsignedByte()
int spawnPitch = data.readUnsignedByte()
int visitRanks = data.readUnsignedByte()
int buildRanks = data.readUnsignedByte()
byte[][][] blocks = new byte[width][height][depth]
int i = 0
BlockManager manager = BlockManager.getBlockManager()
for(int z = 0;z<depth;z++) {
for(int y = 0;y<height;y++) {
byte[] row = new byte[height]
data.readFully(row)
for(int x = 0;x<width;x++) {
blocks[x][y][z] = translateBlock(row[x])
}
}
}
lvl.setBlocks(blocks, new byte[width][height][depth], width, height, depth)
lvl.setSpawnPosition(new Position(spawnX, spawnY, spawnZ))
lvl.setSpawnRotation(new Rotation(spawnRotation, spawnPitch))
lvl.setEnvironment(new Environment())
return lvl
}"""