1 Commits

2 changed files with 240 additions and 106 deletions

240
mc_addon_loader.py Normal file
View File

@@ -0,0 +1,240 @@
import paramiko
import os
import json
# Server-Details und Pfade
SSH_HOST = "XXX.XXX.XXX.XXX"
SSH_USER = "root"
SSH_PASSWORD = "XXXXXXXXXX"
DOCKER_VOLUME_PATH = "/media/usb0/docker-data/volumes/minecraft_mc/_data2"
BEHAVIOR_PACKS_PATH = f"{DOCKER_VOLUME_PATH}/behavior_packs"
RESOURCE_PACKS_PATH = f"{DOCKER_VOLUME_PATH}/resource_packs"
WORLDS_PATH = f"{DOCKER_VOLUME_PATH}/worlds"
WORLD_NAME = "Bedrock level"
def ssh_connect():
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(SSH_HOST, username=SSH_USER, password=SSH_PASSWORD)
return client
def get_mods(ssh, behavior_packs_path, resource_packs_path):
# Befehl zum Auflisten der Verzeichnisse im Behavior Packs Pfad
command_behavior = f'find {behavior_packs_path} -maxdepth 1 -type d'
stdin, stdout, stderr = ssh.exec_command(command_behavior)
behavior_packs = stdout.read().decode().strip().split('\n')
# Filtere den Basispfad, leere Zeilen und unerwünschte Ordner heraus
behavior_packs = [pack for pack in behavior_packs if pack and pack != behavior_packs_path and not os.path.basename(pack).startswith(("vanilla", "chemistry", "experimental"))]
# Befehl zum Auflisten der Verzeichnisse im Resource Packs Pfad
command_resource = f'find {resource_packs_path} -maxdepth 1 -type d'
stdin, stdout, stderr = ssh.exec_command(command_resource)
resource_packs = stdout.read().decode().strip().split('\n')
# Filtere den Basispfad, leere Zeilen und unerwünschte Ordner heraus
resource_packs = [pack for pack in resource_packs if pack and pack != resource_packs_path and not os.path.basename(pack).startswith(("vanilla", "chemistry", "experimental"))]
# Bereinige die Pfade, um nur die Verzeichnisnamen zu erhalten
behavior_packs = [os.path.basename(pack) for pack in behavior_packs]
resource_packs = [os.path.basename(pack) for pack in resource_packs]
print("Behavior Packs:")
for pack in behavior_packs:
print(pack)
print("\nResource Packs:")
for pack in resource_packs:
print(pack)
def mod_install_dialog(sftp):
AUSWAHL = input("\nWas soll installiert werden?\n1 - Behavior Pack\n2 - Ressource Pack\n -> ")
install_path = None # Initialisiere install_path mit None
if AUSWAHL == "1":
print("Behavior Pack wird installiert...")
install_path = mod_install(sftp, "behavior")
elif AUSWAHL == "2":
print("Ressource Pack wird installiert...")
install_path = mod_install(sftp, "ressource")
if install_path:
print(f"Mod wurde installiert unter: {install_path}")
else:
print("Installation fehlgeschlagen oder abgebrochen.")
def mod_install(sftp, Pack_Type):
world_name = WORLD_NAME
local_dir_input = input("\nPfad zum Mod: ")
local_dir = local_dir_input.strip('"').strip()
local_dir_name = os.path.basename(local_dir)
if Pack_Type == "behavior":
remote_base_dir = BEHAVIOR_PACKS_PATH
pack_type = "behavior"
elif Pack_Type == "ressource":
remote_base_dir = RESOURCE_PACKS_PATH
pack_type = "ressource"
else:
print("Unbekannter Pack-Typ:", Pack_Type)
return
remote_dir = os.path.join(remote_base_dir, local_dir_name).replace('\\', '/')
upload_directory(sftp, local_dir, remote_dir)
# Extrahiere die UUID und Version aus der manifest.json
uuid, version = extract_manifest_data(sftp, remote_dir)
# Füge die Daten in die Welt-JSON-Datei ein
world_path = os.path.join(WORLDS_PATH, world_name).replace('\\', '/')
json_add(sftp, world_path, pack_type, uuid, version)
return remote_dir
def upload_directory(sftp, local_dir, remote_dir):
"""Hilfsfunktion zum rekursiven Hochladen des Inhalts eines Verzeichnisses."""
if not os.path.isdir(local_dir):
print("Der angegebene Pfad ist kein Verzeichnis:", local_dir)
return
for item in os.listdir(local_dir):
local_path = os.path.join(local_dir, item)
# Konvertiere Windows-Pfade in Unix-Pfade für den Remote-Server
remote_path = os.path.join(remote_dir, item).replace('\\', '/')
if os.path.isdir(local_path):
# Es ist ein Verzeichnis, rekursiv weitermachen
try:
sftp.listdir(remote_path)
except IOError:
sftp.mkdir(remote_path)
upload_directory(sftp, local_path, remote_path) # Rekursiver Aufruf mit korrekten Pfaden
else:
# Es ist eine Datei, hochladen
sftp.put(local_path, remote_path)
def extract_manifest_data(sftp, mod_path):
manifest_path = os.path.join(mod_path, "manifest.json").replace('\\', '/')
try:
with sftp.open(manifest_path, "r") as manifest_file:
manifest_data = json.load(manifest_file)
uuid = manifest_data['header']['uuid']
version = ".".join(str(v) for v in manifest_data['header']['version'])
return uuid, version
except Exception as e:
print(f"Fehler beim Lesen der manifest.json: {e}")
return None, None
def json_add(sftp, world_path, pack_type, uuid, version):
if pack_type == "behavior":
json_file_path = os.path.join(world_path, "world_behavior_packs.json").replace('\\', '/')
elif pack_type == "ressource":
json_file_path = os.path.join(world_path, "world_resource_packs.json").replace('\\', '/')
else:
print("Unbekannter Pack-Typ")
return
# Stelle sicher, dass das Verzeichnis existiert
try:
sftp.chdir(world_path) # Versuche, in das Verzeichnis zu wechseln
except IOError:
print(f"Das Verzeichnis {world_path} existiert nicht auf dem Server.")
return
data = [] # Initialisiere eine leere Liste für den Fall, dass die Datei nicht existiert
try:
# Versuche, die existierende JSON-Datei zu lesen
with sftp.open(json_file_path, "r") as json_file:
data = json.load(json_file)
except IOError:
print(f"Die Datei {json_file_path} existiert nicht. Eine neue Datei wird erstellt.")
# Füge das neue Pack hinzu
new_pack = {"pack_id": uuid, "version": version}
if new_pack not in data:
data.append(new_pack)
# Schreibe die aktualisierte Liste zurück in die Datei
with sftp.open(json_file_path, "w") as json_file:
json.dump(data, json_file, indent=4)
print(f"Die Informationen wurden erfolgreich zu {json_file_path} hinzugefügt.")
def remove_mod_from_json(sftp, world_path, pack_type, uuid):
if pack_type == "behavior":
json_file_path = os.path.join(world_path, "world_behavior_packs.json").replace('\\', '/')
elif pack_type == "ressource":
json_file_path = os.path.join(world_path, "world_resource_packs.json").replace('\\', '/')
else:
print("Unbekannter Pack-Typ")
return False
try:
with sftp.open(json_file_path, "r") as json_file:
data = json.load(json_file)
except IOError:
print(f"Die Datei {json_file_path} existiert nicht.")
return False
# Entferne den Eintrag mit der entsprechenden UUID
data = [pack for pack in data if pack.get("pack_id") != uuid]
# Schreibe die aktualisierte Liste zurück in die Datei
with sftp.open(json_file_path, "w") as json_file:
json.dump(data, json_file, indent=4)
print(f"Mod mit UUID {uuid} wurde aus {json_file_path} entfernt.")
return True
def delete_mod_folder(sftp, mod_path):
try:
# Liste alle Dateien/Ordner im Mod-Ordner auf und lösche sie
for item in sftp.listdir(mod_path):
item_path = os.path.join(mod_path, item).replace('\\', '/')
try:
sftp.remove(item_path) # Versuche, die Datei zu löschen
except IOError:
delete_mod_folder(sftp, item_path) # Falls es ein Ordner ist, rekursiv löschen
sftp.rmdir(mod_path) # Lösche den nun leeren Mod-Ordner
print(f"Mod-Ordner {mod_path} wurde gelöscht.")
return True
except Exception as e:
print(f"Fehler beim Löschen des Mod-Ordners {mod_path}: {e}")
return False
def mod_uninstall_dialog(sftp):
pack_type_input = input("\nWelcher Typ von Mod soll deinstalliert werden?\n1 - Behavior Pack\n2 - Ressource Pack\n -> ")
pack_type = "behavior" if pack_type_input == "1" else "ressource"
mod_name = input("Gib den Namen des Mods ein: ").strip()
# Pfade für den Mod und die JSON-Datei
remote_base_dir = BEHAVIOR_PACKS_PATH if pack_type == "behavior" else RESOURCE_PACKS_PATH
mod_path = os.path.join(remote_base_dir, mod_name).replace('\\', '/')
world_path = os.path.join(WORLDS_PATH, WORLD_NAME).replace('\\', '/')
# Extrahiere die UUID aus der manifest.json des Mods
uuid, _ = extract_manifest_data(sftp, mod_path)
if uuid:
# Entferne den Mod aus der JSON-Datei und lösche den Mod-Ordner
if remove_mod_from_json(sftp, world_path, pack_type, uuid) and delete_mod_folder(sftp, mod_path):
print(f"Mod {mod_name} wurde erfolgreich deinstalliert.")
else:
print("Fehler beim Deinstallieren des Mods.")
else:
print("Mod konnte nicht gefunden oder UUID konnte nicht extrahiert werden.")
if __name__ == "__main__":
ssh = ssh_connect()
run = True
while run:
AUSWAHL = input("\nBefehl eingeben:\n1 - Mods auflisten\n2 - Mod installieren\n3 - Mod deinstallieren\nq - Beenden\n -> ").strip()
if(AUSWAHL == "1"):
get_mods(ssh, BEHAVIOR_PACKS_PATH, RESOURCE_PACKS_PATH)
elif(AUSWAHL == "2"):
sftp = ssh.open_sftp()
mod_install_dialog(sftp)
elif(AUSWAHL == "3"):
sftp = ssh.open_sftp()
mod_uninstall_dialog(sftp)
elif(AUSWAHL == "q"):
ssh.close()
run = False

