Compare commits

..

No commits in common. "1d8d473e260f3243d85276237bfb24c2f805ca3d" and "caa3fbb2a4f7c459430ca073f3e49a30215df6d5" have entirely different histories.

5 changed files with 44 additions and 227 deletions

24
bot.py
View File

@ -55,18 +55,10 @@ def tick(global_state):
target = None target = None
# make sure current chunks are loaded for physics # make sure current chunks are loaded for physics
if not g.chunks.check_loaded(p, 288): if not g.chunks.check_loaded(p, 9):
if not g.chunks.loading:
print('Loading chunks', end='', flush=True)
g.chunks.loading = True
packet = serverbound.play.PositionAndLookPacket(x=p.x, feet_y=p.y, z=p.z, pitch=0, yaw=0, on_ground=True) packet = serverbound.play.PositionAndLookPacket(x=p.x, feet_y=p.y, z=p.z, pitch=0, yaw=0, on_ground=True)
g.connection.write_packet(packet, force=True) g.connection.write_packet(packet, force=True)
return return
else:
if g.chunks.loading:
print()
print('Chunks loaded.')
g.chunks.loading = False
g.chunks.unload_chunks(p) g.chunks.unload_chunks(p)
@ -213,7 +205,7 @@ def init(global_state):
g.item_lock = False g.item_lock = False
g.command_lock = False g.command_lock = False
g.trades = [] g.window = None
g.job = jobs.JobStates(g) g.job = jobs.JobStates(g)
g.chopped_tree = False g.chopped_tree = False
@ -254,8 +246,11 @@ def bot(global_state):
time.sleep(utils.TICK) time.sleep(utils.TICK)
print('Player loaded.') print('Player loaded.')
while not g.chunks.check_loaded(g.pos, 529):
time.sleep(utils.TICK)
print('Chunks loaded.')
init(g) init(g)
g.game.close_window()
print('Initialized.') print('Initialized.')
while g.running: while g.running:
@ -274,3 +269,10 @@ def bot(global_state):
g.connection.early_outgoing_packet_listeners = [] g.connection.early_outgoing_packet_listeners = []
print('Bot module loaded.') print('Bot module loaded.')
print(mcdata.mcd.blockCollisionShapes['blocks']['brewing_stand'])
print(mcdata.mcd.blockCollisionShapes['shapes']['107'])

58
game.py
View File

@ -309,40 +309,6 @@ class MCWorld:
result.append(mob) result.append(mob)
return result return result
def find_villagers(self, center, distance):
# finds villagers within distance
result = []
for eid, mob in copy(self.g.mobs).items():
type_name = mobs.MOB_NAMES[mob.type]
if type_name != 'villager' : continue
pos = utils.pint((mob.x, mob.y, mob.z))
if utils.phyp(center, pos) > distance:
continue
result.append(mob)
return result
def find_villager_openings(self, villager):
# returns coords in a cardinal direction where we can stand by a villager
maze_solver = path.Pathfinder(self.g.chunks)
result = []
for distance in range(3):
for direction in path.CHECK_DIRECTIONS:
offset = utils.pmul(direction, distance+1)
if not maze_solver.check_traverse(villager, offset):
continue
# check for line of sight
for check in range(distance+1):
offset2 = utils.pmul(direction, check+1)
offset2 = utils.padd(offset2, path.BLOCK_ABOVE)
check = utils.padd(villager, offset2)
if self.block_at(*check) not in blocks.NON_SOLID_IDS:
break
else: # for
result.append(utils.padd(villager, offset))
return result
class Game: class Game:
@ -676,12 +642,7 @@ class Game:
self.g.job.state = self.g.job.loiter self.g.job.state = self.g.job.loiter
reply = 'ok' reply = 'ok'
if command == 'trade':
self.g.job.state = self.g.job.trade
reply = 'ok'
if command == 'stop': if command == 'stop':
self.close_window()
bot.init(self.g) bot.init(self.g)
reply = 'ok' reply = 'ok'
@ -798,7 +759,7 @@ class Game:
try: try:
item = self.g.window.contents[slot] item = self.g.window.contents[slot]
except KeyError: except KeyError:
item = Slot(present=False) item = Slot(present=False, item_id=None, item_count=None, nbt=None)
print(item) print(item)
self.click_window(slot, button, mode, item) self.click_window(slot, button, mode, item)
else: else:
@ -812,8 +773,7 @@ class Game:
if command == 'test': if command == 'test':
reply = 'ok' reply = 'ok'
r = self.g.world.find_villager_openings((615, 78, 493)) self.select_next_item()
print(r)
################# Authorized commands ########################## ################# Authorized commands ##########################
if authed: if authed:
@ -933,9 +893,7 @@ class Game:
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
# and optionally the most damaged item
inv_items = list(self.g.inv.items()) inv_items = list(self.g.inv.items())
inv_items.sort(key=lambda x: (x[1].nbt or {}).get('Damage', 0), reverse=True)
inv_items.sort(key=lambda x: x[1].item_count or 0) inv_items.sort(key=lambda x: x[1].item_count or 0)
for slot, item in inv_items: for slot, item in inv_items:
if item.item_id in items: if item.item_id in items:
@ -964,9 +922,7 @@ class Game:
def select_next_item(self): def select_next_item(self):
# select the next item slot that has an item # select the next item slot that has an item
for slot, item in self.g.inv.items(): for slot, item in self.g.inv.items():
if slot < 9: continue # skip armour slots
if item.present: if item.present:
print('slot:', slot, 'item:', item)
self.g.game.choose_slot(slot) self.g.game.choose_slot(slot)
self.g.holding = item.item_id self.g.holding = item.item_id
return True return True
@ -1005,11 +961,10 @@ class Game:
w.count += 1 w.count += 1
def close_window(self): def close_window(self):
if self.g.window: packet = CloseWindowPacket()
packet = CloseWindowPacket() packet.window_id = self.g.window.data.window_id
packet.window_id = self.g.window.data.window_id self.g.connection.write_packet(packet)
self.g.connection.write_packet(packet) self.g.window = None
self.g.window = None
def handle_window_confirmation(self, packet): def handle_window_confirmation(self, packet):
print(packet) print(packet)
@ -1184,7 +1139,6 @@ class Game:
def handle_trade_list(self, packet): def handle_trade_list(self, packet):
print(packet) print(packet)
self.g.trades = packet.trades
def tick(self): def tick(self):
if self.g.breaking: if self.g.breaking:

