Source code for mcedit

# !/usr/bin/env python2.7
# -*- coding: utf_8 -*-
# import resource_packs # not the right place, moving it a bit further

#-# Modified by D.C.-G. for translation purpose
#.# Marks the layout modifications. -- D.C.-G.

"""
mcedit.py

Startup, main menu, keyboard configuration, automatic updating.
"""
import splash
import OpenGL
import sys
import os

if "--debug-ogl" not in sys.argv:
    OpenGL.ERROR_CHECKING = False

import logging

# Setup file and stderr logging.
logger = logging.getLogger()

# Set the log level up while importing OpenGL.GL to hide some obnoxious warnings about old array handlers
logger.setLevel(logging.WARN)
logger.setLevel(logging.DEBUG)

logfile = 'mcedit.log'

# if hasattr(sys, 'frozen'):
#     if sys.platform == "win32":
#         import esky
#         app = esky.Esky(sys.executable)

#         logfile = os.path.join(app.appdir, logfile)
#
if sys.platform == "darwin":
    logfile = os.path.expanduser("~/Library/Logs/mcedit.log")
else:
    logfile = os.path.join(os.getcwdu(), logfile)
fh = logging.FileHandler(logfile, mode="w")
fh.setLevel(logging.DEBUG)

ch = logging.StreamHandler()
ch.setLevel(logging.WARN)

if "--log-info" in sys.argv:
    ch.setLevel(logging.INFO)
if "--log-debug" in sys.argv:
    ch.setLevel(logging.DEBUG)