View File

@@ -1,106 +0,0 @@
import tkinter as tk
import paramiko as pm
import json
def on_btn_list():
hostname = ent_server_hostname.get()
user = ent_user.get()
password = ent_password.get()
ssh_list_addons(hostname, user, password)
def ssh_list_addons(hn, user, pw):
ssh = pm.SSHClient()
ssh.set_missing_host_key_policy(pm.AutoAddPolicy())
ssh.connect(hostname=hn, username=user, password=pw)
get_installed_addons(ssh)
#get_addon_json_data(ssh, "behavior_pack", "Bedrock-Bridge")
ssh.close()
def get_installed_addons(ssh):
stdin, stdout, stderr = ssh.exec_command("docker exec -t minecraft ls -1 /data/behavior_packs/")
txt_box.delete(1.0, tk.END)
txt_box.insert(tk.END, "Installed behavior packs:\n")
output = stdout.readlines()
for item in output:
line = str(item).replace("\n", "")
#print(line)
if(line.find("vanilla") == -1 and line.find("experimental") == -1 and line.find("chemistry") == -1):
#print("LINE = " + line)
uuid, version = get_addon_json_data(ssh, "behavior_pack", line)
#uuid = "abc"
#version = "123"
#txt_box.insert(tk.END, '> ' + line + "(UUID: " + uuid + "; Version: " + version + ")\n")
txt_box.insert(tk.END, f"> {line}\n (UUID = {str(uuid)}; Version = {str(version)})\n\n")
txt_box.insert(tk.END, "\nInstalled resource packs:\n")
stdin, stdout, stderr = ssh.exec_command("docker exec -t minecraft ls -1 /data/resource_packs/")
output = stdout.readlines()
for item in output:
line = str(item).replace("\n", "")
#print(line)
if(line.find("vanilla") == -1 and line.find("experimental") == -1 and line.find("chemistry") == -1):
uuid, version = get_addon_json_data(ssh, "resource_pack", line)
#txt_box.insert(tk.END, '> ' + line)
txt_box.insert(tk.END, f"> {line}\n (UUID = {str(uuid)}; Version = {str(version)})\n\n")
def get_addon_json_data(ssh, pack_type:str, addon:str):
print("\n" + pack_type + "\n")
print("\n" + addon + "\n")
command = f"docker exec -t minecraft cat /data/{pack_type}s/{addon.strip()}/manifest.json"
stdin, stdout, stderr = ssh.exec_command(command)
output = stdout.readlines()
string = ""
for item in output:
line = str(item)
string = string + line
manifest = json.loads(string)
uuid = manifest.get('header', {}).get('uuid', 'No UUID found')
version_list = manifest.get('header', {}).get('version', [])
version = '.'.join(map(str, version_list)) if version_list else 'No version found'
print(f"UUID = {uuid} VERSION = {version} VERSION_LIST = {version_list}")
#return uuid, version
return uuid, version_list
window = tk.Tk()
frm_a = tk.Frame(master=window)
frm_b = tk.Frame(master=window, bg="green")
lbl_server_hostname = tk.Label(master=frm_a, text="Server Hostname").pack(side="top")
ent_server_hostname = tk.Entry(master=frm_a)
ent_server_hostname.pack()
lbl_user = tk.Label(master=frm_a, text="user").pack()
ent_user = tk.Entry(master=frm_a)
ent_user.pack()
lbl_password = tk.Label(master=frm_a, text="password").pack()
ent_password = tk.Entry(master=frm_a,show='*')
ent_password.pack()
txt_box = tk.Text(master=frm_b, bg='black', fg='green')
txt_box.pack(expand=True, fill="both")
btn_login = tk.Button(master=frm_a,text="list installed addons", command=on_btn_list).pack()
frm_a.pack(side="left", padx=20, pady=20)
frm_b.pack(expand=True, fill="both", padx=20, pady=20)
window.mainloop()