import time import unittest from munch import Munch from minecraft.networking.modern import BlockEventPacket from mosfet.game import Game from mosfet.protocol.managers import ChestOpenManager class FakeConnection: def __init__(self): self.registry_ids = {'minecraft:block': { 'minecraft:stone': 1, 'minecraft:chest': 2, 'minecraft:trapped_chest': 3, }} self.listeners = [] def register_packet_listener(self, handler, packet_type): self.listeners.append((handler, packet_type)) class ChestDetectionTests(unittest.TestCase): def setUp(self): self.connection = FakeConnection() self.g = Munch(connection=self.connection) self.manager = ChestOpenManager(self.g) self.position = (12, 64, -7) def event(self, block_id=2, action=1, viewers=1, position=None): x, y, z = position or self.position return Munch( location=Munch(x=x, y=y, z=z), block_id=block_id, action=action, parameter=viewers, ) def test_registers_block_event_packet_and_records_other_player_open(self): self.assertIn((self.manager.handle_block_event, BlockEventPacket), self.connection.listeners) self.manager.handle_block_event(self.event(viewers=1)) self.assertEqual(self.g.chest_viewers[self.position], 1) self.assertEqual(self.g.last_chest_opened_by_other['position'], self.position) self.assertEqual(self.g.last_chest_opened_by_other['block'], 'chest') self.assertEqual(len(self.g.chest_open_events), 1) def test_bot_open_is_not_misreported_but_later_viewer_is(self): self.g.pending_chest_open = { 'position': self.position, 'requested_at': time.monotonic(), } self.manager.handle_block_event(self.event(viewers=1)) self.assertIsNone(self.g.last_chest_opened_by_other) self.assertIsNotNone(self.g.pending_chest_open) self.manager.handle_block_event(self.event(viewers=2)) self.assertEqual(self.g.last_chest_opened_by_other['viewers'], 2) self.assertEqual(self.g.last_chest_opened_by_other['previous_viewers'], 1) def test_bot_open_of_either_double_chest_half_is_not_misreported(self): other_half = (13, 64, -7) self.g.pending_chest_open = { 'position': self.position, 'positions': (self.position, other_half), 'requested_at': time.monotonic(), } self.manager.handle_block_event( self.event(position=other_half, viewers=1)) self.assertIsNone(self.g.last_chest_opened_by_other) self.assertIsNotNone(self.g.pending_chest_open) self.assertEqual(self.g.chest_viewers[other_half], 1) def test_ignores_non_chests_and_tracks_close(self): self.manager.handle_block_event(self.event(block_id=1, viewers=1)) self.assertIsNone(self.g.last_chest_opened_by_other) self.manager.handle_block_event(self.event(viewers=1)) self.manager.handle_block_event(self.event(viewers=0)) self.assertNotIn(self.position, self.g.chest_viewers) self.assertEqual(len(self.g.chest_open_events), 1) def test_open_container_marks_bot_initiated_chest_open(self): sent = [] game = Game.__new__(Game) other_half = (12, 64, -8) game.g = Munch( chunks=Munch(get_block_at=lambda *_position: None), world=Munch(_double_chest_positions=lambda _position: (self.position,))) game.place_block = lambda location, face, **kwargs: sent.append( (location, face, kwargs)) game.open_container(self.position) self.assertEqual(sent[0][0], self.position) self.assertEqual(game.g.pending_chest_open['position'], self.position) self.assertIn(self.position, game.g.pending_chest_open['positions']) self.assertIn(other_half, game.g.pending_chest_open['positions']) self.assertIsInstance(game.g.pending_chest_open['requested_at'], float) if __name__ == '__main__': unittest.main()