170
jobs.py
View File

@ -303,7 +303,7 @@ class GatherWartStates:
def select_wart(self): def select_wart(self):
p = utils.pint(self.g.pos) p = utils.pint(self.g.pos)
if self.g.game.select_item([items.NETHERWART_ID]): if self.g.game.select_item(items.NETHERWART_ID):
self.state = self.wait_select self.state = self.wait_select
self.wait_time = 0.5 self.wait_time = 0.5
else: else:
@ -403,7 +403,6 @@ class GatherWoodStates:
print('Unable to get to tree', self.tree) print('Unable to get to tree', self.tree)
if self.tree not in self.good_trees: if self.tree not in self.good_trees:
self.bad_trees.append(self.tree) self.bad_trees.append(self.tree)
print('Added to bad trees list')
self.state = self.cleanup self.state = self.cleanup
return return
@ -508,6 +507,7 @@ class GatherWoodStates:
# never gets ran, placeholder # never gets ran, placeholder
return None return None
def __init__(self, global_state): def __init__(self, global_state):
self.g = global_state self.g = global_state
self.state = self.idle self.state = self.idle
@ -893,6 +893,7 @@ class CacheItemsStates:
self.g.look_at = self.area self.g.look_at = self.area
self.state = self.open_chest self.state = self.open_chest
def select_chest(self): def select_chest(self):
if self.g.game.select_item([items.CHEST_ID]): if self.g.game.select_item([items.CHEST_ID]):
self.state = self.find_cache_spot self.state = self.find_cache_spot
@ -1287,23 +1288,19 @@ class ClearLeavesStates:
return None return None
def init(self): def init(self):
if not self.g.chopped_tree: if self.g.chopped_tree:
print('Didnt chop tree, clearing leaves') sapling_type = self.g.chopped_tree + '_sapling'
self.state = self.cleanup sapling_item = items.get_id(sapling_type)
return num_saplings = self.g.game.count_items([sapling_item])
print('Have', num_saplings, sapling_type, 'in inventory')
sapling_type = self.g.chopped_tree + '_sapling' if num_saplings > 8:
sapling_item = items.get_id(sapling_type) print('Aborting clearing leaves')
num_saplings = self.g.game.count_items([sapling_item]) self.state = self.cleanup
print('Have', num_saplings, sapling_type, 'in inventory') return
if num_saplings > 8: self.state = self.select_log
print('Have enough saplings, aborting clearing leaves') print('Clearing leaves...')
self.state = self.cleanup
return
self.state = self.select_log
print('Clearing leaves...')
def select_log(self): def select_log(self):
# select a log to avoid using tools # select a log to avoid using tools
@ -1561,10 +1558,6 @@ class FillBlocksStates:
return return
self.last_block = check self.last_block = check
else: # for
self.state = self.cleanup
print('Aborting, no air left')
return
def select_item(self): def select_item(self):
f = self.g.filling f = self.g.filling
@ -1772,114 +1765,6 @@ class EatFoodStates:
self.state() self.state()
class SellToVillagerStates:
def idle(self):
return None
def init(self):
self.state = self.find_villager
def find_villager(self):
print('Finding new villager...')
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:
break
else: # for
print('No good villagers left, aborting.')
self.state = self.cleanup
return
self.villager = villager
self.villager_pos = utils.pint((villager.x, villager.y, villager.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.state = self.select_trade
def select_trade(self):
if not self.g.window or not self.g.trades:
return
print('Got trades window')
self.state = self.freeze
def freeze(self):
return
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.openings = []
self.wait_time = 0
def run(self):
self.state()
class JobStates: class JobStates:
def idle(self): def idle(self):
@ -1901,7 +1786,6 @@ class JobStates:
self.gather_wart_states = GatherWartStates(self.g) self.gather_wart_states = GatherWartStates(self.g)
self.gather_crop_states = GatherCropStates(self.g) self.gather_crop_states = GatherCropStates(self.g)
self.eat_food_states = EatFoodStates(self.g) self.eat_food_states = EatFoodStates(self.g)
self.sell_to_villager = SellToVillagerStates(self.g)
def run_machines(self, machines): def run_machines(self, machines):
for m in machines: for m in machines:
@ -2013,13 +1897,12 @@ class JobStates:
self.sleep_with_bed_states.silent = True self.sleep_with_bed_states.silent = True
f = self.g.filling f = self.g.filling
if f: name = blocks.BLOCKS[f.block]
name = blocks.BLOCKS[f.block] item = items.ITEMS['minecraft:'+name]['protocol_id']
item = items.ITEMS['minecraft:'+name]['protocol_id']
self.grab_supplies_states.supplies = { self.grab_supplies_states.supplies = {
tuple([item]): 0, tuple([item]): 0,
} }
return machines return machines
def loiter(self): def loiter(self):
@ -2031,21 +1914,6 @@ class JobStates:
self.sleep_with_bed_states.silent = True self.sleep_with_bed_states.silent = True
return machines return machines
def trade(self):
machines = [
#self.grab_supplies_states,
self.sell_to_villager,
#self.sleep_with_bed_states,
#self.eat_food_states,
#self.cache_items_states,
]
self.sleep_with_bed_states.silent = True
self.cache_items_states.silent = True
self.grab_supplies_states.supplies = {
tuple(items.AXE_IDS): 9,
}
return machines
def stop(self): def stop(self):
self.init_machines() self.init_machines()
self.state = self.idle self.state = self.idle

View File

@ -44,7 +44,6 @@ class ChunksManager:
self.chunks = {} self.chunks = {}
self.biomes = {} self.biomes = {}
self.index = {} self.index = {}
self.loading = False
def handle_block(self, block_packet): def handle_block(self, block_packet):
self.set_block_at(block_packet.location.x, block_packet.location.y, block_packet.location.z, block_packet.block_state_id) self.set_block_at(block_packet.location.x, block_packet.location.y, block_packet.location.z, block_packet.block_state_id)
@ -75,8 +74,6 @@ class ChunksManager:
self.index[item_id].append(coords) self.index[item_id].append(coords)
self.biomes[(chunk_packet.x, None, chunk_packet.z)] = chunk_packet.biomes # FIXME self.biomes[(chunk_packet.x, None, chunk_packet.z)] = chunk_packet.biomes # FIXME
if self.loading:
print('.', end='', flush=True)
def register(self, connection): def register(self, connection):
connection.register_packet_listener(self.handle_block, clientbound.play.BlockChangePacket) connection.register_packet_listener(self.handle_block, clientbound.play.BlockChangePacket)

View File

@ -103,7 +103,7 @@ class Nbt(Type):
class Slot(Type): class Slot(Type):
def __init__(self, present, item_id=None, item_count=None, nbt=None): def __init__(self, present, item_id, item_count, nbt):
self.present = present self.present = present
self.item_id = item_id self.item_id = item_id
self.item_count = item_count self.item_count = item_count
@ -112,11 +112,8 @@ class Slot(Type):
def __str__(self): def __str__(self):
return str(self.__dict__) return str(self.__dict__)
def __repr__(self): def __repr__(self):
if self.present: return 'Slot(present={}, item_id={}, item_count={}, nbt={}'.format(
return 'Slot(present={}, item_id={}, item_count={}, nbt={}'.format( self.present, self.item_id, self.item_count, self.nbt)
self.present, self.item_id, self.item_count, self.nbt)
else:
return 'Slot(present={})'.format(self.present)
@staticmethod @staticmethod
def read(file_object): def read(file_object):
@ -134,10 +131,9 @@ class Slot(Type):
@staticmethod @staticmethod
def send(value, socket): def send(value, socket):
Boolean.send(value.present, socket) Boolean.send(value.present, socket)
if value.present: VarInt.send(value.item_id, socket)
VarInt.send(value.item_id, socket) Byte.send(value.item_count, socket)
Byte.send(value.item_count, socket) Byte.send(0x00, socket)
Byte.send(0x00, socket)
class Entry(Type): class Entry(Type):