Files
minecraft-bot/tests/test_signs.py
T

197 lines
7.8 KiB
Python

import unittest
from unittest.mock import patch
from munch import Munch
from mosfet.commands import Commands
from mosfet.info import blocks
from mosfet.protocol.managers import EntityManager, WorldState
from mosfet.world import World
class SignReadingTests(unittest.TestCase):
def test_world_decodes_front_and_back_sign_components(self):
chunks = Munch(block_entities={
(2, 64, 3): {
'type': 7,
'data': {
'front_text': {'messages': [
'{"text":"Hello","extra":[{"text":" world"}]}',
'{"text":"line two"}', '', ''],
},
'back_text': {'messages': [
'{"text":"back"}', '', '', ''],
},
},
},
})
signs = World(Munch(chunks=chunks)).find_signs((0, 64, 0), 10)
self.assertEqual(signs, [
{'position': (2, 64, 3), 'side': 'front',
'lines': ('Hello world', 'line two', '', '')},
{'position': (2, 64, 3), 'side': 'back',
'lines': ('back', '', '', '')},
])
def test_block_entity_update_is_cached_for_sign_search(self):
chunks = WorldState()
manager = object.__new__(EntityManager)
manager.g = Munch(chunks=chunks)
manager.handle_block_entity_data(Munch(
location=Munch(x=4, y=65, z=-2),
block_entity_type=7,
data={'front_text': {'messages': ['{"text":"Farm"}', '', '', '']}},
))
signs = World(Munch(chunks=chunks)).find_signs((4, 65, -2), 1)
self.assertEqual(signs[0]['lines'], ('Farm', '', '', ''))
def test_broken_sign_block_update_removes_cached_sign_entity(self):
position = (4, 65, -2)
sign_state = blocks.MCD_BLOCKS['oak_wall_sign']['minStateId']
class FakeColumn:
def __init__(self):
self.states = {}
def get_block_at(self, x, y, z):
return self.states.get((x, y, z), blocks.AIR)
def set_block_at(self, x, y, z, state_id):
previous = self.get_block_at(x, y, z)
self.states[(x, y, z)] = state_id
return previous
chunks = WorldState()
chunks.chunks[(0, -1)] = FakeColumn()
chunks.set_block_at(*position, sign_state)
chunks.set_block_entity(position, 7, {
'front_text': {'messages': ['mosfet1 stay', 'within 8 square', '', '']},
})
world = World(Munch(chunks=chunks))
self.assertEqual(len(world.find_signs(position, 1)), 1)
chunks.set_block_at(*position, blocks.AIR)
self.assertNotIn(position, chunks.block_entities)
self.assertEqual(world.find_signs(position, 1), [])
def test_sign_search_ignores_stale_block_entity_for_non_sign_block(self):
position = (4, 65, -2)
chunks = Munch(
block_entities={position: {'data': {'front_text': {
'messages': ['mosfet1 stay', 'within 8 square', '', ''],
}}}},
get_block_at=lambda *_position: blocks.AIR,
)
self.assertEqual(World(Munch(chunks=chunks)).find_signs(position, 1), [])
def test_group_and_individual_sign_addresses(self):
group_world = World(Munch(chunks=Munch(block_entities={
(0, 64, 0): {'data': {'front_text': {'messages': [
'mosfet', 'stay within25', 'square', '',
]}}},
}), pos=(0, 64, 0)))
for bot_name in ('mosfet1', 'mosfet2', 'mosfet3'):
self.assertEqual([p['shape'] for p in
group_world.sign_policies(bot_name)], ['square'])
self.assertEqual(group_world.sign_policies('mosfet4'), [])
individual_world = World(Munch(chunks=Munch(block_entities={
(1, 64, 0): {'data': {'front_text': {'messages': [
'mosfet2', 'stay within 10 circle', '', '',
]}}},
}), pos=(1, 64, 0)))
self.assertEqual([p['shape'] for p in
individual_world.sign_policies('mosfet2')], ['circle'])
self.assertEqual(individual_world.sign_policies('mosfet1'), [])
def test_nearest_sign_policy_overrides_farther_matching_sign(self):
chunks = Munch(block_entities={
(-138, 71, -268): {'data': {'front_text': {'messages': [
'mosfet1', 'stay within 25 square', '', '',
]}}},
(-158, 71, -248): {'data': {'front_text': {'messages': [
'mosfet1', 'stay within 6 squares', '', '',
]}}},
})
world = World(Munch(chunks=chunks, pos=(-158, 71, -248)))
self.assertEqual(world.sign_policies('mosfet1'), [{
'position': (-158, 71, -248), 'distance': 6,
'shape': 'square', 'side': 'front',
}])
def test_work_paths_obey_sign_boundary_but_cache_paths_do_not(self):
sign_data = {'front_text': {'messages': [
'mosfet1', 'stay within 25 square', '', '',
]}}
chunks = Munch(block_entities={(0, 64, 0): {'data': sign_data}})
work_machine = object()
cache_machine = object()
job = Munch(active_machine=work_machine,
cache_items_states=cache_machine)
world = World(Munch(chunks=chunks, job=job, name='mosfet1',
pos=(0, 64, 0)))
class FixedPathfinder:
@staticmethod
def astar(_start, _place):
return [(0, 64, 0), (20, 64, 0), (30, 64, 0)]
with patch('mosfet.world.path.Pathfinder', return_value=FixedPathfinder()):
self.assertIsNone(world.path_to_place((0, 64, 0), (30, 64, 0)))
job.active_machine = cache_machine
self.assertEqual(world.path_to_place(
(0, 64, 0), (30, 64, 0)),
[(0, 64, 0), (20, 64, 0), (30, 64, 0)])
policy = {'position': (0, 64, 0), 'distance': 25, 'shape': 'square'}
self.assertTrue(World._path_allowed_by_sign(
[(30, 64, 0), (27, 64, 0), (24, 64, 0)], policy))
self.assertFalse(World._path_allowed_by_sign(
[(30, 64, 0), (32, 64, 0), (24, 64, 0)], policy))
six_square = {'position': (-158, 71, -248),
'distance': 6, 'shape': 'square'}
six_circle = dict(six_square, shape='circle')
crop = (-162, 68, -247)
self.assertEqual(World._sign_policy_distance(crop, six_square), 4)
self.assertAlmostEqual(World._sign_policy_distance(crop, six_circle),
(17 ** 0.5))
four_square = {'position': (0, 64, 0),
'distance': 4, 'shape': 'square'}
self.assertEqual(World._sign_policy_distance((4, 70, 4), four_square), 4)
self.assertTrue(World._inside_sign_policy((4, 70, 4), four_square))
self.assertFalse(World._inside_sign_policy((5, 64, 4), four_square))
same_xz_far_y = (-158, -20, -248)
self.assertEqual(
World._sign_policy_distance(same_xz_far_y, six_square), 0)
def test_signs_command_replies_with_nearby_text(self):
class FakeChat:
def __init__(self):
self.sent = []
def set_handler(self, handler):
self.handler = handler
def send(self, message):
self.sent.append(message)
chat = FakeChat()
world = Munch(find_signs=lambda _position, _distance: [{
'position': (1, 64, 2), 'side': 'front',
'lines': ('Hello', 'world', '', ''),
}])
commands = Commands(Munch(
name='mosfet1', chat=chat, world=world, pos=(0.5, 64.0, 0.5)))
commands.handle_chat(('CHAT', 'tester', 'tester: !signs'))
self.assertEqual(chat.sent, ['front (1, 64, 2): Hello | world'])
if __name__ == '__main__':
unittest.main()