Jump to content

  • Curse Sites
Become a Premium Member! Help
Latest News Article

pymclevel: Minecraft Levels for Python


  • Please log in to reply
85 replies to this topic

#1

codewarrior
  • Location: Big Island

Posted 26 August 2010 - 12:32 PM

Here it is, the code I've built MCEdit upon.

http://github.com/co...rior0/pymclevel

Documentation?  Begin reading here

Requires Python and Numpy.

Excerpt:
# Convenience method to load a numbered world from the saves folder.
world1 = mclevel.loadWorldNumber(1);

# Find out which chunks are present
chunkPositions = world1.presentChunks

# presentChunks returns a list of tuples (xPos, zPos)
xPos, zPos = chunkPositions[0];

# retrieve an InfdevChunk object. getChunk is a special method;  
# it will load the chunk from disk, decompress it, inflate the NBT structures, and unpack the data arrays for you.
aChunk = world1.getChunk(xPos, zPos)

### Access the data arrays of the chunk like so:

# Fire to Leaves.
aChunk.Blocks[aChunk.Blocks==world.materials.materialNamed("Fire")] = world.materials.materialNamed("Leaves")

MCEdit: Minecraft World Editor

"We will absolutely not keep in mind what external mapeditors will have to do to read data from the disk, that makes no sense whatsoever." - Grum

Register or log in to remove.

#2

ramiel
    ramiel

    Carpenter

  • Members
  • 50 posts

Posted 26 August 2010 - 01:35 PM

Looks pretty sweet. Don't know that I'd use it in pynemap since it loads the extra stuff (heightmap, lighting) on chunk load but I definitely would if I was working on a map editor or something.

#3

codewarrior
  • Location: Big Island

Posted 26 August 2010 - 01:48 PM

I left it out of the examples, but you can call compress() on a chunk to compress it back down without completely unloading it.  It will automatically decompress the next time you try to use it.
MCEdit: Minecraft World Editor

"We will absolutely not keep in mind what external mapeditors will have to do to read data from the disk, that makes no sense whatsoever." - Grum

#4

virulentRant
  • Location: Strawberry Fields

Posted 26 August 2010 - 06:03 PM

Sexy.

I'll look at it for help on my project.

Thanks.

Posted ImagePosted Image


#5

benloran

Posted 27 August 2010 - 08:47 PM

This is awesome, thanks for releasing it.

I'm just getting started with it, but noticed that the save path is incorrect for OS X.

mclevel.py line 138 is:
'darwin':os.path.expanduser("~/Library/Application Support/Minecraft"),
and should instead be (case sensitive):
'darwin':os.path.expanduser("~/Library/Application Support/minecraft/saves"),


#6

Complexes

Posted 07 September 2010 - 05:32 PM

Little question of interest, is this python 2, or 3?

Posted Image


#7

codewarrior
  • Location: Big Island

Posted 07 September 2010 - 09:25 PM

I've been using it on Python 2.6.  I have no idea how well it works with other versions and platforms.

Also, I've pushed some code from the latest MCEdit to the repository.
MCEdit: Minecraft World Editor

"We will absolutely not keep in mind what external mapeditors will have to do to read data from the disk, that makes no sense whatsoever." - Grum

#8

codewarrior
  • Location: Big Island

Posted 20 September 2010 - 04:21 AM

Just bumping this because it now includes a command-line interface.
MCEdit: Minecraft World Editor

"We will absolutely not keep in mind what external mapeditors will have to do to read data from the disk, that makes no sense whatsoever." - Grum

#9

codewarrior
  • Location: Big Island

Posted 23 September 2010 - 02:01 PM

Made with mce.py:

Posted Image

replace Stationary water with Stationary lava
replace Water with Lava
replace Grass with Dirt
replace Dirt with Sand
replace Leaves with Air
replace Tree with Cactus

MCEdit: Minecraft World Editor

"We will absolutely not keep in mind what external mapeditors will have to do to read data from the disk, that makes no sense whatsoever." - Grum

#10

zagzaggr

Posted 06 October 2010 - 03:57 PM

I'm having some trouble copying blocks ...
world1 = mclevel.loadWorldNumber(1)
origspawn = world1.playerSpawnPosition()
world4 = mclevel.loadWorldNumber(4)
playerspawn = world4.playerSpawnPosition()

sourcebox = BoundingBox(origin=origspawn,size=(10,10,10))
world4.copyBlocksFrom(world1, sourcebox, playerspawn, None)
world4.saveInPlace()

The above should copy 10x10x10 blocks from playerspawn at world1 to playerspawn at world4, right? Except it doesn't... I tried with logging and I get 0 Blocks copied, although all else is reported ok.

After searching for a while, I noticed line 2339 in mclevel.py :
			for s in itertools.product(*map(lambda x:range(*x), zip(sourceBox.origin, sourceBox.size))):

didn't enter the for loop at all. Seems range expects start and finish positions, not start and size, as it was getting there.
I tried again with lambda x: range(x[0],x[0]+x[1]) and it worked.

Am I misunderstanding how 'size' is to be used? Or was this a bug?

#11

codewarrior
  • Location: Big Island

Posted 07 October 2010 - 02:22 AM

