219 lines
6.0 KiB
Python
219 lines
6.0 KiB
Python
|
import re
|
||
|
import time
|
||
|
import importlib
|
||
|
import random
|
||
|
from itertools import count
|
||
|
from math import hypot, floor
|
||
|
|
||
|
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 mcdata
|
||
|
importlib.reload(mcdata)
|
||
|
import mobs
|
||
|
importlib.reload(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 not in self.bad_villagers and v not in self.spent_villagers:
|
||
|
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.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.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.wait
|
||
|
self.wait_time = 10
|
||
|
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()
|