diff --git a/mosfet/bot.py b/mosfet/bot.py index 2652e92..a8eb0b5 100644 --- a/mosfet/bot.py +++ b/mosfet/bot.py @@ -57,6 +57,26 @@ PITCH_ANGLE_DIR = vector.Vector3D((0, 1, 0)) YAW_ANGLE_DIR = vector.Vector3D((0, 0, -1)) YAW_ANGLE_REF = vector.Vector3D((0, 1, 0)) YAW_LOOK_AHEAD = 4 +FARMING_PITCH = 45.0 + + +def pitch_lock_for_job(job_state): + state = getattr(job_state, 'state', None) if job_state else None + return (FARMING_PITCH if getattr(state, '__name__', None) == 'farm_crop' + else None) + + +def update_pitch(g, look_at_d, fixed_pitch=None): + if fixed_pitch is not None: + target_pitch = fixed_pitch + elif look_at_d is None: + target_pitch = 0.0 + elif look_at_d.length() > 0.6: + target_pitch = look_at_d.normalized().angleDeg(PITCH_ANGLE_DIR) + target_pitch = (target_pitch - 90) * -1 + else: + return + g.pitch += utils.cap(target_pitch - g.pitch, 10) def missing_movement_chunks(g): @@ -218,16 +238,12 @@ def tick(global_state): else: look_at = None + pitch_lock = pitch_lock_for_job(g.get('job')) if look_at: look_at.x += 0.5 look_at.z += 0.5 look_at_d = p - look_at - - if look_at_d.length() > 0.6: - target_pitch = look_at_d.normalized().angleDeg(PITCH_ANGLE_DIR) - target_pitch = (target_pitch - 90) * -1 - target_pitch_d = target_pitch - g.pitch - g.pitch += utils.cap(target_pitch_d, 10) + update_pitch(g, look_at_d, pitch_lock) # remove vertical component for yaw calculation look_at_d.y = 0 @@ -238,8 +254,7 @@ def tick(global_state): target_yaw_d = (target_yaw_d + 180) % 360 - 180 g.yaw += utils.cap(target_yaw_d, 30) else: - target_pitch_d = 0 - g.pitch - g.pitch += utils.cap(target_pitch_d, 10) + update_pitch(g, None, pitch_lock) from minecraft.networking.modern import ( ClientTickEnd, PlayerPositionRotation, diff --git a/tests/test_farming_pitch.py b/tests/test_farming_pitch.py new file mode 100644 index 0000000..bed7be8 --- /dev/null +++ b/tests/test_farming_pitch.py @@ -0,0 +1,33 @@ +import unittest + +from munch import Munch + +from mosfet.bot import FARMING_PITCH, pitch_lock_for_job, update_pitch + + +class TestFarmingPitch(unittest.TestCase): + def test_only_crop_farming_locks_pitch(self): + def farm_crop(): + pass + + def sleep(): + pass + + self.assertEqual( + pitch_lock_for_job(Munch(state=farm_crop)), FARMING_PITCH) + self.assertIsNone(pitch_lock_for_job(Munch(state=sleep))) + self.assertIsNone(pitch_lock_for_job(None)) + + def test_pitch_is_held_at_45_despite_look_target_changes(self): + state = Munch(pitch=0.0) + for _ in range(5): + update_pitch(state, object(), FARMING_PITCH) + self.assertEqual(state.pitch, 45.0) + + # Without the farming lock, ordinary look behavior is restored. + update_pitch(state, None) + self.assertEqual(state.pitch, 35.0) + + +if __name__ == '__main__': + unittest.main()