[docs]class FileLineFormatter(logging.Formatter):
[docs] def format(self, record): record.__dict__['fileline'] = "%(module)s.py:%(lineno)d" % record.__dict__ record.__dict__['nameline'] = "%(name)s.py:%(lineno)d" % record.__dict__ return super(FileLineFormatter, self).format(record)
fmt = FileLineFormatter( '[%(levelname)8s][%(nameline)30s]:%(message)s' ) fh.setFormatter(fmt) ch.setFormatter(fmt) logger.addHandler(fh) logger.addHandler(ch) import release start_msg = 'Starting MCEdit-Unified v%s'%release.TAG logger.info(start_msg) print '[ ****** ] ~~~~~~~~~~ %s'%start_msg #--------------------------------------------------------------------- # NEW FEATURES HANDLING # # The idea is to be able to implement and test/use new code without stripping off the current one. # These features/new code will be in the released stuff, but unavailable until explicitly requested. # # The new features which are under development can be enabled using the 'new_features.def' file. # This file is a plain text file with one feature to enable a line. # The file is parsed and each feature is added to the builtins using the pattern 'mcenf_<feature>'. # The value for these builtins is 'True'. # Then, in the code, just check if the builtins has the key 'mcenf_<feature>' to use the new version of the code: # # ``` # def foo_old(): # # Was 'foo', code here is the one used unless the new version is wanted. # [...] # # def foo_new(): # # This is the new version of the former 'foo' (current 'foo_old'). # [...] # # if __builtins__.get('mcenf_foo', False): # foo = foo_new # else: # foo = foo_old # # ``` # if '--new-features' in sys.argv: if not os.path.exists('new_features.def'): logger.warn("New features requested, but file 'new_features.def' not found!") else: logger.warn("New features mode requested.") lines = [a.strip() for a in open('new_features.def', 'r').readlines()] for line in lines: setattr(__builtins__, 'mcenf_%s'%line, True) logger.warn("New features list loaded.") from version_utils import PlayerCache import directories import keys import albow import locale DEF_ENC = locale.getdefaultlocale()[1] if DEF_ENC is None: DEF_ENC = "UTF-8" from albow.translate import _, getPlatInfo from albow.openglwidgets import GLViewport from albow.root import RootWidget from config import config albow.resource.resource_dir = directories.getDataDir() import panels import leveleditor # Building translation template if "-tt" in sys.argv: sys.argv.remove('-tt') # Overwrite the default marker to have one adapted to our specific needs. albow.translate.buildTemplateMarker = """ ### THE FOLLOWING LINES HAS BEEN ADDED BY THE TEMPLATE UPDATE FUNCTION. ### Please, consider to analyze them and remove the entries referring ### to ones containing string formatting. ### ### For example, if you have a line already defined with this text: ### My %{animal} has %d legs. ### you may find lines like these below: ### My parrot has 2 legs. ### My dog has 4 legs. ### ### You also may have unwanted partial strings, especially the ones ### used in hotkeys. Delete them too. ### And, remove this paragraph, or it will be displayed in the program... """ albow.translate.buildTemplate = True albow.translate.loadTemplate() # Save the language defined in config and set en_US as current one. logging.warning('MCEdit is invoked to update the translation template.') orglang = config.settings.langCode.get() logging.warning('The actual language is %s.'%orglang) logging.warning('Setting en_US as language for this session.') config.settings.langCode.set('en_US') import mceutils import mcplatform # The two next switches '--debug-wm' and '--no-wm' are used to debug/disable the internal window handler. # They are exclusive. You can't debug if it is disabled. if "--debug-wm" in sys.argv: mcplatform.DEBUG_WM = True if "--no-wm" in sys.argv: mcplatform.DEBUG_WM = False mcplatform.USE_WM = False else: mcplatform.setupWindowHandler() DEBUG_WM = mcplatform.DEBUG_WM USE_WM = mcplatform.USE_WM #-# DEBUG if mcplatform.hasXlibDisplay and DEBUG_WM: print '*** Xlib version', str(mcplatform.Xlib.__version__).replace(' ', '').replace(',', '.')[1:-1], 'found in', if os.path.expanduser('~/.local/lib/python2.7/site-packages') in mcplatform.Xlib.__file__: print 'user\'s', else: print 'system\'s', print 'libraries.' #-# from mcplatform import platform_open import numpy from pymclevel.minecraft_server import ServerJarStorage import os import os.path import pygame from pygame import display, rect import pymclevel # import release import shutil import sys import traceback import threading from utilities.gl_display_context import GLDisplayContext #&# Prototype fro blocks/items names import mclangres #&# getPlatInfo(OpenGL=OpenGL, numpy=numpy, pygame=pygame) ESCAPE = '\033'
[docs]class MCEdit(GLViewport): def_enc = DEF_ENC def __init__(self, displayContext, *args): if DEBUG_WM: print "############################ __INIT__ ###########################" self.resizeAlert = config.settings.showWindowSizeWarning.get() self.maximized = config.settings.windowMaximized.get() self.saved_pos = config.settings.windowX.get(), config.settings.windowY.get() if displayContext.win and DEBUG_WM: print "* self.displayContext.win.state", displayContext.win.get_state() print "* self.displayContext.win.position", displayContext.win.get_position() self.dis = None self.win = None self.wParent = None self.wGrandParent = None self.linux = False if sys.platform == 'linux2' and mcplatform.hasXlibDisplay: self.linux = True self.dis = dis = mcplatform.Xlib.display.Display() self.win = win = dis.create_resource_object('window', display.get_wm_info()['window']) curDesk = os.environ.get('XDG_CURRENT_DESKTOP') if curDesk in ('GNOME', 'X-Cinnamon', 'Unity'): self.geomReciever = self.maximizeHandler = wParent = win.query_tree().parent self.geomSender = wGrandParent = wParent.query_tree().parent elif curDesk == 'KDE': self.maximizeHandler = win.query_tree().parent wParent = win.query_tree().parent.query_tree().parent wGrandParent = wParent.query_tree().parent.query_tree().parent self.geomReciever = self.geomSender = win.query_tree().parent.query_tree().parent.query_tree().parent else: self.maximizeHandler = self.geomReciever = self.geomSender = wGrandParent = wParent = None self.wParent = wParent self.wGrandParent = wGrandParent root = dis.screen().root windowID = root.get_full_property(dis.intern_atom('_NET_ACTIVE_WINDOW'), mcplatform.Xlib.X.AnyPropertyType).value[0] print "###\nwindowID", windowID window = dis.create_resource_object('window', windowID) print "###\nwindow.get_geometry()", window.get_geometry() print "###\nself.win", self.win.get_geometry() print "###\nself.wParent.get_geometry()", self.wParent.get_geometry() print "###\nself.wGrandParent.get_geometry()", self.wGrandParent.get_geometry() try: print "###\nself.wGrandParent.query_tree().parent.get_geometry()", self.wGrandParent.query_tree().parent.get_geometry() except: pass print "###\nself.maximizeHandler.get_geometry()", self.maximizeHandler.get_geometry() print "###\nself.geomReciever.get_geometry()", self.geomReciever.get_geometry() print "###\nself.geomSender.get_geometry()", self.geomSender.get_geometry() print "###\nself.win", self.win print "###\nself.wParent", self.wParent print "###\nself.wGrandParent", self.wGrandParent print "###\nself.maximizeHandler", self.maximizeHandler print "###\nself.geomReciever", self.geomReciever print "###\nself.geomSender", self.geomSender ws = displayContext.getWindowSize() r = rect.Rect(0, 0, ws[0], ws[1]) GLViewport.__init__(self, r) if DEBUG_WM: print "self.size", self.size, "ws", ws if displayContext.win and self.maximized: # Send a maximize event now displayContext.win.set_state(mcplatform.MAXIMIZED) # Flip pygame.display to avoid to see the splash un-centered. pygame.display.flip() self.displayContext = displayContext self.bg_color = (0, 0, 0, 1) self.anchor = 'tlbr' if not config.config.has_section("Recent Worlds"): config.config.add_section("Recent Worlds") self.setRecentWorlds([""] * 5) self.optionsPanel = panels.OptionsPanel(self) if not albow.translate.buildTemplate: self.optionsPanel.getLanguageChoices() lng = config.settings.langCode.get() if lng not in self.optionsPanel.sgnal: lng = "en_US" config.settings.langCode.set(lng) albow.translate.setLang(lng) # Set the window caption here again, since the initialization is done through several steps... display.set_caption(('MCEdit ~ ' + release.get_version()%_("for")).encode('utf-8'), 'MCEdit') self.optionsPanel.initComponents() self.graphicsPanel = panels.GraphicsPanel(self) #&# Prototype for blocks/items names mclangres.buildResources(lang=albow.translate.getLang()) #&# #.# self.keyConfigPanel = keys.KeyConfigPanel(self) #.# self.droppedLevel = None self.nbtCopyBuffer = None self.reloadEditor() """ check command line for files dropped from explorer """ if len(sys.argv) > 1: for arg in sys.argv[1:]: f = arg.decode(sys.getfilesystemencoding()) if os.path.isdir(os.path.join(pymclevel.minecraftSaveFileDir, f)): f = os.path.join(pymclevel.minecraftSaveFileDir, f) self.droppedLevel = f break if os.path.exists(f): self.droppedLevel = f break self.fileOpener = albow.FileOpener(self) self.add(self.fileOpener) self.fileOpener.focus() #-# Translation live updtate preparation
[docs] def set_update_ui(self, v): GLViewport.set_update_ui(self, v) if v: #&# Prototype for blocks/items names mclangres.buildResources(lang=albow.translate.getLang()) #&# self.keyConfigPanel = keys.KeyConfigPanel(self) self.graphicsPanel = panels.GraphicsPanel(self) if self.fileOpener in self.subwidgets: idx = self.subwidgets.index(self.fileOpener) self.remove(self.fileOpener) self.fileOpener = albow.FileOpener(self) if idx is not None: self.add(self.fileOpener) self.fileOpener.focus() #-#
editor = None
[docs] def reloadEditor(self): reload(leveleditor) level = None pos = None if self.editor: level = self.editor.level self.remove(self.editor) c = self.editor.mainViewport pos, yaw, pitch = c.position, c.yaw, c.pitch self.editor = leveleditor.LevelEditor(self) self.editor.anchor = 'tlbr' if level: self.add(self.editor) self.editor.gotoLevel(level) self.focus_switch = self.editor if pos is not None: c = self.editor.mainViewport c.position, c.yaw, c.pitch = pos, yaw, pitch
[docs] def add_right(self, widget): w, h = self.size widget.centery = h // 2 widget.right = w self.add(widget)
[docs] def showOptions(self): self.optionsPanel.present()
[docs] def showGraphicOptions(self): self.graphicsPanel.present()
[docs] def showKeyConfig(self): self.keyConfigPanel.presentControls()
[docs] def loadRecentWorldNumber(self, i): worlds = list(self.recentWorlds()) if i - 1 < len(worlds): self.loadFile(worlds[i - 1])
numRecentWorlds = 5 @staticmethod
[docs] def removeLevelDat(filename): if filename.endswith("level.dat"): filename = os.path.dirname(filename) return filename
[docs] def recentWorlds(self): worlds = [] for i in range(self.numRecentWorlds): if config.config.has_option("Recent Worlds", str(i)): try: filename = (config.config.get("Recent Worlds", str(i)).decode('utf-8')) worlds.append(self.removeLevelDat(filename)) except Exception, e: logging.error(repr(e)) return list((f for f in worlds if f and os.path.exists(f)))
[docs] def addRecentWorld(self, filename): filename = self.removeLevelDat(filename) rw = list(self.recentWorlds()) if filename in rw: return rw = [filename] + rw[:self.numRecentWorlds - 1] self.setRecentWorlds(rw)
@staticmethod
[docs] def setRecentWorlds(worlds): for i, filename in enumerate(worlds): config.config.set("Recent Worlds", str(i), filename.encode('utf-8'))
[docs] def makeSideColumn1(self): def showLicense(): platform_open(os.path.join(directories.getDataDir(), "LICENSE.txt")) def refresh(): PlayerCache().force_refresh() hotkeys = ([("", "Controls", self.showKeyConfig), ("", "Graphics", self.showGraphicOptions), ("", "Options", self.showOptions), ("", "Homepage", lambda: platform_open("http://www.mcedit-unified.net"), "http://www.mcedit-unified.net"), ("", "About MCEdit", lambda: platform_open("http://www.mcedit-unified.net/about.html"), "http://www.mcedit-unified.net/about.html"), ("", "License", showLicense, os.path.join(directories.getDataDir(), "LICENSE.txt")), ("", "Refresh Player Names", refresh) ]) c = albow.HotkeyColumn(hotkeys) return c
[docs] def makeSideColumn2(self): def showCacheDir(): try: os.mkdir(directories.getCacheDir()) except OSError: pass platform_open(directories.getCacheDir()) def showScreenshotsDir(): try: os.mkdir(os.path.join(directories.getCacheDir(), "screenshots")) except OSError: pass platform_open(os.path.join(directories.getCacheDir(), "screenshots")) hotkeys = ([("", "Config Files", showCacheDir, directories.getCacheDir()), ("", "Screenshots", showScreenshotsDir, os.path.join(directories.getCacheDir(), "screenshots")) ]) c = albow.HotkeyColumn(hotkeys) return c
[docs] def resized(self, dw, dh): """ Handle window resizing events. """ if DEBUG_WM: print "############################ RESIZED ############################" (w, h) = self.size config_w, config_h = config.settings.windowWidth.get(), config.settings.windowHeight.get() win = self.displayContext.win if DEBUG_WM and win: print "dw", dw, "dh", dh print "self.size (w, h) 1", self.size, "win.get_size", win.get_size() print "size 1", config_w, config_h elif DEBUG_WM and not win: print "win is None, unable to print debug messages" if win: x, y = win.get_position() if DEBUG_WM: print "position", x, y print "config pos", (config.settings.windowX.get(), config.settings.windowY.get()) if w == 0 and h == 0: # The window has been minimized, no need to draw anything. self.editor.renderer.render = False return # Mac window handling works better now, but `win` # doesn't exist. So to get this alert to show up # I'm checking if the platform is darwin. This only # works because the code block never actually references # `win`, otherwise it WOULD CRASH!!! # You cannot change further if statements like this # because they reference `win` if win or sys.platform == "darwin": # Handling too small resolutions. # Dialog texts. # "MCEdit does not support window resolutions below 1000x700.\nYou may not be able to access all functions at this resolution." # New buttons: # "Don't warn me again": disable the window popup across sessions. # Tooltip: "Disable this message. Definitively. Even the next time you start MCEdit." # "OK": dismiss the window and let go, don't pop up again for the session # Tooltip: "Continue and not see this message until you restart MCEdit" # "Cancel": resizes the window to the minimum size # Tooltip: "Resize the window to the minimum recommended resolution." # If the config showWindowSizeWarning is true and self.resizeAlert is true, show the popup if (w < 1000 or h < 680) and config.settings.showWindowSizeWarning.get(): _w = w _h = h if self.resizeAlert: answer = "_OK" # Force the size only for the dimension that needs it. if w < 1000 and h < 680: _w = 1000 _h = 680 elif w < 1000: _w = 1000 elif h < 680: _h = 680 if not albow.dialogs.ask_tied_to: answer = albow.ask( "MCEdit does not support window resolutions below 1000x700.\nYou may not be able to access all functions at this resolution.", ["Don't remind me again.", "OK", "Cancel"], default=1, cancel=1, responses_tooltips = {"Don't remind me again.": "Disable this message. Definitively. Even the next time you start MCEdit.", "OK": "Continue and not see this message until you restart MCEdit", "Cancel": "Resize the window to the minimum recommended resolution."}, tie_widget_to=True) else: if not albow.dialogs.ask_tied_to._visible: albow.dialogs.ask_tied_to._visible = True answer = albow.dialogs.ask_tied_to.present() if answer == "Don't remind me again.": config.settings.showWindowSizeWarning = False self.resizeAlert = False elif answer == "OK": w, h = self.size self.resizeAlert = False elif answer == "Cancel": w, h = _w, _h else: if albow.dialogs.ask_tied_to: albow.dialogs.ask_tied_to.dismiss("_OK") del albow.dialogs.ask_tied_to albow.dialogs.ask_tied_to = None elif (w >= 1000 or h >= 680): if albow.dialogs.ask_tied_tos: for ask_tied_to in albow.dialogs.ask_tied_tos: ask_tied_to._visible = False ask_tied_to.dismiss("_OK") ask_tied_to.set_parent(None) del ask_tied_to if not win: if w < 1000: config.settings.windowWidth.set(1000) w = 1000 x = config.settings.windowX.get() if h < 680: config.settings.windowHeight.set(680) h = 680 y = config.settings.windowY.get() if not self.editor.renderer.render: self.editor.renderer.render = True save_geom = True if win: maximized = win.get_state() == mcplatform.MAXIMIZED sz = map(max, win.get_size(), (w, h)) if DEBUG_WM: print "sz", sz print "maximized", maximized, "self.maximized", self.maximized if maximized: if DEBUG_WM: print "maximize, saving maximized size" config.settings.windowMaximizedWidth.set(sz[0]) config.settings.windowMaximizedHeight.set(sz[1]) config.save() self.saved_pos = config.settings.windowX.get(), config.settings.windowY.get() save_geom = False self.resizing = 0 win.set_mode(sz, self.displayContext.displayMode()) else: if DEBUG_WM: print "size 2", config.settings.windowWidth.get(), config.settings.windowHeight.get() print "config_w", config_w, "config_h", config_h print "pos", config.settings.windowX.get(), config.settings.windowY.get() if self.maximized != maximized: if DEBUG_WM: print "restoring window pos and size" print "(config.settings.windowX.get(), config.settings.windowY.get())", (config.settings.windowX.get(), config.settings.windowY.get()) (w, h) = (config_w, config_h) win.set_state(1, (w, h), self.saved_pos) else: if DEBUG_WM: print "window resized" print "setting size to", (w, h), "and pos to", (x,y) win.set_mode((w, h), self.displayContext.displayMode()) win.set_position((x, y)) config.settings.windowMaximizedWidth.set(0) config.settings.windowMaximizedHeight.set(0) config.save() self.maximized = maximized if DEBUG_WM: print "self.size (w, h) 2", self.size, (w, h) surf = pygame.display.get_surface() print "display surf rect", surf.get_rect() if win: if hasattr(win.base_handler, 'get_geometry'): print "win.base_handler geometry", win.base_handler.get_geometry() print "win.base_handler.parent geometry", win.base_handler.query_tree().parent.get_geometry() print "win.base_handler.parent.parent geometry", win.base_handler.query_tree().parent.query_tree().parent.get_geometry() if save_geom: config.settings.windowWidth.set(w) config.settings.windowHeight.set(h) config.save() # The alert window is disabled if win is not None if not win and (dw > 20 or dh > 20): if not hasattr(self, 'resizeAlert'): self.resizeAlert = self.shouldResizeAlert if self.resizeAlert: albow.alert( "Window size increased. You may have problems using the cursor until MCEdit is restarted.") self.resizeAlert = False if win: win.sync() GLViewport.resized(self, dw, dh)
shouldResizeAlert = config.settings.shouldResizeAlert.property()
[docs] def loadFile(self, filename, addToRecent=True): if os.path.exists(filename): try: self.editor.loadFile(filename, addToRecent=addToRecent) except Exception, e: logging.error(u'Failed to load file {0}: {1!r}'.format( filename, e)) return None self.remove(self.fileOpener) self.fileOpener = None if self.editor.level: self.editor.size = self.size self.add(self.editor) self.focus_switch = self.editor
[docs] def createNewWorld(self): level = self.editor.createNewLevel() if level: self.remove(self.fileOpener) self.editor.size = self.size self.add(self.editor) self.focus_switch = self.editor albow.alert( "World created. To expand this infinite world, explore the world in Minecraft or use the Chunk Control tool to add or delete chunks.")
[docs] def removeEditor(self): self.remove(self.editor) self.fileOpener = albow.FileOpener(self) self.add(self.fileOpener) self.focus_switch = self.fileOpener
[docs] def confirm_quit(self): #-# saving language template if hasattr(albow.translate, "saveTemplate"): albow.translate.saveTemplate() #-# self.saveWindowPosition() config.save() if self.editor.unsavedEdits: # if config.settings.savePositionOnClose.get(): # self.editor.waypointManager.saveLastPosition(self.editor.mainViewport, self.editor.level.getPlayerDimension()) # self.editor.waypointManager.save() result = albow.ask(_("There are {0} unsaved changes.").format(self.editor.unsavedEdits), responses=["Save and Quit", "Quit", "Cancel"]) if result == "Save and Quit": self.saveAndQuit() elif result == "Quit": self.justQuit() elif result == "Cancel": return False else: raise SystemExit
[docs] def saveAndQuit(self): self.editor.saveFile() raise SystemExit
@staticmethod
[docs] def justQuit(): raise SystemExit
@classmethod
[docs] def fetch_version(cls): with cls.version_lock: cls.version_info = release.fetch_new_version_info()
[docs] def check_for_version(self): new_version = release.check_for_new_version(self.version_info) if new_version is not False: answer = albow.ask( _('Version {} is available').format(new_version["tag_name"]), [ 'Download', 'View', 'Ignore' ], default=1, cancel=2 ) if answer == "View": platform_open(new_version["html_url"]) elif answer == "Download": platform_open(new_version["asset"]["browser_download_url"]) albow.alert(_(' {} should now be downloading via your browser. You will still need to extract the downloaded file to use the updated version.').format(new_version["asset"]["name"]))
@classmethod
[docs] def main(cls): PlayerCache().load() displayContext = GLDisplayContext(splash.splash, caption=(('MCEdit ~ ' + release.get_version()%_("for")).encode('utf-8'), 'MCEdit')) os.environ['SDL_VIDEO_CENTERED'] = '0' rootwidget = RootWidget(displayContext.display) mcedit = MCEdit(displayContext) rootwidget.displayContext = displayContext rootwidget.confirm_quit = mcedit.confirm_quit rootwidget.mcedit = mcedit rootwidget.add(mcedit) rootwidget.focus_switch = mcedit if 0 == len(pymclevel.alphaMaterials.yamlDatas): albow.alert("Failed to load minecraft.yaml. Check the console window for details.") if mcedit.droppedLevel: mcedit.loadFile(mcedit.droppedLevel) cls.version_lock = threading.Lock() cls.version_info = None cls.version_checked = False fetch_version_thread = threading.Thread(target=cls.fetch_version) fetch_version_thread.start() # Disabled old update code # if hasattr(sys, 'frozen'): # # We're being run from a bundle, check for updates. # import esky # # app = esky.Esky( # sys.executable.decode(sys.getfilesystemencoding()), # 'https://bitbucket.org/codewarrior0/mcedit/downloads' # ) # try: # update_version = app.find_update() # except: # # FIXME: Horrible, hacky kludge. # update_version = None # logging.exception('Error while checking for updates') # # if update_version: # answer = albow.ask( # 'Version "%s" is available, would you like to ' # 'download it?' % update_version, # [ # 'Yes', # 'No', # ], # default=0, # cancel=1 # ) # if answer == 'Yes': # def callback(args): # status = args['status'] # status_texts = { # 'searching': u"Finding updates...", # 'found': u"Found version {new_version}", # 'downloading': u"Downloading: {received} / {size}", # 'ready': u"Downloaded {path}", # 'installing': u"Installing {new_version}", # 'cleaning up': u"Cleaning up...", # 'done': u"Done." # } # text = status_texts.get(status, 'Unknown').format(**args) # # panel = Dialog() # panel.idleevent = lambda event: panel.dismiss() # label = albow.Label(text, width=600) # panel.add(label) # panel.size = (500, 250) # panel.present() # # try: # app.auto_update(callback) # except (esky.EskyVersionError, EnvironmentError): # albow.alert(_("Failed to install update %s") % update_version) # else: # albow.alert(_("Version %s installed. Restart MCEdit to begin using it.") % update_version) # raise SystemExit() if config.settings.closeMinecraftWarning.get(): answer = albow.ask( "Warning: Only open a world in one program at a time. If you open a world at the same time in MCEdit and in Minecraft, you will lose your work and possibly damage your save file.\n\n If you are using Minecraft 1.3 or earlier, you need to close Minecraft completely before you use MCEdit.", ["Don't remind me again.", "OK"], default=1, cancel=1) if answer == "Don't remind me again.": config.settings.closeMinecraftWarning.set(False) # Disabled Crash Reporting Option # if not config.settings.reportCrashesAsked.get(): # answer = albow.ask( # "When an error occurs, MCEdit can report the details of the error to its developers. " # "The error report will include your operating system version, MCEdit version, " # "OpenGL version, plus the make and model of your CPU and graphics processor. No personal " # "information will be collected.\n\n" # "Error reporting can be enabled or disabled in the Options dialog.\n\n" # "Enable error reporting?", # ["Yes", "No"], # default=0) # config.settings.reportCrashes.set(answer == "Yes") # config.settings.reportCrashesAsked.set(True) config.settings.reportCrashes.set(False) config.settings.reportCrashesAsked.set(True) config.save() if "update" in config.version.version.get(): answer = albow.ask("There are new default controls. Do you want to replace your current controls with the new ones?", ["Yes", "No"]) if answer == "Yes": for configKey, k in keys.KeyConfigPanel.presets["WASD"]: config.keys[config.convert(configKey)].set(k) config.version.version.set("1.1.2.0") config.save() if "-causeError" in sys.argv: raise ValueError("Error requested via -causeError") while True: try: rootwidget.run() except (SystemExit, KeyboardInterrupt): print "Shutting down..." exc_txt = traceback.format_exc() if mcedit.editor.level: if config.settings.savePositionOnClose.get(): mcedit.editor.waypointManager.saveLastPosition(mcedit.editor.mainViewport, mcedit.editor.level.dimNo) mcedit.editor.waypointManager.save() # The following Windows specific code won't be executed if we're using '--debug-wm' switch. if not USE_WM and sys.platform == "win32" and config.settings.setWindowPlacement.get(): (flags, showCmd, ptMin, ptMax, rect) = mcplatform.win32gui.GetWindowPlacement( display.get_wm_info()['window']) X, Y, r, b = rect #w = r-X #h = b-Y if (showCmd == mcplatform.win32con.SW_MINIMIZE or showCmd == mcplatform.win32con.SW_SHOWMINIMIZED): showCmd = mcplatform.win32con.SW_SHOWNORMAL config.settings.windowX.set(X) config.settings.windowY.set(Y) config.settings.windowShowCmd.set(showCmd) # Restore the previous language if we ran with '-tt' (update translation template). if albow.translate.buildTemplate: logging.warning('Restoring %s.'%orglang) config.settings.langCode.set(orglang) # config.save() mcedit.editor.renderer.discardAllChunks() mcedit.editor.deleteAllCopiedSchematics() if mcedit.editor.level: mcedit.editor.level.close() mcedit.editor.root.RemoveEditFiles() if 'SystemExit' in traceback.format_exc() or 'KeyboardInterrupt' in traceback.format_exc(): raise else: if 'SystemExit' in exc_txt: raise SystemExit if 'KeyboardInterrupt' in exc_txt: raise KeyboardInterrupt except MemoryError: traceback.print_exc() mcedit.editor.handleMemoryError()
[docs] def saveWindowPosition(self): """Save the window position in the configuration handler.""" if DEBUG_WM: print "############################ EXITING ############################" win = self.displayContext.win # The following Windows specific code will not be executed if we're using '--debug-wm' switch. if not USE_WM and sys.platform == "win32" and config.settings.setWindowPlacement.get(): (flags, showCmd, ptMin, ptMax, rect) = mcplatform.win32gui.GetWindowPlacement( display.get_wm_info()['window']) X, Y, r, b = rect #w = r-X #h = b-Y if (showCmd == mcplatform.win32con.SW_MINIMIZE or showCmd == mcplatform.win32con.SW_SHOWMINIMIZED): showCmd = mcplatform.win32con.SW_SHOWNORMAL config.settings.windowX.set(X) config.settings.windowY.set(Y) config.settings.windowShowCmd.set(showCmd) elif win: config.settings.windowMaximized.set(self.maximized) if not self.maximized: x, y = win.get_position() else: x, y = self.saved_pos if DEBUG_WM: print "x", x, "y", y config.settings.windowX.set(x) config.settings.windowY.set(y)
[docs] def restart(self): self.saveWindowPosition() config.save() self.editor.renderer.discardAllChunks() self.editor.deleteAllCopiedSchematics() if self.editor.level: self.editor.level.close() self.editor.root.RemoveEditFiles() python = sys.executable if sys.argv[0].endswith('.exe') or hasattr(sys, 'frozen'): os.execl(python, python, * sys.argv[1:]) else: os.execl(python, python, * sys.argv)
[docs]def main(argv): """ Setup display, bundled schematics. Handle unclean shutdowns. """ # This should eventually be revived, what is "squash_python"? # try: # import squash_python # # squash_python.uploader.SquashUploader.headers.pop("Content-encoding", None) # squash_python.uploader.SquashUploader.headers.pop("Accept-encoding", None) # # version = release.get_version() # client = squash_python.get_client() # client.APIKey = "6ea52b17-ac76-4fd8-8db4-2d7303473ca2" # client.environment = "unknown" # client.host = "http://pixelhost.ezekielelin.com" # client.notifyPath = "/mcedit_bugs.php" # client.build = version # client.timeout = 5 # # Disabled Crash Reporting Option # client.disabled = not config.settings.reportCrashesNew.get() # client.disabled = True # # def _reportingChanged(val): # client.disabled = not val # # config.settings.reportCrashes.addObserver(client, '_enabled', _reportingChanged) # client.reportErrors() # client.hook() # except (ImportError, UnicodeError) as e: # pass try: display.init() except pygame.error: os.environ['SDL_VIDEODRIVER'] = 'directx' try: display.init() except pygame.error: os.environ['SDL_VIDEODRIVER'] = 'windib' display.init() pygame.font.init() try: if not os.path.exists(directories.schematicsDir): shutil.copytree( os.path.join(directories.getDataDir(), u'stock-schematics'), directories.schematicsDir ) except Exception, e: logging.warning('Error copying bundled schematics: {0!r}'.format(e)) try: os.mkdir(directories.schematicsDir) except Exception, e: logging.warning('Error creating schematics folder: {0!r}'.format(e)) try: ServerJarStorage() except Exception, e: logging.warning('Error creating server jar storage folder: {0!r}'.format(e)) try: MCEdit.main() except Exception as e: print "mcedit.main MCEdit exited with errors." logging.error("MCEdit version %s", release.get_version()) display.quit() if hasattr(sys, 'frozen') and sys.platform == 'win32': logging.exception("%s", e) print "Press RETURN or close this window to dismiss." raw_input() raise return 0
[docs]def getSelectedMinecraftVersion(): profile = directories.getMinecraftProfileJSON()[directories.getSelectedProfile()] if 'lastVersionId' in profile: return profile['lastVersionId'] else: return '1.8'
[docs]def getLatestMinecraftVersion(snapshots=False): import urllib2 import json versioninfo = json.loads(urllib2.urlopen("http://s3.amazonaws.com/Minecraft.Download/versions/versions.json ").read()) if snapshots: return versioninfo['latest']['snapshot'] else: return versioninfo['latest']['release']
[docs]def weird_fix(): try: from OpenGL.platform import win32 except Exception: pass
[docs]class FakeStdOutErr: """Fake file object to redirect very last Python output. Used to track 'errors' not handled in MCEdit. Mimics 'write' and 'close' file objects methods. Used on Linux only.""" mode = 'a' def __init__(self, *args, **kwargs): """*args and **kwargs are ignored. Deletes the 'logger' object and reopen 'logfile' in append mode.""" global logger global logfile del logger self.fd = open(logfile, 'a')
[docs] def write(self, msg): self.fd.write(msg)
[docs] def close(self, *args, **kwargs): self.fd.flush() self.fd.close()
if __name__ == "__main__": try: main(sys.argv) except (SystemExit, KeyboardInterrupt): # It happens that on Linux, Python tries to kill already dead processes and display errors in the console. # Redirecting them to the log file preserve them and other errors which may occur. if sys.platform == "linux2": logger.debug("MCEdit is exiting normally.") logger.debug("Lines below this one are pure Python output.") sys.stdout = sys.stderr = FakeStdOutErr() pass except: traceback.print_exc() print "" print "==================================" print "\t\t\t MCEdit has crashed" print "==================================" raw_input("Press the Enter key to close this window") pass #sys.exit(main(sys.argv))