12. API - Events

The events module defines the Events class, which provides methods for querying events in the Minecraft world, and BlockHitEvent which is the only event type currently supported.

Note

All items in this module are available from the picraft namespace without having to import picraft.events directly.

The following items are defined in the module:

12.1. Events

class picraft.events.Events(connection)[source]

This class implements the events attribute.

There are two ways of responding to picraft’s events: the first is to poll() for them manually, and process each event in the resulting list:

>>> for event in world.events.poll():
...     print(repr(event))
...
<BlockHitEvent pos=1,1,1 face="y+" player=1>,
<PlayerPosEvent old_pos=0.2,1.0,0.7 new_pos=0.3,1.0,0.7 player=1>

The second is to “tag” functions as event handlers with the decorators provided and then call the main_loop() function which will handle polling the server for you, and call all the relevant functions as needed:

@world.events.on_block_hit(pos=Vector(1,1,1))
def hit_block(event):
    print('You hit the block at %s' % event.pos)

world.events.main_loop()

By default, only block hit events will be tracked. This is because it is the only type of event that the Minecraft server provides information about itself, and thus the only type of event that can be processed relatively efficiently. If you wish to track player positions, assign a set of player ids to the track_players attribute. If you wish to include idle events (which fire when nothing else is produced in response to poll()) then set include_idle to True.

Finally, the poll_gap attribute specifies how long to pause during each iteration of main_loop() to permit event handlers some time to interact with the server. Setting this to 0 will provide the fastest response to events, but will result in event handlers having to fight with event polling for access to the server.

clear()[source]

Forget all pending events that have not yet been retrieved with poll().

This method is used to clear the list of events that have occurred since the last call to poll() without retrieving them. This is useful for ensuring that events subsequently retrieved definitely occurred after the call to clear().

main_loop()[source]

Starts the event polling loop when using the decorator style of event handling (see on_block_hit()).

This method will not return, so be sure that you have specified all your event handlers before calling it. The event loop can only be broken by an unhandled exception, or by closing the world’s connection (in the latter case the resulting ConnectionClosed exception will be suppressed as it is assumed that you want to end the script cleanly).

on_block_hit(thread=False, multi=True, pos=None, face=None)[source]

Decorator for registering a function as an event handler.

This decorator is used to mark a function as an event handler which will be called for any events indicating a block has been hit while main_loop() is executing. The function will be called with the corresponding BlockHitEvent as the only argument.

The pos attribute can be used to specify a vector or sequence of vectors (including a vector_range); in this case the event handler will only be called for block hits on matching vectors.

The face attribute can be used to specify a face or sequence of faces for which the handler will be called.

For example, to specify that one handler should be called for hits on the top of any blocks, and another should be called only for hits on any face of block at the origin one could use the following code:

from picraft import World, Vector

world = World()

@world.events.on_block_hit(pos=Vector(0, 0, 0))
def origin_hit(event):
    world.say('You hit the block at the origin')

@world.events.on_block_hit(face="y+")
def top_hit(event):
    world.say('You hit the top of a block at %d,%d,%d' % event.pos)

world.events.main_loop()

The thread parameter (which defaults to False) can be used to specify that the handler should be executed in its own background thread, in parallel with other handlers.

Finally, the multi parameter (which only applies when thread is True) specifies whether multi-threaded handlers should be allowed to execute in parallel. When True (the default), threaded handlers execute as many times as activated in parallel. When False, a single instance of a threaded handler is allowed to execute at any given time; simultaneous activations are ignored (but not queued, as with unthreaded handlers).

on_idle(thread=False, multi=True)[source]

Decorator for registering a function as an idle handler.

This decorator is used to mark a function as an event handler which will be called when no other event handlers have been called in an iteration of main_loop(). The function will be called with the corresponding IdleEvent as the only argument.

Note that idle events will only be generated if include_idle is set to True.

on_player_pos(thread=False, multi=True, old_pos=None, new_pos=None)[source]

Decorator for registering a function as a position change handler.

This decorator is used to mark a function as an event handler which will be called for any events indicating that a player’s position has changed while main_loop() is executing. The function will be called with the corresponding PlayerPosEvent as the only argument.

