Port and tune 26.3 wood farming
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import math
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from munch import Munch
|
||||
|
||||
from mosfet import utils
|
||||
from mosfet.game import Game
|
||||
from mosfet.info import blocks, items
|
||||
|
||||
|
||||
class BlockBreakTimingTests(unittest.TestCase):
|
||||
def test_leaf_time_uses_actual_tool_speed_and_game_ticks(self):
|
||||
oak_leaves = blocks.MCD_BLOCKS['oak_leaves']['minStateId']
|
||||
oak_log = items.get_id('oak_log')
|
||||
wooden_hoe = items.get_id('wooden_hoe')
|
||||
|
||||
self.assertAlmostEqual(utils.break_time(oak_leaves, oak_log), 0.3)
|
||||
self.assertAlmostEqual(utils.break_time(oak_leaves, wooden_hoe), 0.15)
|
||||
self.assertAlmostEqual(
|
||||
utils.break_time(oak_leaves, oak_log, in_water=True), 1.5)
|
||||
self.assertAlmostEqual(
|
||||
utils.break_time(oak_leaves, oak_log, on_ground=False), 1.5)
|
||||
|
||||
def test_efficiency_haste_and_fatigue_affect_break_ticks(self):
|
||||
oak_leaves = blocks.MCD_BLOCKS['oak_leaves']['minStateId']
|
||||
wooden_hoe = items.get_id('wooden_hoe')
|
||||
self.assertAlmostEqual(utils.break_time(
|
||||
oak_leaves, wooden_hoe, enchantments={'efficiency': 1}), 0.1)
|
||||
self.assertAlmostEqual(utils.break_time(
|
||||
oak_leaves, wooden_hoe, effects={'haste': 0}), 0.15)
|
||||
self.assertAlmostEqual(utils.break_time(
|
||||
oak_leaves, wooden_hoe,
|
||||
effects={'mining_fatigue': 0}), 0.5)
|
||||
|
||||
def test_unbreakable_blocks_have_no_completion_deadline(self):
|
||||
bedrock = blocks.MCD_BLOCKS['bedrock']['minStateId']
|
||||
self.assertTrue(math.isinf(utils.break_time(bedrock)))
|
||||
|
||||
def test_game_sends_finish_after_calculated_tick_duration(self):
|
||||
class RecordingConnection:
|
||||
def __init__(self):
|
||||
self.packets = []
|
||||
|
||||
def write_packet(self, packet, force=False):
|
||||
self.packets.append(packet)
|
||||
|
||||
class FakeChunks:
|
||||
@staticmethod
|
||||
def get_block_at(*_position):
|
||||
return blocks.MCD_BLOCKS['oak_leaves']['minStateId']
|
||||
|
||||
connection = RecordingConnection()
|
||||
game = object.__new__(Game)
|
||||
game.g = Munch(
|
||||
connection=connection, chunks=FakeChunks(), inv={},
|
||||
holding=items.get_id('oak_log'), holding_hand=0,
|
||||
holding_slot=0)
|
||||
game.sequence = 0
|
||||
game.break_deadline = None
|
||||
game.breaking_state = None
|
||||
game.next_swing_at = 0.0
|
||||
|
||||
with patch('mosfet.game.time.monotonic', return_value=100.0):
|
||||
self.assertTrue(game.break_block((0, 64, 0)))
|
||||
self.assertAlmostEqual(game.break_deadline, 100.3)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,37 @@
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from munch import Munch
|
||||
|
||||
from mosfet.jobs.clear_leaves import ClearLeavesStates
|
||||
|
||||
|
||||
class ClearLeavesTests(unittest.TestCase):
|
||||
def test_spaces_leaf_breaks_at_configured_interval(self):
|
||||
class FakeGame:
|
||||
def __init__(self):
|
||||
self.broken = []
|
||||
|
||||
def break_block(self, location):
|
||||
self.broken.append(location)
|
||||
return True
|
||||
|
||||
game = FakeGame()
|
||||
state = ClearLeavesStates(Munch(
|
||||
breaking=False, game=game, look_at=None))
|
||||
state.leaves = [(0, 64, 0), (1, 64, 0)]
|
||||
|
||||
with patch('mosfet.jobs.clear_leaves.time.monotonic', return_value=10):
|
||||
state.break_leaves()
|
||||
self.assertEqual(game.broken, [(0, 64, 0)])
|
||||
|
||||
with patch('mosfet.jobs.clear_leaves.time.monotonic', return_value=10.59):
|
||||
state.break_leaves()
|
||||
self.assertEqual(game.broken, [(0, 64, 0)])
|
||||
|
||||
with patch('mosfet.jobs.clear_leaves.time.monotonic', return_value=10.6):
|
||||
state.break_leaves()
|
||||
self.assertEqual(game.broken, [(0, 64, 0), (1, 64, 0)])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,9 +1,15 @@
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from munch import Munch
|
||||
|
||||
from mosfet.bot import start_automation
|
||||
from mosfet.commands import Commands
|
||||
from mosfet.info import blocks, items
|
||||
from mosfet.job import JobStates
|
||||
from mosfet.jobs.gather_wood import GatherWoodStates
|
||||
from mosfet.jobs.grab_supplies import GrabSuppliesStates
|
||||
from mosfet.protocol.types import Slot
|
||||
from mosfet.world import World
|
||||
|
||||
|
||||
@@ -21,6 +27,27 @@ class GatherWoodPortTests(unittest.TestCase):
|
||||
self.assertTrue(blocks.LOG_IDS)
|
||||
self.assertTrue(blocks.LOG_IDS.issubset(blocks.INDEXED_IDS))
|
||||
|
||||
def test_mangrove_uses_its_26_3_propagule_and_unplantable_logs_are_skipped(self):
|
||||
self.assertEqual(items.get_sapling_id('mangrove'),
|
||||
items.get_id('mangrove_propagule'))
|
||||
self.assertIsNone(items.get_sapling_id('crimson'))
|
||||
|
||||
class FakeWorld:
|
||||
def find_trees(self, _position, _distance):
|
||||
return [(0, 64, 0), (3, 64, 0)]
|
||||
|
||||
def block_at(self, x, y, z):
|
||||
return (blocks.MCD_BLOCKS['crimson_stem']['minStateId']
|
||||
if x == 0 else
|
||||
blocks.MCD_BLOCKS['mangrove_log']['minStateId'])
|
||||
|
||||
state = GatherWoodStates(
|
||||
Munch(world=FakeWorld(), pos=(0, 64, 0)))
|
||||
state.find_new_tree()
|
||||
self.assertEqual(state.tree, (3, 64, 0))
|
||||
self.assertEqual(state.type, 'mangrove')
|
||||
self.assertEqual(state.bad_trees, [(0, 64, 0)])
|
||||
|
||||
def test_tree_search_finds_indexed_26_3_log_states(self):
|
||||
oak_log = blocks.MCD_BLOCKS['oak_log']['minStateId']
|
||||
oak_leaves = blocks.MCD_BLOCKS['oak_leaves']['minStateId']
|
||||
@@ -54,7 +81,76 @@ class GatherWoodPortTests(unittest.TestCase):
|
||||
self.assertIs(job.gather_wood_states.state.__func__,
|
||||
job.gather_wood_states.idle.__func__)
|
||||
|
||||
def test_gather_wood_command_is_enabled_but_farm_wood_is_not(self):
|
||||
def test_grab_supplies_reads_protocol_777_container_shape(self):
|
||||
axe_id = next(iter(items.AXE_IDS))
|
||||
axe = Slot(present=True, item_id=axe_id, item_count=1)
|
||||
clicks = []
|
||||
|
||||
class FakeGame:
|
||||
def count_inventory_slots(self):
|
||||
return 10
|
||||
|
||||
def click_window(self, *args):
|
||||
clicks.append(args)
|
||||
|
||||
g = Munch(
|
||||
item_lock=False,
|
||||
window=Munch(container_slots=27, contents={0: axe}),
|
||||
maximum_supply_slots=33,
|
||||
game=FakeGame(),
|
||||
)
|
||||
state = GrabSuppliesStates(g)
|
||||
state.target_items = {axe_id}
|
||||
state.maximum_stacks = 9
|
||||
state.grab_items()
|
||||
|
||||
self.assertTrue(g.item_lock)
|
||||
self.assertEqual(state.count, 1)
|
||||
self.assertEqual(clicks, [(0, 0, 1, axe)])
|
||||
|
||||
def test_modern_automation_sets_supply_inventory_limit(self):
|
||||
g = Munch()
|
||||
with patch('mosfet.bot.threading.Thread') as thread:
|
||||
start_automation(g, initialize=False)
|
||||
self.assertEqual(g.maximum_supply_slots, 33)
|
||||
thread.return_value.start.assert_called_once()
|
||||
|
||||
def test_farm_wood_job_keeps_legacy_machine_sequence(self):
|
||||
job = JobStates(Munch())
|
||||
try:
|
||||
self.assertEqual(job.farm_wood(), [
|
||||
job.grab_supplies_states,
|
||||
job.gather_wood_states,
|
||||
job.clear_leaves_states,
|
||||
job.plant_tree_states,
|
||||
job.grab_sapling_states,
|
||||
job.sleep_with_bed_states,
|
||||
job.eat_food_states,
|
||||
job.cache_items_states,
|
||||
])
|
||||
self.assertEqual(job.grab_supplies_states.supplies, {
|
||||
tuple(items.AXE_IDS): (1, 9),
|
||||
})
|
||||
self.assertTrue(job.sleep_with_bed_states.silent)
|
||||
self.assertTrue(job.cache_items_states.silent)
|
||||
self.assertTrue(items.AXE_IDS.issubset(items.NEEDED_ITEMS))
|
||||
self.assertTrue(items.SAPLING_IDS.issubset(items.WANTED_ITEMS))
|
||||
|
||||
job.grab_supplies_states.state = job.grab_supplies_states.find_barrels
|
||||
job.clear_leaves_states.state = job.clear_leaves_states.find_leaves
|
||||
job.plant_tree_states.state = job.plant_tree_states.check_feet
|
||||
job.grab_sapling_states.state = job.grab_sapling_states.find_saplings
|
||||
job.stop()
|
||||
for machine in (job.grab_supplies_states,
|
||||
job.clear_leaves_states,
|
||||
job.plant_tree_states,
|
||||
job.grab_sapling_states):
|
||||
self.assertIs(machine.state.__func__, machine.idle.__func__)
|
||||
finally:
|
||||
items.set_needed(set())
|
||||
items.set_wanted(set())
|
||||
|
||||
def test_gather_and_farm_wood_commands_are_enabled(self):
|
||||
class FakeChat:
|
||||
def __init__(self):
|
||||
self.sent = []
|
||||
@@ -75,7 +171,8 @@ class GatherWoodPortTests(unittest.TestCase):
|
||||
|
||||
chat.sent.clear()
|
||||
Commands(g).handle_chat(('CHAT', 'tester', 'tester: 1farm wood'))
|
||||
self.assertEqual(chat.sent, ['not migrated to Minecraft 26.3 yet'])
|
||||
self.assertEqual(chat.sent, ['ok'])
|
||||
self.assertIs(job.state.__func__, job.farm_wood.__func__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import io
|
||||
import unittest
|
||||
from munch import Munch
|
||||
|
||||
from minecraft.networking.modern import (
|
||||
ModernPlayingReactor, SetEntityDataPacket,
|
||||
)
|
||||
from mosfet.info import items
|
||||
from mosfet.protocol.managers import EntityManager
|
||||
from mosfet.world import World
|
||||
|
||||
|
||||
def encode_varint(value):
|
||||
encoded = bytearray()
|
||||
while value & ~0x7F:
|
||||
encoded.append((value & 0x7F) | 0x80)
|
||||
value >>= 7
|
||||
encoded.append(value)
|
||||
return bytes(encoded)
|
||||
|
||||
|
||||
class SaplingEntityTests(unittest.TestCase):
|
||||
def test_protocol_777_item_metadata_decodes_item_stack(self):
|
||||
sapling_id = items.get_id('oak_sapling')
|
||||
payload = (
|
||||
encode_varint(42) +
|
||||
bytes((8,)) + encode_varint(7) +
|
||||
encode_varint(1) + encode_varint(sapling_id) +
|
||||
encode_varint(0) + encode_varint(0) +
|
||||
bytes((0xFF,))
|
||||
)
|
||||
packet = SetEntityDataPacket()
|
||||
packet.read(io.BytesIO(payload))
|
||||
|
||||
self.assertEqual(packet.entity_id, 42)
|
||||
self.assertEqual(len(packet.item_stacks), 1)
|
||||
self.assertEqual(packet.item_stacks[0].item_id, sapling_id)
|
||||
self.assertIn(SetEntityDataPacket,
|
||||
ModernPlayingReactor.get_clientbound_packets(None))
|
||||
|
||||
def test_item_metadata_makes_dropped_sapling_searchable(self):
|
||||
sapling_id = items.get_id('oak_sapling')
|
||||
entity = Munch(entity_id=42, x=1.0, y=65.0, z=2.0)
|
||||
manager = object.__new__(EntityManager)
|
||||
manager.g = Munch(objects={42: entity})
|
||||
packet = Munch(
|
||||
entity_id=42,
|
||||
item_stacks=[Munch(present=True, item_id=sapling_id,
|
||||
item_count=1)],
|
||||
)
|
||||
manager.handle_entity_data(packet)
|
||||
|
||||
found = World(Munch(objects={42: entity})).find_objects(
|
||||
items.SAPLING_IDS)
|
||||
self.assertEqual(found, [entity])
|
||||
self.assertEqual(entity.item_count, 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user