commit
aad078e0c9
19
.gitignore
vendored
19
.gitignore
vendored
@ -1,19 +1,20 @@
|
|||||||
|
# Python object code.
|
||||||
# git-ls-files --others --exclude-from=.git/info/exclude
|
|
||||||
# Lines that start with '#' are comments.
|
|
||||||
# For a project mostly in C, the following would be a good set of
|
|
||||||
# exclude patterns (uncomment them if you want to use them):
|
|
||||||
# *.[oa]
|
|
||||||
# *~
|
|
||||||
|
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
*~
|
*~
|
||||||
|
|
||||||
|
# Vim temporary files.
|
||||||
|
*.sw*
|
||||||
|
|
||||||
|
# Folders created by setup.py.
|
||||||
dist
|
dist
|
||||||
build
|
build
|
||||||
|
*.egg-info
|
||||||
|
|
||||||
|
# The "standard" virtualenv directory.
|
||||||
|
ENV
|
||||||
|
|
||||||
#profiling/outputs
|
#profiling/outputs
|
||||||
mcedit.ini
|
mcedit.ini
|
||||||
*.log
|
*.log
|
||||||
mcedit.profile
|
mcedit.profile
|
||||||
|
63
README.md
Normal file
63
README.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# MCEdit
|
||||||
|
|
||||||
|
MCEdit is an open-source, BSD-licenced world editor for the viral indie hit [Minecraft](http://www.minecraft.net/).
|
||||||
|
|
||||||
|
## For Developers
|
||||||
|
|
||||||
|
MCEdit is written in Python using a variety of open source modules. When developing it is recommended to use virtualenv to keep dependencies sane and to easy deployment.
|
||||||
|
|
||||||
|
### Development Quick Guide
|
||||||
|
|
||||||
|
You'll need Python 2.6+ and `easy_install`/`pip` at a minimum before getting started. This quick guide assumes a unix-y OS.
|
||||||
|
|
||||||
|
Clone MCEdit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/mcdevs/mcedit
|
||||||
|
cd mcedit
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally (but highly recommended), setup and activate [virtualenv](http://pypi.python.org/pypi/virtualenv). virtualenv will simplify development by creating an isolated and barebones Python environment. Anything you install while virtualenv is active won't affect your system-wide Python installation, for example.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
easy_install virtualenv
|
||||||
|
virtualenv ENV
|
||||||
|
. ENV/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
Install various dependencies. This may take a bit (especially numpy). If installing pygame errors, try installing from a [binary packages](http://pygame.org/install.html) or following one of the guides from that page to install from source.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
easy_install PyOpenGL
|
||||||
|
easy_install numpy
|
||||||
|
easy_install pygame
|
||||||
|
easy_install pyyaml
|
||||||
|
```
|
||||||
|
|
||||||
|
You should now be able to run MCEdit with `python main.py` assuming you've installed all the dependencies correctly.
|
||||||
|
|
||||||
|
### Freezing/Packaging
|
||||||
|
|
||||||
|
"Freezing" Python applications to deploy them for use by non-technical users is not in any way fun, expect errors and edge cases.
|
||||||
|
|
||||||
|
Additional dependenies are required to package MCEdit. Regardless of which platform you're targetting, [esky](http://pypi.python.org/pypi/esky/) will be required.
|
||||||
|
|
||||||
|
#### OS X
|
||||||
|
*Note:* These instructions have only been testing on OS X Lion.
|
||||||
|
|
||||||
|
You will run into errors attempting to use the system Python when packaging anything under OS X. The easiest way to install a new Python is by using [Homebrew](http://mxcl.github.com/homebrew/).
|
||||||
|
|
||||||
|
If you were using the system python while developing and using virtualenv, you'll need to overwrite it with your newly installed version.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install python
|
||||||
|
virtualenv -p /usr/local/bin/python ENV
|
||||||
|
|
||||||
|
easy_install esky
|
||||||
|
easy_install py2app
|
||||||
|
python setup.py bdist_esky
|
||||||
|
```
|
||||||
|
|
||||||
|
This will leave you with a zip file in `dist/` that contains a portable `.app` bundle.
|
185
mcedit.py
185
mcedit.py
@ -36,7 +36,7 @@ class SafeOutputStream(object):
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class tee(object):
|
class tee(object):
|
||||||
def __init__(self, _fd1, _fd2) :
|
def __init__(self, _fd1, _fd2) :
|
||||||
@ -48,7 +48,7 @@ class tee(object):
|
|||||||
self.fd1.close()
|
self.fd1.close()
|
||||||
if self.fd2 != sys.stdout and self.fd2 != sys.stderr :
|
if self.fd2 != sys.stdout and self.fd2 != sys.stderr :
|
||||||
self.fd2.close()
|
self.fd2.close()
|
||||||
|
|
||||||
|
|
||||||
def write(self, text) :
|
def write(self, text) :
|
||||||
self.fd1.write(text)
|
self.fd1.write(text)
|
||||||
@ -66,13 +66,13 @@ sys.stderr = sys.stdout
|
|||||||
try:
|
try:
|
||||||
from release import release
|
from release import release
|
||||||
print "Release: ", release
|
print "Release: ", release
|
||||||
|
|
||||||
import locale
|
import locale
|
||||||
locale.setlocale(locale.LC_ALL, '')
|
locale.setlocale(locale.LC_ALL, '')
|
||||||
import traceback
|
import traceback
|
||||||
import logging
|
import logging
|
||||||
from os.path import exists, isdir, join
|
from os.path import exists, isdir, join
|
||||||
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import gc
|
import gc
|
||||||
import functools
|
import functools
|
||||||
@ -84,9 +84,9 @@ try:
|
|||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
import platform
|
import platform
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from errorreporting import reportException
|
from errorreporting import reportException
|
||||||
|
|
||||||
if "-debug" in sys.argv and platform.architecture()[0] == "32bit":
|
if "-debug" in sys.argv and platform.architecture()[0] == "32bit":
|
||||||
os.environ['PATH'] = "C:\\Program Files (x86)\\GLIntercept_1_0_Beta01" + os.pathsep + os.environ['PATH']
|
os.environ['PATH'] = "C:\\Program Files (x86)\\GLIntercept_1_0_Beta01" + os.pathsep + os.environ['PATH']
|
||||||
try:
|
try:
|
||||||
@ -109,15 +109,15 @@ try:
|
|||||||
OpenGL.ERROR_ON_COPY = True
|
OpenGL.ERROR_ON_COPY = True
|
||||||
if "-full" in sys.argv:
|
if "-full" in sys.argv:
|
||||||
OpenGL.FULL_LOGGING = True
|
OpenGL.FULL_LOGGING = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
OpenGL.ERROR_CHECKING = False
|
OpenGL.ERROR_CHECKING = False
|
||||||
logging.basicConfig(format=u'%(levelname)s:%(message)s')
|
logging.basicConfig(format=u'%(levelname)s:%(message)s')
|
||||||
logging.getLogger().level = logging.WARN
|
logging.getLogger().level = logging.WARN
|
||||||
|
|
||||||
from OpenGL import GL
|
from OpenGL import GL
|
||||||
logging.getLogger().level = loglevel
|
logging.getLogger().level = loglevel
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print "Loading numpy..."
|
print "Loading numpy..."
|
||||||
import numpy
|
import numpy
|
||||||
@ -150,13 +150,13 @@ try:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print "Error opening logfile", repr(e)
|
print "Error opening logfile", repr(e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#from OpenGL.GLUT import glutBitmapCharacter, glutInit
|
#from OpenGL.GLUT import glutBitmapCharacter, glutInit
|
||||||
|
|
||||||
|
|
||||||
print "Loading albow..."
|
print "Loading albow..."
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ class FileOpener(Widget):
|
|||||||
self.add(contentRow)
|
self.add(contentRow)
|
||||||
self.sideColumn = sideColumn
|
self.sideColumn = sideColumn
|
||||||
|
|
||||||
|
|
||||||
def gl_draw_self(self, root, offset):
|
def gl_draw_self(self, root, offset):
|
||||||
#self.mcedit.editor.mainViewport.setPerspective();
|
#self.mcedit.editor.mainViewport.setPerspective();
|
||||||
self.mcedit.editor.drawStars()
|
self.mcedit.editor.drawStars()
|
||||||
@ -323,7 +323,7 @@ class FileOpener(Widget):
|
|||||||
def idleevent(self, evt):
|
def idleevent(self, evt):
|
||||||
self.mcedit.editor.doWorkUnit()
|
self.mcedit.editor.doWorkUnit()
|
||||||
#self.invalidate()
|
#self.invalidate()
|
||||||
|
|
||||||
def key_down(self, evt):
|
def key_down(self, evt):
|
||||||
keyname = key.name(evt.key)
|
keyname = key.name(evt.key)
|
||||||
if keyname == 'f4' and (key.get_mods() & (KMOD_ALT | KMOD_LALT | KMOD_RALT)):
|
if keyname == 'f4' and (key.get_mods() & (KMOD_ALT | KMOD_LALT | KMOD_RALT)):
|
||||||
@ -525,19 +525,19 @@ class KeyConfigPanel(Dialog):
|
|||||||
oldkey = config.config.get("Keys", configKey)#save key before recursive call
|
oldkey = config.config.get("Keys", configKey)#save key before recursive call
|
||||||
config.config.set("Keys", configKey, keyname)
|
config.config.set("Keys", configKey, keyname)
|
||||||
for keyname, setting in occupiedKeys:
|
for keyname, setting in occupiedKeys:
|
||||||
if self.askAssignKey(setting,
|
if self.askAssignKey(setting,
|
||||||
"The key {0} is no longer bound to {1}.\n"
|
"The key {0} is no longer bound to {1}.\n"
|
||||||
"Press a new key for the action \"{1}\"\n\n"
|
"Press a new key for the action \"{1}\"\n\n"
|
||||||
"Press ESC to cancel."
|
"Press ESC to cancel."
|
||||||
.format(keyname, setting)):
|
.format(keyname, setting)):
|
||||||
config.config.set("Keys", configKey, oldkey) #revert
|
config.config.set("Keys", configKey, oldkey) #revert
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class GraphicsPanel(Panel):
|
class GraphicsPanel(Panel):
|
||||||
def __init__(self, mcedit):
|
def __init__(self, mcedit):
|
||||||
Panel.__init__(self)
|
Panel.__init__(self)
|
||||||
@ -561,25 +561,25 @@ class GraphicsPanel(Panel):
|
|||||||
|
|
||||||
texturePackRow = Row((Label("Skin: "), texturePackChoice))
|
texturePackRow = Row((Label("Skin: "), texturePackChoice))
|
||||||
|
|
||||||
fieldOfViewRow = FloatInputRow("Field of View: ",
|
fieldOfViewRow = FloatInputRow("Field of View: ",
|
||||||
ref=Settings.fov.propertyRef(), width=100, min=25, max=120)
|
ref=Settings.fov.propertyRef(), width=100, min=25, max=120)
|
||||||
|
|
||||||
targetFPSRow = IntInputRow("Target FPS: ",
|
targetFPSRow = IntInputRow("Target FPS: ",
|
||||||
ref=Settings.targetFPS.propertyRef(), width=100, min=1, max=60)
|
ref=Settings.targetFPS.propertyRef(), width=100, min=1, max=60)
|
||||||
|
|
||||||
bufferLimitRow = IntInputRow("Vertex Buffer Limit (MB): ",
|
bufferLimitRow = IntInputRow("Vertex Buffer Limit (MB): ",
|
||||||
ref=Settings.vertexBufferLimit.propertyRef(), width=100, min=0)
|
ref=Settings.vertexBufferLimit.propertyRef(), width=100, min=0)
|
||||||
|
|
||||||
fastLeavesRow = CheckBoxLabel("Fast Leaves",
|
fastLeavesRow = CheckBoxLabel("Fast Leaves",
|
||||||
ref=Settings.fastLeaves.propertyRef(),
|
ref=Settings.fastLeaves.propertyRef(),
|
||||||
tooltipText="Leaves are solid, like Minecraft's 'Fast' graphics")
|
tooltipText="Leaves are solid, like Minecraft's 'Fast' graphics")
|
||||||
|
|
||||||
roughGraphicsRow = CheckBoxLabel("Rough Graphics",
|
roughGraphicsRow = CheckBoxLabel("Rough Graphics",
|
||||||
ref=Settings.roughGraphics.propertyRef(),
|
ref=Settings.roughGraphics.propertyRef(),
|
||||||
tooltipText="All blocks are drawn the same way (overrides 'Fast Leaves')")
|
tooltipText="All blocks are drawn the same way (overrides 'Fast Leaves')")
|
||||||
|
|
||||||
enableMouseLagRow = CheckBoxLabel("Enable Mouse Lag",
|
enableMouseLagRow = CheckBoxLabel("Enable Mouse Lag",
|
||||||
ref=Settings.enableMouseLag.propertyRef(),
|
ref=Settings.enableMouseLag.propertyRef(),
|
||||||
tooltipText="Enable choppy mouse movement for faster loading.")
|
tooltipText="Enable choppy mouse movement for faster loading.")
|
||||||
|
|
||||||
settingsColumn = Column(( fastLeavesRow,
|
settingsColumn = Column(( fastLeavesRow,
|
||||||
@ -606,7 +606,7 @@ class GraphicsPanel(Panel):
|
|||||||
|
|
||||||
texturePack = Settings.skin.configProperty(_reloadTextures)
|
texturePack = Settings.skin.configProperty(_reloadTextures)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class OptionsPanel(Dialog):
|
class OptionsPanel(Dialog):
|
||||||
anchor = 'wh'
|
anchor = 'wh'
|
||||||
@ -616,59 +616,59 @@ class OptionsPanel(Dialog):
|
|||||||
self.mcedit = mcedit
|
self.mcedit = mcedit
|
||||||
|
|
||||||
|
|
||||||
autoBrakeRow = CheckBoxLabel("Autobrake",
|
autoBrakeRow = CheckBoxLabel("Autobrake",
|
||||||
ref=ControlSettings.autobrake.propertyRef(),
|
ref=ControlSettings.autobrake.propertyRef(),
|
||||||
tooltipText="Apply brake when not pressing movement keys")
|
tooltipText="Apply brake when not pressing movement keys")
|
||||||
|
|
||||||
swapAxesRow = CheckBoxLabel("Swap Axes Looking Down",
|
swapAxesRow = CheckBoxLabel("Swap Axes Looking Down",
|
||||||
ref=ControlSettings.swapAxes.propertyRef(),
|
ref=ControlSettings.swapAxes.propertyRef(),
|
||||||
tooltipText="Change the direction of the Forward and Backward keys when looking down")
|
tooltipText="Change the direction of the Forward and Backward keys when looking down")
|
||||||
|
|
||||||
cameraAccelRow = FloatInputRow("Camera Acceleration: ",
|
cameraAccelRow = FloatInputRow("Camera Acceleration: ",
|
||||||
ref=ControlSettings.cameraAccel.propertyRef(), width=100, min=5.0)
|
ref=ControlSettings.cameraAccel.propertyRef(), width=100, min=5.0)
|
||||||
|
|
||||||
cameraDragRow = FloatInputRow("Camera Drag: ",
|
cameraDragRow = FloatInputRow("Camera Drag: ",
|
||||||
ref=ControlSettings.cameraDrag.propertyRef(), width=100, min=1.0)
|
ref=ControlSettings.cameraDrag.propertyRef(), width=100, min=1.0)
|
||||||
|
|
||||||
cameraMaxSpeedRow = FloatInputRow("Camera Max Speed: ",
|
cameraMaxSpeedRow = FloatInputRow("Camera Max Speed: ",
|
||||||
ref=ControlSettings.cameraMaxSpeed.propertyRef(), width=100, min=1.0)
|
ref=ControlSettings.cameraMaxSpeed.propertyRef(), width=100, min=1.0)
|
||||||
|
|
||||||
cameraBrakeSpeedRow = FloatInputRow("Camera Braking Speed: ",
|
cameraBrakeSpeedRow = FloatInputRow("Camera Braking Speed: ",
|
||||||
ref=ControlSettings.cameraBrakingSpeed.propertyRef(), width=100, min=1.0)
|
ref=ControlSettings.cameraBrakingSpeed.propertyRef(), width=100, min=1.0)
|
||||||
|
|
||||||
mouseSpeedRow = FloatInputRow("Mouse Speed: ",
|
mouseSpeedRow = FloatInputRow("Mouse Speed: ",
|
||||||
ref=ControlSettings.mouseSpeed.propertyRef(), width=100, min=0.1, max=20.0)
|
ref=ControlSettings.mouseSpeed.propertyRef(), width=100, min=0.1, max=20.0)
|
||||||
|
|
||||||
invertRow = CheckBoxLabel("Invert Mouse",
|
invertRow = CheckBoxLabel("Invert Mouse",
|
||||||
ref=ControlSettings.invertMousePitch.propertyRef(),
|
ref=ControlSettings.invertMousePitch.propertyRef(),
|
||||||
tooltipText="Reverse the up and down motion of the mouse.")
|
tooltipText="Reverse the up and down motion of the mouse.")
|
||||||
|
|
||||||
spaceHeightRow = IntInputRow("Low Detail Height",
|
spaceHeightRow = IntInputRow("Low Detail Height",
|
||||||
ref=Settings.spaceHeight.propertyRef(),
|
ref=Settings.spaceHeight.propertyRef(),
|
||||||
tooltipText="When you are this far above the top of the world, move fast and use low-detail mode.")
|
tooltipText="When you are this far above the top of the world, move fast and use low-detail mode.")
|
||||||
|
|
||||||
blockBufferRow = IntInputRow("Block Buffer",
|
blockBufferRow = IntInputRow("Block Buffer",
|
||||||
ref=Settings.blockBuffer.propertyRef(), min=1,
|
ref=Settings.blockBuffer.propertyRef(), min=1,
|
||||||
tooltipText="Amount of memory used for temporary storage. When more than this is needed, the disk is used instead.")
|
tooltipText="Amount of memory used for temporary storage. When more than this is needed, the disk is used instead.")
|
||||||
|
|
||||||
setWindowPlacementRow = CheckBoxLabel("Set Window Placement",
|
setWindowPlacementRow = CheckBoxLabel("Set Window Placement",
|
||||||
ref=Settings.setWindowPlacement.propertyRef(),
|
ref=Settings.setWindowPlacement.propertyRef(),
|
||||||
tooltipText="Try to save and restore the window position.")
|
tooltipText="Try to save and restore the window position.")
|
||||||
|
|
||||||
windowSizeRow = CheckBoxLabel("Window Resize Alert",
|
windowSizeRow = CheckBoxLabel("Window Resize Alert",
|
||||||
ref=Settings.shouldResizeAlert.propertyRef(),
|
ref=Settings.shouldResizeAlert.propertyRef(),
|
||||||
tooltipText="Reminds you that the cursor won't work correctly after resizing the window.")
|
tooltipText="Reminds you that the cursor won't work correctly after resizing the window.")
|
||||||
|
|
||||||
visibilityCheckRow = CheckBoxLabel("Visibility Check",
|
visibilityCheckRow = CheckBoxLabel("Visibility Check",
|
||||||
ref=Settings.visibilityCheck.propertyRef(),
|
ref=Settings.visibilityCheck.propertyRef(),
|
||||||
tooltipText="Do a visibility check on chunks while loading. May cause a crash.")
|
tooltipText="Do a visibility check on chunks while loading. May cause a crash.")
|
||||||
|
|
||||||
longDistanceRow = CheckBoxLabel("Long-Distance Mode",
|
longDistanceRow = CheckBoxLabel("Long-Distance Mode",
|
||||||
ref=Settings.longDistanceMode.propertyRef(),
|
ref=Settings.longDistanceMode.propertyRef(),
|
||||||
tooltipText="Always target the farthest block under the cursor, even in mouselook mode. Shortcut: ALT-Z")
|
tooltipText="Always target the farthest block under the cursor, even in mouselook mode. Shortcut: ALT-Z")
|
||||||
|
|
||||||
flyModeRow = CheckBoxLabel("Fly Mode",
|
flyModeRow = CheckBoxLabel("Fly Mode",
|
||||||
ref=Settings.flyMode.propertyRef(),
|
ref=Settings.flyMode.propertyRef(),
|
||||||
tooltipText="Moving forward and backward will not change your altitude in Fly Mode.")
|
tooltipText="Moving forward and backward will not change your altitude in Fly Mode.")
|
||||||
|
|
||||||
self.goPortableButton = goPortableButton = Button("Change", action=self.togglePortable)
|
self.goPortableButton = goPortableButton = Button("Change", action=self.togglePortable)
|
||||||
@ -676,8 +676,8 @@ class OptionsPanel(Dialog):
|
|||||||
goPortableButton.tooltipText = self.portableButtonTooltip()
|
goPortableButton.tooltipText = self.portableButtonTooltip()
|
||||||
goPortableRow = Row((ValueDisplay(ref=AttrRef(self, 'portableLabelText'), width=250, align='r'), goPortableButton))
|
goPortableRow = Row((ValueDisplay(ref=AttrRef(self, 'portableLabelText'), width=250, align='r'), goPortableButton))
|
||||||
|
|
||||||
reportRow = CheckBoxLabel("Report Crashes",
|
reportRow = CheckBoxLabel("Report Crashes",
|
||||||
ref=Settings.reportCrashes.propertyRef(),
|
ref=Settings.reportCrashes.propertyRef(),
|
||||||
tooltipText="Automatically report fatal errors to the author.")
|
tooltipText="Automatically report fatal errors to the author.")
|
||||||
|
|
||||||
inputs = (
|
inputs = (
|
||||||
@ -690,7 +690,7 @@ class OptionsPanel(Dialog):
|
|||||||
mouseSpeedRow,
|
mouseSpeedRow,
|
||||||
)
|
)
|
||||||
|
|
||||||
options = (
|
options = (
|
||||||
longDistanceRow,
|
longDistanceRow,
|
||||||
flyModeRow,
|
flyModeRow,
|
||||||
autoBrakeRow,
|
autoBrakeRow,
|
||||||
@ -706,10 +706,10 @@ class OptionsPanel(Dialog):
|
|||||||
) + (
|
) + (
|
||||||
goPortableRow,
|
goPortableRow,
|
||||||
)
|
)
|
||||||
|
|
||||||
rightcol = Column(options, align='r')
|
rightcol = Column(options, align='r')
|
||||||
leftcol = Column(inputs, align='r')
|
leftcol = Column(inputs, align='r')
|
||||||
|
|
||||||
|
|
||||||
optionsColumn = Column((Label("Options"),
|
optionsColumn = Column((Label("Options"),
|
||||||
Row((leftcol, rightcol), align="t")))
|
Row((leftcol, rightcol), align="t")))
|
||||||
@ -805,7 +805,7 @@ class MCEdit(GLViewport):
|
|||||||
|
|
||||||
self.fileOpener = FileOpener(self)
|
self.fileOpener = FileOpener(self)
|
||||||
self.add(self.fileOpener)
|
self.add(self.fileOpener)
|
||||||
|
|
||||||
self.fileOpener.focus()
|
self.fileOpener.focus()
|
||||||
|
|
||||||
|
|
||||||
@ -926,7 +926,7 @@ class MCEdit(GLViewport):
|
|||||||
platform_open(os.path.join(mcplatform.dataDir, "LICENSE.txt"))
|
platform_open(os.path.join(mcplatform.dataDir, "LICENSE.txt"))
|
||||||
|
|
||||||
readmePath = os.path.join(mcplatform.dataDir, "README.html")
|
readmePath = os.path.join(mcplatform.dataDir, "README.html")
|
||||||
|
|
||||||
hotkeys = ([("",
|
hotkeys = ([("",
|
||||||
"Keys",
|
"Keys",
|
||||||
self.showKeyConfig),
|
self.showKeyConfig),
|
||||||
@ -985,10 +985,10 @@ class MCEdit(GLViewport):
|
|||||||
if self.resizeAlert:
|
if self.resizeAlert:
|
||||||
alert("Window size increased. You may have problems using the cursor until MCEdit is restarted.")
|
alert("Window size increased. You may have problems using the cursor until MCEdit is restarted.")
|
||||||
self.resizeAlert = False
|
self.resizeAlert = False
|
||||||
|
|
||||||
shouldResizeAlert = Settings.shouldResizeAlert.configProperty()
|
shouldResizeAlert = Settings.shouldResizeAlert.configProperty()
|
||||||
|
|
||||||
|
|
||||||
#self.size = (w,h)
|
#self.size = (w,h)
|
||||||
|
|
||||||
|
|
||||||
@ -1032,7 +1032,7 @@ class MCEdit(GLViewport):
|
|||||||
|
|
||||||
def confirm_quit(self):
|
def confirm_quit(self):
|
||||||
if self.editor.unsavedEdits:
|
if self.editor.unsavedEdits:
|
||||||
result = ask("There are {0} unsaved changes.".format(self.editor.unsavedEdits),
|
result = ask("There are {0} unsaved changes.".format(self.editor.unsavedEdits),
|
||||||
responses = ["Save and Quit", "Quit", "Cancel"] )
|
responses = ["Save and Quit", "Quit", "Cancel"] )
|
||||||
if result == "Save and Quit":self.saveAndQuit()
|
if result == "Save and Quit":self.saveAndQuit()
|
||||||
elif result == "Quit": self.justQuit()
|
elif result == "Quit": self.justQuit()
|
||||||
@ -1057,7 +1057,7 @@ class MCEdit(GLViewport):
|
|||||||
|
|
||||||
displayContext = GLDisplayContext()
|
displayContext = GLDisplayContext()
|
||||||
|
|
||||||
|
|
||||||
#mcedit.size = displayContext.getWindowSize()
|
#mcedit.size = displayContext.getWindowSize()
|
||||||
rootwidget = RootWidget(displayContext.display)
|
rootwidget = RootWidget(displayContext.display)
|
||||||
mcedit = MCEdit(displayContext)
|
mcedit = MCEdit(displayContext)
|
||||||
@ -1069,7 +1069,7 @@ class MCEdit(GLViewport):
|
|||||||
rootwidget.focus_switch = mcedit
|
rootwidget.focus_switch = mcedit
|
||||||
if 0 == len(alphaMaterials.yamlDatas):
|
if 0 == len(alphaMaterials.yamlDatas):
|
||||||
alert("Failed to load minecraft.yaml. Check the console window for details.")
|
alert("Failed to load minecraft.yaml. Check the console window for details.")
|
||||||
|
|
||||||
if mcedit.droppedLevel:
|
if mcedit.droppedLevel:
|
||||||
mcedit.loadFile(mcedit.droppedLevel)
|
mcedit.loadFile(mcedit.droppedLevel)
|
||||||
|
|
||||||
@ -1080,8 +1080,8 @@ class MCEdit(GLViewport):
|
|||||||
if answer == "Don't remind me again.":
|
if answer == "Don't remind me again.":
|
||||||
mcedit.closeMinecraftWarning = False
|
mcedit.closeMinecraftWarning = False
|
||||||
print "Disabled warning"
|
print "Disabled warning"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print "saveConfig()"
|
print "saveConfig()"
|
||||||
@ -1099,7 +1099,7 @@ class MCEdit(GLViewport):
|
|||||||
if (showCmd == mcplatform.win32con.SW_MINIMIZE or
|
if (showCmd == mcplatform.win32con.SW_MINIMIZE or
|
||||||
showCmd == mcplatform.win32con.SW_SHOWMINIMIZED):
|
showCmd == mcplatform.win32con.SW_SHOWMINIMIZED):
|
||||||
showCmd = mcplatform.win32con.SW_SHOWNORMAL
|
showCmd = mcplatform.win32con.SW_SHOWNORMAL
|
||||||
|
|
||||||
Settings.windowX.set(X)
|
Settings.windowX.set(X)
|
||||||
Settings.windowY.set(Y)
|
Settings.windowY.set(Y)
|
||||||
Settings.windowShowCmd.set(showCmd)
|
Settings.windowShowCmd.set(showCmd)
|
||||||
@ -1168,10 +1168,10 @@ import cProfile
|
|||||||
def _profilemain():
|
def _profilemain():
|
||||||
|
|
||||||
cProfile.run("_main()", mcplatform.dataDir + os.path.sep + "mcedit.profile")
|
cProfile.run("_main()", mcplatform.dataDir + os.path.sep + "mcedit.profile")
|
||||||
# p = Stats("mcedit.profile");
|
# p = Stats("mcedit.profile");
|
||||||
# p.sort_stats('cum');
|
# p.sort_stats('cum');
|
||||||
# p.print_stats(15);
|
# p.print_stats(15);
|
||||||
# #system("c:\program files (x86)\graphviz\")
|
# #system("c:\program files (x86)\graphviz\")
|
||||||
if mcplatform.runningInEditor:
|
if mcplatform.runningInEditor:
|
||||||
del os.environ["PYTHONPATH"]
|
del os.environ["PYTHONPATH"]
|
||||||
os.system("python gprof2dot.py -f pstats mcedit.profile > mcedit.dot ")
|
os.system("python gprof2dot.py -f pstats mcedit.profile > mcedit.dot ")
|
||||||
@ -1210,7 +1210,7 @@ class GLDisplayContext(object):
|
|||||||
print("Failed to set vertical sync: {0!r}".format(e))
|
print("Failed to set vertical sync: {0!r}".format(e))
|
||||||
|
|
||||||
d = display.set_mode(self.getWindowSize(), self.displayMode())
|
d = display.set_mode(self.getWindowSize(), self.displayMode())
|
||||||
try:
|
try:
|
||||||
pygame.scrap.init()
|
pygame.scrap.init()
|
||||||
except:
|
except:
|
||||||
print "scrap not available"
|
print "scrap not available"
|
||||||
@ -1221,7 +1221,7 @@ class GLDisplayContext(object):
|
|||||||
Settings.setWindowPlacement.set(False)
|
Settings.setWindowPlacement.set(False)
|
||||||
config.saveConfig()
|
config.saveConfig()
|
||||||
X, Y = Settings.windowX.get(), Settings.windowY.get()
|
X, Y = Settings.windowX.get(), Settings.windowY.get()
|
||||||
|
|
||||||
if X:
|
if X:
|
||||||
w, h = self.getWindowSize()
|
w, h = self.getWindowSize()
|
||||||
hwndOwner = display.get_wm_info()['window']
|
hwndOwner = display.get_wm_info()['window']
|
||||||
@ -1233,7 +1233,7 @@ class GLDisplayContext(object):
|
|||||||
print "GetWindowPlacement", ptMin, ptMax, rect
|
print "GetWindowPlacement", ptMin, ptMax, rect
|
||||||
showCmd = Settings.windowShowCmd.get()
|
showCmd = Settings.windowShowCmd.get()
|
||||||
rect = (X, Y, X+realW, Y+realH) #left, top, right, bottom
|
rect = (X, Y, X+realW, Y+realH) #left, top, right, bottom
|
||||||
|
|
||||||
|
|
||||||
mcplatform.win32gui.SetWindowPlacement(hwndOwner , (0, showCmd, ptMin, ptMax, rect))
|
mcplatform.win32gui.SetWindowPlacement(hwndOwner , (0, showCmd, ptMin, ptMax, rect))
|
||||||
|
|
||||||
@ -1260,14 +1260,14 @@ class GLDisplayContext(object):
|
|||||||
GL.glScale(1 / 256., 1 / 256., 1 / 256.)
|
GL.glScale(1 / 256., 1 / 256., 1 / 256.)
|
||||||
|
|
||||||
self.loadTextures()
|
self.loadTextures()
|
||||||
|
|
||||||
def getTerrainTexture(self, level):
|
def getTerrainTexture(self, level):
|
||||||
return self.terrainTextures.get(level.materials.name, self.terrainTextures["Alpha"])
|
return self.terrainTextures.get(level.materials.name, self.terrainTextures["Alpha"])
|
||||||
|
|
||||||
def loadTextures(self):
|
def loadTextures(self):
|
||||||
print "Loading terrain textures..."
|
print "Loading terrain textures..."
|
||||||
self.terrainTextures = {}
|
self.terrainTextures = {}
|
||||||
|
|
||||||
def makeTerrainTexture(mats):
|
def makeTerrainTexture(mats):
|
||||||
w, h = 1, 1
|
w, h = 1, 1
|
||||||
teximage = zeros((w, h, 4), dtype='uint8')
|
teximage = zeros((w, h, 4), dtype='uint8')
|
||||||
@ -1280,15 +1280,15 @@ class GLDisplayContext(object):
|
|||||||
(indevMaterials, "terrain-classic.png"),
|
(indevMaterials, "terrain-classic.png"),
|
||||||
(alphaMaterials, "terrain.png"),
|
(alphaMaterials, "terrain.png"),
|
||||||
(pocketMaterials, "terrain-pocket.png") ):
|
(pocketMaterials, "terrain-pocket.png") ):
|
||||||
matName = mats.name
|
matName = mats.name
|
||||||
try:
|
try:
|
||||||
if matName=="Alpha":
|
if matName=="Alpha":
|
||||||
tex = loadAlphaTerrainTexture()
|
tex = loadAlphaTerrainTexture()
|
||||||
else:
|
else:
|
||||||
tex = loadPNGTexture(matFile)
|
tex = loadPNGTexture(matFile)
|
||||||
|
|
||||||
self.terrainTextures[matName] = tex
|
self.terrainTextures[matName] = tex
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print repr(e), "while loading Classic terrain texture from {0}. Using flat colors.".format(matFile)
|
print repr(e), "while loading Classic terrain texture from {0}. Using flat colors.".format(matFile)
|
||||||
self.terrainTextures[matName] = Texture(functools.partial(makeTerrainTexture, mats))
|
self.terrainTextures[matName] = Texture(functools.partial(makeTerrainTexture, mats))
|
||||||
@ -1316,6 +1316,7 @@ if __name__ == "__main__":
|
|||||||
main()
|
main()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print "An error has been found! Please send the above to codewarrior0@gmail.com."
|
print("An error occured. Please post the above exception as an issue"
|
||||||
|
"on https://github.com/mcdevs/mcedit/issues/new")
|
||||||
raw_input("Press ENTER to dismiss...")
|
raw_input("Press ENTER to dismiss...")
|
||||||
|
|
||||||
|
138
setup.py
Normal file
138
setup.py
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
from esky import bdist_esky
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
import platform
|
||||||
|
|
||||||
|
LONG_DESC = '''
|
||||||
|
World / Saved Game Editor for the indie game Minecraft
|
||||||
|
|
||||||
|
Import and export creations from saved games. Brush tools allow modifying
|
||||||
|
terrain on a larger scale. Create, remove, and regenerate chunks in modern
|
||||||
|
'infinite' Minecraft levels.
|
||||||
|
|
||||||
|
Works with saved games from Minecraft Classic, Indev, Infdev, Alpha, Beta,
|
||||||
|
Release, and Pocket Edition.
|
||||||
|
'''
|
||||||
|
|
||||||
|
# setup() options that are common on all platforms.
|
||||||
|
SETUP_COMMON = {
|
||||||
|
# General fields,
|
||||||
|
'name': 'MCEdit',
|
||||||
|
'version': '0.1.1',
|
||||||
|
'description': 'Minecraft World Editor',
|
||||||
|
'long_description': LONG_DESC,
|
||||||
|
|
||||||
|
'author': 'David Vierra',
|
||||||
|
'author_email': 'codewarrior0@gmail.com',
|
||||||
|
|
||||||
|
'maintainer': 'MCDevs',
|
||||||
|
'maintainer_email': 'mcdevs@tkte.ch',
|
||||||
|
|
||||||
|
'url': 'http://www.github.com/mcedit/mcedit',
|
||||||
|
|
||||||
|
# PyPi,
|
||||||
|
'keywords': 'minecraft world editor',
|
||||||
|
'classifiers': [
|
||||||
|
'Programming Language :: Python',
|
||||||
|
'Programming Language :: Python :: 2',
|
||||||
|
],
|
||||||
|
|
||||||
|
# Building,
|
||||||
|
'packages': [
|
||||||
|
'pymclevel',
|
||||||
|
],
|
||||||
|
'package_data': {
|
||||||
|
'pymclevel': [
|
||||||
|
'*.yaml',
|
||||||
|
'*.txt',
|
||||||
|
'_nbt.*'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'scripts': [
|
||||||
|
'main.py'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
ESKY_OPTIONS = {
|
||||||
|
'bdist_esky': {
|
||||||
|
'includes':[
|
||||||
|
'ctypes',
|
||||||
|
'logging',
|
||||||
|
'OpenGL.arrays.*',
|
||||||
|
'OpenGL.platform',
|
||||||
|
'OpenGL.platform.win32',
|
||||||
|
'encodings'
|
||||||
|
],
|
||||||
|
'excludes':[
|
||||||
|
'Tkconstants',
|
||||||
|
'Tkinter',
|
||||||
|
'tcl',
|
||||||
|
'Cython'
|
||||||
|
],
|
||||||
|
'freezer_options': {
|
||||||
|
'optimize': 2,
|
||||||
|
'compressed': True,
|
||||||
|
'bundle_files': 3,
|
||||||
|
'dll_excludes': [
|
||||||
|
'mswsock.dll',
|
||||||
|
'powrprof.dll'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def build_nbt():
|
||||||
|
"""
|
||||||
|
Builds _nbt.py.
|
||||||
|
"""
|
||||||
|
os.chdir('pymclevel')
|
||||||
|
os.system(sys.executable + ' setup.py build_ext --inplace --force')
|
||||||
|
os.chdir('..')
|
||||||
|
|
||||||
|
def setup_win32():
|
||||||
|
"""
|
||||||
|
Packing setup for Windows 32/64.
|
||||||
|
"""
|
||||||
|
import py2exe
|
||||||
|
|
||||||
|
# This little ditty makes sure the font module is available
|
||||||
|
origIsSystemDLL = py2exe.build_exe.isSystemDLL
|
||||||
|
def isSystemDLL(pathname):
|
||||||
|
if os.path.basename(pathname).lower() in ['sdl_ttf.dll']:
|
||||||
|
return 0
|
||||||
|
return origIsSystemDLL(pathname)
|
||||||
|
py2exe.build_exe.isSystemDLL = isSystemDLL
|
||||||
|
|
||||||
|
def get_data_files(*args):
|
||||||
|
return [(d, glob.glob(d+'/*')) for d in args]
|
||||||
|
|
||||||
|
def main():
|
||||||
|
build_nbt()
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
setup_win32()
|
||||||
|
|
||||||
|
data_files = get_data_files('fonts', 'toolicons') + [
|
||||||
|
('', [
|
||||||
|
'history.txt',
|
||||||
|
'README.html',
|
||||||
|
'favicon.png',
|
||||||
|
'terrain-classic.png',
|
||||||
|
'terrain-pocket.png',
|
||||||
|
'char.png',
|
||||||
|
'gui.png',
|
||||||
|
'terrain.png'
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
data_files=data_files,
|
||||||
|
options=ESKY_OPTIONS,
|
||||||
|
**SETUP_COMMON
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
135
setup_esky.py
135
setup_esky.py
@ -1,135 +0,0 @@
|
|||||||
"""Copyright (c) 2010-2012 David Rio Vierra
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE."""
|
|
||||||
|
|
||||||
|
|
||||||
from esky import bdist_esky
|
|
||||||
import glob
|
|
||||||
## ...
|
|
||||||
## ModuleFinder can't handle runtime changes to __path__, but win32com uses them
|
|
||||||
#try:
|
|
||||||
# # py2exe 0.6.4 introduced a replacement modulefinder.
|
|
||||||
# # This means we have to add package paths there, not to the built-in
|
|
||||||
# # one. If this new modulefinder gets integrated into Python, then
|
|
||||||
# # we might be able to revert this some day.
|
|
||||||
# # if this doesn't work, try import modulefinder
|
|
||||||
# try:
|
|
||||||
# import py2exe.mf as modulefinder
|
|
||||||
# except ImportError:
|
|
||||||
# import modulefinder
|
|
||||||
# import win32com, sys
|
|
||||||
# for p in win32com.__path__[1:]:
|
|
||||||
# modulefinder.AddPackagePath("win32com", p)
|
|
||||||
# for extra in ["win32com.shell"]: #,"win32com.mapi"
|
|
||||||
# __import__(extra)
|
|
||||||
# m = sys.modules[extra]
|
|
||||||
# for p in m.__path__[1:]:
|
|
||||||
# modulefinder.AddPackagePath(extra, p)
|
|
||||||
#except ImportError:
|
|
||||||
# # no build path setup, no worries.
|
|
||||||
# pass
|
|
||||||
|
|
||||||
|
|
||||||
from distutils.core import setup
|
|
||||||
|
|
||||||
# This little ditty makes sure the font module is available
|
|
||||||
import os
|
|
||||||
import py2exe
|
|
||||||
origIsSystemDLL = py2exe.build_exe.isSystemDLL
|
|
||||||
def isSystemDLL(pathname):
|
|
||||||
if os.path.basename(pathname).lower() in ["sdl_ttf.dll"]:
|
|
||||||
return 0
|
|
||||||
return origIsSystemDLL(pathname)
|
|
||||||
py2exe.build_exe.isSystemDLL = isSystemDLL
|
|
||||||
|
|
||||||
build_number = 1
|
|
||||||
|
|
||||||
NAME = "MCEdit"
|
|
||||||
VERSION = "0.1.0r"+str(build_number)
|
|
||||||
DESCRIPTION = "Minecraft World Editor"
|
|
||||||
LONG_DESC = """World / Saved Game Editor for the indie game Minecraft
|
|
||||||
|
|
||||||
Import and export creations from saved games. Brush tools allow modifying terrain
|
|
||||||
on a larger scale. Create, remove, and regenerate chunks in modern "infinite"
|
|
||||||
Minecraft levels.
|
|
||||||
|
|
||||||
Works with saved games from Minecraft Classic, Indev, Infdev, Alpha, Beta, Release, and Pocket Edition.
|
|
||||||
"""
|
|
||||||
AUTHOR = "David Vierra"
|
|
||||||
AUTHOR_EMAIL = "codewarrior0@gmail.com"
|
|
||||||
URL = "http://github.com/mcedit/mcedit"
|
|
||||||
LICENSE = "Creative Commons Attribution;Non-Commercial;No-Derivatives"
|
|
||||||
KEYWORDS = "minecraft world editor"
|
|
||||||
CLASSIFIERS = [
|
|
||||||
"Programming Language :: Python",
|
|
||||||
"Programming Language :: Python :: 2",
|
|
||||||
]
|
|
||||||
|
|
||||||
import platform
|
|
||||||
ARCH = "win32" if platform.architecture()[0] == "32bit" else "win-amd64"
|
|
||||||
|
|
||||||
PACKAGES = ["pymclevel", "pymclevel.yaml"]
|
|
||||||
EXT_MODULES = []
|
|
||||||
PACKAGE_DATA = {"pymclevel":["*.yaml", "*.txt", "_nbt.*"]}
|
|
||||||
|
|
||||||
def get_data_files(*args):
|
|
||||||
return [(d, glob.glob(d+"/*")) for d in args]
|
|
||||||
|
|
||||||
DATA_FILES = get_data_files("fonts", "toolicons") + [
|
|
||||||
("", "history.txt README.html favicon.png terrain-classic.png terrain-pocket.png char.png gui.png terrain.png".split()),
|
|
||||||
]
|
|
||||||
|
|
||||||
ESKY_OPTIONS = {
|
|
||||||
"bdist_esky": {
|
|
||||||
'includes':['ctypes', 'logging', 'OpenGL.arrays.*', 'OpenGL.platform', 'OpenGL.platform.win32', 'encodings'],
|
|
||||||
'excludes':["Tkconstants", "Tkinter", "tcl", "Cython"],
|
|
||||||
"freezer_options": {
|
|
||||||
"optimize":2,
|
|
||||||
"compressed":True,
|
|
||||||
"bundle_files": 3,
|
|
||||||
'dll_excludes': [ "mswsock.dll", "powrprof.dll" ],
|
|
||||||
#"skip_archive":True,
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
import logging
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
#build _nbt.pyd
|
|
||||||
os.chdir("pymclevel")
|
|
||||||
os.system(sys.executable + " setup.py build_ext --inplace --force")
|
|
||||||
os.chdir("..")
|
|
||||||
|
|
||||||
setup(name=NAME,
|
|
||||||
version=VERSION,
|
|
||||||
author=AUTHOR,
|
|
||||||
author_email=AUTHOR_EMAIL,
|
|
||||||
url=URL,
|
|
||||||
description=DESCRIPTION,
|
|
||||||
long_description=LONG_DESC,
|
|
||||||
keywords=KEYWORDS,
|
|
||||||
packages=PACKAGES,
|
|
||||||
ext_modules=EXT_MODULES,
|
|
||||||
package_data=PACKAGE_DATA,
|
|
||||||
data_files=DATA_FILES,
|
|
||||||
license=LICENSE,
|
|
||||||
classifiers=CLASSIFIERS,
|
|
||||||
scripts=["main.py"],
|
|
||||||
options=ESKY_OPTIONS,
|
|
||||||
)
|
|
||||||
|
|
Reference in New Issue
Block a user