The old_pos and new_pos attributes can be used to specify vectors or sequences of vectors (including a vector_range) that the player position events must match in order to activate the associated handler. For example, to fire a handler every time any player enters or walks over blocks within (-10, 0, -10) to (10, 0, 10):

from picraft import World, Vector, vector_range

world = World()
world.events.track_players = world.players

from_pos = Vector(-10, 0, -10)
to_pos = Vector(10, 0, 10)
@world.events.on_player_pos(new_pos=vector_range(from_pos, to_pos + 1))
def in_box(event):
    world.say('Player %d stepped in the box' % event.player.player_id)

world.events.main_loop()

Various effects can be achieved by combining old_pos and new_pos filters. For example, one could detect when a player crosses a boundary in a particular direction, or decide when a player enters or leaves a particular area.

Note that only players specified in track_players will generate player position events.

poll()[source]

Return a list of all events that have occurred since the last call to poll().

For example:

>>> w = World()
>>> w.events.track_players = w.players
>>> w.events.include_idle = True
>>> w.events.poll()
[<PlayerPosEvent old_pos=0.2,1.0,0.7 new_pos=0.3,1.0,0.7 player=1>,
 <BlockHitEvent pos=1,1,1 face="x+" player=1>,
 <BlockHitEvent pos=1,1,1 face="x+" player=1>]
>>> w.events.poll()
[<IdleEvent>]
process()[source]

Poll the server for events and call any relevant event handlers registered with on_block_hit().

This method is called repeatedly the event handler loop implemented by main_loop(); developers should only call this method when their (presumably non-threaded) event handler is engaged in a long operation and they wish to permit events to be processed in the meantime.

include_idle

If True, generate an idle event when no other events would be generated by poll(). This attribute defaults to False.

poll_gap

The length of time (in seconds) to pause during main_loop().

This property specifies the length of time to wait at the end of each iteration of main_loop(). By default this is 0.1 seconds.

The purpose of the pause is to give event handlers executing in the background time to communicate with the Minecraft server. Setting this to 0.0 will result in faster response to events, but also starves threaded event handlers of time to communicate with the server, resulting in “choppy” performance.

track_players

The set of player ids for which movement should be tracked.

By default the poll() method will not produce player position events (PlayerPosEvent). Producing these events requires extra interactions with the Minecraft server (one for each player tracked) which slow down response to block hit events.

If you wish to track player positions, set this attribute to the set of player ids you wish to track and their positions will be stored. The next time poll() is called it will query the positions for all specified players and fire player position events if they have changed.

Given that the players attribute represents a dictionary mapping player ids to players, if you wish to track all players you can simply do:

>>> world.events.track_players = world.players

12.2. BlockHitEvent

class picraft.events.BlockHitEvent(pos, face, player)[source]

Event representing a block being hit by a player.

This tuple derivative represents the event resulting from a player striking a block with their sword in the Minecraft world. Users will not normally need to construct instances of this class, rather they are constructed and returned by calls to poll().

Note

Please note that the block hit event only registers when the player right clicks with the sword. For some reason, left clicks do not count.

pos

A Vector indicating the position of the block which was struck.

face

A string indicating which side of the block was struck. This can be one of six values: ‘x+’, ‘x-‘, ‘y+’, ‘y-‘, ‘z+’, or ‘z-‘. The value indicates the axis, and direction along that axis, that the side faces:

_images/block_faces.png
player

A Player instance representing the player that hit the block.

12.3. PlayerPosEvent

class picraft.events.PlayerPosEvent(old_pos, new_pos, player)[source]

Event representing a player moving.

This tuple derivative represents the event resulting from a player moving within the Minecraft world. Users will not normally need to construct instances of this class, rather they are constructed and returned by calls to poll().

old_pos

A Vector indicating the location of the player prior to this event. The location includes decimal places (it is not the tile-position, but the actual position).

new_pos

A Vector indicating the location of the player as of this event. The location includes decimal places (it is not the tile-position, but the actual position).

player

A Player instance representing the player that moved.

12.4. IdleEvent

class picraft.events.IdleEvent[source]

Event that fires in the event that no other events have occurred since the last poll. This is only used if Events.include_idle is True.