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 SellToVillagerStates: def idle(self): return None def init(self): self.trade = None self.state = self.find_villager def find_villager(self): print('Finding new villager...') w = self.g.world p = utils.pint(self.g.pos) for v in w.find_villagers(p, 100): print('Found villager:', v) if v in self.bad_villagers: print('In bad villager list') continue if v in self.spent_villagers: print('In spent villager list') continue if 'profession' not in v: print('Villager has unknown profession') continue if v.profession not in mobs.TRADES: print('Villager doesnt sell stuff we collect') continue trades = mobs.TRADES[v.profession] if not self.g.game.count_items(trades): print('We dont have anything to sell him') continue break else: # for print('No good villagers left, aborting.') self.spent_villagers = [] self.state = self.cleanup return self.villager = v self.villager_pos = utils.pint((v.x, v.y, v.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.find_villager return navpath = w.path_to_place(p, self.openings[0]) if navpath: self.g.path = navpath self.state = self.going_to_villager self.g.look_at = None else: self.openings.pop(0) time.sleep(0.1) 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.wait_time = 0.5 self.state = self.wait_for_window def wait_for_window(self): if self.wait_time > 0: self.wait_time -= utils.TICK else: self.state = self.choose_trade def choose_trade(self): g = self.g.game w = self.g.window if not w or not self.g.trades: print('Didnt get a trade window, aborting') self.state = self.cleanup return if w.data.window_type != mcdata.VILLAGER_TRADE: print('Got wrong window, aborting') self.state = self.cleanup return for trade_num, trade in enumerate(self.g.trades): in_id = trade.input_item_1.item_id in_num = trade.input_item_1.item_count out_id = trade.output_item.item_id price = in_num \ + floor(in_num * trade.price_multiplier * trade.demand) \ + trade.special_price if price < 1: price = 1 if g.count_items([in_id]) < price: continue print('Checking trade #', trade_num) if trade.trade_disabled: print('Trade disabled, skipping') continue if out_id != items.EMERALD_ID: print('Not for emeralds, skipping') continue if price > in_num: print('Trade in demand, skipping') continue print('Found trade:', trade) print('Adjusted price:', price) self.trade = trade self.trade_num = trade_num self.state = self.click_trade break else: print('Villager has been spent, aborting') self.g.game.close_window() self.spent_villagers.append(self.villager) self.state = self.find_villager return def click_trade(self): print('Clicking trade') self.g.item_lock = True self.g.game.select_trade(self.trade_num) self.state = self.execute_trade def execute_trade(self): if self.g.item_lock: return w = self.g.window w_info = mcdata.WINDOWS[w.data.window_type] slot_num = w_info.output if slot_num in w.contents: print('Executing trade') slot = w.contents[slot_num] self.g.game.click_window(slot_num, 0, 1, slot) else: print('Bad trade, aborting') self.state = self.end_trade def end_trade(self): print('Trading complete') self.g.game.close_window() self.wait_time = 1 self.state = self.wait_for_trade def wait_for_trade(self): if self.wait_time > 0: self.wait_time -= utils.TICK else: self.state = self.interact_villager 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.spent_villagers = [] self.openings = [] self.trade = None self.wait_time = 0 def run(self): self.state()