From 729fcda9643254e06e5994ede9b64b65e8f559fb Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sun, 11 Mar 2012 17:59:29 -0400 Subject: [PATCH] Display a spawn marker --- overviewer.py | 1 + overviewer_core/data/js_src/overviewer.js | 7 ++++- overviewer_core/data/js_src/util.js | 3 ++ overviewer_core/data/js_src/views.js | 26 ++++++++++++++++ overviewer_core/tileset.py | 2 ++ overviewer_core/world.py | 37 ++++++++++++++++++----- 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/overviewer.py b/overviewer.py index d7f72d0..96ed27a 100755 --- a/overviewer.py +++ b/overviewer.py @@ -406,6 +406,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces. # only pass to the TileSet the options it really cares about render['name'] = render_name # perhaps a hack. This is stored here for the asset manager tileSetOpts = util.dict_subset(render, ["name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "imgquality", "optimizeimg", "rendermode", "worldname_orig", "title", "dimension", "changelist"]) + tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this tset = tileset.TileSet(rset, assetMrg, tex, tileSetOpts, tileset_dir) tilesets.append(tset) diff --git a/overviewer_core/data/js_src/overviewer.js b/overviewer_core/data/js_src/overviewer.js index a8ad80b..00dd283 100644 --- a/overviewer_core/data/js_src/overviewer.js +++ b/overviewer_core/data/js_src/overviewer.js @@ -36,7 +36,12 @@ overviewer.collections = { /** * Hold the raw marker data for each tilest */ - 'markerInfo': {} + 'markerInfo': {}, + + /** + * holds a reference to the spawn marker. + */ + 'spawnMarker': null, }; overviewer.classes = { diff --git a/overviewer_core/data/js_src/util.js b/overviewer_core/data/js_src/util.js index 0a1655f..0e738da 100644 --- a/overviewer_core/data/js_src/util.js +++ b/overviewer_core/data/js_src/util.js @@ -63,6 +63,8 @@ overviewer.util = { signs.registerEvents(signs); } + var spawnmarker = new overviewer.views.SpawnIconView(); + // Update coords on mousemove google.maps.event.addListener(overviewer.map, 'mousemove', function (event) { coordsdiv.updateCoords(event.latLng); @@ -77,6 +79,7 @@ overviewer.util = { overviewer.mapView.updateCurrentTileset(); compass.render(); + spawnmarker.render(); // re-center on the last viewport var currentWorldView = overviewer.mapModel.get("currentWorldView"); diff --git a/overviewer_core/data/js_src/views.js b/overviewer_core/data/js_src/views.js index b4ffbb9..323c1fc 100644 --- a/overviewer_core/data/js_src/views.js +++ b/overviewer_core/data/js_src/views.js @@ -359,3 +359,29 @@ overviewer.views.SignControlView = Backbone.View.extend({ }, }); +/** + * SpawnIconView + */ +overviewer.views.SpawnIconView = Backbone.View.extend({ + render: function() { + // + var curTileSet = overviewer.mapView.options.currentTileSet; + if (overviewer.collections.spawnMarker) { + overviewer.collections.spawnMarker.setMap(null); + overviewer.collections.spawnMarker = null; + } + var spawn = curTileSet.get("spawn"); + if (spawn) { + overviewer.collections.spawnMarker = new google.maps.Marker({ + 'position': overviewer.util.fromWorldToLatLng(spawn[0], + spawn[1], spawn[2], overviewer.mapView.options.currentTileSet), + 'map': overviewer.map, + 'title': 'spawn', + 'icon': overviewerConfig.CONST.image.spawnMarker, + 'visible': false + }); + overviewer.collections.spawnMarker.setVisible(true); + } + } +}); + diff --git a/overviewer_core/tileset.py b/overviewer_core/tileset.py index 8102328..8f78c97 100644 --- a/overviewer_core/tileset.py +++ b/overviewer_core/tileset.py @@ -518,6 +518,8 @@ class TileSet(object): last_rendertime = self.max_chunk_mtime, imgextension = self.imgextension, ) + if (self.regionset.get_type() == "overworld"): + d.update({"spawn": self.options.get("spawn")}) try: d['north_direction'] = self.regionset.north_dir except AttributeError: diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 12a5d0a..7323a4a 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -19,6 +19,8 @@ import os.path from glob import glob import logging import hashlib +import time +import random import numpy @@ -91,8 +93,21 @@ class World(object): if not os.path.exists(os.path.join(self.worlddir, "level.dat")): raise ValueError("level.dat not found in %s" % self.worlddir) - # Hard-code this to only work with format version 19133, "Anvil" data = nbt.load(os.path.join(self.worlddir, "level.dat"))[1]['Data'] + # it seems that reading a level.dat file is unstable, particularly with respect + # to the spawnX,Y,Z variables. So we'll try a few times to get a good reading + # empirically, it seems that 0,50,0 is a "bad" reading + retrycount = 0 + while (data['SpawnX'] == 0 and data['SpawnY'] == 50 and data['SpawnZ'] ==0 ): + logging.debug("bad level read, retrying") + time.sleep(random.random()) + data = nbt.load(os.path.join(self.worlddir, "level.dat"))[1]['Data'] + retrycount += 1 + if retrycount > 10: + raise Exception("Failed to correctly read level.dat") + + + # Hard-code this to only work with format version 19133, "Anvil" if not ('version' in data and data['version'] == 19133): logging.critical("Sorry, This version of Minecraft-Overviewer only works with the 'Anvil' chunk format") raise ValueError("World at %s is not compatible with Overviewer" % self.worlddir) @@ -163,7 +178,7 @@ class World(object): # location ## read spawn info from level.dat - data = self.data + data = self.leveldat disp_spawnX = spawnX = data['SpawnX'] spawnY = data['SpawnY'] disp_spawnZ = spawnZ = data['SpawnZ'] @@ -175,24 +190,32 @@ class World(object): ## clamp spawnY to a sane value, in-chunk value if spawnY < 0: spawnY = 0 - if spawnY > 127: - spawnY = 127 + if spawnY > 255: + spawnY = 255 # Open up the chunk that the spawn is in - regionset = self.get_regionset(0) + regionset = self.get_regionset("overworld") try: chunk = regionset.get_chunk(chunkX, chunkZ) except ChunkDoesntExist: return (spawnX, spawnY, spawnZ) + + def getBlock(y): + "This is stupid and slow but I don't care" + targetSection = spawnY//16 + for section in chunk['Sections']: + if section['Y'] == targetSection: + blockArray = section['Blocks'] + return blockArray[inChunkX, inChunkZ, y % 16] + - blockArray = chunk['Blocks'] ## The block for spawn *within* the chunk inChunkX = spawnX - (chunkX*16) inChunkZ = spawnZ - (chunkZ*16) ## find the first air block - while (blockArray[inChunkX, inChunkZ, spawnY] != 0) and spawnY < 127: + while (getBlock(spawnY) != 0) and spawnY < 256: spawnY += 1 return spawnX, spawnY, spawnZ