If you have existing scripts that use the reference implementation (minecraft-pi aka mcpi), and you wish to convert them to using the picraft library, this section contains details and examples covering equivalent functionality between the libraries.
Equivalent: World
To create a connection using default settings is similar in both libraries:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> from picraft import World
>>> w = World()
Creating a connection with an explicit hostname and port is also similar:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create('localhost', 4711)
>>> from picraft import World
>>> w = World('localhost', 4711)
See Minecraft.getBlockWithData below.
Equivalent: blocks
Accessing the id of a block is rather different. There is no direct equivalent to getBlock, just getBlockWithData (as there’s no difference in operational cost so there’s little point in retrieving a block id without the data). In mcpi this is done by executing a method; in picraft this is done by querying an attribute with a Vector:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.getBlock(0, -1, 0)
2
>>> mc.getBlockWithData(0, -1, 0)
Block(2, 0)
>>> from picraft import World, Vector
>>> w = World()
>>> w.blocks[Vector(0, -1, 0)]
<Block "grass" id=2 data=0>
The id and data can be extracted from the Block tuple that is returned:
>>> w.blocks[Vector(0, -1, 0)].id
2
>>> w.blocks[Vector(0, -1, 0)].data
0
Equivalent: blocks
Setting the id (and optionally data) of a block is also rather different. In picraft the same attribute is used as for accessing block ids; just assign a Block instance to the attribute, instead of querying it:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.getBlock(0, -1, 0)
2
>>> mc.setBlock(0, -1, 0, 1, 0)
>>> from picraft import World, Vector, Block
>>> w = World()
>>> w.blocks[Vector(0, -1, 0)]
<Block "grass" id=2 data=0>
>>> w.blocks[Vector(0, -1, 0)] = Block(1, 0)
Equivalent: blocks
Again, the same attribute as for setBlock is used for setBlocks; just pass a slice of vectors instead of a single vector (the example below shows an easy method of generating such a slice by adding two vectors together for the upper end of the slice):
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.getBlock(0, -1, 0)
2
>>> mc.setBlocks(0, -1, 0, 0, 5, 0, 1, 0)
>>> from picraft import World, Vector, Block
>>> w = World()
>>> v = Vector(0, -1, 0)
>>> w.blocks[v]
<Block "grass" id=2 data=0>
>>> w.blocks[v:v + Vector(1, 7, 1)] = Block(1, 0)
Equivalent: height
Retrieving the height of the world in a specific location is done with an attribute (like retrieving the id and type of blocks). Unlike mcpi, you pass a full vector (of which the Y-coordinate is ignored), and the property returns a full vector with the same X- and Z-coordinates, but the Y-coordinate of the first non-air block from the top of the world:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.getHeight(0, 0)
0
>>> from picraft import World, Vector
>>> w = World()
>>> w.height[Vector(0, -10, 0)]
Vector(x=0, y=0, z=0)
Equivalent: players
The connected player’s entity ids can be retrieved by iterating over the players attribute which acts as a mapping from player id to Player instances:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.getPlayerEntityIds()
[1]
>>> from picraft import World
>>> w = World()
>>> list(w.players)
[1]
Equivalent: save()
Checkpoints can be saved in a couple of ways with picraft. Either you can explicitly call the save() method, or you can use the checkpoint attribute as a context manager:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.saveCheckpoint()
>>> from picraft import World
>>> w = World()
>>> w.checkpoint.save()
In the context manager case, the checkpoint will be saved upon entry to the context and will only be restored if an exception occurs within the context:
>>> from picraft import World, Vector, Block
>>> w = World()
>>> with w.checkpoint:
... # Do something with blocks...
... w.blocks[Vector()] = Block.from_name('stone')
Equivalent: restore()
As with saving a checkpoint, either you can call restore() directly:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.saveCheckpoint()
>>> mc.restoreCheckpoint()
>>> from picraft import World
>>> w = World()
>>> w.checkpoint.save()
>>> w.checkpoint.restore()
Or you can use the context manager to restore the checkpoint automatically in the case of an exception:
>>> from picraft import World, Vector, Block
>>> w = World()
>>> with w.checkpoint:
... # Do something with blocks
... w.blocks[Vector()] = Block.from_name('stone')
... # Raising an exception within the block will implicitly
... # cause the checkpoint to restore
... raise Exception('roll back to the checkpoint')
Equivalent: say()
The postToChat method is simply replaced with the say() method with the one exception that the latter correctly recognizes line breaks in the message:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.postToChat('Hello world!')
>>> from picraft import World
>>> w = World()
>>> w.say('Hello world!')
Equivalent: immutable and nametags_visible
The setting method is replaced with (write-only) properties with the equivalent names to the settings that can be used:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.setting('world_immutable', True)
>>> mc.setting('nametags_visible', True)
>>> from picraft import World
>>> w = World()
>>> w.immutable = True
>>> w.nametags_visible = True
Equivalent: pos
The player.getPos and player.setPos methods are replaced with the pos attribute which returns a Vector of floats and accepts the same to move the host player:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.player.getPos()
Vec3(12.7743,12.0,-8.39158)
>>> mc.player.setPos(12,12,-8)
>>> from picraft import World, Vector
>>> w = World()
>>> w.player.pos
Vector(x=12.7743, y=12.0, z=-8.39158)
>>> w.player.pos = Vector(12, 12, -8)
One advantage of this implementation is that adjusting the player’s position relatively to their current one becomes simple:
>>> w.player.pos += Vector(y=20)
See Minecraft.player.getPos above.
Equivalent: tile_pos
The player.getTilePos and player.setTilePos methods are replaced with the tile_pos attribute which returns a Vector of ints, and accepts the same to move the host player:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.player.getTilePos()
Vec3(12,12,-9)
>>> mc.player.setTilePos(12, 12, -8)
>>> from picraft import World, Vector
>>> w = World()
>>> w.player.tile_pos
Vector(x=12, y=12, z=-9)
>>> w.player.tile_pos += Vector(y=20)
See Minecraft.player.getTilePos above.
Equivalent: autojump
The player.setting method is replaced with the write-only autojump attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.player.setting('autojump', False)
>>> from picraft import World
>>> w = World()
>>> w.player.autojump = False
Equivalent: heading
The player.getRotation method is replaced with the read-only heading attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.player.getRotation()
49.048615
>>> from picraft import World
>>> w = World()
>>> w.player.heading
49.048615
Equivalent: pitch
The player.getPitch method is replaced with the read-only pitch attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.player.getPitch()
4.3500223
>>> from picraft import World
>>> w = World()
>>> w.player.pitch
4.3500223
Equivalent: direction
The player.getDuration method is replaced with the read-only duration attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.player.getDirection()
Vec3(0.1429840348766887,-0.3263934845430674,0.934356922711132)
>>> from picraft import World
>>> w = World()
>>> w.player.direction
Vector(x=0.1429840348766887, y=-0.3263934845430674, z=0.934356922711132)
Equivalent: pos
The entity.getPos and entity.setPos methods are replaced with the pos attribute. Access the relevant Player instance by indexing the players attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.entity.getPos(1)
Vec3(12.7743,12.0,-8.39158)
>>> mc.entity.setPos(1, 12, 12, -8)
>>> from picraft import World, Vector
>>> w = World()
>>> w.players[1].pos
Vector(x=12.7743, y=12.0, z=-8.39158)
>>> w.players[1].pos = Vector(12, 12, -8)
See Minecraft.entity.getPos above.
Equivalent: tile_pos
The entity.getTilePos and entity.setTilePos methods are replaced with the tile_pos attribute. Access the relevant Player instance by indexing the players attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.entity.getTilePos(1)
Vec3(12,12,-9)
>>> mc.entity.setTilePos(1, 12, 12, -8)
>>> from picraft import World, Vector
>>> w = World()
>>> w.players[1].tile_pos
Vector(x=12, y=12, z=-9)
>>> w.players[1].tile_pos += Vector(y=20)
See Minecraft.entity.getTilePos above.
Equivalent: heading
The entity.getRotation method is replaced with the read-only heading attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.entity.getRotation(213)
49.048615
>>> from picraft import World
>>> w = World()
>>> w.players[213].heading
49.048615
Equivalent: pitch
The entity.getPitch method is replaced with the read-only pitch attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.entity.getPitch(213)
4.3500223
>>> from picraft import World
>>> w = World()
>>> w.players[213].pitch
4.3500223
Equivalent: direction
The entity.getDuration method is replaced with the read-only duration attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.entity.getDirection(213)
Vec3(0.1429840348766887,-0.3263934845430674,0.934356922711132)
>>> from picraft import World
>>> w = World()
>>> w.players[213].direction
Vector(x=0.1429840348766887, y=-0.3263934845430674, z=0.934356922711132)
Equivalent: first_person()
The camera attribute in picraft holds a Camera instance which controls the camera in the Minecraft world. The first_person() method can be used to set the camera to view the world through the eyes of the specified player. The player is specified as the world’s player attribute, or as a player retrieved from the players attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.camera.setNormal()
>>> mc.camera.setNormal(2)
>>> from picraft import World
>>> w = World()
>>> w.camera.first_person(w.player)
>>> w.camera.first_person(w.players[2])
Equivalent: third_person()
The camera attribute in picraft holds a Camera instance which controls the camera in the Minecraft world. The third_person() method can be used to set the camera to view the specified player from above. The player is specified as the world’s player attribute, or as a player retrieved from the players attribute:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.camera.setFollow()
>>> mc.camera.setNormal(1)
>>> from picraft import World
>>> w = World()
>>> w.camera.third_person(w.player)
>>> w.camera.third_person(w.players[1])
Equivalent: pos
The pos attribute can be passed a Vector instance to specify the absolute position of the camera. The camera will be pointing straight down (y=-1) from the given position and will not move to follow any entity:
>>> import mcpi.minecraft as minecraft
>>> mc = minecraft.Minecraft.create()
>>> mc.camera.setFixed()
>>> mc.camera.setPos(0,20,0)
>>> from picraft import World, Vector
>>> w = World()
>>> w.camera.pos = Vector(0, 20, 0)
See Minecraft.camera.setFixed above.
Equivalent: Block
The Block class in picraft is similar to the Block class in mcpi but with one major difference: in picraft a Block instance is a tuple descendent and therefore immutable (you cannot change the id or data attributes of a Block instance).
This may seem like an arbitrary barrier, but firstly its quite rare to adjust the the id or data attribute (it’s rather more common to just overwrite a block in the world with an entirely new type), and secondly this change permits blocks to be used as keys in a Python dictionary, or to be stored in a set.
The Block class also provides several means of construction, and additional properties:
>>> from picraft import Block
>>> Block(1, 0)
<Block "stone" id=1 data=0>
>>> Block(35, 1)
<Block "wool" id=35 data=1>
>>> Block.from_name('wool', data=1).description
u'Orange Wool'
>>> Block.from_color('#ffffff').description
u'White Wool'