Track reopened supply chests and fix API snapshots
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
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):
|
||||
x, y, z = 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.assertIsNone(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_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):
|
||||
chest_state = 5552
|
||||
sent = []
|
||||
game = Game.__new__(Game)
|
||||
game.g = Munch(chunks=Munch(
|
||||
get_block_at=lambda *_position: chest_state))
|
||||
game.place_block = lambda location, face: sent.append(
|
||||
(location, face))
|
||||
|
||||
game.open_container(self.position)
|
||||
|
||||
self.assertEqual(sent[0][0], self.position)
|
||||
self.assertEqual(game.g.pending_chest_open['position'], self.position)
|
||||
self.assertIsInstance(game.g.pending_chest_open['requested_at'], float)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -78,6 +78,44 @@ class GroundSupplyTests(unittest.TestCase):
|
||||
self.assertEqual(state.chest, position)
|
||||
self.assertIs(state.state.__func__, state.path_to_supply_chest.__func__)
|
||||
|
||||
def test_empty_supply_chest_is_skipped_until_another_player_opens_it(self):
|
||||
position = (4, 64, 0)
|
||||
key = (position,)
|
||||
event = {'position': position, 'timestamp': 1.0}
|
||||
g = Munch(chest_open_events=[])
|
||||
state = GrabSuppliesStates(g)
|
||||
state.supplies = {(999999,): (1, 1)}
|
||||
state.current_supply_chest_key = key
|
||||
|
||||
class FakeGame:
|
||||
@staticmethod
|
||||
def count_items(_item_ids):
|
||||
return 1
|
||||
|
||||
state.g.game = FakeGame()
|
||||
state.choose_items()
|
||||
self.assertIn(key, state.useless_chests)
|
||||
self.assertIs(state.state.__func__, state.close_supply_chest.__func__)
|
||||
|
||||
second_position = (8, 64, 0)
|
||||
state.supply_chests = [
|
||||
{'position': position, 'positions': key},
|
||||
{'position': second_position, 'positions': (second_position,)},
|
||||
]
|
||||
state.checked_supply_chests = {key}
|
||||
state.choose_supply_chest()
|
||||
self.assertEqual(state.chest, second_position)
|
||||
|
||||
g.chest_open_events.append(event)
|
||||
state.state = state.idle
|
||||
state.run()
|
||||
self.assertNotIn(key, state.useless_chests)
|
||||
self.assertNotIn(key, state.checked_supply_chests)
|
||||
|
||||
state.supply_chests = [{'position': position, 'positions': key}]
|
||||
state.choose_supply_chest()
|
||||
self.assertEqual(state.chest, position)
|
||||
|
||||
def test_unreachable_supply_chest_ends_task_without_searching_barrels(self):
|
||||
class FakeWorld:
|
||||
@staticmethod
|
||||
|
||||
@@ -31,7 +31,8 @@ class TestWebInventoryAPI(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.g = mosfet_web.g
|
||||
self.original = {
|
||||
key: self.g.get(key) for key in ('connected', 'game', 'inv')
|
||||
key: self.g.get(key) for key in
|
||||
('connected', 'game', 'inv', 'chest_viewers')
|
||||
}
|
||||
self.game = FakeGame()
|
||||
self.g.connected = True
|
||||
@@ -53,6 +54,16 @@ class TestWebInventoryAPI(unittest.TestCase):
|
||||
item = response.get_json()['inv']['9']
|
||||
self.assertEqual(item['components']['custom_name']['text'], 'Test Paper')
|
||||
|
||||
def test_global_api_stringifies_tuple_keys(self):
|
||||
self.g.chest_viewers = {(12, 64, -7): 1}
|
||||
|
||||
response = self.client.get('/api/global')
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.get_json()['chest_viewers'], {
|
||||
'(12, 64, -7)': 1,
|
||||
})
|
||||
|
||||
def test_drop_endpoint_supports_one_stack_and_matching_actions(self):
|
||||
one = self.client.post('/api/inventory/drop', json={
|
||||
'slot': 9, 'action': 'one'})
|
||||
|
||||
Reference in New Issue
Block a user