-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interact plugin #85
Merged
Merged
Interact plugin #85
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
4e94683
Add interact plugin
Gjum f83f2f7
Improve _entity_action and look_at
Gjum 107bacc
Fix interact, improve usability
Gjum d3753d9
Copy-paste error, duh
Gjum 8ecf327
interact.py: Add look_at_rel()
Gjum ad6af55
Merge branch 'master' of github.com:SpockBotMC/SpockBot
Gjum 426f5e7
Merge branch 'master' of github.com:SpockBotMC/SpockBot
Gjum 14506ab
Tabs to spaces in interact plugin
Gjum c777130
Convert interact plugin to new PluginBase form
Gjum ee490ed
Make flake8 pass
Gjum 3796a83
Merge branch 'master' of github.com:SpockBotMC/SpockBot
Gjum 6ee3823
Merge branch 'master' of github.com:SpockBotMC/SpockBot
Gjum b4b1b2e
Merge branch 'vector-fixes' into master
Gjum 1111bad
Fix and improve InteractPlugin
Gjum 7eef08b
Add InteractPlugin to DefaultPlugins
Gjum 308cc4b
Clean up DefaultPlugins
Gjum 8ef2317
Fix super call in InteractPlugin
Gjum 5a45067
Add empty test file for InteractPlugin
Gjum 3627453
Reorder stuff
Gjum 6323f86
Add some unit tests
Gjum 98ee4cd
Merge branch 'master' of github.com:SpockBotMC/SpockBot
Gjum 3a34ef9
Make flake happy
Gjum File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,25 @@ | ||
from spock.plugins.core import auth, event, net, ticker, timer | ||
from spock.plugins.helpers import clientinfo, entities, inventory, keepalive, \ | ||
move, physics, respawn, start, world | ||
from spock.plugins.helpers import clientinfo, entities, interact, inventory,\ | ||
keepalive, move, physics, respawn, start, world | ||
|
||
DefaultPlugins = [ | ||
core_plugins = [ | ||
('auth', auth.AuthPlugin), | ||
('event', event.EventPlugin), | ||
('net', net.NetPlugin), | ||
('auth', auth.AuthPlugin), | ||
('ticker', ticker.TickerPlugin), | ||
('timers', timer.TimerPlugin), | ||
('start', start.StartPlugin), | ||
('keepalive', keepalive.KeepalivePlugin), | ||
('respawn', respawn.RespawnPlugin), | ||
('move', move.MovementPlugin), | ||
('world', world.WorldPlugin), | ||
] | ||
helper_plugins = [ | ||
('clientinfo', clientinfo.ClientInfoPlugin), | ||
('entities', entities.EntityPlugin), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for this |
||
('physics', physics.PhysicsPlugin), | ||
('interact', interact.InteractPlugin), | ||
('inventory', inventory.InventoryPlugin), | ||
('keepalive', keepalive.KeepalivePlugin), | ||
('move', move.MovementPlugin), | ||
('physics', physics.PhysicsPlugin), | ||
('respawn', respawn.RespawnPlugin), | ||
('start', start.StartPlugin), | ||
('world', world.WorldPlugin), | ||
] | ||
default_plugins = core_plugins + helper_plugins | ||
DefaultPlugins = default_plugins # for compatibility |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
""" | ||
Interact with the world: | ||
- swing the arm, sneak, sprint, jump with a horse, leave the bed | ||
- chat, whisper (private message) | ||
- look around | ||
- dig/place/use blocks | ||
- use the held (active) item | ||
- use/attack entities | ||
- steer vehicles | ||
|
||
By default, the client sends swing and look packets like the vanilla client. | ||
This can be disabled by setting the auto_swing and auto_look flags. | ||
""" | ||
from spock.plugins.base import PluginBase | ||
from spock.utils import pl_announce | ||
from spock.vector import Vector3 | ||
|
||
PLAYER_HEIGHT = 1.74 # TODO get from physics or where else it belongs | ||
|
||
INTERACT_ENTITY = 0 | ||
ATTACK_ENTITY = 1 | ||
INTERACT_ENTITY_AT = 2 | ||
|
||
ENTITY_ACTION_SNEAK = 0 | ||
ENTITY_ACTION_UNSNEAK = 1 | ||
ENTITY_ACTION_LEAVE_BED = 2 | ||
ENTITY_ACTION_START_SPRINT = 3 | ||
ENTITY_ACTION_STOP_SPRINT = 4 | ||
ENTITY_ACTION_JUMP_HORSE = 5 | ||
ENTITY_ACTION_OPEN_INVENTORY = 6 | ||
|
||
# the six faces of a block | ||
FACE_Y_NEG = 0 | ||
FACE_Y_POS = 1 | ||
FACE_Z_NEG = 2 | ||
FACE_Z_POS = 3 | ||
FACE_X_NEG = 4 | ||
FACE_X_POS = 5 | ||
|
||
DIG_START = 0 | ||
DIG_CANCEL = 1 | ||
DIG_FINISH = 2 | ||
DIG_DROP_STACK = 3 | ||
DIG_DROP_ITEM = 4 | ||
DIG_DEACTIVATE_ITEM = 5 | ||
|
||
|
||
@pl_announce('Interact') | ||
class InteractPlugin(PluginBase): | ||
requires = ('ClientInfo', 'Inventory', 'Net') | ||
|
||
def __init__(self, ploader, settings): | ||
super(InteractPlugin, self).__init__(ploader, settings) | ||
ploader.provides('Interact', self) | ||
|
||
self.sneaking = False | ||
self.sprinting = False | ||
self.auto_swing = True # move arm when clicking | ||
self.auto_look = True # look at clicked things | ||
|
||
self.dig_pos_dict = {'x': 0, 'y': 0, 'z': 0} | ||
|
||
def swing_arm(self): | ||
self.net.push_packet('PLAY>Animation', {}) | ||
|
||
def _entity_action(self, action, jump_boost=100): | ||
entity_id = self.clientinfo.eid | ||
self.net.push_packet('PLAY>Entity Action', { | ||
'eid': entity_id, | ||
'action': action, | ||
'jump_boost': jump_boost, | ||
}) | ||
|
||
def leave_bed(self): | ||
self._entity_action(ENTITY_ACTION_LEAVE_BED) | ||
|
||
def sneak(self, sneak=True): | ||
self._entity_action(ENTITY_ACTION_SNEAK | ||
if sneak else ENTITY_ACTION_UNSNEAK) | ||
self.sneaking = sneak | ||
|
||
def unsneak(self): | ||
self.sneak(False) | ||
|
||
def sprint(self, sprint=True): | ||
self._entity_action(ENTITY_ACTION_START_SPRINT | ||
if sprint else ENTITY_ACTION_STOP_SPRINT) | ||
self.sprinting = sprint | ||
|
||
def unsprint(self): | ||
self.sprint(False) | ||
|
||
def jump_horse(self, jump_boost=100): | ||
self._entity_action(ENTITY_ACTION_JUMP_HORSE, jump_boost) | ||
|
||
def chat(self, message): | ||
self.net.push_packet('PLAY>Chat Message', {'message': message}) | ||
|
||
def whisper(self, player, message): | ||
self.chat('/tell %s %s' % (player, message)) | ||
|
||
def look(self, yaw=0.0, pitch=0.0): | ||
""" | ||
Turn the head. Both angles are in degrees. | ||
""" | ||
self.clientinfo.position.pitch = pitch | ||
self.clientinfo.position.yaw = yaw | ||
self.net.push_packet('PLAY>Player Look', { | ||
'yaw': int(yaw), | ||
'pitch': int(pitch), | ||
'on_ground': self.clientinfo.position.on_ground | ||
}) | ||
|
||
def look_rel(self, d_yaw=0.0, d_pitch=0.0): | ||
self.look(self.clientinfo.position.yaw + d_yaw, | ||
self.clientinfo.position.pitch + d_pitch) | ||
|
||
def look_at_rel(self, delta): | ||
self.look(*delta.yaw_pitch) | ||
|
||
def look_at(self, pos): | ||
delta = pos - self.clientinfo.position - Vector3(0, PLAYER_HEIGHT, 0) | ||
self.look_at_rel(delta) | ||
|
||
def _send_dig_block(self, status, pos=None, face=FACE_Y_POS): | ||
if status == DIG_START: | ||
self.dig_pos_dict = pos.get_dict().copy() | ||
self.net.push_packet('PLAY>Player Digging', { | ||
'status': status, | ||
'location': self.dig_pos_dict, | ||
'face': face, | ||
}) | ||
|
||
def start_digging(self, pos): | ||
if self.auto_look: | ||
self.look_at(pos) # TODO look at block center | ||
self._send_dig_block(DIG_START, pos) | ||
if self.auto_swing: | ||
self.swing_arm() | ||
# TODO send swing animation until done or stopped | ||
|
||
def cancel_digging(self): | ||
self._send_dig_block(DIG_CANCEL) | ||
|
||
def finish_digging(self): | ||
self._send_dig_block(DIG_FINISH) | ||
|
||
def dig_block(self, pos): | ||
""" | ||
Not cancelable. | ||
""" | ||
self.start_digging(pos) | ||
self.finish_digging() | ||
|
||
def _send_click_block(self, pos, face=1, cursor_pos=Vector3(8, 8, 8)): | ||
self.net.push_packet('PLAY>Player Block Placement', { | ||
'location': pos.get_dict(), | ||
'direction': face, | ||
'held_item': self.inventory.active_slot.get_dict(), | ||
'cur_pos_x': int(cursor_pos.x), | ||
'cur_pos_y': int(cursor_pos.y), | ||
'cur_pos_z': int(cursor_pos.z), | ||
}) | ||
|
||
def click_block(self, pos, face=1, cursor_pos=Vector3(8, 8, 8), | ||
look_at_block=True, swing=True): | ||
""" | ||
Click on a block. | ||
Examples: push button, open window, make redstone ore glow | ||
:param face: side of the block on which the block is placed on | ||
:param cursor_pos: where to click inside the block, each dimension 0-15 | ||
""" | ||
if look_at_block and self.auto_look: | ||
# TODO look at cursor_pos | ||
self.look_at(pos) | ||
self._send_click_block(pos, face, cursor_pos) | ||
if swing and self.auto_swing: | ||
self.swing_arm() | ||
|
||
def place_block(self, pos, face=1, cursor_pos=Vector3(8, 8, 8), | ||
sneak=True, look_at_block=True, swing=True): | ||
""" | ||
Place a block next to pos. If the block at pos is air, place at pos. | ||
""" | ||
sneaking_before = self.sneaking | ||
if sneak: | ||
self.sneak() | ||
self.click_block(pos, face, cursor_pos, look_at_block, swing) | ||
if sneak: | ||
self.sneak(sneaking_before) | ||
|
||
def use_bucket(self, pos): # TODO | ||
""" | ||
Using buckets is different from placing blocks. | ||
See "Special note on using buckets" | ||
in http://wiki.vg/Protocol#Player_Block_Placement | ||
""" | ||
raise NotImplementedError(self.use_bucket.__doc__) | ||
|
||
def activate_item(self): | ||
""" | ||
Use (hold right-click) the item in the active slot. | ||
Examples: pull the bow, start eating once, throw an egg. | ||
""" | ||
self._send_click_block(pos=Vector3(-1, 255, -1), | ||
face=-1, | ||
cursor_pos=Vector3(-1, -1, -1)) | ||
|
||
def deactivate_item(self): | ||
""" | ||
Stop using (release right-click) the item in the active slot. | ||
Examples: shoot the bow, stop eating. | ||
""" | ||
self._send_dig_block(DIG_DEACTIVATE_ITEM) | ||
|
||
def use_entity(self, entity, cursor_pos=None, action=INTERACT_ENTITY): | ||
""" | ||
Uses (right-click) an entity to open its window. | ||
Setting `cursor_pos` sets `action` to "interact at". | ||
""" | ||
if self.auto_look: | ||
self.look_at(Vector3(entity)) # TODO look at cursor_pos | ||
if cursor_pos is not None: | ||
action = INTERACT_ENTITY_AT | ||
packet = {'target': entity.eid, 'action': action} | ||
if action == INTERACT_ENTITY_AT: | ||
packet['target_x'] = cursor_pos.x | ||
packet['target_y'] = cursor_pos.y | ||
packet['target_z'] = cursor_pos.z | ||
self.net.push_packet('PLAY>Use Entity', packet) | ||
if self.auto_swing: | ||
self.swing_arm() | ||
|
||
def attack_entity(self, entity): | ||
self.use_entity(entity, action=ATTACK_ENTITY) | ||
|
||
def mount_vehicle(self, entity): | ||
self.use_entity(entity) | ||
|
||
def steer_vehicle(self, sideways=0.0, forward=0.0, | ||
jump=False, unmount=False): | ||
flags = 0 | ||
if jump: | ||
flags += 1 | ||
if unmount: | ||
flags += 2 | ||
self.net.push_packet('PLAY>Steer Vehicle', { | ||
'sideways': sideways, | ||
'forward': forward, | ||
'flags': flags, | ||
}) | ||
|
||
def unmount_vehicle(self): | ||
self.steer_vehicle(unmount=True) | ||
|
||
def jump_vehicle(self): | ||
self.steer_vehicle(jump=True) |
Empty file.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this should be
timer
instead oftimers
? The rest are singularThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Problem is that every plugin requires it with "Timers". This would have to be changed everywhere.
But I agree, keeping it consistent would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats not how that value works, that value is just for the settings dict that gets passed into Client, so that can be changed without much consequence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd still like it to be the same as in Timer's
pl_announce
.