From a5642409d27dd5986aa7de691c2d0234cccc4187 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Fri, 23 Apr 2021 07:01:00 +0000 Subject: [PATCH] Move command processing to separate file --- mosfet/bot.py | 3 + mosfet/commands.py | 524 +++++++++++++++++++++++++++++++++++++++++++ mosfet/game.py | 513 +----------------------------------------- mosfet/print_help.py | 2 +- 4 files changed, 533 insertions(+), 509 deletions(-) create mode 100644 mosfet/commands.py diff --git a/mosfet/bot.py b/mosfet/bot.py index 10ea490..f45155a 100644 --- a/mosfet/bot.py +++ b/mosfet/bot.py @@ -24,6 +24,7 @@ from mosfet.protocol.managers import DataManager, ChunksManager, ChatManager, Ch from munch import Munch +from mosfet import commands from mosfet import game from mosfet import job from mosfet import path @@ -38,6 +39,7 @@ from mosfet.info import mobs for module in [ blocks, + commands, game, items, job, @@ -267,6 +269,7 @@ def bot(global_state): g.game = game.Game(g) g.world = world.World(g) + g.commands = commands.Commands(g) try: while not g.pos: diff --git a/mosfet/commands.py b/mosfet/commands.py new file mode 100644 index 0000000..bf0d5a8 --- /dev/null +++ b/mosfet/commands.py @@ -0,0 +1,524 @@ +import re +import time +import random +from math import hypot +from itertools import count +from munch import Munch + +from mosfet.protocol.types import Slot + +from mosfet import print_help +from mosfet import utils +from mosfet import path +from mosfet import bot +from mosfet.info import blocks +from mosfet.info import items +from mosfet.info import mobs + +class Commands: + def __init__(self, global_state): + self.g = global_state + + self.g.chat.set_handler(self.handle_chat) + + def handle_chat(self, message): + source, text = message + reply = None + private = False + for_me = False + authed = False + + if source == 'SYSTEM': + self.g.command_lock = False + + if text == 'You are now AFK.': + self.g.afk = True + elif text == 'You are no longer AFK.': + self.g.afk = False + + match1 = re.match(r' (.*)', text) + match2 = re.match(r'\[(\w+) -> me] (.*)', text) + if match1: + sender, text = match1.groups() + elif match2: + sender, text = match2.groups() + private = True + else: + return + + if sender == 'tanner6': + authed = True + + if text.startswith('zzz'): + text = '!zzz' + + bot_num = self.g.name[-1] + + if text.startswith(bot_num): + text = text[1:] + for_me = True + elif text.startswith('! '): + text = text[2:] + elif text.startswith('!'): + text = text[1:] + else: + return + + if ' ' in text: + command = text.split(' ', 1)[0] + data = text.split(' ', 1)[1] + else: + command = text + data = None + + try: + + ## ### Public Commands + ## These can be ran by anyone, all bots will reply. + + ## !help - prints this whole help message to console + ## !help [command] - replies in-game explaining command + if command == 'help': + if data: + for line in print_help.HELP_LINES: + if line[1:].startswith(data) or line[1:].startswith(data[1:]): + reply = 'command ' + line + break + else: # for + reply = 'command not found' + else: + print() + print() + for line in print_help.HELP_LINES: + print(line) + reply = 'check console' + + ## !ping - replies with "pong" + if command == 'ping': + reply = 'pong' + + ## !echo [data] - replies with "data" + if command == 'echo' and data: + reply = data + + ## !pos - replies with position and dimension + if command == 'pos': + reply = str(utils.pint(self.g.pos))[1:-1] + ', ' + self.g.dimension + + ## !afk - goes AFK with /afk + if command == 'afk': + if not self.g.afk: + reply = '/afk' + + ## !unafk - goes not AFK with /afk + if command == 'unafk': + if self.g.afk: + reply = '/afk' + + ## !error - raises an error + if command == 'error': + reply = 'ok' + raise + + ## !inv - prints current inventory + if command == 'inv': + inv_list = [] + for i in self.g.inv.values(): + if i.present: + inv_list.append('{}:{} x {}'.format(items.ITEM_NAMES[i.item_id], str(i.item_id), i.item_count)) + inv_list.sort() + result = '\n'.join(inv_list) + print(result or 'Empty') + + ## !time - replies with Minecraft world time + if command == 'time': + reply = str(self.g.time) + + ## !count [id] - counts the number of items with that id + if command == 'count' and data: + item = int(data) + reply = str(self.g.game.count_items([item])) + + ## !loaded - replies with the current loaded area + if command == 'loaded': + reply = str(self.g.chunks.get_loaded_area()) + + ## !players - prints the current players + ## !players clear - clears the current player list + if command == 'players': + if data == 'clear': + self.g.players = {} + reply = 'ok' + else: + for k, v in self.g.players.items(): + print(str(k) + ':', v, self.g.player_names[v.player_uuid]) + + ## !objects - prints the current items on ground + ## !objects clear - clears the current object list + if command == 'objects': + if data == 'clear': + self.g.objects = {} + reply = 'ok' + else: + for k, v in self.g.objects.items(): + if data and v.item_id != int(data): continue + print(str(k) + ':', v, items.ITEM_NAMES[v.item_id]) + + ## !mobs - prints the current mobs + ## !mobs clear - clears the current mob list + if command == 'mobs': + if data == 'clear': + self.g.mobs = {} + reply = 'ok' + else: + all_mobs = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) + for k, v in all_mobs: + if data and v.type != int(data): continue + print(str(k) + ':', v, mobs.MOB_NAMES[v.type]) + reply = str(len(all_mobs)) + ' mobs' + + ## !monsters - prints the current monsters + if command == 'monsters': + monsters = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) + count = 0 + for k, v in monsters: + if v.type not in mobs.EVIL_IDS: continue + if data and v.type != int(data): continue + count += 1 + print(str(k) + ':', v, mobs.MOB_NAMES[v.type]) + reply = str(count) + ' monsters' + + ## !villagers - prints the current villagers + if command == 'villagers': + all_mobs = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) + count = 0 + for k, v in all_mobs: + type_name = mobs.MOB_NAMES[v.type] + if type_name != 'villager' : continue + count += 1 + print(str(k) + ':', v, type_name) + reply = str(count) + ' villagers' + + ## !threats - prints the dangerous monsters within 20 blocks + ## !threats [num] - prints the dangerous monsters within num blocks + if command == 'threats': + distance = int(data) if data else 20 + p = utils.pint(self.g.pos) + threats = self.g.world.find_threats(p, distance) + + for t in threats: + print(str(t.entity_id) + ':', t, mobs.MOB_NAMES[t.type]) + reply = str(len(threats)) + ' threats' + + if command == 'spiral' and data: + for i in range(int(data)): + print(utils.spiral(i)) + + if command == 'sand_slice': + result = self.g.world.find_sand_slice(utils.pint(self.g.pos), 50) + reply = str(result) + + ## "zzz" or !zzz - bot does /afk to let others sleep + if command == 'zzz': + if not self.g.afk and self.g.dimension == 'overworld': + reply = '/afk' + self.g.afk_timeout = 5.0 + + ## !tree - replies with the closest tree + if command == 'tree': + pos = utils.pint(self.g.pos) + tree = next(self.g.world.find_trees(pos, 50)) + reply = str(tree)[1:-1] + + ## !block x y z - replies what block is at (x, y, z) + if command == 'block': + try: + data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') + x1, y1, z1 = [int(x) for x in data.split()] + except (AttributeError, ValueError): + reply = 'usage: !block x1 y1 z1' + + if not reply: + coord = (x1, y1, z1) + block = self.g.world.block_at(*coord) + + if not reply and block is None: + reply = 'first coord out of range' + + if not reply: + reply = blocks.BLOCKS[block] + ':' + str(block) + + + ################# Specific commands ########################## + + ## ### Bot-specific Commands + ## These will only run for the bot they are addressed to. + + if for_me: + + ## 1respawn - respawns the bot if it's dead + if command == 'respawn': + self.g.game.respawn() + reply = 'ok' + + ## 1gather wood - gathers wood from the world + ## 1gather sand - gathers sand from the world + if command == 'gather' and data: + if data == 'wood': + self.g.job.state = self.g.job.gather_wood + reply = 'ok' + elif data == 'sand': + self.g.job.state = self.g.job.gather_sand + reply = 'ok' + + if reply: + for i in self.g.inv.values(): + print(i.item_id) + if i.item_id in items.BED_IDS: + break + else: + reply += ', I need a bed' + + ## 1farm wood - farms wood from a certain area + ## 1farm sand - farms sand from a certain area + ## 1farm wart - farms netherwart from a certain area + ## 1farm crop - farms mature crops from a certain area + if command == 'farm' and data: + if data == 'wood': + self.g.job.state = self.g.job.farm_wood + reply = 'ok' + elif data == 'sand': + self.g.job.state = self.g.job.farm_sand + reply = 'ok' + elif data == 'wart': + self.g.job.state = self.g.job.farm_wart + reply = 'ok' + elif data.startswith('crop'): + self.g.job.state = self.g.job.farm_crop + reply = 'ok' + + if reply and self.g.dimension == 'overworld': + for i in self.g.inv.values(): + if i.item_id in items.BED_IDS: + break + else: + reply += ', I need a bed' + + ## 1loiter - stands still but eats, sleeps, and flees + if command == 'loiter': + self.g.job.state = self.g.job.loiter + reply = 'ok' + + ## 1trade - sells items to villagers to get emeralds + if command == 'trade': + self.g.job.state = self.g.job.trade + reply = 'ok' + + ## 1stop - stops the current job and resets bot + if command == 'stop': + self.g.game.close_window() + bot.init(self.g) + reply = 'ok' + + ## 1drop - drops the current stack its holding + if command == 'drop': + self.g.game.drop_stack() + + ## 1select [id] - moves item with id into main hand + if command == 'select' and data: + item = int(data) + if self.g.game.select_item([item]): + reply = 'ok' + else: + reply = 'not found' + + ## 1dump [id] - drops all items matching id + if command == 'dump' and data: + item = int(data) + if self.g.game.count_items([item]): + self.g.dumping = item + reply = 'ok' + else: + reply = 'not found' + + ## 1drain - drops all items in inventory + if command == 'drain': + self.g.draining = True + reply = 'ok' + + if command == 'gapple': + self.g.job.state = self.g.job.find_gapple + if data: + self.g.job.find_gapple_states.count = int(data) + reply = 'ok' + + if command == 'cache': + self.g.job.state = self.g.job.cache_items + self.g.job.cache_items_states.minimum = 0 + self.g.job.cache_items_states.silent = True + reply = 'ok' + + + ## 1fill [x] [y] [z] [x] [y] [z] - fills the cuboid with the block at the first coordinate + if command == 'fill': + try: + data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') + x1, y1, z1, x2, y2, z2 = [int(x) for x in data.split()] + except (AttributeError, ValueError): + reply = 'usage: !fill x1 y1 z1 x2 y2 z2' + + if not reply: + coord1 = (x1, y1, z1) + coord2 = (x2, y2, z2) + block = self.g.world.block_at(*coord1) + + if not reply and y1 > y2: + reply = 'can only fill upwards' + + if not reply and block is None: + reply = 'first coord out of range' + + if not reply and block == 0: + reply = 'can\'t fill with air' + + if not reply: + self.g.filling = Munch(coord1=coord1, coord2=coord2, block=block) + self.g.job.state = self.g.job.fill_blocks + reply = 'filling ' + str(utils.pvolume(coord1, coord2)) + ' with ' + blocks.BLOCKS[block] + + ## 1here - bot comes to your location + if command == 'here': + try: + sender_uuid = self.g.player_names[sender] + except KeyError: + reply = 'can\'t find your uuid' + + if not reply: + for p in self.g.players.values(): + if p.player_uuid == sender_uuid: + player = p + break + else: # for + reply = 'can\'t find you' + + if not reply: + pos = utils.pint(self.g.pos) + goal = utils.pint((p.x, p.y, p.z)) + start = time.time() + navpath = self.g.world.path_to_place(pos, goal) + + if navpath: + self.g.path = navpath + if self.g.job: + self.g.job.stop() + print(len(navpath)) + print(navpath) + print(round(time.time() - start, 3), 'seconds') + if self.g.job: + self.g.job.stop() + self.g.look_at = None + reply = 'ok' + else: + reply = 'no path' + + ## 1goto [x] [y] [z] - sends the bot to coordinate (x, y, z) + if command == 'goto': + try: + data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') + x2, y2, z2 = [int(x) for x in data.split()] + except (AttributeError, ValueError): + reply = 'usage: !goto x y z' + + if not reply: + pos = utils.pint(self.g.pos) + goal = utils.pint((x2, y2, z2)) + start = time.time() + navpath = self.g.world.path_to_place(pos, goal) + + if navpath: + self.g.path = navpath + if self.g.job: + self.g.job.stop() + print(len(navpath)) + print(navpath) + print(round(time.time() - start, 3), 'seconds') + if self.g.job: + self.g.job.stop() + self.g.look_at = None + reply = 'ok' + else: + reply = 'no path' + + if command == 'break': + self.g.game.break_block(blocks.TEST_BLOCK) + reply = 'ok' + + if command == 'open': + self.g.game.open_container(blocks.TEST_BLOCK) + + ## 1close - closes the current Minecraft window + if command == 'close': + if self.g.window: + self.g.game.close_window() + reply = 'ok' + else: + reply = 'nothing open' + + ## 1click [slot] [button] [mode] - clicks the current window + if command == 'click' and data: + if self.g.window: + slot, button, mode = [int(x) for x in data.split(' ')] + try: + item = self.g.window.contents[slot] + except KeyError: + item = Slot(present=False) + print(item) + self.g.game.click_window(slot, button, mode, item) + else: + reply = 'nothing open' + + ## 1use - use the item it's currently holding + if command == 'use': + self.g.game.use_item(0) + + ## 1interact [entity id] - interacts with that entity + if command == 'interact' and data: + self.g.game.interact(int(data)) + + if command == 'test': + reply = 'ok' + r = self.g.world.find_villager_openings((615, 78, 493)) + print(r) + + ################# Authorized commands ########################## + + ## ### Authorized Commands + ## These dangerous commands can only be ran by the bot owner. + + if authed: + + ## 1print [expression] - replies with Python eval(expression) + if command == 'print': + data = data.replace('`', '.') + reply = str(eval(data)) + + ## 1exit - exits the program + if command == 'exit': + import os + os._exit(0) + + + + except BaseException as e: + import traceback + print(traceback.format_exc()) + reply = 'Error: {} - {}\n'.format(e.__class__.__name__, e) + pass + + if reply: + print(reply) + if private and not reply.startswith('/'): + self.g.chat.send('/m ' + sender + ' ' + reply) + else: + self.g.chat.send(reply) + diff --git a/mosfet/game.py b/mosfet/game.py index fa5fc65..05a9184 100644 --- a/mosfet/game.py +++ b/mosfet/game.py @@ -1,6 +1,5 @@ import re import time -import importlib import random from math import hypot from itertools import count @@ -22,7 +21,6 @@ from mosfet.protocol.packets import ( from mosfet.protocol.types import Slot -from mosfet import print_help from mosfet import utils from mosfet import path from mosfet import bot @@ -64,8 +62,6 @@ class Game: #register(self.handle_packet, Packet, early=True) - self.g.chat.set_handler(self.handle_chat) - def handle_login_success(self, packet): print(packet) self.g.name = packet.Username @@ -126,510 +122,6 @@ class Game: if new_path: self.g.path = new_path - def handle_chat(self, message): - source, text = message - reply = None - private = False - for_me = False - authed = False - - if source == 'SYSTEM': - self.g.command_lock = False - - if text == 'You are now AFK.': - self.g.afk = True - elif text == 'You are no longer AFK.': - self.g.afk = False - - match1 = re.match(r' (.*)', text) - match2 = re.match(r'\[(\w+) -> me] (.*)', text) - if match1: - sender, text = match1.groups() - elif match2: - sender, text = match2.groups() - private = True - else: - return - - if sender == 'tanner6': - authed = True - - if text.startswith('zzz'): - text = '!zzz' - - bot_num = self.g.name[-1] - - if text.startswith(bot_num): - text = text[1:] - for_me = True - elif text.startswith('! '): - text = text[2:] - elif text.startswith('!'): - text = text[1:] - else: - return - - if ' ' in text: - command = text.split(' ', 1)[0] - data = text.split(' ', 1)[1] - else: - command = text - data = None - - try: - - ## ### Public Commands - ## These can be ran by anyone, all bots will reply. - - ## !help - prints this whole help message to console - ## !help [command] - replies in-game explaining command - if command == 'help': - if data: - for line in print_help.HELP_LINES: - if line[1:].startswith(data) or line[1:].startswith(data[1:]): - reply = 'command ' + line - break - else: # for - reply = 'command not found' - else: - print() - print() - for line in print_help.HELP_LINES: - print(line) - reply = 'check console' - - ## !ping - replies with "pong" - if command == 'ping': - reply = 'pong' - - ## !echo [data] - replies with "data" - if command == 'echo' and data: - reply = data - - ## !pos - replies with position and dimension - if command == 'pos': - reply = str(utils.pint(self.g.pos))[1:-1] + ', ' + self.g.dimension - - ## !afk - goes AFK with /afk - if command == 'afk': - if not self.g.afk: - reply = '/afk' - - ## !unafk - goes not AFK with /afk - if command == 'unafk': - if self.g.afk: - reply = '/afk' - - ## !error - raises an error - if command == 'error': - reply = 'ok' - raise - - ## !inv - prints current inventory - if command == 'inv': - inv_list = [] - for i in self.g.inv.values(): - if i.present: - inv_list.append('{}:{} x {}'.format(items.ITEM_NAMES[i.item_id], str(i.item_id), i.item_count)) - inv_list.sort() - result = '\n'.join(inv_list) - print(result or 'Empty') - - ## !time - replies with Minecraft world time - if command == 'time': - reply = str(self.g.time) - - ## !count [id] - counts the number of items with that id - if command == 'count' and data: - item = int(data) - reply = str(self.count_items([item])) - - ## !loaded - replies with the current loaded area - if command == 'loaded': - reply = str(self.g.chunks.get_loaded_area()) - - ## !players - prints the current players - ## !players clear - clears the current player list - if command == 'players': - if data == 'clear': - self.g.players = {} - reply = 'ok' - else: - for k, v in self.g.players.items(): - print(str(k) + ':', v, self.g.player_names[v.player_uuid]) - - ## !objects - prints the current items on ground - ## !objects clear - clears the current object list - if command == 'objects': - if data == 'clear': - self.g.objects = {} - reply = 'ok' - else: - for k, v in self.g.objects.items(): - if data and v.item_id != int(data): continue - print(str(k) + ':', v, items.ITEM_NAMES[v.item_id]) - - ## !mobs - prints the current mobs - ## !mobs clear - clears the current mob list - if command == 'mobs': - if data == 'clear': - self.g.mobs = {} - reply = 'ok' - else: - all_mobs = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) - for k, v in all_mobs: - if data and v.type != int(data): continue - print(str(k) + ':', v, mobs.MOB_NAMES[v.type]) - reply = str(len(all_mobs)) + ' mobs' - - ## !monsters - prints the current monsters - if command == 'monsters': - monsters = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) - count = 0 - for k, v in monsters: - if v.type not in mobs.EVIL_IDS: continue - if data and v.type != int(data): continue - count += 1 - print(str(k) + ':', v, mobs.MOB_NAMES[v.type]) - reply = str(count) + ' monsters' - - ## !villagers - prints the current villagers - if command == 'villagers': - all_mobs = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) - count = 0 - for k, v in all_mobs: - type_name = mobs.MOB_NAMES[v.type] - if type_name != 'villager' : continue - count += 1 - print(str(k) + ':', v, type_name) - reply = str(count) + ' villagers' - - ## !threats - prints the dangerous monsters within 20 blocks - ## !threats [num] - prints the dangerous monsters within num blocks - if command == 'threats': - distance = int(data) if data else 20 - p = utils.pint(self.g.pos) - threats = self.g.world.find_threats(p, distance) - - for t in threats: - print(str(t.entity_id) + ':', t, mobs.MOB_NAMES[t.type]) - reply = str(len(threats)) + ' threats' - - if command == 'spiral' and data: - for i in range(int(data)): - print(utils.spiral(i)) - - if command == 'sand_slice': - result = self.g.world.find_sand_slice(utils.pint(self.g.pos), 50) - reply = str(result) - - ## "zzz" or !zzz - bot does /afk to let others sleep - if command == 'zzz': - if not self.g.afk and self.g.dimension == 'overworld': - reply = '/afk' - self.g.afk_timeout = 5.0 - - ## !tree - replies with the closest tree - if command == 'tree': - pos = utils.pint(self.g.pos) - tree = next(self.g.world.find_trees(pos, 50)) - reply = str(tree)[1:-1] - - ## !block x y z - replies what block is at (x, y, z) - if command == 'block': - try: - data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') - x1, y1, z1 = [int(x) for x in data.split()] - except (AttributeError, ValueError): - reply = 'usage: !block x1 y1 z1' - - if not reply: - coord = (x1, y1, z1) - block = self.g.world.block_at(*coord) - - if not reply and block is None: - reply = 'first coord out of range' - - if not reply: - reply = blocks.BLOCKS[block] + ':' + str(block) - - - ################# Specific commands ########################## - - ## ### Bot-specific Commands - ## These will only run for the bot they are addressed to. - - if for_me: - pass - - ## 1respawn - respawns the bot if it's dead - if command == 'respawn': - packet = serverbound.play.ClientStatusPacket() - packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN - self.g.connection.write_packet(packet) - reply = 'ok' - - ## 1gather wood - gathers wood from the world - ## 1gather sand - gathers sand from the world - if command == 'gather' and data: - if data == 'wood': - self.g.job.state = self.g.job.gather_wood - reply = 'ok' - elif data == 'sand': - self.g.job.state = self.g.job.gather_sand - reply = 'ok' - - if reply: - for i in self.g.inv.values(): - print(i.item_id) - if i.item_id in items.BED_IDS: - break - else: - reply += ', I need a bed' - - ## 1farm wood - farms wood from a certain area - ## 1farm sand - farms sand from a certain area - ## 1farm wart - farms netherwart from a certain area - ## 1farm crop - farms mature crops from a certain area - if command == 'farm' and data: - if data == 'wood': - self.g.job.state = self.g.job.farm_wood - reply = 'ok' - elif data == 'sand': - self.g.job.state = self.g.job.farm_sand - reply = 'ok' - elif data == 'wart': - self.g.job.state = self.g.job.farm_wart - reply = 'ok' - elif data.startswith('crop'): - self.g.job.state = self.g.job.farm_crop - reply = 'ok' - - if reply and self.g.dimension == 'overworld': - for i in self.g.inv.values(): - if i.item_id in items.BED_IDS: - break - else: - reply += ', I need a bed' - - ## 1loiter - stands still but eats, sleeps, and flees - if command == 'loiter': - self.g.job.state = self.g.job.loiter - reply = 'ok' - - ## 1trade - sells items to villagers to get emeralds - if command == 'trade': - self.g.job.state = self.g.job.trade - reply = 'ok' - - ## 1stop - stops the current job and resets bot - if command == 'stop': - self.close_window() - bot.init(self.g) - reply = 'ok' - - ## 1drop - drops the current stack its holding - if command == 'drop': - self.drop_stack() - - ## 1select [id] - moves item with id into main hand - if command == 'select' and data: - item = int(data) - if self.select_item([item]): - reply = 'ok' - else: - reply = 'not found' - - ## 1dump [id] - drops all items matching id - if command == 'dump' and data: - item = int(data) - if self.count_items([item]): - self.g.dumping = item - reply = 'ok' - else: - reply = 'not found' - - ## 1drain - drops all items in inventory - if command == 'drain': - self.g.draining = True - reply = 'ok' - - if command == 'gapple': - self.g.job.state = self.g.job.find_gapple - if data: - self.g.job.find_gapple_states.count = int(data) - reply = 'ok' - - if command == 'cache': - self.g.job.state = self.g.job.cache_items - self.g.job.cache_items_states.minimum = 0 - self.g.job.cache_items_states.silent = True - reply = 'ok' - - - ## 1fill [x] [y] [z] [x] [y] [z] - fills the cuboid with the block at the first coordinate - if command == 'fill': - try: - data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') - x1, y1, z1, x2, y2, z2 = [int(x) for x in data.split()] - except (AttributeError, ValueError): - reply = 'usage: !fill x1 y1 z1 x2 y2 z2' - - if not reply: - coord1 = (x1, y1, z1) - coord2 = (x2, y2, z2) - block = self.g.world.block_at(*coord1) - - if not reply and y1 > y2: - reply = 'can only fill upwards' - - if not reply and block is None: - reply = 'first coord out of range' - - if not reply and block == 0: - reply = 'can\'t fill with air' - - if not reply: - self.g.filling = Munch(coord1=coord1, coord2=coord2, block=block) - self.g.job.state = self.g.job.fill_blocks - reply = 'filling ' + str(utils.pvolume(coord1, coord2)) + ' with ' + blocks.BLOCKS[block] - - ## 1here - bot comes to your location - if command == 'here': - try: - sender_uuid = self.g.player_names[sender] - except KeyError: - reply = 'can\'t find your uuid' - - if not reply: - for p in self.g.players.values(): - if p.player_uuid == sender_uuid: - player = p - break - else: # for - reply = 'can\'t find you' - - if not reply: - pos = utils.pint(self.g.pos) - goal = utils.pint((p.x, p.y, p.z)) - start = time.time() - navpath = self.g.world.path_to_place(pos, goal) - - if navpath: - self.g.path = navpath - if self.g.job: - self.g.job.stop() - print(len(navpath)) - print(navpath) - print(round(time.time() - start, 3), 'seconds') - if self.g.job: - self.g.job.stop() - self.g.look_at = None - reply = 'ok' - else: - reply = 'no path' - - ## 1goto [x] [y] [z] - sends the bot to coordinate (x, y, z) - if command == 'goto': - try: - data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') - x2, y2, z2 = [int(x) for x in data.split()] - except (AttributeError, ValueError): - reply = 'usage: !goto x y z' - - if not reply: - pos = utils.pint(self.g.pos) - goal = utils.pint((x2, y2, z2)) - start = time.time() - navpath = self.g.world.path_to_place(pos, goal) - - if navpath: - self.g.path = navpath - if self.g.job: - self.g.job.stop() - print(len(navpath)) - print(navpath) - print(round(time.time() - start, 3), 'seconds') - if self.g.job: - self.g.job.stop() - self.g.look_at = None - reply = 'ok' - else: - reply = 'no path' - - if command == 'break': - self.break_block(blocks.TEST_BLOCK) - reply = 'ok' - - if command == 'open': - self.open_container(blocks.TEST_BLOCK) - - ## 1close - closes the current Minecraft window - if command == 'close': - if self.g.window: - self.close_window() - reply = 'ok' - else: - reply = 'nothing open' - - ## 1click [slot] [button] [mode] - clicks the current window - if command == 'click' and data: - if self.g.window: - slot, button, mode = [int(x) for x in data.split(' ')] - try: - item = self.g.window.contents[slot] - except KeyError: - item = Slot(present=False) - print(item) - self.click_window(slot, button, mode, item) - else: - reply = 'nothing open' - - ## 1use - use the item it's currently holding - if command == 'use': - self.use_item(0) - - ## 1interact [entity id] - interacts with that entity - if command == 'interact' and data: - self.interact(int(data)) - - if command == 'test': - reply = 'ok' - r = self.g.world.find_villager_openings((615, 78, 493)) - print(r) - - ################# Authorized commands ########################## - - ## ### Authorized Commands - ## These dangerous commands can only be ran by the bot owner. - - if authed: - - ## 1print [expression] - replies with Python eval(expression) - if command == 'print': - data = data.replace('`', '.') - reply = str(eval(data)) - - ## 1exit - exits the program - if command == 'exit': - import os - os._exit(0) - - - - except BaseException as e: - import traceback - print(traceback.format_exc()) - reply = 'Error: {} - {}\n'.format(e.__class__.__name__, e) - pass - - if reply: - print(reply) - if private and not reply.startswith('/'): - self.g.chat.send('/m ' + sender + ' ' + reply) - else: - self.g.chat.send(reply) - def handle_time_update(self, packet): self.g.time = packet.time_of_day % 24000 @@ -683,6 +175,11 @@ class Game: #print(packet) return + def respawn(self): + packet = serverbound.play.ClientStatusPacket() + packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN + self.g.connection.write_packet(packet) + def animate(self): packet = serverbound.play.AnimationPacket() packet.hand = packet.HAND_MAIN diff --git a/mosfet/print_help.py b/mosfet/print_help.py index 96bf93c..5ee0cac 100644 --- a/mosfet/print_help.py +++ b/mosfet/print_help.py @@ -1,6 +1,6 @@ HELP_LINES = [] -with open('mosfet/game.py', 'r') as f: +with open('mosfet/commands.py', 'r') as f: for line in f.readlines(): if line.strip().startswith('## '): HELP_LINES.append(line.strip()[3:])