Add sign-labeled chest storage

This commit is contained in:
Tanner
2026-11-07 16:35:57 +00:00
parent ab8f59a89b
commit 43b37b76f6
7 changed files with 401 additions and 66 deletions
+117
View File
@@ -9,6 +9,7 @@ from copy import copy
from mosfet import utils
from mosfet import path
from mosfet.info import blocks
from mosfet.info import items
from mosfet.info import mobs
class World:
@@ -76,6 +77,122 @@ class World:
result.sort(key=lambda sign: utils.phyp(center, sign['position']))
return result
def _double_chest_positions(self, chest):
state_id = self.block_at(*chest)
properties = blocks.PROPS.get(state_id, {})
chest_type = properties.get('type')
if chest_type not in ('left', 'right'):
return (tuple(chest),)
other_type = 'right' if chest_type == 'left' else 'left'
for offset in ((1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 0, -1)):
partner = utils.padd(chest, offset)
other = blocks.PROPS.get(self.block_at(*partner), {})
if (other.get('type') == other_type and
other.get('facing') == properties.get('facing')):
return tuple(sorted((tuple(chest), partner)))
return (tuple(chest),)
def find_labeled_chests(self, center, distance=80):
"""Find single/double chests assigned item categories by nearby signs."""
grouped = {}
sign_offsets = (
(0, 0, 0), (0, -1, 0),
(1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 0, -1),
)
for sign in self.find_signs(center, distance):
categories = set()
labels = set()
for line in sign['lines']:
item_ids = items.storage_item_ids_for_label(line)
if item_ids:
categories.update(item_ids)
labels.add(line.strip())
if not categories:
continue
sign_pos = sign['position']
adjacent = {
utils.padd(sign_pos, offset)
for offset in sign_offsets
if self.block_at(*utils.padd(sign_pos, offset)) in blocks.CHEST_IDS
}
if not adjacent:
nearby = self.find_blocks_indexed(
sign_pos, blocks.CHEST_IDS, 2)
if nearby:
nearest = min(utils.phyp(sign_pos, chest)
for chest in nearby)
adjacent = {chest for chest in nearby
if utils.phyp(sign_pos, chest) == nearest}
for chest in adjacent:
positions = self._double_chest_positions(chest)
record = grouped.setdefault(positions, {
'position': tuple(chest),
'positions': positions,
'item_ids': set(),
'labels': set(),
'sign_positions': set(),
})
record['item_ids'].update(categories)
record['labels'].update(labels)
record['sign_positions'].add(sign_pos)
result = list(grouped.values())
result.sort(key=lambda chest: utils.phyp(center, chest['position']))
return result
def find_supply_chests(self, center, bot_name, distance=80):
"""Find chests whose sign is addressed to this bot's supplies."""
bot_name = str(bot_name).casefold()
group_name = (bot_name[:-1] if len(bot_name) > 1 and
bot_name[-1] in '123' else None)
addresses = {bot_name}
if group_name:
addresses.add(group_name)
grouped = {}
sign_offsets = (
(0, 0, 0), (0, -1, 0),
(1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 0, -1),
)
for sign in self.find_signs(center, distance):
text = ' '.join(line for line in sign['lines'] if line.strip())
tokens = re.findall(r'[a-z0-9_]+', text.casefold())
if (len(tokens) < 2 or tokens[0] not in addresses or
'supplies' not in tokens[1:]):
continue
sign_pos = sign['position']
candidates = {
utils.padd(sign_pos, offset)
for offset in sign_offsets
if self.block_at(*utils.padd(sign_pos, offset)) in blocks.CHEST_IDS
}
if not candidates:
nearby = self.find_blocks_indexed(
sign_pos, blocks.CHEST_IDS, 2)
if nearby:
nearest = min(utils.phyp(sign_pos, chest) for chest in nearby)
candidates = {chest for chest in nearby
if utils.phyp(sign_pos, chest) == nearest}
for chest in candidates:
positions = self._double_chest_positions(chest)
record = grouped.setdefault(positions, {
'position': tuple(chest),
'positions': positions,
'labels': set(),
'sign_positions': set(),
})
record['labels'].update(tokens[1:])
record['sign_positions'].add(sign_pos)
result = list(grouped.values())
result.sort(key=lambda chest: utils.phyp(center, chest['position']))
return result
def sign_policies(self, bot_name, distance=64):
"""Parse sign policies addressed to this bot or its numbered group."""
bot_name = str(bot_name).casefold()