Files
minecraft-bot/mosfet/jobs/gather_crop.py
T

186 lines
6.1 KiB
Python

import re
import time
import importlib
import random
from itertools import count
from math import floor
from minecraft.networking.types import BlockFace
from mosfet.protocol.managers import ChunkNotLoadedException
from mosfet import utils
from mosfet import path
from mosfet.info import blocks
from mosfet.info import items
from mosfet.info import mcdata
from mosfet.info import mobs
class GatherCropStates:
def idle(self):
return None
def init(self):
self.state = self.find_new_crop
def find_new_crop(self):
print('Finding new crop...')
w = self.g.world
p = utils.pint(self.g.pos)
mature_crops = [
blocks.MATURE_WHEAT_ID,
blocks.MATURE_POTATO_ID,
blocks.MATURE_CARROT_ID,
blocks.MATURE_BEETROOT_ID,
]
candidates = w.find_blocks_indexed(p, mature_crops, 50)
for crop in candidates:
if crop not in self.bad_crops:
break
else: # for
print('No good crops left; retrying after a short wait.')
self.retry_after = time.monotonic() + 15.0
self.state = self.wait_for_crops
return
print('Found crop:', crop)
self.crop = crop
self.type_id = w.block_at(*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):
w = self.g.world
p = utils.pint(self.g.pos)
navpath = w.path_to_place(p, self.crop)
if navpath:
print('Going to crop', self.crop)
self.g.path = navpath
self.g.look_at = utils.padd(self.crop, path.BLOCK_BELOW)
self.state = self.going_to_crop
else:
print('Cant get to it, blacklisting')
time.sleep(0.1)
self.bad_crops.append(self.crop)
self.state = self.find_new_crop
def going_to_crop(self):
if utils.pint(self.g.pos) == self.crop:
print('At the crop')
self.state = self.break_crop
def break_crop(self):
print('Requesting crop break at {}: block={}, mode={}, held={}'.format(
self.crop, self.g.world.block_at(*self.crop),
self.g.get('game_mode'), self.g.get('holding')))
if self.g.game.break_block(self.crop):
print('Started breaking crop {} (state {})'.format(
self.crop, self.type_id))
self.break_deadline = time.time() + 5.0
self.state = self.wait_break
else:
print('Break request skipped; current block is',
self.g.world.block_at(*self.crop))
self.bad_crops.append(self.crop)
self.state = self.find_new_crop
def wait_break(self):
current_state = self.g.world.block_at(*self.crop)
if current_state != self.type_id:
print('Crop break confirmed at {}: {} -> {}'.format(
self.crop, self.type_id, current_state))
self.seed_deadline = time.monotonic() + 8.0
self.seed_wait_logged = False
self.state = self.select_seed
elif time.time() > self.break_deadline:
print('Crop break timed out at {}: expected state {}, server still has {}'.format(
self.crop, self.type_id, current_state))
print('Crop did not break; blacklisting', self.crop)
self.bad_crops.append(self.crop)
self.state = self.find_new_crop
def select_seed(self):
p = utils.pint(self.g.pos)
crop_seeds = {
blocks.MATURE_WHEAT_ID: items.WHEAT_SEEDS_ID,
blocks.MATURE_POTATO_ID: items.POTATO_ID,
blocks.MATURE_CARROT_ID: items.CARROT_ID,
blocks.MATURE_BEETROOT_ID: items.BEETROOT_SEEDS_ID,
}
self.target_seed = crop_seeds[self.type_id]
if self.g.game.select_item([self.target_seed]):
self.seed_deadline = None
self.state = self.wait_select
else:
if (self.seed_deadline is not None and
time.monotonic() > self.seed_deadline):
print('No seed collected for crop; skipping', self.crop)
self.bad_crops.append(self.crop)
self.seed_deadline = None
self.state = self.find_new_crop
elif not getattr(self, 'seed_wait_logged', False):
print('Waiting for crop seed {} in inventory/hotbar'.format(
self.target_seed))
self.seed_wait_logged = True
return
def wait_select(self):
if self.target_seed != self.g.holding:
return
else:
self.state = self.place_crop
def place_crop(self):
p = utils.padd(self.crop, path.BLOCK_BELOW)
self.place_deadline = time.time() + 3.0
self.g.game.place_block(p, BlockFace.TOP)
print('Placed crop')
self.state = self.wait_place
def wait_place(self):
w = self.g.world
current_state = w.block_at(*self.crop)
crop_name = blocks.BLOCKS.get(self.type_id)
replanted = (current_state not in (None, blocks.AIR) and
blocks.BLOCKS.get(current_state) == crop_name and
current_state != self.type_id)
if replanted:
self.state = self.cleanup
elif time.time() > getattr(self, 'place_deadline', 0):
print('Crop did not replant; blacklisting', self.crop)
self.bad_crops.append(self.crop)
self.state = self.find_new_crop
def cleanup(self):
self.g.look_at = None
self.state = self.done
def done(self):
# never gets ran, placeholder
return None
def __init__(self, global_state):
self.g = global_state
self.state = self.idle
self.crop = None
self.type_id = None
self.target_seed = None
self.seed_deadline = None
self.seed_wait_logged = False
self.retry_after = 0.0
self.bad_crops = []
def run(self):
self.state()