diff --git a/.gitignore b/.gitignore index 0411fcd..b435bb5 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ lodestone/test_plugins.py *Database.json lodestone/cache/ lodestone/.env +lodestone/favicon.png diff --git a/lodestone/__main__.py b/lodestone/__main__.py index 465ccf0..86bf451 100644 --- a/lodestone/__main__.py +++ b/lodestone/__main__.py @@ -112,7 +112,7 @@ def check_python_command(): try: - lodestone.ui.queue().launch(server_name=f"{host}", server_port=port, show_api=False, auth=(f'{os.environ["LODESTONE_USERNAME"]}', f'{os.environ["LODESTONE_PASSWORD"]}'), share=False, quiet=True, favicon_path="favicon.png") + lodestone.ui.queue().launch(server_name=f"{host}", server_port=port, show_api=False, auth=(f'{os.environ["LODESTONE_USERNAME"]}', f'{os.environ["LODESTONE_PASSWORD"]}'), share=False, quiet=True, favicon_path="favicon.png", auth_message="Please login with your set username and password. These are not your Minecraft credentials.") except OSError: raise OSError(f"Port {port} is already in use!") diff --git a/lodestone/types.py b/lodestone/_types.py similarity index 100% rename from lodestone/types.py rename to lodestone/_types.py diff --git a/lodestone/bot.py b/lodestone/bot.py index 8cdc833..6f87427 100644 --- a/lodestone/bot.py +++ b/lodestone/bot.py @@ -369,7 +369,7 @@ def __init__( self.mineflayer = require('mineflayer') self.once_with_cleanup = require('mineflayer').promise_utils if not self.disable_viewer: - self.mineflayer_viewer = require('prismarine-viewer').mineflayer + self.mineflayer_viewer = require('prismarine-viewer') self.python_command = self.__check_python_command() if not ls_skip_checks: with self.console.status("[bold]Checking for updates...\n") as status: @@ -811,9 +811,14 @@ def handleMsg(_, sender: str, message: str, *args): def __start_viewer(self): try: - self.mineflayer_viewer(self.bot, {"port": self.viewer_port}) + self.mineflayer_viewer.mineflayer(self.bot, {"port": self.viewer_port}) + # _ = require("node-canvas-webgl") + # @self.once("spawn") + # def ___start_viewer(*args): + # self.mineflayer_viewer.headless(self.bot, { "output": f"127.0.0.1:{self.viewer_port}", "frames": 200, "width": 512, "height": 512 }) self.log(f"Viewer started on port {self.viewer_port}", info=True) - except: + except Exception as e: + print(e) self.log("There was an error while starting the viewer!", warning=True) @@ -1031,35 +1036,41 @@ def collect_block(self, block:str, amount:int=1, max_distance:int=64): bot.collect_block("oak_log", amount=20) """ # Get the correct block type - with self.console.status(f"[bold]Collecting {block}...") as status: - blockType = self.bot.registry.blocksByName[block] - if not blockType: - self.log("No blocks with that name.", error=True) - status.stop() - return - # Try and find that block type in the world - def find_block(): - try: - found_block = self.bot.findBlock({ 'matching': blockType.id, 'maxDistance': max_distance}) - # if "ore" in block: - # found_block = self.bot.collectBlock.findFromVein(found_block) - return found_block - except: - self.log(f"No {block} found nearby.", error=True) - for i in range(0, amount): - if i == 0: i = 1 - current_block = find_block() - if not current_block: - self.log(f"No {block} found nearby. Try increasing the `max_distance` pram", warning=True) + self.collected = 0 + def collect(): + try: + self.collected = 0 + blockType = self.bot.registry.blocksByName[block] + if not blockType: return - # Collect the block if we found one + blocks = self.bot.findBlocks({ + 'matching': blockType.id, + 'maxDistance': 64, + 'count': amount + }) + if len(blocks.valueOf()) == 0: + self.chat("I don't see that block nearby.") + return + targets = [] + for i in range(min(len(blocks.valueOf()), amount)): + targets.append(self.bot.blockAt(blocks[i])) + self.chat(f"Found {len(targets)}") try: - self.bot.collectBlock.collect(current_block) - except: - self.log(f"No {block} found nearby.", error=True) - status.update(f"[bold]Collecting {block}... ({i}/{amount})\n") + self.bot.collectBlock.collect(targets, timeout=10000) + # All blocks have been collected. + self.chat('Done') + except Exception as err: + # An error occurred, report it. + print(err) + except Exception as err: + print(err) + task = threading.Thread(target=collect) + task.start() + task.join() + + - def goto(self, x: int, z: int, y: int = 0, timeout: int = 600000000): + def goto(self, x: int, y: int, z: int, timeout: int = 600000000): """ Go to the specified coordinates (x, y, z). @@ -1078,7 +1089,7 @@ def goto(self, x: int, z: int, y: int = 0, timeout: int = 600000000): """ # Get the correct block type with self.console.status(f"[bold]Moving to ({x}, {y}, {z})...") as status: - if y == 0: + if y == None: self.bot.pathfinder.goto(self.goals.GoalNearXZ(int(x), int(z), 1), timeout=timeout) else: self.bot.pathfinder.goto(self.goals.GoalNear(int(x), int(y), int(z), 1), timeout=timeout) diff --git a/lodestone/gradios.py b/lodestone/gradios.py index 2b0a98c..2559291 100644 --- a/lodestone/gradios.py +++ b/lodestone/gradios.py @@ -7,19 +7,32 @@ created = False global chat_history chat_history = [] +global plugin_list +plugin_list = [] + + +css = """ +.error { + color: red +} +""" + def get_bot_status(): - if 'bot' in locals() or 'bot' in globals(): + if 'bot' in globals(): return "Stop Bot" else: return "Start/Stop Bot" - + +def change_tab(): + return gr.Tabs.update(selected=1) + def create(email, auth, host, port, version, viewer, plugin, enable_viewer, skip_checks): try: - if 'bot' in locals() or 'bot' in globals(): + if 'bot' in globals(): def stop_bot(): try: global bot @@ -40,8 +53,6 @@ def stop_bot(): global bot - - plugin_list = [] plugin_str = "" if plugin: plugin_str += "Plugins: " @@ -75,7 +86,7 @@ def stop_bot(): ) @bot.on('messagestr') - def chat(this, message, messagePosition, jsonMsg, sender, *args): + def chat_history_add(this, message, messagePosition, jsonMsg, sender, *args): message = str(message).replace("\n","") if str(sender).lower() == "none": chat_history.append(f"{message}") @@ -92,7 +103,7 @@ def chat(this, message, messagePosition, jsonMsg, sender, *args): def create_multiple(email, auth, host, port, version, amount): try: - if 'bot' in locals() or 'bot' in globals(): + if 'bot' in globals(): def stop_bot(): try: global bot @@ -144,33 +155,33 @@ def stop_bot(): def get_username(): - try: + if 'bot' in globals(): return bot.username - except: + else: return "None" def get_player_health(): - try: + if 'bot' in globals(): return bot.health - except: + else: return "Unknown" def get_player_food(): - try: + if 'bot' in globals(): return bot.food - except: + else: return "Unknown" def get_player_experience(): - try: + if 'bot' in globals(): return bot.experience.level - except: + else: return "Unknown" def get_player_difficulty(): - try: + if 'bot' in globals(): if bot.settings.difficulty == 0: return "peaceful" @@ -181,21 +192,21 @@ def get_player_difficulty(): elif bot.settings.difficulty == 3: return "hard" - except: + else: return "Unknown" def get_all_data(): - try: + if 'bot' in globals(): return bot.player - except: + else: return "Unknown" def get_latest_chats(): - try: + if 'bot' in globals(): if len(chat_history) > 30: chat_history.clear() return "No chat messages yet!" @@ -203,7 +214,7 @@ def get_latest_chats(): for i in chat_history[-9:]: string += i + "\n" return string - except: + else: return "No chat messages yet!" @@ -220,7 +231,7 @@ def build_schematic(files, x, z): if not x or not z or not files: gr.Warning("not all fields are filled in!") return - if 'bot' in locals() or 'bot' in globals(): + if 'bot' in globals(): bot.goto(x, z) time.sleep(2) bot.build_schematic(f'{files.name}') @@ -233,71 +244,69 @@ def build_schematic(files, x, z): with gr.Tab("Bot Settings"): # gr.Markdown(requests.get('https://raw.githubusercontent.com/the-lodestone-project/Lodestone/main/README.md').text) # gr.Image("https://github.com/the-lodestone-project/Lodestone/blob/main/assets/logo.png?raw=true", min_width=2000) - with gr.Row(): - with gr.Column(scale=1, variant='panel'): - with gr.Tab("Signle Bot"): - email = gr.Textbox(placeholder="Notch", label="Username",info="Username to login with") - auth = gr.Dropdown(["microsoft", "offline"], value="microsoft", label="Authentication Method",info="Authentication method to login with") - host = gr.Textbox(placeholder="2b2t.org", label="Server Ip",info="Server ip to connect to") - port = gr.Number(value=25565, label="Sever Port", info="Server port to connect to. Most servers use 25565",precision=0) - version = gr.Dropdown(["auto","1.20", "1.19", "1.18", "1.17", "1.16.4", "1.16", "1.15", "1.14", "1.13", "1.12", "1.11", "1.10", "1.9", "1.8"], value="auto", label="Version",info="Version to connect with. Use auto to automatically detect the version of the server") - with gr.Accordion("Optional Settings", open=False): - enable_viewer = gr.Checkbox(value=True, label="Enable Viewer", info="Enable the viewer to see the bot's view",interactive=True) - skip_checks = gr.Checkbox(value=True, label="Skip Checks/Updates", info="Skip checks to speed up the bot",interactive=True) - viewer = gr.Number(value=5001, label="Viewer Port", info="Viewer port to display the bot's view",precision=0) - plugin = gr.Dropdown(["Schematic Builder", "Cactus Farm Builder", "Discord Rich Presence"],multiselect=True, label="Plugins",info="Plugins to load on startup") - btn = gr.Button(value=get_bot_status,variant='primary') - - - - - out_username = gr.Textbox(value="", label="Logged in as") - info = gr.Textbox(value="", label="Info") - - btn.click(create, inputs=[email, auth, host, port, version, viewer, plugin, enable_viewer, skip_checks], outputs=[out_username, info, btn], show_progress="minimal") - # with gr.Tab("Parameters"): - # def live_view(): - # try: - # if bot.viewer_port: - # port = bot.viewer_port - # else: - # port = 5001 - # except: - # port = 5001 - # return f'' - # gr.HTML(f'') - # pass - with gr.Tab("Multiple Bot"): - email = gr.Textbox(placeholder="Notch", label="Username Prefix",info="Username prefix. The bot will login with this prefix and a number after it") - auth = gr.Dropdown(["offline"], value="offline", label="Authentication Method",info="Authentication method to login with") - host = gr.Textbox(placeholder="2b2t.org", label="Server Ip",info="Server ip to connect to") - port = gr.Number(value=25565, label="Sever Port", info="Server port to connect to. Most servers use 25565",precision=0) - version = gr.Dropdown(["auto","1.20", "1.19", "1.18", "1.17", "1.16.4", "1.16", "1.15", "1.14", "1.13", "1.12", "1.11", "1.10", "1.9", "1.8"], value="auto", label="Version",info="Version to connect with. Use auto to automatically detect the version of the server") - amount = gr.Slider(minimum=1, maximum=50, step=1, label="Amount", info="Amount of bots to create", interactive=True) - with gr.Accordion("Optional Settings", open=False): - enable_viewer = gr.Checkbox(value=False, label="Enable Viewer", info="Enable the viewer to see the bot's view",interactive=False) - viewer = gr.Number(value=5001, label="Viewer Port", info="Viewer port to display the bot's view",precision=0, interactive=False) - # plugin = gr.Dropdown(["Schematic Builder", "Cactus Farm Builder", "Discord Rich Presence"],multiselect=True, label="Plugins",info="Plugins to load on startup") - btn = gr.Button(value=get_bot_status,variant='primary') - - - - - out_username = gr.Textbox(value="", label="Bot count") - info = gr.Textbox(value="", label="Info") - - btn.click(create_multiple, inputs=[email, auth, host, port, version, amount], outputs=[out_username, info, btn], show_progress="minimal") + with gr.Tab("Signle Bot"): + email = gr.Textbox(placeholder="Notch", label="Username",info="Username to login with") + auth = gr.Dropdown(["microsoft", "offline"], value="microsoft", label="Authentication Method",info="Authentication method to login with") + host = gr.Textbox(placeholder="2b2t.org", label="Server Ip",info="Server ip to connect to") + port = gr.Number(value=25565, label="Sever Port", info="Server port to connect to. Most servers use 25565",precision=0) + version = gr.Dropdown(["auto","1.20", "1.19", "1.18", "1.17", "1.16.4", "1.16", "1.15", "1.14", "1.13", "1.12", "1.11", "1.10", "1.9", "1.8"], value="auto", label="Version",info="Version to connect with. Use auto to automatically detect the version of the server") + with gr.Accordion("Optional Settings", open=False): + enable_viewer = gr.Checkbox(value=True, label="Enable Viewer", info="Enable the viewer to see the bot's view",interactive=True) + skip_checks = gr.Checkbox(value=True, label="Skip Checks/Updates", info="Skip checks to speed up the bot",interactive=True) + viewer = gr.Number(value=5001, label="Viewer Port", info="Viewer port to display the bot's view",precision=0) + plugin = gr.Dropdown(["Schematic Builder", "Cactus Farm Builder", "Discord Rich Presence"],multiselect=True, label="Plugins",info="Plugins to load on startup") + btn = gr.Button(value=get_bot_status,variant='primary') + + + + + out_username = gr.Textbox(value="", label="Logged in as") + info = gr.Textbox(value="", label="Info") + + btn.click(create, inputs=[email, auth, host, port, version, viewer, plugin, enable_viewer, skip_checks], outputs=[out_username, info, btn], show_progress="minimal") + # with gr.Tab("Parameters"): + # def live_view(): + # try: + # if bot.viewer_port: + # port = bot.viewer_port + # else: + # port = 5001 + # except: + # port = 5001 + # return f'' + # gr.HTML(f'') + # pass + with gr.Tab("Multiple Bot"): + email = gr.Textbox(placeholder="Notch", label="Username Prefix",info="Username prefix. The bot will login with this prefix and a number after it") + auth = gr.Dropdown(["offline"], value="offline", label="Authentication Method",info="Authentication method to login with") + host = gr.Textbox(placeholder="2b2t.org", label="Server Ip",info="Server ip to connect to") + port = gr.Number(value=25565, label="Sever Port", info="Server port to connect to. Most servers use 25565",precision=0) + version = gr.Dropdown(["auto","1.20", "1.19", "1.18", "1.17", "1.16.4", "1.16", "1.15", "1.14", "1.13", "1.12", "1.11", "1.10", "1.9", "1.8"], value="auto", label="Version",info="Version to connect with. Use auto to automatically detect the version of the server") + amount = gr.Slider(minimum=1, maximum=50, step=1, label="Amount", info="Amount of bots to create", interactive=True) + with gr.Accordion("Optional Settings", open=False): + enable_viewer = gr.Checkbox(value=False, label="Enable Viewer", info="Enable the viewer to see the bot's view",interactive=False) + viewer = gr.Number(value=5001, label="Viewer Port", info="Viewer port to display the bot's view",precision=0, interactive=False) + # plugin = gr.Dropdown(["Schematic Builder", "Cactus Farm Builder", "Discord Rich Presence"],multiselect=True, label="Plugins",info="Plugins to load on startup") + btn = gr.Button(value=get_bot_status,variant='primary') + + + + + out_username = gr.Textbox(value="", label="Bot count") + info = gr.Textbox(value="", label="Info") + + btn.click(create_multiple, inputs=[email, auth, host, port, version, amount], outputs=[out_username, info, btn], show_progress="minimal") with gr.Tab("Chat"): - chatbot = gr.Textbox(value=get_latest_chats,every=5,label="Chat History (Updated every 5 seconds)") - msg = gr.Textbox(label="Message to send",placeholder="Hello world!",elem_id="msg") - clear = gr.ClearButton([msg, chatbot],value="Clear Chat History") + chat = gr.TextArea(value=get_latest_chats,every=5,label="Chat History (Updated every 5 seconds)",lines=10) + msg = gr.Textbox(label="Message to send",placeholder="Hello world!") + clear = gr.ClearButton([msg, chat],value="Clear Chat History") def respond(message): - try: + if 'bot' in globals(): bot.chat(message) return "" - except: + else: return "" def delete(): @@ -307,53 +316,76 @@ def delete(): msg.submit(respond, inputs=[msg],outputs=[msg]) with gr.Tab("Plugins"): - with gr.Tab("Schematic Builder"): + with gr.Accordion("Schematic Builder", open=False): + + def check(): + if not plugins.schematic in plugin_list: + return "The Schematic Builder plugin is not loaded" + else: + return "pluginloaded" + + gr.Textbox(value=check, every=30, show_label=False) # with gr.Row(): - # with gr.Column(scale=1, variant='panel'): + # with gr.Column(scale=1, ): file_output = gr.File(file_types=[".schematic", ".nbt", ".schem"], label="Schematic File (.schematic .nbt .schem)",file_count="single") - with gr.Row(variant="panel"): - with gr.Column(scale=1, variant='panel'): + with gr.Row(): + with gr.Column(scale=1, ): x = gr.Number(label="X Coordinate",info="The X coord to build at", precision=0) - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): z = gr.Number(label="Z Coordinate",info="The Z coord to build at", precision=0) # upload_button = gr.UploadButton("Click to Upload a schematic", file_count="single") # upload_button.upload(upload_file, upload_button, file_output) build = gr.Button("Build schematic", variant='primary') build.click(build_schematic, inputs=[file_output, x, z]) - with gr.Tab("Build Cactus Farm"): + + + with gr.Accordion("Build Cactus Farm", open=False): gr.Markdown("") - with gr.Tab("Discord Rich Presence"): - # state=f"{self.bot.local_host} - {self.bot.bot.version}", - # details=f"{self.bot.username}", - # large_image=(f"https://mc-heads.net/avatar/{self.bot.username}/180/nohelm.png"), - # large_text=f"{self.bot.username}", - # small_image=(f"https://eu.mc-api.net/v3/server/favicon/{self.bot.local_host}"), small_text=f"{self.bot.local_host} on {self.bot.bot.version}", - # start=time.time(), + with gr.Accordion("Auto Farm", open=False): + with gr.Row(): + with gr.Column(scale=1, ): + crop_type = gr.Dropdown(["wheat_seeds", "wheat", "beetroot_seeds", "beetroot", "carrot", "potato", "poisonous_potato", "melon", "melon_slice", "melon_seeds", "melon_stem", "attached_melon_stem", "pumpkin", "carved_pumpkin", "pumpkin_seeds", "pumpkin_stem", "attached_pumpkin_stem", "torchflower_seeds", "torchflower_crop", "torchflower", "pitcher_pod", "pitcher_crop", "pitcher_plant", "farmland", "bamboo", "cocoa_beans", "sugar_cane", "sweet_berries", "cactus", "mushrooms", "kelp", "sea_pickle", "nether_wart", "chorus_fruit", "fungus", "glow_berries"], label="Crop Type",info="The Crop type to farm", interactive=True) + with gr.Column(scale=1, ): + seed_name = gr.Dropdown(["wheat_seeds", "wheat", "beetroot_seeds", "beetroot", "carrot", "potato", "poisonous_potato", "melon", "melon_slice", "melon_seeds", "melon_stem", "attached_melon_stem", "pumpkin", "carved_pumpkin", "pumpkin_seeds", "pumpkin_stem", "attached_pumpkin_stem", "torchflower_seeds", "torchflower_crop", "torchflower", "pitcher_pod", "pitcher_crop", "pitcher_plant", "farmland", "bamboo", "cocoa_beans", "sugar_cane", "sweet_berries", "cactus", "mushrooms", "kelp", "sea_pickle", "nether_wart", "chorus_fruit", "fungus", "glow_berries"], label="Seed Name",info="The Seed name to plant back", interactive=True) + with gr.Column(scale=1, ): + harvest_name = gr.Dropdown(["wheat_seeds", "wheat", "beetroot_seeds", "beetroot", "carrot", "potato", "poisonous_potato", "melon", "melon_slice", "melon_seeds", "melon_stem", "attached_melon_stem", "pumpkin", "carved_pumpkin", "pumpkin_seeds", "pumpkin_stem", "attached_pumpkin_stem", "torchflower_seeds", "torchflower_crop", "torchflower", "pitcher_pod", "pitcher_crop", "pitcher_plant", "farmland", "bamboo", "cocoa_beans", "sugar_cane", "sweet_berries", "cactus", "mushrooms", "kelp", "sea_pickle", "nether_wart", "chorus_fruit", "fungus", "glow_berries"], label="Harvest Name",info="The block name to harvest", interactive=True) + + with gr.Row(): + with gr.Column(scale=1, ): + x = gr.Number(label="X Coordinate",info="The X coord to build at", precision=0) + with gr.Column(scale=1, ): + z = gr.Number(label="Z Coordinate",info="The Z coord to build at", precision=0) - def get_time(): - return time.time() + with gr.Row(): + with gr.Column(scale=1, ): + x = gr.Number(label="X Coordinate",info="The X coord to build at", precision=0) + with gr.Column(scale=1, ): + z = gr.Number(label="Z Coordinate",info="The Z coord to build at", precision=0) + with gr.Accordion("Optional Settings", open=False): + gr.Markdown("Optional Settings") + start_farm = gr.Button("Start auto Farming", variant='primary') - with gr.Row(variant="panel"): - with gr.Column(scale=1, variant='panel'): + with gr.Accordion("Discord Rich Presence", open=False): + with gr.Row(): + with gr.Column(scale=1, ): state = gr.Textbox(label="State",info="The state to display") - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): details = gr.Textbox(label="Details",info="The details to display") - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): large_image = gr.Textbox(label="Large Image (url)",info="The large image to display") - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): large_text = gr.Textbox(label="Large Text",info="The large text to display") - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): small_image = gr.Textbox(label="Small Image (url)",info="The small image to display") - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): small_text = gr.Textbox(label="Small Text",info="The small text to display") def update_presence_def(state="No state provided", details="No details Provided", large_image=None, large_text=None, small_image=None, small_text=None): print(details) - try: + if 'bot' in globals(): bot.discordrp(state=state, details=details, start=time.time()) - except Exception as e: - print(e) + else: pass update_presence = gr.Button("Update Presence", variant='primary') @@ -363,10 +395,10 @@ def update_presence_def(state="No state provided", details="No details Provided" with gr.Tab("Movements"): with gr.Tab("Basic Movements"): with gr.Row(): - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): jump = gr.Button("Start Jumping") jump = gr.Button("Stop Jumping") - with gr.Column(scale=1, variant='panel'): + with gr.Column(scale=1, ): jump = gr.Button("Start walking forward") jump = gr.Button("Stop walking forward") with gr.Tab("Follow Player/Entity"): @@ -417,5 +449,7 @@ def ram_available(): difficulty = gr.Textbox(value=platform.system, label=f"System Type") # refresh_button.click(get_player_info, outputs=[health, food, experience]) if __name__ == "__main__": - ui.queue().launch(server_port=8000, show_api=False, share=False, quiet=True) + ui.queue().launch(server_port=8000, show_api=False, quiet=True) + + # gr.themes.builder() diff --git a/pyproject.toml b/pyproject.toml index fbf52aa..f5bbf23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ dependencies = [ "requests", "python-dotenv", "aiofiles", - "gradio", + "gradio==3.*", "psutil", ]