diff --git a/bot.py b/bot.py index bac151e..22abac4 100644 --- a/bot.py +++ b/bot.py @@ -205,7 +205,6 @@ def init(global_state): g.item_lock = False g.command_lock = False - g.window = None g.trades = [] g.job = jobs.JobStates(g) @@ -252,6 +251,7 @@ def bot(global_state): print('Chunks loaded.') init(g) + g.game.close_window() print('Initialized.') while g.running: @@ -270,10 +270,3 @@ def bot(global_state): g.connection.early_outgoing_packet_listeners = [] print('Bot module loaded.') - -print(mcdata.mcd.blockCollisionShapes['blocks']['brewing_stand']) -print(mcdata.mcd.blockCollisionShapes['shapes']['107']) - - - - diff --git a/game.py b/game.py index d315ab6..965f0ee 100644 --- a/game.py +++ b/game.py @@ -309,6 +309,40 @@ class MCWorld: result.append(mob) return result + def find_villagers(self, center, distance): + # finds villagers within distance + result = [] + for eid, mob in copy(self.g.mobs).items(): + type_name = mobs.MOB_NAMES[mob.type] + if type_name != 'villager' : continue + pos = utils.pint((mob.x, mob.y, mob.z)) + if utils.phyp(center, pos) > distance: + continue + result.append(mob) + return result + + def find_villager_openings(self, villager): + # returns coords in a cardinal direction where we can stand by a villager + maze_solver = path.Pathfinder(self.g.chunks) + result = [] + + for distance in range(3): + for direction in path.CHECK_DIRECTIONS: + offset = utils.pmul(direction, distance+1) + + if not maze_solver.check_traverse(villager, offset): + continue + + # check for line of sight + for check in range(distance+1): + offset2 = utils.pmul(direction, check+1) + offset2 = utils.padd(offset2, path.BLOCK_ABOVE) + check = utils.padd(villager, offset2) + if self.block_at(*check) not in blocks.NON_SOLID_IDS: + break + else: # for + result.append(utils.padd(villager, offset)) + return result class Game: @@ -642,7 +676,12 @@ class Game: self.g.job.state = self.g.job.loiter reply = 'ok' + if command == 'trade': + self.g.job.state = self.g.job.trade + reply = 'ok' + if command == 'stop': + self.close_window() bot.init(self.g) reply = 'ok' @@ -773,7 +812,8 @@ class Game: if command == 'test': reply = 'ok' - self.select_next_item() + r = self.g.world.find_villager_openings((615, 78, 493)) + print(r) ################# Authorized commands ########################## if authed: @@ -965,10 +1005,11 @@ class Game: w.count += 1 def close_window(self): - packet = CloseWindowPacket() - packet.window_id = self.g.window.data.window_id - self.g.connection.write_packet(packet) - self.g.window = None + if self.g.window: + packet = CloseWindowPacket() + packet.window_id = self.g.window.data.window_id + self.g.connection.write_packet(packet) + self.g.window = None def handle_window_confirmation(self, packet): print(packet) @@ -1143,6 +1184,7 @@ class Game: def handle_trade_list(self, packet): print(packet) + self.g.trades = packet.trades def tick(self): if self.g.breaking: diff --git a/jobs.py b/jobs.py index bf66cb7..fc7443d 100644 --- a/jobs.py +++ b/jobs.py @@ -1772,6 +1772,114 @@ class EatFoodStates: self.state() +class SellToVillagerStates: + def idle(self): + return None + + def init(self): + self.state = self.find_villager + + def find_villager(self): + print('Finding new villager...') + w = self.g.world + p = utils.pint(self.g.pos) + + for villager in w.find_villagers(p, 100): + print('Found villager:', villager) + if villager not in self.bad_villagers: + break + else: # for + print('No good villagers left, aborting.') + self.state = self.cleanup + return + + self.villager = villager + self.villager_pos = utils.pint((villager.x, villager.y, villager.z)) + self.state = self.find_openings + + def find_openings(self): + w = self.g.world + self.openings = w.find_villager_openings(self.villager_pos) + 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 villager:', self.villager) + if self.villager not in self.good_villagers: + self.bad_villagers.append(self.villager) + print('Added to bad villager list') + 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_villager + else: + self.openings.pop(0) + + def going_to_villager(self): + if utils.pint(self.g.pos) == self.openings[0]: + print('Arrived at villager') + self.g.look_at = self.villager_pos + self.wait_time = 0.5 + self.state = self.wait_to_interact + + def wait_to_interact(self): + if self.wait_time > 0: + self.wait_time -= utils.TICK + else: + self.state = self.interact_villager + + def interact_villager(self): + print('Interacting with villager') + self.g.game.interact(self.villager.entity_id) + self.g.game.animate() + self.state = self.select_trade + + def select_trade(self): + if not self.g.window or not self.g.trades: + return + + print('Got trades window') + self.state = self.freeze + + def freeze(self): + return + + def wait(self): + if self.wait_time > 0: + self.wait_time -= utils.TICK + else: + 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.villager = None + self.villager_pos = None + self.bad_villagers = [] + self.good_villagers = [] + self.openings = [] + self.wait_time = 0 + + def run(self): + self.state() + class JobStates: def idle(self): @@ -1793,6 +1901,7 @@ class JobStates: self.gather_wart_states = GatherWartStates(self.g) self.gather_crop_states = GatherCropStates(self.g) self.eat_food_states = EatFoodStates(self.g) + self.sell_to_villager = SellToVillagerStates(self.g) def run_machines(self, machines): for m in machines: @@ -1922,6 +2031,21 @@ class JobStates: self.sleep_with_bed_states.silent = True return machines + def trade(self): + machines = [ + #self.grab_supplies_states, + self.sell_to_villager, + #self.sleep_with_bed_states, + #self.eat_food_states, + #self.cache_items_states, + ] + self.sleep_with_bed_states.silent = True + self.cache_items_states.silent = True + self.grab_supplies_states.supplies = { + tuple(items.AXE_IDS): 9, + } + return machines + def stop(self): self.init_machines() self.state = self.idle