That's a bug, and you have the right fix.  That codepath is the one for copying directly from one infinite level to another without an intermediate buffer. The functionality isn't exposed anywhere in either program so it never gets used. You might notice it accesses the blocks one by one instead of doing a mass block copy via numpy. This is extraordinarily slow and my dread about rewriting it in numpy is why it's still in such bad shape.
MCEdit: Minecraft World Editor

"We will absolutely not keep in mind what external mapeditors will have to do to read data from the disk, that makes no sense whatsoever." - Grum

#12

zagzaggr

Posted 07 October 2010 - 03:16 AM

Turns out I'm using an even slower path, nested fors, block for block for now.
I'm trying to do something that would copy a segment from one map to another, perform block replacements with some probability (ie not always) and do other stuff like drop orphan blocks to the ground, so it has to be pretty much block for block. Plus numpy is very confusing to me and I'd like it to be as simple as possible to understand, no matter how slow...
Forgot to thank you for the module btw: thank you =D

#13

neckbear
  • Location: nomadic

Posted 07 October 2010 - 03:26 AM

This is fucking awesome

#14

ratty
    ratty

    Forum/Wiki Sponsor

  • Members
  • 187 posts
  • Minecraft: kilorat

Posted 07 October 2010 - 12:05 PM

Just amazing, thanks for making this!

I just have an idea to give, hopefully someone will run with it now that there's such a nice library. Make it dump the text off signs? It could just put the coordinates, and the 4 lines of text. I'd love to see all the fun sign text people have made on our server.

#15

zagzaggr

Posted 07 October 2010 - 03:42 PM

I've posted what I'm trying to make in another topic, linking back here, I hope it's ok :iapprove:

http://www.minecraft...php?f=1&t=46420

#16

ZomBuster

Posted 08 October 2010 - 12:24 PM

I am trying to read chunks using this, it seems pretty simple but it's not working for me
import mclevel

world1 = mclevel.loadWorldNumber(1);
chunkPositions = world1.presentChunks
xPos, zPos = chunkPositions[1];
aChunk = world1.getChunk(xPos,zPos)

print aChunk.Data[0]

gives me empty arrays. What am I doing wrong?

EDIT: ok I needed to use Blocks instead of Data.. doh

#17

bbot
    bbot

    Out of the Water

  • Members
  • 3 posts

Posted 14 October 2010 - 08:31 AM

I hate it when clueless newbies post begging posts, thus flaunting how clueless and new they are, but:

>>> import mclevel

Traceback (most recent call last):
  File "", line 1, in 
	import mclevel
  File "C:\Users\bbot\Downloads\pymclevel-20100920\mclevel.py", line 112, in 
	import nbt
  File "C:\Users\bbot\Downloads\pymclevel-20100920\nbt.py", line 23, in 
	from numpy import array, zeros, uint8, fromstring
  File "C:\Python27\lib\site-packages\numpy\__init__.py", line 136, in 
	import add_newdocs
  File "C:\Python27\lib\site-packages\numpy\add_newdocs.py", line 9, in 
	from numpy.lib import add_newdoc
  File "C:\Python27\lib\site-packages\numpy\lib\__init__.py", line 4, in 
	from type_check import *
  File "C:\Python27\lib\site-packages\numpy\lib\type_check.py", line 8, in 
	import numpy.core.numeric as _nx
  File "C:\Python27\lib\site-packages\numpy\core\__init__.py", line 5, in 
	import multiarray
ImportError: DLL load failed: The specified module could not be found.
>>> 

What the hell is happening here? Installing numpy was an enormous pain in the ass, requiring a registry edit, since apparently python doesn't set registry keys right on 64-bit versions of windows? Previously numpy just refused to work at all, but after the registry edit, it didn't install correctly?

#18

codewarrior
  • Location: Big Island

Posted 14 October 2010 - 10:28 AM

If you installed the win32 superpack from Sourceforge, uninstall it. Then, install the amd64 build of numpy from about halfway down this page.
MCEdit: Minecraft World Editor

"We will absolutely not keep in mind what external mapeditors will have to do to read data from the disk, that makes no sense whatsoever." - Grum

#19

xolotl
    xolotl

    Gold Miner

  • Members
  • 351 posts
  • Minecraft: xolotl

Posted 14 October 2010 - 07:21 PM

Edit: Nevermind, eventually found it, in TileEntities.  Just have to construct a new NBT_Compound with the appropriate stuff to add a sign with a message.  Thanks again!

(original post follows)

Hey, this is a great package btw - I'm enjoying playing around with it (writing a little converter to load maps from Eschalon into Minecraft).  I did have a quick question, though - is there a way to get at (and set) the text on signs?  I haven't yet found anything in the API which looks right.  Perhaps it's just something I need to do with the block Data structure?

Oh, and I should mention I'm just using the Python API, not the CLI tool.

Regardless, great work, and thanks again!

#20

bbot
    bbot

    Out of the Water

  • Members
  • 3 posts

Posted 14 October 2010 - 10:07 PM

codewarrior said:

If you installed the win32 superpack from Sourceforge, uninstall it. Then, install the amd64 build of numpy from about halfway down this page.
This resulted in more mysterious errors, until I figured out that 64-bit numpy also wanted a 64-bit version of python. Now it works! Thanks.