"""
MovementPlugin provides a centralized plugin for controlling all outgoing
position packets so the client doesn't try to pull itself in a dozen
directions.
Also provides very basic pathfinding
"""

import logging
import math

from spock.plugins.base import PluginBase
from spock.utils import Position, pl_announce

logger = logging.getLogger('spock')


class MovementCore(object):
    def __init__(self):
        self.move_location = None

    def move_to(self, x, y, z):
        self.move_location = Position(x, y, z)


@pl_announce('Movement')
class MovementPlugin(PluginBase):
    requires = ('Net', 'Physics', 'ClientInfo')
    events = {
        'client_tick': 'client_tick',
        'action_tick': 'action_tick',
        'cl_position_update': 'handle_position_update',
        'phy_collision': 'handle_collision',
    }

    def __init__(self, ploader, settings):
        super(MovementPlugin, self).__init__(ploader, settings)

        self.movement = MovementCore()
        ploader.provides('Movement', self.movement)

    def client_tick(self, name, data):
        self.net.push_packet('PLAY>Player Position',
                             self.clientinfo.position.get_dict())

    def handle_position_update(self, name, data):
        self.net.push_packet('PLAY>Player Position and Look', data.get_dict())

    def handle_collision(self, name, data):
        if self.movement.move_location is not None:
            self.physics.jump()

    def action_tick(self, name, data):
        self.do_pathfinding()

    def do_pathfinding(self):
        if self.movement.move_location is not None:
            if self.movement.move_location.x == math.floor(
                    self.clientinfo.position.x) and \
                    self.movement.move_location.z == math.floor(
                    self.clientinfo.position.z):
                self.movement.move_location = None
            else:
                dx = self.movement.move_location.x - self.clientinfo.position.x
                dz = self.movement.move_location.z - self.clientinfo.position.z
                deg = 0
                if abs(dx) >= abs(dz):
                    # we should go along x
                    if dx > 0:
                        # go positive x
                        deg = 90
                    else:
                        # go neg x
                        deg = 270

                elif abs(dx) < abs(dz):
                    # we should go along z
                    if dz > 0:
                        # go positive z
                        deg = 0
                    else:
                        # go neg z
                        deg = 180

                self.physics.walk(deg)

@@ -291,18 +291,8 @@
 port
- Position,
  pl_
@@ -299,16 +299,49 @@
 announce
+%0Afrom spock.vector import Vector3
 %0A%0Alogger
@@ -520,24 +520,23 @@
 ation = 
-Position
+Vector3
 (x, y, z
@@ -1563,34 +1563,38 @@
 (self):%0A        
-if
+move =
  self.movement.m
@@ -1583,32 +1583,81 @@
  = self.movement
+%0A        clinfo = self.clientinfo%0A        if move
 .move_location i
@@ -1679,37 +1679,28 @@
          if 
-self.movement
+move
 .move_locati
@@ -1722,40 +1722,10 @@
 oor(
-%0A                    self.client
+cl
 info
@@ -1736,20 +1736,16 @@
 ition.x)
- and
  %5C%0A     
@@ -1755,37 +1755,32 @@
             
-self.movement
+and move
 .move_locati
@@ -1802,40 +1802,10 @@
 oor(
-%0A                    self.client
+cl
 info
@@ -1834,29 +1834,20 @@
         
-self.movement
+move
 .move_lo
@@ -1899,29 +1899,20 @@
    dx = 
-self.movement
+move
 .move_lo
@@ -1922,27 +1922,18 @@
 ion.x - 
-self.client
+cl
 info.pos
@@ -1961,29 +1961,20 @@
    dz = 
-self.movement
+move
 .move_lo
@@ -1984,27 +1984,18 @@
 ion.z - 
-self.client
+cl
 info.pos

Use Vector3 in MovementPlugin