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,
|
ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket,
|
||||||
ClientWindowConfirmationPacket, EntityMetadataPacket,
|
ClientWindowConfirmationPacket, EntityMetadataPacket,
|
||||||
SpawnLivingEntityPacket, EntityPositionRotationPacket, DestroyEntitiesPacket,
|
SpawnLivingEntityPacket, EntityPositionRotationPacket, DestroyEntitiesPacket,
|
||||||
EntityActionPacket, EntityTeleport, InteractEntityPacket, TradeListPacket
|
EntityActionPacket, EntityTeleport, InteractEntityPacket, TradeListPacket,
|
||||||
|
SelectTradePacket,
|
||||||
)
|
)
|
||||||
|
|
||||||
from protocol.types import Slot
|
from protocol.types import Slot
|
||||||
|
@ -789,6 +790,7 @@ class Game:
|
||||||
if command == 'close':
|
if command == 'close':
|
||||||
if self.g.window:
|
if self.g.window:
|
||||||
self.close_window()
|
self.close_window()
|
||||||
|
reply = 'ok'
|
||||||
else:
|
else:
|
||||||
reply = 'nothing open'
|
reply = 'nothing open'
|
||||||
|
|
||||||
|
@ -930,6 +932,16 @@ class Game:
|
||||||
count += item.item_count
|
count += item.item_count
|
||||||
return 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):
|
def select_item(self, items):
|
||||||
# select the first match from items of inv
|
# select the first match from items of inv
|
||||||
# uses smallest stack of that match
|
# uses smallest stack of that match
|
||||||
|
@ -1186,6 +1198,11 @@ class Game:
|
||||||
print(packet)
|
print(packet)
|
||||||
self.g.trades = packet.trades
|
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):
|
def tick(self):
|
||||||
if self.g.breaking:
|
if self.g.breaking:
|
||||||
self.animate()
|
self.animate()
|
||||||
|
|
2
items.py
2
items.py
|
@ -108,5 +108,7 @@ POTATO_ID = get_id('potato')
|
||||||
WHEAT_SEEDS_ID = get_id('wheat_seeds')
|
WHEAT_SEEDS_ID = get_id('wheat_seeds')
|
||||||
BEETROOT_SEEDS_ID = get_id('beetroot_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])
|
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])
|
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
|
return None
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
self.trade = None
|
||||||
self.state = self.find_villager
|
self.state = self.find_villager
|
||||||
|
|
||||||
def find_villager(self):
|
def find_villager(self):
|
||||||
|
@ -1784,17 +1785,18 @@ class SellToVillagerStates:
|
||||||
w = self.g.world
|
w = self.g.world
|
||||||
p = utils.pint(self.g.pos)
|
p = utils.pint(self.g.pos)
|
||||||
|
|
||||||
for villager in w.find_villagers(p, 100):
|
for v in w.find_villagers(p, 100):
|
||||||
print('Found villager:', villager)
|
print('Found villager:', v)
|
||||||
if villager not in self.bad_villagers:
|
if v not in self.bad_villagers and v not in self.spent_villagers:
|
||||||
break
|
break
|
||||||
else: # for
|
else: # for
|
||||||
print('No good villagers left, aborting.')
|
print('No good villagers left, aborting.')
|
||||||
|
self.spent_villagers = []
|
||||||
self.state = self.cleanup
|
self.state = self.cleanup
|
||||||
return
|
return
|
||||||
|
|
||||||
self.villager = villager
|
self.villager = v
|
||||||
self.villager_pos = utils.pint((villager.x, villager.y, villager.z))
|
self.villager_pos = utils.pint((v.x, v.y, v.z))
|
||||||
self.state = self.find_openings
|
self.state = self.find_openings
|
||||||
|
|
||||||
def find_openings(self):
|
def find_openings(self):
|
||||||
|
@ -1841,14 +1843,83 @@ class SellToVillagerStates:
|
||||||
print('Interacting with villager')
|
print('Interacting with villager')
|
||||||
self.g.game.interact(self.villager.entity_id)
|
self.g.game.interact(self.villager.entity_id)
|
||||||
self.g.game.animate()
|
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:
|
if not self.g.window or not self.g.trades:
|
||||||
return
|
return
|
||||||
|
|
||||||
print('Got trades window')
|
for trade_num, trade in enumerate(self.g.trades):
|
||||||
self.state = self.freeze
|
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):
|
def freeze(self):
|
||||||
return
|
return
|
||||||
|
@ -1874,7 +1945,9 @@ class SellToVillagerStates:
|
||||||
self.villager_pos = None
|
self.villager_pos = None
|
||||||
self.bad_villagers = []
|
self.bad_villagers = []
|
||||||
self.good_villagers = []
|
self.good_villagers = []
|
||||||
|
self.spent_villagers = []
|
||||||
self.openings = []
|
self.openings = []
|
||||||
|
self.trade = None
|
||||||
self.wait_time = 0
|
self.wait_time = 0
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
|
@ -10,6 +10,7 @@ with open('minecraft_data/registries.json') as f:
|
||||||
|
|
||||||
SINGLE_CHEST = 2
|
SINGLE_CHEST = 2
|
||||||
DOUBLE_CHEST = 5
|
DOUBLE_CHEST = 5
|
||||||
|
VILLAGER_TRADE = 18
|
||||||
|
|
||||||
WINDOWS = {
|
WINDOWS = {
|
||||||
SINGLE_CHEST: Munch(
|
SINGLE_CHEST: Munch(
|
||||||
|
@ -22,4 +23,10 @@ WINDOWS = {
|
||||||
inventory=list(range(54, 90)),
|
inventory=list(range(54, 90)),
|
||||||
slot_diff=45,
|
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.experience = VarInt.read(file_object)
|
||||||
self.is_regular_villager = Boolean.read(file_object)
|
self.is_regular_villager = Boolean.read(file_object)
|
||||||
self.can_restock = 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