minecraft-bot/mosfet/jobs/sell_to_villager.py

235 lines
6.6 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 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()