import re import time import importlib import random 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) 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) trees = w.find_trees(p, 100) print('Found trees:', trees) try: while trees[0] in self.bad_trees: trees.pop(0) self.tree = trees[0] except IndexError: print('No good tress left, aborting.') self.state = self.cleanup return 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) 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.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.tree = None self.openings = [] self.bad_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) == 66 def idle(self): return None def init(self): self.state = self.find_new_sand def find_new_sand(self): print('Finding new sand...') w = self.g.world p = utils.pint(self.g.pos) sand = w.find_sand(p, 50, self.origin) print('Found sand:', sand) for check in sand: if check in self.bad_sand: continue self.sand = check break self.state = self.nav_to_sand def nav_to_sand(self): w = self.g.world p = utils.pint(self.g.pos) self.g.chunks.set_block_at(*self.sand, blocks.AIR) navpath = w.path_to_place(p, self.sand) self.g.chunks.set_block_at(*self.sand, blocks.SAND) if navpath: self.g.path = navpath[:-1] self.state = self.going_to_sand else: 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.game.break_block(self.sand) print('digging sand') else: self.state = self.get_sand def get_sand(self): w = self.g.world p = utils.pint(self.g.pos) navpath = w.path_to_place(p, self.sand) if navpath: self.g.path = navpath self.state = self.going_to_item else: self.bad_sand.append(self.sand) self.state = self.find_new_sand def going_to_item(self): if utils.pint(self.g.pos) == self.sand: self.g.look_at = 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.origin = utils.pint(self.g.pos) self.sand = None self.bad_sand = [] self.wait_time = 0 def run(self): self.state() class SleepWithBedStates: def idle(self): return None def init(self): if self.g.time >= 12000: self.state = self.find_bed_spot else: print('Aborting sleep, not night') 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 = self.area self.state = self.select_bed def select_bed(self): if self.g.game.select_item(items.BED_IDS): self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW) self.state = self.place_bed else: self.g.chat.send('I need a bed') self.state = self.cleanup 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): if self.g.time < 100: print('Woke up') 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 >= 27: self.state = self.find_cache_spot else: print('Aborting caching, not full') 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.select_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.place_chest else: self.g.chat.send('I need a chest') self.state = self.cleanup 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() 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 # 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.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): print('Finding an open spot to stand...') w = self.g.world p = utils.pint(self.g.pos) for area in w.find_cache_areas(p, 20): 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 navpath = w.path_to_place(p, self.area) if not navpath: print('Unable to get to open area', self.area) self.bad_areas.append(self.area) self.state = self.cleanup return self.g.path = navpath self.state = self.going_to_area print('Going to area', self.area) 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 self.bad_areas = [] 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 saplings = w.find_objects(items.SAPLING_IDS) if not saplings: print('No saplings objects found, aborting') self.state = self.cleanup return random.shuffle(saplings) for s in saplings: p = utils.pint(self.g.pos) 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 # slip 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 saplings, aborting') self.state = self.cleanup def going_to_sapling(self): if utils.pint(self.g.pos) == self.sapling: 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.sapling = None self.eid_blacklist = [] def run(self): self.state() class JobStates: def idle(self): return None def cache_items(self): s1 = self.cache_items_states if s1.state == s1.idle: s1.state = s1.init elif s1.state == s1.done: self.state = self.idle s1.run() def find_gapple(self): s1 = self.find_gapple_states if s1.state == s1.idle: s1.state = s1.init elif s1.state == s1.done: s1.state = s1.tp_to_coord s1.run() def gather_sand(self): s1 = self.gather_sand_states s2 = self.sleep_with_bed_states s3 = self.cache_items_states if s1.state == s1.idle: s1.state = s1.init s2.state = s2.init s3.state = s3.init elif s1.state == s1.done: if s2.state != s2.done: s2.run() return if s3.state != s3.done: s3.run() return s1.state = s1.init s2.state = s2.init s3.state = s3.init return s1.run() def gather_wood(self): s1 = self.gather_wood_states s2 = self.sleep_with_bed_states s3 = self.cache_items_states if s1.state == s1.idle: s1.state = s1.init s2.state = s2.init s3.state = s3.init elif s1.state == s1.done: if s2.state != s2.done: s2.run() return if s3.state != s3.done: s3.run() return s1.state = s1.init s2.state = s2.init s3.state = s3.init return s1.run() def farm_wood(self): self.sleep_with_bed_states.silent = True s1 = self.gather_wood_states s2 = self.plant_tree_states s3 = self.sleep_with_bed_states s4 = self.cache_items_states s5 = self.grab_sapling_states if s1.state == s1.idle: s1.state = s1.init s2.state = s2.init s3.state = s3.init s4.state = s4.init s5.state = s5.init elif s1.state == s1.done: if s2.state != s2.done: s2.run() return if s3.state != s3.done: s3.run() return if s4.state != s4.done: s4.run() return if s5.state != s5.done: s5.run() return s1.state = s1.init s2.state = s2.init s3.state = s3.init s4.state = s4.init s5.state = s5.init return s1.run() def stop(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.grab_sapling_states = GrabSaplingStates(self.g) self.state = self.idle def __init__(self, global_state): self.g = global_state self.state = self.idle self.prev_state = None 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.grab_sapling_states = GrabSaplingStates(self.g) def tick(self): self.state()