Refactor: Reorder members and methods of MCInfdevOldLevel to place related methods closer together.

Change version to use TagProperty. Remove some backward compatibility from MCServerChunkGenerator
Add # --- Subheaders --- to mark related method groups
Fix whitespace according to pep8
This commit is contained in:
David Vierra 2012-10-26 17:24:21 -10:00
parent f4b40912a3
commit 38cd052bb0
2 changed files with 220 additions and 228 deletions

View File

@ -10,6 +10,7 @@ import itertools
from logging import getLogger from logging import getLogger
from math import floor from math import floor
import os import os
import re
import random import random
import time import time
import traceback import traceback
@ -39,6 +40,7 @@ DIM_END = 1
__all__ = ["ZeroChunk", "AnvilChunk", "ChunkedLevelMixin", "MCInfdevOldLevel", "MCAlphaDimension", "ZipSchematic"] __all__ = ["ZeroChunk", "AnvilChunk", "ChunkedLevelMixin", "MCInfdevOldLevel", "MCAlphaDimension", "ZipSchematic"]
_zeros = {} _zeros = {}
def ZeroChunk(height=512): def ZeroChunk(height=512):
z = _zeros.get(height) z = _zeros.get(height)
if z is None: if z is None:
@ -46,7 +48,6 @@ def ZeroChunk(height=512):
return z return z
class _ZeroChunk(ChunkBase): class _ZeroChunk(ChunkBase):
" a placebo for neighboring-chunk routines " " a placebo for neighboring-chunk routines "
@ -86,7 +87,6 @@ class AnvilChunk(LightedChunk):
for better handling. for better handling.
""" """
@property @property
def filename(self): def filename(self):
cx, cz = self.chunkPosition cx, cz = self.chunkPosition
rx, rz = cx >> 5, cz >> 5 rx, rz = cx >> 5, cz >> 5
@ -99,7 +99,6 @@ class AnvilChunk(LightedChunk):
index=4 * ((cx & 0x1f) + ((cz & 0x1f) * 32)) index=4 * ((cx & 0x1f) + ((cz & 0x1f) * 32))
) )
root_tag = None root_tag = None
def __init__(self, world, chunkPosition, create=False): def __init__(self, world, chunkPosition, create=False):
@ -114,13 +113,11 @@ class AnvilChunk(LightedChunk):
self.SkyLight = zeros((16, 16, self.Height), 'uint8') self.SkyLight = zeros((16, 16, self.Height), 'uint8')
self.SkyLight[:] = 15 self.SkyLight[:] = 15
if create: if create:
self._create() self._create()
else: else:
self._load() self._load()
def _create(self): def _create(self):
(cx, cz) = self.chunkPosition (cx, cz) = self.chunkPosition
chunkTag = nbt.TAG_Compound() chunkTag = nbt.TAG_Compound()
@ -162,7 +159,6 @@ class AnvilChunk(LightedChunk):
arr[..., y:y + 16] = secarray.swapaxes(0, 2) arr[..., y:y + 16] = secarray.swapaxes(0, 2)
def save(self): def save(self):
""" does not recalculate any data or light """ """ does not recalculate any data or light """
@ -213,7 +209,6 @@ class AnvilChunk(LightedChunk):
self.Blocks[:, :, 1:][badsnow] = self.materials.Air.ID self.Blocks[:, :, 1:][badsnow] = self.materials.Air.ID
def __str__(self): def __str__(self):
return u"AnvilChunk, coords:{0}, world: {1}, D:{2}, L:{3}".format(self.chunkPosition, self.world.displayName, self.dirty, self.needsLighting) return u"AnvilChunk, coords:{0}, world: {1}, D:{2}, L:{3}".format(self.chunkPosition, self.world.displayName, self.dirty, self.needsLighting)
@ -234,7 +229,6 @@ class AnvilChunk(LightedChunk):
else: else:
computeChunkHeightMap(self.materials, self.Blocks, self.HeightMap) computeChunkHeightMap(self.materials, self.Blocks, self.HeightMap)
def addEntity(self, entityTag): def addEntity(self, entityTag):
def doubleize(name): def doubleize(name):
@ -256,7 +250,6 @@ class AnvilChunk(LightedChunk):
self.dirty = True self.dirty = True
return super(AnvilChunk, self).removeTileEntitiesInBox(box) return super(AnvilChunk, self).removeTileEntitiesInBox(box)
@property @property
def HeightMap(self): def HeightMap(self):
return self.root_tag["Level"]["HeightMap"].value.reshape((16, 16)) return self.root_tag["Level"]["HeightMap"].value.reshape((16, 16))
@ -315,6 +308,7 @@ def deflate(data):
# return zdata # return zdata
return zlib.compress(data) return zlib.compress(data)
def inflate(data): def inflate(data):
return zlib.decompress(data) return zlib.decompress(data)
@ -532,7 +526,6 @@ class ChunkedLevelMixin(MCLevel):
if i: if i:
info("Finished {2} chunks in {0} ({1} per chunk)".format(d, d / i, i)) info("Finished {2} chunks in {0} ({1} per chunk)".format(d, d / i, i))
def copyBlocksFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy, create=False): def copyBlocksFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy, create=False):
""" copy blocks between two infinite levels by looping through the """ copy blocks between two infinite levels by looping through the
destination's chunks. make a sub-box of the source level for each chunk destination's chunks. make a sub-box of the source level for each chunk
@ -846,7 +839,6 @@ class ChunkedLevelMixin(MCLevel):
progressInfo = u"{0} Pass {1}: {2} chunks".format(light, i, len(newDirtyChunks)) progressInfo = u"{0} Pass {1}: {2} chunks".format(light, i, len(newDirtyChunks))
info(progressInfo) info(progressInfo)
# propagate light! # propagate light!
# for each of the six cardinal directions, figure a new light value for # for each of the six cardinal directions, figure a new light value for
# adjoining blocks by reducing this chunk's light by light absorption and fall off. # adjoining blocks by reducing this chunk's light by light absorption and fall off.
@ -1027,6 +1019,7 @@ class ChunkedLevelMixin(MCLevel):
for ch in startingDirtyChunks: for ch in startingDirtyChunks:
ch.needsLighting = False ch.needsLighting = False
def TagProperty(tagName, tagType, defaultValueFunc=lambda self: None): def TagProperty(tagName, tagType, defaultValueFunc=lambda self: None):
def getter(self): def getter(self):
if tagName not in self.root_tag["Data"]: if tagName not in self.root_tag["Data"]:
@ -1038,152 +1031,8 @@ def TagProperty(tagName, tagType, defaultValueFunc=lambda self: None):
return property(getter, setter) return property(getter, setter)
class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel): class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
materials = alphaMaterials
isInfinite = True
parentWorld = None
dimNo = 0
Height = 256
@property
def displayName(self):
# shortname = os.path.basename(self.filename)
# if shortname == "level.dat":
shortname = os.path.basename(os.path.dirname(self.filename))
return shortname
@classmethod
def _isLevel(cls, filename):
join = os.path.join
exists = os.path.exists
if exists(join(filename, "chunks.dat")):
return False # exclude Pocket Edition folders
if not os.path.isdir(filename):
f = os.path.basename(filename)
if f not in ("level.dat", "level.dat_old"):
return False
filename = os.path.dirname(filename)
files = os.listdir(filename)
if "level.dat" in files or "level.dat_old" in files:
return True
return False
def getWorldBounds(self):
if self.chunkCount == 0:
return BoundingBox((0, 0, 0), (0, 0, 0))
allChunks = array(list(self.allChunks))
mincx = (allChunks[:, 0]).min()
maxcx = (allChunks[:, 0]).max()
mincz = (allChunks[:, 1]).min()
maxcz = (allChunks[:, 1]).max()
origin = (mincx << 4, 0, mincz << 4)
size = ((maxcx - mincx + 1) << 4, self.Height, (maxcz - mincz + 1) << 4)
return BoundingBox(origin, size)
def __str__(self):
return "MCInfdevOldLevel(\"" + os.path.split(self.worldDir)[1] + "\")"
SizeOnDisk = TagProperty('SizeOnDisk', nbt.TAG_Long)
RandomSeed = TagProperty('RandomSeed', nbt.TAG_Long)
Time = TagProperty('Time', nbt.TAG_Long) # Age of the world in ticks. 20 ticks per second; 24000 ticks per day.
LastPlayed = TagProperty('LastPlayed', nbt.TAG_Long, lambda self: long(time.time() * 1000))
LevelName = TagProperty('LevelName', nbt.TAG_String, lambda self: self.displayName)
MapFeatures = TagProperty('MapFeatures', nbt.TAG_Byte, lambda self: 1)
GameType = TagProperty('GameType', nbt.TAG_Int, lambda self: 0) # 0 for survival, 1 for creative
GAMETYPE_SURVIVAL = 0
GAMETYPE_CREATIVE = 1
VERSION_MCR = 19132
VERSION_ANVIL = 19133
_bounds = None
@property
def bounds(self):
if self._bounds is None:
self._bounds = self.getWorldBounds()
return self._bounds
@property
def size(self):
return self.bounds.size
def close(self):
for rf in (self.regionFiles or {}).values():
rf.close()
self.regionFiles = {}
self._allChunks = None
self._loadedChunks = {}
def _create(self, filename, random_seed, last_played):
# create a new level
root_tag = nbt.TAG_Compound()
root_tag["Data"] = nbt.TAG_Compound()
root_tag["Data"]["SpawnX"] = nbt.TAG_Int(0)
root_tag["Data"]["SpawnY"] = nbt.TAG_Int(2)
root_tag["Data"]["SpawnZ"] = nbt.TAG_Int(0)
if last_played is None:
last_played = long(time.time() * 1000)
if random_seed is None:
random_seed = long(random.random() * 0xffffffffffffffffL) - 0x8000000000000000L
self.root_tag = root_tag
root_tag["Data"]['version'] = nbt.TAG_Int(self.VERSION_ANVIL)
self.LastPlayed = long(last_played)
self.RandomSeed = long(random_seed)
self.SizeOnDisk = 0
self.Time = 1
self.LevelName = os.path.basename(self.worldDir)
### if singleplayer:
self.createPlayer("Player")
if not os.path.exists(self.worldDir):
os.mkdir(self.worldDir)
def createPlayer(self, playerName):
if playerName == "Player":
playerTag = self.root_tag["Data"].setdefault(playerName, nbt.TAG_Compound())
else:
playerTag = nbt.TAG_Compound()
playerTag['Air'] = nbt.TAG_Short(300)
playerTag['AttackTime'] = nbt.TAG_Short(0)
playerTag['DeathTime'] = nbt.TAG_Short(0)
playerTag['Fire'] = nbt.TAG_Short(-20)
playerTag['Health'] = nbt.TAG_Short(20)
playerTag['HurtTime'] = nbt.TAG_Short(0)
playerTag['Score'] = nbt.TAG_Int(0)
playerTag['FallDistance'] = nbt.TAG_Float(0)
playerTag['OnGround'] = nbt.TAG_Byte(0)
playerTag["Inventory"] = nbt.TAG_List()
playerTag['Motion'] = nbt.TAG_List([nbt.TAG_Double(0) for i in range(3)])
playerTag['Pos'] = nbt.TAG_List([nbt.TAG_Double([0.5, 2.8, 0.5][i]) for i in range(3)])
playerTag['Rotation'] = nbt.TAG_List([nbt.TAG_Float(0), nbt.TAG_Float(0)])
if playerName != "Player":
playerTag.save(self.getPlayerPath(playerName))
def __init__(self, filename=None, create=False, random_seed=None, last_played=None): def __init__(self, filename=None, create=False, random_seed=None, last_played=None):
""" """
@ -1250,7 +1099,38 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
self.players.append("Player") self.players.append("Player")
self.preloadDimensions() self.preloadDimensions()
# self.preloadChunkPositions()
# --- Load, save, create ---
def _create(self, filename, random_seed, last_played):
# create a new level
root_tag = nbt.TAG_Compound()
root_tag["Data"] = nbt.TAG_Compound()
root_tag["Data"]["SpawnX"] = nbt.TAG_Int(0)
root_tag["Data"]["SpawnY"] = nbt.TAG_Int(2)
root_tag["Data"]["SpawnZ"] = nbt.TAG_Int(0)
if last_played is None:
last_played = long(time.time() * 1000)
if random_seed is None:
random_seed = long(random.random() * 0xffffffffffffffffL) - 0x8000000000000000L
self.root_tag = root_tag
root_tag["Data"]['version'] = nbt.TAG_Int(self.VERSION_ANVIL)
self.LastPlayed = long(last_played)
self.RandomSeed = long(random_seed)
self.SizeOnDisk = 0
self.Time = 1
self.LevelName = os.path.basename(self.worldDir)
### if singleplayer:
self.createPlayer("Player")
if not os.path.exists(self.worldDir):
os.mkdir(self.worldDir)
def loadLevelDat(self, create=False, random_seed=None, last_played=None): def loadLevelDat(self, create=False, random_seed=None, last_played=None):
@ -1273,6 +1153,128 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
info("Error loading level.dat_old. Initializing with defaults.") info("Error loading level.dat_old. Initializing with defaults.")
self._create(self.filename, random_seed, last_played) self._create(self.filename, random_seed, last_played)
def saveInPlace(self):
for level in self.dimensions.itervalues():
level.saveInPlace(True)
dirtyChunkCount = 0
if self._loadedChunks:
for chunk in self._loadedChunks.itervalues():
if chunk.dirty:
dirtyChunkCount += 1
chunk.save()
for path, tag in self.playerTagCache.iteritems():
tag.save(path)
self.playerTagCache = {}
self.root_tag.save(self.filename)
info(u"Saved {0} chunks".format(dirtyChunkCount))
def close(self):
for rf in (self.regionFiles or {}).values():
rf.close()
self.regionFiles = {}
self._allChunks = None
self._loadedChunks = {}
# --- Constants ---
GAMETYPE_SURVIVAL = 0
GAMETYPE_CREATIVE = 1
VERSION_MCR = 19132
VERSION_ANVIL = 19133
# --- Instance variables ---
materials = alphaMaterials
isInfinite = True
parentWorld = None
dimNo = 0
Height = 256
_bounds = None
# --- NBT Tag variables ---
SizeOnDisk = TagProperty('SizeOnDisk', nbt.TAG_Long)
RandomSeed = TagProperty('RandomSeed', nbt.TAG_Long)
Time = TagProperty('Time', nbt.TAG_Long) # Age of the world in ticks. 20 ticks per second; 24000 ticks per day.
LastPlayed = TagProperty('LastPlayed', nbt.TAG_Long, lambda self: long(time.time() * 1000))
LevelName = TagProperty('LevelName', nbt.TAG_String, lambda self: self.displayName)
MapFeatures = TagProperty('MapFeatures', nbt.TAG_Byte, lambda self: 1)
GameType = TagProperty('GameType', nbt.TAG_Int, lambda self: 0) # 0 for survival, 1 for creative
version = TagProperty('version', nbt.TAG_Int, lambda s: MCInfdevOldLevel.VERSION_ANVIL)
# --- World info ---
def __str__(self):
return "MCInfdevOldLevel(\"" + os.path.split(self.worldDir)[1] + "\")"
@property
def displayName(self):
# shortname = os.path.basename(self.filename)
# if shortname == "level.dat":
shortname = os.path.basename(os.path.dirname(self.filename))
return shortname
@property
def bounds(self):
if self._bounds is None:
self._bounds = self.getWorldBounds()
return self._bounds
def getWorldBounds(self):
if self.chunkCount == 0:
return BoundingBox((0, 0, 0), (0, 0, 0))
allChunks = array(list(self.allChunks))
mincx = (allChunks[:, 0]).min()
maxcx = (allChunks[:, 0]).max()
mincz = (allChunks[:, 1]).min()
maxcz = (allChunks[:, 1]).max()
origin = (mincx << 4, 0, mincz << 4)
size = ((maxcx - mincx + 1) << 4, self.Height, (maxcz - mincz + 1) << 4)
return BoundingBox(origin, size)
@property
def size(self):
return self.bounds.size
# --- Format detection ---
@classmethod
def _isLevel(cls, filename):
join = os.path.join
exists = os.path.exists
if exists(join(filename, "chunks.dat")):
return False # exclude Pocket Edition folders
if not os.path.isdir(filename):
f = os.path.basename(filename)
if f not in ("level.dat", "level.dat_old"):
return False
filename = os.path.dirname(filename)
files = os.listdir(filename)
if "level.dat" in files or "level.dat_old" in files:
return True
return False
# --- Dimensions ---
def preloadDimensions(self): def preloadDimensions(self):
worldDirs = os.listdir(self.worldDir) worldDirs = os.listdir(self.worldDir)
@ -1307,15 +1309,11 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
self.dimensions[dirname] = dim self.dimensions[dirname] = dim
return dim return dim
def getRegionForChunk(self, cx, cz): # --- Region I/O ---
rx = cx >> 5
rz = cz >> 5
return self.getRegionFile(rx, rz)
def preloadChunkPositions(self): def preloadChunkPositions(self):
self.preloadRegions() self.preloadRegions()
def findRegionFiles(self): def findRegionFiles(self):
regionDir = os.path.join(self.worldDir, "region") regionDir = os.path.join(self.worldDir, "region")
if not os.path.exists(regionDir): if not os.path.exists(regionDir):
@ -1353,6 +1351,11 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
self.regionFiles[rx, rz] = regionFile self.regionFiles[rx, rz] = regionFile
return regionFile return regionFile
def getRegionForChunk(self, cx, cz):
rx = cx >> 5
rz = cz >> 5
return self.getRegionFile(rx, rz)
def unloadRegions(self): def unloadRegions(self):
self.close() self.close()
@ -1383,21 +1386,7 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
regionFile.close() regionFile.close()
os.unlink(regionFile.path) os.unlink(regionFile.path)
@property # --- Chunk I/O ---
def version(self):
if 'version' in self.root_tag['Data']:
return self.root_tag['Data']['version'].value
else:
return None
@version.setter
def version(self, val):
if 'version' in self.root_tag['Data']:
self.root_tag['Data']['version'].value = val
@version.deleter
def version(self):
self.root_tag['Data'].pop('version')
def _loadChunk(self, cx, cz): def _loadChunk(self, cx, cz):
""" load the chunk data from disk, and return its root tag as an NBT_Compound""" """ load the chunk data from disk, and return its root tag as an NBT_Compound"""
@ -1440,11 +1429,6 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
"c.%s.%s.dat" % (base36(cx), base36(cz))) "c.%s.%s.dat" % (base36(cx), base36(cz)))
return s return s
def chunkFilenameAt(self, x, y, z):
cx = x >> 4
cz = z >> 4
return self._loadedChunks.get((cx, cz)).filename
def extractChunksInBox(self, box, parentFolder): def extractChunksInBox(self, box, parentFolder):
for cx, cz in box.chunkPositions: for cx, cz in box.chunkPositions:
if self.containsChunk(cx, cz): if self.containsChunk(cx, cz):
@ -1462,19 +1446,6 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
with file(outputFile, "wb") as f: with file(outputFile, "wb") as f:
chunk.root_tag.save(buf=f) chunk.root_tag.save(buf=f)
def heightMapAt(self, x, z):
zc = z >> 4
xc = x >> 4
xInChunk = x & 0xf
zInChunk = z & 0xf
ch = self.getChunk(xc, zc)
heightMap = ch.HeightMap
return heightMap[zInChunk, xInChunk]
# the heightmap is ordered differently because in minecraft it is a flat array
@property @property
def chunkCount(self): def chunkCount(self):
"""Returns the number of chunks in the level. May initiate a costly """Returns the number of chunks in the level. May initiate a costly
@ -1491,7 +1462,6 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
self.preloadChunkPositions() self.preloadChunkPositions()
return self._allChunks.__iter__() return self._allChunks.__iter__()
def getChunk(self, cx, cz): def getChunk(self, cx, cz):
""" read the chunk from disk, load it, and return it.""" """ read the chunk from disk, load it, and return it."""
@ -1511,24 +1481,21 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
for cx, cz in box.chunkPositions: for cx, cz in box.chunkPositions:
self.markDirtyChunk(cx, cz) self.markDirtyChunk(cx, cz)
def saveInPlace(self): # --- HeightMaps ---
for level in self.dimensions.itervalues():
level.saveInPlace(True)
dirtyChunkCount = 0 def heightMapAt(self, x, z):
if self._loadedChunks: zc = z >> 4
for chunk in self._loadedChunks.itervalues(): xc = x >> 4
if chunk.dirty: xInChunk = x & 0xf
dirtyChunkCount += 1 zInChunk = z & 0xf
chunk.save()
for path, tag in self.playerTagCache.iteritems(): ch = self.getChunk(xc, zc)
tag.save(path)
self.playerTagCache = {} heightMap = ch.HeightMap
self.root_tag.save(self.filename) return heightMap[zInChunk, xInChunk] # HeightMap indices are backwards
info(u"Saved {0} chunks".format(dirtyChunkCount))
# --- Entities and TileEntities ---
def addEntity(self, entityTag): def addEntity(self, entityTag):
assert isinstance(entityTag, nbt.TAG_Compound) assert isinstance(entityTag, nbt.TAG_Compound)
@ -1583,10 +1550,7 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
info("Removed {0} tile entities".format(count)) info("Removed {0} tile entities".format(count))
return count return count
def containsPoint(self, x, y, z): # --- Chunk manipulation ---
if y < 0 or y > 127:
return False
return self.containsChunk(x >> 4, z >> 4)
def containsChunk(self, cx, cz): def containsChunk(self, cx, cz):
if self._allChunks is not None: if self._allChunks is not None:
@ -1601,6 +1565,11 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
return self.getRegionFile(rx, rz).containsChunk(cx, cz) return self.getRegionFile(rx, rz).containsChunk(cx, cz)
def containsPoint(self, x, y, z):
if y < 0 or y > 127:
return False
return self.containsChunk(x >> 4, z >> 4)
def createChunk(self, cx, cz): def createChunk(self, cx, cz):
if self.containsChunk(cx, cz): if self.containsChunk(cx, cz):
raise ValueError("{0}:Chunk {1} already present!".format(self, (cx, cz))) raise ValueError("{0}:Chunk {1} already present!".format(self, (cx, cz)))
@ -1670,7 +1639,7 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
return ret return ret
spawnxyz = ["SpawnX", "SpawnY", "SpawnZ"] # --- Player and spawn manipulation ---
def playerSpawnPosition(self, player=None): def playerSpawnPosition(self, player=None):
""" """
@ -1683,7 +1652,7 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
else: else:
playerSpawnTag = self.getPlayerTag(player) playerSpawnTag = self.getPlayerTag(player)
return [playerSpawnTag.get(i, dataTag[i]).value for i in self.spawnxyz] return [playerSpawnTag.get(i, dataTag[i]).value for i in ("SpawnX", "SpawnY", "SpawnZ")]
def setPlayerSpawnPosition(self, pos, player=None): def setPlayerSpawnPosition(self, pos, player=None):
""" xxx if player is None then it sets the default spawn position for the world """ """ xxx if player is None then it sets the default spawn position for the world """
@ -1691,7 +1660,7 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
playerSpawnTag = self.root_tag["Data"] playerSpawnTag = self.root_tag["Data"]
else: else:
playerSpawnTag = self.getPlayerTag(player) playerSpawnTag = self.getPlayerTag(player)
for name, val in zip(self.spawnxyz, pos): for name, val in zip(("SpawnX", "SpawnY", "SpawnZ"), pos):
playerSpawnTag[name] = nbt.TAG_Int(val) playerSpawnTag[name] = nbt.TAG_Int(val)
def getPlayerPath(self, player): def getPlayerPath(self, player):
@ -1795,6 +1764,31 @@ class MCInfdevOldLevel(ChunkedLevelMixin, EntityLevel):
playerTag = self.getPlayerTag(player) playerTag = self.getPlayerTag(player)
return playerTag["playerGameType"].value return playerTag["playerGameType"].value
def createPlayer(self, playerName):
if playerName == "Player":
playerTag = self.root_tag["Data"].setdefault(playerName, nbt.TAG_Compound())
else:
playerTag = nbt.TAG_Compound()
playerTag['Air'] = nbt.TAG_Short(300)
playerTag['AttackTime'] = nbt.TAG_Short(0)
playerTag['DeathTime'] = nbt.TAG_Short(0)
playerTag['Fire'] = nbt.TAG_Short(-20)
playerTag['Health'] = nbt.TAG_Short(20)
playerTag['HurtTime'] = nbt.TAG_Short(0)
playerTag['Score'] = nbt.TAG_Int(0)
playerTag['FallDistance'] = nbt.TAG_Float(0)
playerTag['OnGround'] = nbt.TAG_Byte(0)
playerTag["Inventory"] = nbt.TAG_List()
playerTag['Motion'] = nbt.TAG_List([nbt.TAG_Double(0) for i in range(3)])
playerTag['Pos'] = nbt.TAG_List([nbt.TAG_Double([0.5, 2.8, 0.5][i]) for i in range(3)])
playerTag['Rotation'] = nbt.TAG_List([nbt.TAG_Float(0), nbt.TAG_Float(0)])
if playerName != "Player":
playerTag.save(self.getPlayerPath(playerName))
class MCAlphaDimension (MCInfdevOldLevel): class MCAlphaDimension (MCInfdevOldLevel):
def __init__(self, parentWorld, dimNo, dirname, create=False): def __init__(self, parentWorld, dimNo, dirname, create=False):
@ -1874,7 +1868,6 @@ class ZipSchematic (MCInfdevOldLevel):
self.Height = 128 self.Height = 128
self.Length = 0 self.Length = 0
def close(self): def close(self):
MCInfdevOldLevel.close(self) MCInfdevOldLevel.close(self)
self.zipfile.close() self.zipfile.close()

View File

@ -315,7 +315,6 @@ class MCServerChunkGenerator(object):
tempWorldDir = os.path.join(tempDir, worldName) tempWorldDir = os.path.join(tempDir, worldName)
tempWorld = infiniteworld.MCInfdevOldLevel(tempWorldDir, create=True, random_seed=level.RandomSeed) tempWorld = infiniteworld.MCInfdevOldLevel(tempWorldDir, create=True, random_seed=level.RandomSeed)
del tempWorld.version # for compatibility with older servers. newer ones will set it again without issue.
self.tempWorldCache[self.serverVersion, level.RandomSeed] = tempWorld self.tempWorldCache[self.serverVersion, level.RandomSeed] = tempWorld