Cache after sleep near labeled chests

This commit is contained in:
Tanner
2026-11-08 17:08:12 +00:00
vanhempi 930f4f3868
commit c79ee932a3
6 muutettua tiedostoa jossa 166 lisäystä ja 10 poistoa
+29 -1
Näytä tiedosto
@@ -3,7 +3,7 @@ import time
import importlib import importlib
import random import random
from itertools import count from itertools import count
from math import floor from math import ceil, floor
from minecraft.networking.types import BlockFace from minecraft.networking.types import BlockFace
@@ -19,6 +19,27 @@ class CacheItemsStates:
def idle(self): def idle(self):
return None return None
def _has_compatible_labeled_chest_near(self, bed, distance=16):
world = self.g.get('world')
if world is None:
return False
keep_slots = self._needed_inventory_slots_to_keep()
for chest in world.find_labeled_chests(bed, distance):
positions = chest.get('positions') or (chest['position'],)
if min(utils.phyp(bed, position) for position in positions) > distance:
continue
item_ids = chest['item_ids']
for slot, item in self.g.inv.items():
if (not 9 <= slot <= 44 or not item.present or
item.item_id not in item_ids or
item.item_id in items.WANTED_ITEMS):
continue
if (item.item_id in items.NEEDED_ITEMS and
slot in keep_slots):
continue
return True
return False
def init(self): def init(self):
self.skip_inventory_slots = set() self.skip_inventory_slots = set()
self.skip_items = [] self.skip_items = []
@@ -30,8 +51,15 @@ class CacheItemsStates:
self.container_item_ids = None self.container_item_ids = None
num_stacks = self.g.game.count_inventory_slots() num_stacks = self.g.game.count_inventory_slots()
has_override = 'minimum' in self.__dict__
minimum = self.__dict__.pop( minimum = self.__dict__.pop(
'minimum', self.g.get('minimum_cache_slots', 27)) 'minimum', self.g.get('minimum_cache_slots', 27))
post_sleep_bed = self.g.pop('post_sleep_cache_bed', None)
if (not has_override and post_sleep_bed is not None and
self._has_compatible_labeled_chest_near(post_sleep_bed)):
minimum = ceil(minimum / 2)
print('Lowering cache threshold after sleep near a compatible chest:',
minimum)
print('Inventory amount:', num_stacks) print('Inventory amount:', num_stacks)
if num_stacks == 0: if num_stacks == 0:
self.state = self.cleanup self.state = self.cleanup
+4 -8
Näytä tiedosto
@@ -105,9 +105,10 @@ class GatherCropStates:
crop, section_size = self._select_crop(candidates, crop_types, p) crop, section_size = self._select_crop(candidates, crop_types, p)
if crop is None: if crop is None:
print('No good crops left; retrying after a short wait.') print('No good crops left; running maintenance after {} harvests'.format(
self.retry_after = time.monotonic() + 15.0 self.completed_crops))
self.state = self.wait_for_crops self.completed_crops = 0
self.state = self.cleanup
return return
print('Found crop:', crop, print('Found crop:', crop,
@@ -116,10 +117,6 @@ class GatherCropStates:
self.type_id = w.block_at(*crop) self.type_id = w.block_at(*crop)
self.state = self.nav_to_crop self.state = self.nav_to_crop
def wait_for_crops(self):
if time.monotonic() >= self.retry_after:
self.state = self.find_new_crop
def nav_to_crop(self): def nav_to_crop(self):
w = self.g.world w = self.g.world
p = utils.pint(self.g.pos) p = utils.pint(self.g.pos)
@@ -251,7 +248,6 @@ class GatherCropStates:
self.seed_deadline = None self.seed_deadline = None
self.seed_wait_logged = False self.seed_wait_logged = False
self.active_section_anchor = None self.active_section_anchor = None
self.retry_after = 0.0
self.bad_crops = [] self.bad_crops = []
self.completed_crops = 0 self.completed_crops = 0
+3
Näytä tiedosto
@@ -21,6 +21,7 @@ class SleepWithBedStates:
return None return None
def init(self): def init(self):
self.sleep_confirmed = False
self.my_bed = False self.my_bed = False
self.area = None self.area = None
self.opening = None self.opening = None
@@ -371,6 +372,8 @@ class SleepWithBedStates:
return return
self.g.look_at = None self.g.look_at = None
self.g.path = [] self.g.path = []
if self.sleep_confirmed and self.area is not None:
self.g.post_sleep_cache_bed = tuple(self.area)
self.my_bed = False self.my_bed = False
self.force_new_bed = False self.force_new_bed = False
self.state = self.done self.state = self.done
+106
Näytä tiedosto
@@ -46,6 +46,112 @@ class CacheItemsTests(unittest.TestCase):
finally: finally:
items.WANTED_ITEMS = old_wanted items.WANTED_ITEMS = old_wanted
def test_post_sleep_halves_threshold_only_with_compatible_nearby_chest(self):
bed = (0, 64, 0)
chest_position = (5, 64, 0)
item_id = items.get_id('stone')
class FakeGame:
@staticmethod
def count_inventory_slots():
return 14
class NearbyWorld:
@staticmethod
def find_labeled_chests(_center, _distance):
return [{
'position': chest_position,
'positions': (chest_position,),
'item_ids': {item_id},
}]
g = Munch(
game=FakeGame(), world=NearbyWorld(),
minimum_cache_slots=27, post_sleep_cache_bed=bed,
inv={9: Munch(present=True, item_id=item_id, item_count=64)})
state = CacheItemsStates(g)
state.init()
self.assertIs(state.state.__func__, state.find_trapped_chests.__func__)
self.assertNotIn('post_sleep_cache_bed', g)
def test_post_sleep_threshold_rounds_27_up_to_14(self):
bed = (0, 64, 0)
item_id = items.get_id('stone')
class FakeGame:
@staticmethod
def count_inventory_slots():
return 13
class NearbyWorld:
@staticmethod
def find_labeled_chests(_center, _distance):
return [{
'position': (5, 64, 0),
'positions': ((5, 64, 0),),
'item_ids': {item_id},
}]
g = Munch(
game=FakeGame(), world=NearbyWorld(), minimum_cache_slots=27,
post_sleep_cache_bed=bed,
inv={9: Munch(present=True, item_id=item_id, item_count=64)})
state = CacheItemsStates(g)
state.init()
self.assertIs(state.state.__func__, state.cleanup.__func__)
def test_post_sleep_does_not_lower_threshold_without_compatible_nearby_chest(self):
class FakeGame:
@staticmethod
def count_inventory_slots():
return 14
class EmptyWorld:
@staticmethod
def find_labeled_chests(_center, _distance):
return []
g = Munch(
game=FakeGame(), world=EmptyWorld(), minimum_cache_slots=27,
post_sleep_cache_bed=(0, 64, 0), inv={})
state = CacheItemsStates(g)
state.init()
self.assertIs(state.state.__func__, state.cleanup.__func__)
self.assertNotIn('post_sleep_cache_bed', g)
def test_post_sleep_ignores_compatible_chest_beyond_16_blocks(self):
item_id = items.get_id('stone')
class FakeGame:
@staticmethod
def count_inventory_slots():
return 14
class FarWorld:
@staticmethod
def find_labeled_chests(_center, _distance):
position = (17, 64, 0)
return [{
'position': position,
'positions': (position,),
'item_ids': {item_id},
}]
state = CacheItemsStates(Munch(
game=FakeGame(), world=FarWorld(), minimum_cache_slots=27,
post_sleep_cache_bed=(0, 64, 0),
inv={9: Munch(present=True, item_id=item_id, item_count=64)}))
state.init()
self.assertIs(state.state.__func__, state.cleanup.__func__)
def test_manual_cache_threshold_override_is_consumed_once(self): def test_manual_cache_threshold_override_is_consumed_once(self):
class FakeGame: class FakeGame:
@staticmethod @staticmethod
+3 -1
Näytä tiedosto
@@ -29,9 +29,11 @@ class SignWorkTargetTests(unittest.TestCase):
return crop_state return crop_state
state = GatherCropStates(Munch(world=FakeWorld(), pos=(0, 64, 0))) state = GatherCropStates(Munch(world=FakeWorld(), pos=(0, 64, 0)))
state.completed_crops = 7
state.find_new_crop() state.find_new_crop()
self.assertIs(state.state.__func__, state.wait_for_crops.__func__) self.assertIs(state.state.__func__, state.cleanup.__func__)
self.assertEqual(state.completed_crops, 0)
self.assertEqual(state.bad_crops, []) self.assertEqual(state.bad_crops, [])
def test_tree_search_skips_out_of_bounds_tree_without_blacklisting_it(self): def test_tree_search_skips_out_of_bounds_tree_without_blacklisting_it(self):
+21
Näytä tiedosto
@@ -52,6 +52,27 @@ class FakeGame:
class TestSleepWithBed(unittest.TestCase): class TestSleepWithBed(unittest.TestCase):
def test_confirmed_sleep_records_bed_for_following_cache_pass(self):
bed = (1, 64, 2)
g = Munch(world=FakeWorld(), path=[], look_at=None)
state = SleepWithBedStates(g)
state.area = bed
state.sleep_confirmed = True
state.cleanup()
self.assertEqual(g.post_sleep_cache_bed, bed)
def test_unconfirmed_sleep_does_not_trigger_post_sleep_cache(self):
g = Munch(world=FakeWorld(), path=[], look_at=None)
state = SleepWithBedStates(g)
state.area = (1, 64, 2)
state.sleep_confirmed = False
state.cleanup()
self.assertNotIn('post_sleep_cache_bed', g)
def test_bed_occupancy_only_logs_first_observation_and_changes(self): def test_bed_occupancy_only_logs_first_observation_and_changes(self):
bed_states = [ bed_states = [
state for state in blocks.BED_IDS state for state in blocks.BED_IDS