minecraft-bot/jobs.py

1417 lines
38 KiB
Python

import re
import time
import importlib
import random
from itertools import count
from math import hypot
from panda3d.core import LPoint3f
from minecraft.networking.types import BlockFace
from protocol.managers import ChunkNotLoadedException
import utils
importlib.reload(utils)
import path
importlib.reload(path)
import blocks
importlib.reload(blocks)
import items
importlib.reload(items)
import data
importlib.reload(data)
import mobs
importlib.reload(mobs)
class FindGappleStates:
def idle(self):
return None
def init(self):
self.state = self.go_spectator
def go_spectator(self):
print('Going spectator...')
self.g.chat.send('/gamemode spectator')
self.state = self.tp_to_coord
def tp_to_coord(self):
step = utils.spiral(self.count)
step_scaled = utils.pmul(step, 192)
self.coord = utils.padd(self.origin, step_scaled)
self.coord = (self.coord[0], 50, self.coord[2])
print('count:', self.count, 'teleporting to:', self.coord)
self.g.chat.send('/tp {} {} {}'.format(*self.coord))
self.g.command_lock = True
self.state = self.wait_for_load
def wait_for_load(self):
if self.g.command_lock:
return
if self.g.chunks.check_loaded(self.g.pos, 169):
print('chunks have been loaded')
self.state = self.pick_chest
def pick_chest(self):
chest_list = []
for chest_id in blocks.CHEST_IDS:
chest_list.extend(self.g.chunks.index.get(chest_id, []))
for chest in chest_list:
if chest in self.checked_chests:
# slow but simple
continue
if utils.phyp_king(self.coord, chest) > 96:
# skip because we can't detect item drops
continue
self.current_chest = chest
self.checked_chests.append(self.current_chest)
self.state = self.break_chest
break
else: # for
print('exhausted chest list')
self.state = self.cleanup
def break_chest(self):
print('Breaking chest', self.current_chest)
self.g.command_lock = True
self.g.item_lock = True
self.g.chat.send('/setblock {} {} {} air destroy'.format(*self.current_chest))
self.wait_time = 0.5
self.state = self.wait_for_items
def wait_for_items(self):
# wait for command to execute
if self.g.command_lock:
return
# wait for items to drop
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
print('done waiting for items')
self.state = self.pick_chest
def cleanup(self):
self.count += 1
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.origin = utils.pint(self.g.pos)
self.count = 0
self.coord = None
self.current_chest = None
self.checked_chests = []
self.wait_time = 0
def run(self):
self.state()
class GatherWoodStates:
def bair(self, p):
return self.g.chunks.get_block_at(*p) in blocks.NON_SOLID_IDS
def blog(self, p):
return self.g.chunks.get_block_at(*p) in blocks.LOG_IDS
def idle(self):
return None
def init(self):
self.g.chopped_tree = False
self.state = self.find_new_tree
def find_new_tree(self):
print('Finding new tree...')
w = self.g.world
p = utils.pint(self.g.pos)
for tree in w.find_trees(p, 100):
print('Found tree:', tree)
if tree not in self.bad_trees:
break
else: # for
print('No good trees left, aborting.')
self.state = self.cleanup
return
self.tree = tree
self.state = self.find_openings
def find_openings(self):
w = self.g.world
self.openings = w.find_tree_openings(self.tree)
self.state = self.choose_opening
def choose_opening(self):
w = self.g.world
p = utils.pint(self.g.pos)
print('openings:', self.openings)
if not len(self.openings):
print('Unable to get to tree', self.tree)
if self.tree not in self.good_trees:
self.bad_trees.append(self.tree)
self.state = self.cleanup
return
navpath = w.path_to_place(p, self.openings[0])
if navpath:
self.g.path = navpath
self.state = self.going_to_tree
else:
self.openings.pop(0)
def going_to_tree(self):
if utils.pint(self.g.pos) == self.openings[0]:
self.g.look_at = self.tree
self.state = self.clear_leaves
def clear_leaves(self):
if not self.g.breaking:
p = utils.pint(self.g.pos)
diff = utils.psub(self.tree, p)
for x in utils.diffrange(diff[0]):
for z in utils.diffrange(diff[2]):
for y in range(2):
check = utils.padd(p, (x, y, z))
if check == self.tree:
break
if not self.bair(check):
print('Breaking leaf')
self.g.game.break_block(check)
return
self.state = self.clear_trunk_base
def clear_trunk_base(self):
if not self.g.breaking:
base = self.tree
above = utils.padd(self.tree, path.BLOCK_ABOVE)
if self.blog(base):
self.g.game.break_block(base)
print('breaking base')
elif self.blog(above):
self.g.game.break_block(above)
print('breaking above')
else:
w = self.g.world
p = utils.pint(self.g.pos)
navpath = w.path_to_place(p, self.tree)
if navpath:
self.g.path = navpath
self.state = self.going_to_trunk_base
else:
self.openings.pop(0)
self.state = self.choose_opening
def going_to_trunk_base(self):
if utils.pint(self.g.pos) == self.tree:
self.g.look_at = utils.padd(self.tree, path.BLOCK_ABOVE2)
self.state = self.clear_trunk
def clear_trunk(self):
if not self.g.breaking:
check = self.tree
count = 0
while self.bair(check) and count < 6:
check = utils.padd(check, path.BLOCK_ABOVE)
count += 1
if self.blog(check):
print('breaking log', check)
self.g.game.break_block(check)
else:
print('Finished clearing tree')
self.wait_time = 0.5
self.state = self.wait
def wait(self):
# wait for the last log to fall
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.g.chopped_tree = True
self.good_trees.append(self.tree)
self.state = self.check_pos
def check_pos(self):
# make sure we are at base of trunk
# doesn't always happen, for some reason
if utils.pint(self.g.pos) == self.tree:
self.state = self.cleanup
else:
self.state = self.find_openings
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.tree = None
self.openings = []
self.bad_trees = []
self.good_trees = []
self.wait_time = 0
def run(self):
self.state()
class GatherSandStates:
def bair(self, p):
return self.g.chunks.get_block_at(*p) in blocks.NON_SOLID_IDS
def bsand(self, p):
return self.g.chunks.get_block_at(*p) == blocks.SAND
def idle(self):
return None
def init(self):
self.state = self.select_shovel
def select_shovel(self):
self.g.game.select_item(items.SHOVEL_IDS)
self.state = self.find_new_slice
def find_new_slice(self):
print('Finding new slice...')
w = self.g.world
print('using origin', self.origin)
start = time.time()
self.prev_layer, s = w.find_sand_slice(self.origin, 200, 10, self.bad_slices, self.prev_layer)
print('Found slice:', s, 'in', time.time() - start, 'seconds')
if s:
self.slice = s
self.bad_slices.append(s)
self.state = self.find_new_sand
else:
print('No slices remaining.')
self.state = self.cleanup
def find_new_sand(self):
print('Finding new sand...')
w = self.g.world
p = utils.pint(self.g.pos)
head = utils.padd(p, path.BLOCK_ABOVE)
for sand in w.find_sand(self.slice, 2, p):
if sand not in self.bad_sand:
print('Found sand:', sand)
break
else: # for
print('No good sands left, aborting.')
self.state = self.cleanup
return
self.sand = sand
if utils.phyp(head, self.sand) < blocks.BREAK_DISTANCE:
self.state = self.dig_sand
else:
self.state = self.nav_to_sand
def nav_to_sand(self):
w = self.g.world
p = utils.pint(self.g.pos)
c = self.g.chunks
tmp = c.get_block_at(*self.sand)
c.set_block_at(*self.sand, blocks.AIR)
navpath = w.path_to_place(p, self.sand)
c.set_block_at(*self.sand, tmp)
if navpath:
self.g.path = navpath[:-1]
self.state = self.going_to_sand
else:
print('Cant get to that sand')
self.bad_sand.append(self.sand)
self.state = self.find_new_sand
def going_to_sand(self):
if not len(self.g.path):
self.g.look_at = self.sand
self.state = self.dig_sand
def dig_sand(self):
if not self.g.breaking:
if self.bsand(self.sand):
self.g.look_at = self.sand
self.g.game.break_block(self.sand)
print('digging sand')
else:
self.state = self.find_new_sand
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.origin = utils.pint(self.g.pos)
self.origin = (2019, 64, 238)
self.slice = None
self.bad_slices = []
self.prev_layer = 0
self.sand = None
self.bad_sand = []
self.wait_time = 0
def run(self):
self.state()
class GrabSandStates:
def idle(self):
return None
def init(self):
self.state = self.find_sand
print('Trying to grab sand')
def find_sand(self):
w = self.g.world
p = utils.pint(self.g.pos)
sand = w.find_objects(items.SAND_ID)
if not sand:
print('No sand objects found, aborting')
self.state = self.cleanup
return
sand.sort(key=lambda s: utils.phyp(p, (s.x, s.y, s.z)))
for s in sand:
s_pos = utils.pint((s.x, s.y, s.z))
check = utils.padd(s_pos, path.BLOCK_BELOW)
if utils.phyp(p, s_pos) > 6:
continue
# skip if the sand is floating
if self.g.chunks.get_block_at(*check) in {0}:
continue
if s.entity_id in self.eid_blacklist:
continue
self.eid_blacklist.append(s.entity_id)
navpath = w.path_to_place(p, s_pos)
if navpath:
self.g.path = navpath
self.state = self.going_to_sand
self.sand = s_pos
print('Going to sand', self.sand)
return
else:
print('Cant get to sand', self.sand)
print('Cant get to any more sand, aborting')
self.state = self.cleanup
def going_to_sand(self):
if utils.pint(self.g.pos) == self.sand:
self.state = self.cleanup
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.sand = None
self.eid_blacklist = []
def run(self):
self.state()
class SleepWithBedStates:
def idle(self):
return None
def init(self):
if self.g.time >= 12000:
self.state = self.select_bed
else:
print('Aborting sleep, not night')
self.state = self.cleanup
def select_bed(self):
if self.g.game.select_item(items.BED_IDS):
self.state = self.find_bed_spot
else:
print('No bed, aborting.')
self.state = self.cleanup
def find_bed_spot(self):
print('Finding a bed spot...')
w = self.g.world
p = utils.pint(self.g.pos)
for area in w.find_bed_areas(p, 100):
print('Found area:', area)
if area not in self.bad_areas:
break
else: # for
print('Unable to find area')
self.state = self.cleanup
return
self.area = area
openings = w.find_bed_openings(self.area)
for o in openings:
navpath = w.path_to_place(p, o)
self.opening = o
if navpath: break
else: # for
print('Unable to get to bed area', self.area)
self.bad_areas.append(self.area)
self.state = self.cleanup
return
self.g.path = navpath
self.state = self.going_to_area
def going_to_area(self):
if utils.pint(self.g.pos) == self.opening:
self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW)
self.state = self.place_bed
def place_bed(self):
self.g.game.place_block(self.area, BlockFace.TOP)
self.state = self.use_bed
def use_bed(self):
if self.g.time >= 12542:
print('Sleeping')
self.g.game.place_block(self.area, BlockFace.TOP)
if not self.silent:
self.g.chat.send('zzz')
self.state = self.sleep_bed
def sleep_bed(self):
w = self.g.world
p = utils.pint(self.g.pos)
threats = w.find_threats(p, 30)
if threats:
print('Waking up due to threats')
self.g.game.leave_bed()
self.state = self.break_bed
elif self.g.time < 100:
print('Woke up time')
self.state = self.break_bed
def break_bed(self):
self.g.game.break_block(self.area)
self.state = self.collect_bed
def collect_bed(self):
if not self.g.breaking:
self.g.path = [utils.padd(self.area, utils.spiral(n)) for n in range(9)]
self.wait_time = 4
self.state = self.wait
def wait(self):
# wait to pick up bed
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.state = self.cleanup
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.silent = False
self.area = None
self.opening = None
self.bad_areas = []
self.wait_time = 0
def run(self):
self.state()
class CacheItemsStates:
def idle(self):
return None
def init(self):
self.skip_slots = []
self.skip_items = []
num_stacks = len([x for x in self.g.inv.values() if x.present])
print('Inventory amount:', num_stacks)
if num_stacks >= self.minimum:
self.state = self.find_trapped_chests
else:
print('Aborting caching, not full')
self.state = self.cleanup
def find_trapped_chests(self):
print('Finding trapped chests...')
w = self.g.world
p = utils.pint(self.g.pos)
self.trapped_chests = w.find_blocks_indexed(p, blocks.TRAPPED_CHEST_IDS, 100)
print('Found:', self.trapped_chests)
self.state = self.choose_trapped_chest
def choose_trapped_chest(self):
print('Choosing a trapped chest...')
w = self.g.world
p = utils.pint(self.g.pos)
c = self.g.chunks
if not len(self.trapped_chests):
print('No trapped chests')
self.state = self.select_chest
return
chest = self.trapped_chests[0]
tmp = c.get_block_at(*chest)
c.set_block_at(*chest, blocks.AIR)
navpath = w.path_to_place(p, chest)
c.set_block_at(*chest, tmp)
print('navpath:', navpath)
if navpath:
self.g.path = navpath[:-1]
self.opening = self.g.path[-1]
self.area = chest
self.state = self.going_to_trapped_chest
return
else:
self.trapped_chests.pop(0)
def going_to_trapped_chest(self):
if utils.pint(self.g.pos) == self.opening:
self.g.look_at = self.area
self.state = self.open_chest
def select_chest(self):
if self.g.game.select_item(items.CHEST_ID):
self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW)
self.state = self.find_cache_spot
else:
print('No chest, aborting')
self.state = self.cleanup
def find_cache_spot(self):
print('Finding a chest spot...')
w = self.g.world
p = utils.pint(self.g.pos)
for area in w.find_cache_areas(p, 100):
print('Found area:', area)
if area not in self.bad_areas:
break
else: # for
print('Unable to find area')
self.state = self.cleanup
return
self.area = area
openings = w.find_cache_openings(self.area)
for o in openings:
navpath = w.path_to_place(p, o)
self.opening = o
if navpath: break
else: # for
print('Unable to get to cache area', self.area)
self.bad_areas.append(self.area)
self.state = self.cleanup
return
self.g.path = navpath
self.state = self.going_to_area
def going_to_area(self):
if utils.pint(self.g.pos) == self.opening:
self.g.look_at = self.area
self.state = self.place_chest
def place_chest(self):
self.g.game.place_block(self.area, BlockFace.TOP)
self.state = self.open_chest
def open_chest(self):
print('Opening chest')
self.g.game.open_container(self.area)
self.wait_time = 1
self.state = self.wait
def wait(self):
# wait for server to send us chest contents
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.state = self.move_items
def move_items(self):
if self.g.item_lock: return
w = self.g.window
w_info = data.WINDOWS[w.data.window_type]
w_inventory_slots = w_info.inventory
slot_list = []
for slot_num in w_inventory_slots:
if slot_num not in w.contents:
continue
slot = w.contents[slot_num]
if not slot.present:
continue
if slot.item_id in self.needed_items:
continue
if slot_num in self.skip_slots:
continue
slot_list.append((slot_num, slot))
slot_list.sort(key=lambda x: x[1].item_count, reverse=True)
for slot_num, slot in slot_list:
if slot.item_id in self.wanted_items and slot.item_id not in self.skip_items:
print('skipping wanted item', slot)
self.skip_slots.append(slot_num)
self.skip_items.append(slot.item_id)
continue
print('moving', slot)
self.g.item_lock = True
self.g.game.click_window(slot_num, 0, 1, slot)
return
print('nothing left to move')
self.state = self.close_chest
def close_chest(self):
print('closing chest')
self.g.game.close_window()
if not self.silent:
self.g.chat.send('cache at ' + str(self.area)[1:-1])
self.state = self.cleanup
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.minimum = 27
self.silent = False
# keep all needed items
self.needed_items = items.NEEDED_ITEMS
# keep one stack of wanted items
self.wanted_items = items.WANTED_ITEMS
self.skip_slots = []
self.skip_items = []
self.area = None
self.opening = None
self.trapped_chests = []
self.bad_areas = []
self.wait_time = 0
def run(self):
self.state()
class PlantTreeStates:
def idle(self):
return None
def init(self):
if self.g.chopped_tree:
self.state = self.check_feet
else:
print('Aborting planting, did not plant')
self.state = self.cleanup
def check_feet(self):
p = utils.pint(self.g.pos)
# check for air at feet
if self.g.chunks.get_block_at(*p) in [0]:
self.state = self.select_sapling
else:
print('Aborting planting, feet not air')
self.state = self.cleanup
def select_sapling(self):
p = utils.pint(self.g.pos)
if self.g.game.select_random_item(items.SAPLING_IDS):
self.g.look_at = utils.padd(p, path.BLOCK_BELOW)
self.state = self.wait_select
self.wait_time = 1
else:
print('Aborting planting, no saplings')
self.state = self.cleanup
def wait_select(self):
# wait a bit to look down
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.state = self.place_sapling
def place_sapling(self):
p = utils.pint(self.g.pos)
self.g.game.place_block(p, BlockFace.TOP)
print('Placed sapling')
self.state = self.wait_place
self.wait_time = 1
def wait_place(self):
# wait a bit for chunk data to update
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.state = self.find_open_spot
def find_open_spot(self):
w = self.g.world
p = utils.pint(self.g.pos)
for opening in w.find_tree_openings(p):
print('trying sapling opening', opening)
navpath = w.path_to_place(p, opening)
if navpath:
self.g.path = navpath
self.area = opening
self.state = self.going_to_area
return
else: # for
print('cant escape sapling')
self.state = self.cleanup
def going_to_area(self):
if utils.pint(self.g.pos) == self.area:
self.state = self.cleanup
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.wait_time = 0
self.area = None
def run(self):
self.state()
class ClearLeavesStates:
def idle(self):
return None
def init(self):
num_saplings = self.g.game.count_items(items.SAPLING_IDS)
print('Have', num_saplings, 'saplings in inventory')
if num_saplings < 8:
self.state = self.find_leaves
print('Clearing leaves...')
else:
print('Aborting clearing leaves')
self.state = self.cleanup
def find_leaves(self):
w = self.g.world
p = utils.pint(self.g.pos)
for l in w.find_leaves(p, blocks.BREAK_DISTANCE):
self.leaves.append(l)
self.state = self.break_leaves
def break_leaves(self):
if not self.g.breaking:
if self.leaves:
leaf = self.leaves.pop(0)
self.g.look_at = leaf
self.g.game.break_block(leaf)
print('Breaking leaf', leaf)
else:
self.wait_time = 1
self.state = self.wait
def wait(self):
# wait for the items to drop
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.state = self.cleanup
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.leaves = []
self.wait_time = 0
def run(self):
self.state()
class GrabSaplingStates:
def idle(self):
return None
def init(self):
self.state = self.find_saplings
print('Trying to grab a sapling')
def find_saplings(self):
w = self.g.world
p = utils.pint(self.g.pos)
saplings = w.find_objects(items.SAPLING_IDS)
if not saplings:
print('No sapling objects found, aborting')
self.state = self.cleanup
return
saplings.sort(key=lambda s: utils.phyp(p, (s.x, s.y, s.z)))
for s in saplings:
s_pos = utils.pint((s.x, s.y, s.z))
check = utils.padd(s_pos, path.BLOCK_BELOW)
if s.entity_id in self.eid_blacklist:
continue
# skip if the sapling is floating
if self.g.chunks.get_block_at(*check) in blocks.LEAF_IDS | {0}:
continue
navpath = w.path_to_place(p, s_pos)
if navpath:
self.g.path = navpath
self.state = self.going_to_sapling
self.sapling = s_pos
self.eid_blacklist.append(s.entity_id)
print('Going to sapling', self.sapling)
return
print('Cant get to any more saplings, aborting')
self.state = self.cleanup
def going_to_sapling(self):
if utils.pint(self.g.pos) == self.sapling:
self.state = self.find_saplings
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.sapling = None
self.eid_blacklist = []
def run(self):
self.state()
class CheckThreatsStates:
def idle(self):
return None
def init(self):
self.state = self.find_threats
print('Checking for threats')
def find_threats(self):
w = self.g.world
p = utils.pint(self.g.pos)
threats = w.find_threats(p, 40)
if threats:
print('Found', len(threats), 'threats, fleeing')
self.state = self.find_safety
else:
print('Aborting, no threats')
self.state = self.cleanup
def find_safety(self):
w = self.g.world
p = utils.pint(self.g.pos)
safety = w.find_blocks_indexed(p, [blocks.EMERALD_BLOCK])
if not safety:
print('No emerald blocks found, aborting')
self.state = self.cleanup
return
safety.sort(key=lambda s: utils.phyp(p, s))
print('Found emerald blocks:', safety)
for s in safety:
s = utils.padd(s, path.BLOCK_ABOVE)
navpath = w.path_to_place(p, s)
if navpath:
self.g.path = navpath
self.state = self.going_to_safety
self.safety = s
print('Going to safety', self.safety)
return
else:
print('Cant get to safety', self.safety)
print('Cant get to safety, aborting')
self.state = self.cleanup
def going_to_safety(self):
if utils.pint(self.g.pos) == self.safety:
print('At safety spot, waiting to be moved')
self.state = self.wait_for_move
def wait_for_move(self):
# wait for the server to move the bot when it's safe
# ie. a piston + daylight sensor
if utils.pint(self.g.pos) != self.safety:
print('Moved, resuming job')
self.state = self.wait
self.wait_time = 3
def wait(self):
# wait to land, etc
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.state = self.cleanup
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.safety = None
self.wait_time = 0
def run(self):
self.state()
class FillBlocksStates:
def idle(self):
return None
def init(self):
f = self.g.filling
if not f:
self.state = self.cleanup
print('Aborting, nothing to fill')
return
if self.last_block:
self.state = self.select_block
else:
self.state = self.find_last_block
def find_last_block(self):
w = self.g.world
f = self.g.filling
print('Finding last block')
b1, b2 = utils.pboundingbox(f.coord1, f.coord2)
y_start = f.coord1[1]
y_end = f.coord2[1]
distance = utils.phyp(f.coord1, f.coord2)
self.next_block = f.coord1
for offset in utils.search_3d(distance):
check = utils.padd(f.coord1, offset)
# ensure block is within fill area
if check[0] < b1[0] or check[0] > b2[0]:
continue
if check[2] < b1[2] or check[2] > b2[2]:
continue
if w.block_at(*check) == blocks.AIR:
self.state = self.select_block
return
self.last_block = check
def select_block(self):
f = self.g.filling
name = blocks.BLOCKS[f.block]
item = items.ITEMS['minecraft:'+name]['protocol_id']
if self.g.game.select_item([item]):
#self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW)
self.state = self.find_next_block
else:
print('No blocks, aborting')
self.state = self.cleanup
def find_next_block(self):
w = self.g.world
f = self.g.filling
print('Finding next block, last:', self.last_block)
b1, b2 = utils.pboundingbox(f.coord1, f.coord2)
box = utils.psub(b2, b1)
xz_distance = hypot(box[0]+1, box[2]+1)
y_start = f.coord1[1]
y_end = f.coord2[1]
print('distance', xz_distance)
for y in range(y_start, y_end+1):
for i in count():
offset = utils.spiral(i)
check = utils.padd(self.last_block, offset)
check = (check[0], y, check[2])
print('layer', y)
print('offset', offset)
print('hypot', hypot(offset[0], offset[2]))
if hypot(offset[0], offset[2]) > xz_distance:
break
# ensure block is within fill area
if check[0] < b1[0] or check[0] > b2[0]:
continue
if check[2] < b1[2] or check[2] > b2[2]:
continue
if w.block_at(*check) == blocks.AIR:
print('Found next block:', check)
self.next_block = check
self.state = self.check_block_distance
return
# if there's nothing left to fill
self.g.filling = None
self.state = self.cleanup
def check_block_distance(self):
w = self.g.world
p = utils.pint(self.g.pos)
head = utils.padd(p, path.BLOCK_ABOVE)
if utils.phyp(head, self.next_block) < 4:
self.state = self.fill_block
else:
self.state = self.nav_to_block
def nav_to_block(self):
w = self.g.world
p = utils.pint(self.g.pos)
c = self.g.chunks
tmp = c.get_block_at(*self.next_block)
c.set_block_at(*self.next_block, blocks.STONE)
pos = utils.padd(self.next_block, path.BLOCK_ABOVE)
navpath = w.path_to_place(p, pos)
c.set_block_at(*self.next_block, tmp)
if navpath:
self.g.path = navpath[:-1]
self.state = self.going_to_block
else:
print('Cant get to that block')
self.state = self.cleanup
#self.bad_sand.append(self.sand)
#self.state = self.find_new_sand
def going_to_block(self):
if not len(self.g.path):
self.state = self.fill_block
def fill_block(self):
print('Filling block', self.next_block)
self.g.game.place_block(self.next_block, BlockFace.TOP)
self.g.look_at = self.next_block
self.wait_time = 0.25
self.state = self.wait_for_block
def wait_for_block(self):
if self.wait_time > 0:
self.wait_time -= utils.TICK
else:
self.state = self.check_block
def check_block(self):
w = self.g.world
if w.block_at(*self.next_block) != blocks.AIR:
self.last_block = self.next_block
else:
print('Block didnt appear')
self.state = self.check_obstruction
def check_obstruction(self):
p = utils.pint(self.g.pos)
print('last', self.last_block)
print('p', p)
if self.last_block[1] >= p[1]:
print('Obstructed, going to last block')
self.state = self.nav_to_last_block
else:
self.state = self.cleanup
def nav_to_last_block(self):
w = self.g.world
p = utils.pint(self.g.pos)
c = self.g.chunks
pos = utils.padd(self.last_block, path.BLOCK_ABOVE)
navpath = w.path_to_place(p, pos)
if navpath:
self.g.path = navpath
self.state = self.going_to_last_block
else:
print('Cant get to that block')
self.state = self.cleanup
def going_to_last_block(self):
if not len(self.g.path):
self.state = self.cleanup
def cleanup(self):
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.wait_time = 0
self.last_block = None
self.next_block = None
def run(self):
self.state()
class JobStates:
def idle(self):
return []
def init_machines(self):
self.gather_wood_states = GatherWoodStates(self.g)
self.gather_sand_states = GatherSandStates(self.g)
self.sleep_with_bed_states = SleepWithBedStates(self.g)
self.cache_items_states = CacheItemsStates(self.g)
self.find_gapple_states = FindGappleStates(self.g)
self.plant_tree_states = PlantTreeStates(self.g)
self.clear_leaves_states = ClearLeavesStates(self.g)
self.grab_sapling_states = GrabSaplingStates(self.g)
self.grab_sand_states = GrabSandStates(self.g)
self.fill_blocks_states = FillBlocksStates(self.g)
self.check_threats_states = CheckThreatsStates(self.g)
def run_machines(self, machines):
for m in machines:
if m.state == m.idle:
continue
if m.state != m.done:
m.run()
return
# if we went through them all
for m in machines:
m.state = m.init
def gather_sand(self):
machines = [
self.gather_sand_states,
self.grab_sand_states,
self.cache_items_states,
self.sleep_with_bed_states,
]
return machines
def farm_sand(self):
machines = [
self.check_threats_states,
self.gather_sand_states,
self.grab_sand_states,
self.cache_items_states,
self.sleep_with_bed_states,
]
self.sleep_with_bed_states.silent = True
self.cache_items_states.silent = True
return machines
def cache_items(self):
machines = [
self.cache_items_states,
]
return machines
def find_gapple(self):
machines = [
self.find_gapple_states,
]
return machines
def gather_wood(self):
machines = [
self.gather_wood_states,
self.sleep_with_bed_states,
self.cache_items_states,
]
return machines
def farm_wood(self):
machines = [
self.gather_wood_states,
self.plant_tree_states,
self.clear_leaves_states,
self.grab_sapling_states,
self.sleep_with_bed_states,
self.cache_items_states,
]
self.sleep_with_bed_states.silent = True
self.cache_items_states.silent = True
return machines
def fill_blocks(self):
machines = [
self.fill_blocks_states,
self.sleep_with_bed_states,
]
return machines
def stop(self):
self.init_machines()
self.state = self.idle
def __init__(self, global_state):
self.g = global_state
self.init_machines()
self.state = self.idle
def tick(self):
self.run_machines(self.state())