Implement 26.3 bed sleeping

This commit is contained in:
Tanner
2026-11-04 19:20:15 +00:00
parent 9fd565c3c9
commit 1ecec547ae
10 changed files with 404 additions and 75 deletions
+46 -26
View File
@@ -158,28 +158,50 @@ class World:
return navpath
def find_bed_areas(self, center, distance):
bed_clearance = 9 # 5x5 area
clear_distance = 2
for a in self.find_blocks_3d(center, [0], distance, 50):
# check for air around the area
if len(self.find_blocks(a, clear_distance, [0], bed_clearance)) < bed_clearance:
"""Yield nearby two-block bed footprints on solid, safe ground."""
# Only search loaded-neighborhood distance. The old 3-D flood fill
# explored millions of air blocks and used overly broad 5x5 clearance.
distance = min(distance, 32)
headroom = path.BLOCK_ABOVE
support = path.BLOCK_BELOW
for offset in utils.search_2d(distance):
if utils.hypot(offset[0], offset[2]) > distance:
continue
for dy in (0, 1, -1, 2, -2):
area = (center[0] + offset[0], center[1] + dy,
center[2] + offset[2])
if area == center:
continue
if self.block_at(*area) != blocks.AIR:
continue
if self.block_at(*utils.padd(area, headroom)) != blocks.AIR:
continue
support_block = self.block_at(*utils.padd(area, support))
if (support_block is None or
support_block in blocks.NON_SOLID_IDS or
support_block in blocks.AVOID_IDS):
continue
# check for ground around the area
if len(self.find_blocks(utils.padd(a, path.BLOCK_BELOW), clear_distance, blocks.NON_SOLID_IDS, bed_clearance)):
continue
footprint_found = False
for direction in path.CHECK_DIRECTIONS:
head = utils.padd(area, direction)
if (self.block_at(*head) != blocks.AIR or
self.block_at(*utils.padd(head, headroom)) != blocks.AIR):
continue
head_support = self.block_at(*utils.padd(head, support))
if (head_support is None or
head_support in blocks.NON_SOLID_IDS or
head_support in blocks.AVOID_IDS):
continue
footprint_found = True
break
if not footprint_found:
continue
# check for air above the area
if len(self.find_blocks(utils.padd(a, path.BLOCK_ABOVE), clear_distance, [0], bed_clearance)) < bed_clearance:
continue
# ensure there's no monsters within 20 blocks
# can't sleep if they are within 10, good to have a buffer
if self.find_monsters(a, 20):
continue
yield a
# Avoid placing a bed within range of nearby monsters.
if self.find_monsters(area, 20):
continue
yield area
def find_cache_areas(self, center, distance):
"""Yield nearby, supported air blocks suitable for placing a chest."""
@@ -294,14 +316,12 @@ class World:
return result
def check_bed_occupied(self, bed):
# returns true if the bed is occupied by a player
"""Return whether a loaded bed block currently has occupied=true."""
bid = self.g.chunks.get_block_at(*bed)
if blocks.PROPS[bid]['occupied'] == 'true':
print('Checking bed occupancy:', bed, '-> occupied')
return True
else:
print('Checking bed occupancy:', bed, '-> free')
return False
occupied = blocks.PROPS.get(bid, {}).get('occupied') == 'true'
print('Checking bed occupancy:', bed, '->',
'occupied' if occupied else 'free')
return occupied
def find_cache_openings(self, area):
return self.find_bed_openings(area)