Finish executing the villager trade
This commit is contained in:
parent
1d8d473e26
commit
28ca442a46
19
game.py
19
game.py
|
@ -20,7 +20,8 @@ from protocol.packets import (
|
|||
ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket,
|
||||
ClientWindowConfirmationPacket, EntityMetadataPacket,
|
||||
SpawnLivingEntityPacket, EntityPositionRotationPacket, DestroyEntitiesPacket,
|
||||
EntityActionPacket, EntityTeleport, InteractEntityPacket, TradeListPacket
|
||||
EntityActionPacket, EntityTeleport, InteractEntityPacket, TradeListPacket,
|
||||
SelectTradePacket,
|
||||
)
|
||||
|
||||
from protocol.types import Slot
|
||||
|
@ -789,6 +790,7 @@ class Game:
|
|||
if command == 'close':
|
||||
if self.g.window:
|
||||
self.close_window()
|
||||
reply = 'ok'
|
||||
else:
|
||||
reply = 'nothing open'
|
||||
|
||||
|
@ -930,6 +932,16 @@ class Game:
|
|||
count += item.item_count
|
||||
return count
|
||||
|
||||
def get_window_slot(self, item_id):
|
||||
# get the first slot that matches item of a window
|
||||
window_items = list(self.g.window.contents.items())
|
||||
for slot, item in window_items:
|
||||
if not item.present: continue
|
||||
if item.item_id == item_id:
|
||||
return slot, item
|
||||
else: #for
|
||||
return False, False
|
||||
|
||||
def select_item(self, items):
|
||||
# select the first match from items of inv
|
||||
# uses smallest stack of that match
|
||||
|
@ -1186,6 +1198,11 @@ class Game:
|
|||
print(packet)
|
||||
self.g.trades = packet.trades
|
||||
|
||||
def select_trade(self, num):
|
||||
packet = SelectTradePacket()
|
||||
packet.selected_slot = num
|
||||
self.g.connection.write_packet(packet)
|
||||
|
||||
def tick(self):
|
||||
if self.g.breaking:
|
||||
self.animate()
|
||||
|
|
2
items.py
2
items.py
|
@ -108,5 +108,7 @@ POTATO_ID = get_id('potato')
|
|||
WHEAT_SEEDS_ID = get_id('wheat_seeds')
|
||||
BEETROOT_SEEDS_ID = get_id('beetroot_seeds')
|
||||
|
||||
EMERALD_ID = get_id('emerald')
|
||||
|
||||
NEEDED_ITEMS = BED_IDS | SHOVEL_IDS | AXE_IDS | FOOD_IDS | set([CHEST_ID])
|
||||
WANTED_ITEMS = SAPLING_IDS | set([NETHERWART_ID, CARROT_ID, POTATO_ID, WHEAT_SEEDS_ID, BEETROOT_SEEDS_ID])
|
||||
|
|
91
jobs.py
91
jobs.py
|
@ -1777,6 +1777,7 @@ class SellToVillagerStates:
|
|||
return None
|
||||
|
||||
def init(self):
|
||||
self.trade = None
|
||||
self.state = self.find_villager
|
||||
|
||||
def find_villager(self):
|
||||
|
@ -1784,17 +1785,18 @@ class SellToVillagerStates:
|
|||
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:
|
||||
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 = villager
|
||||
self.villager_pos = utils.pint((villager.x, villager.y, villager.z))
|
||||
self.villager = v
|
||||
self.villager_pos = utils.pint((v.x, v.y, v.z))
|
||||
self.state = self.find_openings
|
||||
|
||||
def find_openings(self):
|
||||
|
@ -1841,14 +1843,83 @@ class SellToVillagerStates:
|
|||
print('Interacting with villager')
|
||||
self.g.game.interact(self.villager.entity_id)
|
||||
self.g.game.animate()
|
||||
self.state = self.select_trade
|
||||
self.state = self.choose_trade
|
||||
|
||||
def choose_trade(self):
|
||||
g = self.g.game
|
||||
|
||||
def select_trade(self):
|
||||
if not self.g.window or not self.g.trades:
|
||||
return
|
||||
|
||||
print('Got trades window')
|
||||
self.state = self.freeze
|
||||
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
|
||||
|
||||
|
||||
if g.count_items([in_id]) < in_num:
|
||||
continue
|
||||
if trade.trade_disabled:
|
||||
continue
|
||||
if out_id != items.EMERALD_ID:
|
||||
continue
|
||||
|
||||
print('Found trade: #', trade_num, trade)
|
||||
self.trade = trade
|
||||
self.trade_num = trade_num
|
||||
self.state = self.click_trade
|
||||
break
|
||||
else:
|
||||
print('Villager has been spent, aborting')
|
||||
self.spent_villagers.append(self.villager)
|
||||
self.state = self.cleanup
|
||||
return
|
||||
|
||||
def click_trade(self):
|
||||
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
|
||||
slot = w.contents[slot_num]
|
||||
|
||||
self.g.item_lock = True
|
||||
self.g.game.click_window(slot_num, 0, 1, slot)
|
||||
self.g.game.close_window()
|
||||
self.state = self.end_trade
|
||||
|
||||
def end_trade(self):
|
||||
if self.g.item_lock:
|
||||
return
|
||||
|
||||
print('Trade completed.')
|
||||
self.state = self.interact_villager
|
||||
|
||||
|
||||
|
||||
#def grab_stack(self):
|
||||
# g = self.g.game
|
||||
# in_id = self.trade.input_item_1.item_id
|
||||
# slot_num, slot = g.get_window_slot(in_id)
|
||||
|
||||
# if not slot:
|
||||
# print('Item not found, aborting')
|
||||
# self.state = self.cleanup
|
||||
# return
|
||||
|
||||
# print('Grabbing:', slot)
|
||||
# self.g.item_lock = True
|
||||
# # double click stack to grab max
|
||||
# self.g.game.click_window(slot_num, 0, 6, slot)
|
||||
|
||||
# self.state = self.freeze
|
||||
|
||||
|
||||
def freeze(self):
|
||||
return
|
||||
|
@ -1874,7 +1945,9 @@ class SellToVillagerStates:
|
|||
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):
|
||||
|
|
|
@ -10,6 +10,7 @@ with open('minecraft_data/registries.json') as f:
|
|||
|
||||
SINGLE_CHEST = 2
|
||||
DOUBLE_CHEST = 5
|
||||
VILLAGER_TRADE = 18
|
||||
|
||||
WINDOWS = {
|
||||
SINGLE_CHEST: Munch(
|
||||
|
@ -22,4 +23,10 @@ WINDOWS = {
|
|||
inventory=list(range(54, 90)),
|
||||
slot_diff=45,
|
||||
),
|
||||
VILLAGER_TRADE: Munch(
|
||||
input1=0,
|
||||
input2=1,
|
||||
output=2,
|
||||
inventory=list(range(3, 38)),
|
||||
),
|
||||
}
|
||||
|
|
|
@ -436,3 +436,14 @@ class TradeListPacket(Packet):
|
|||
self.experience = VarInt.read(file_object)
|
||||
self.is_regular_villager = Boolean.read(file_object)
|
||||
self.can_restock = Boolean.read(file_object)
|
||||
|
||||
class SelectTradePacket(Packet):
|
||||
# Sent when a player selects a specific trade offered by a villager
|
||||
# https://wiki.vg/Protocol#Select_Trade
|
||||
|
||||
id = 0x23
|
||||
packet_name = 'select trade entity'
|
||||
|
||||
definition = [
|
||||
{'selected_slot': VarInt},
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue
Block a user