You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
6.6 KiB
234 lines
6.6 KiB
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()
|
|
|