удаление модов

This commit is contained in:
Евгений Храмов 2023-05-14 21:57:51 +03:00
parent 779c15d301
commit 9eb8987989

75
hlna.py

@ -17,9 +17,9 @@ from rcon.source import Client
home_dir = Path.home() home_dir = Path.home()
logging.basicConfig(stream=sys.stderr, level=logging.CRITICAL) logging.basicConfig(stream=sys.stderr, level=logging.CRITICAL)
class UnpackException(Exception): class UnpackException(Exception):
pass pass
@ -59,10 +59,12 @@ def path_server():
yaml_create(game := "path_server", dir_server) yaml_create(game := "path_server", dir_server)
return dir_server return dir_server
@click.group() @click.group()
def hlna(): def hlna():
pass pass
def unpack(src, dst): def unpack(src, dst):
with open(src, 'rb') as f: with open(src, 'rb') as f:
sigver = struct.unpack('q', f.read(8))[0] sigver = struct.unpack('q', f.read(8))[0]
@ -73,13 +75,14 @@ def unpack(src, dst):
size_packed = struct.unpack('q', packed)[0] size_packed = struct.unpack('q', packed)[0]
size_unpacked = struct.unpack('q', unpacked)[0] size_unpacked = struct.unpack('q', unpacked)[0]
#Verify the integrity of the Archive Header # Verify the integrity of the Archive Header
if sigver == 2653586369: if sigver == 2653586369:
if isinstance(size_unpacked_chunk, int) and isinstance(size_packed , int) and isinstance(size_unpacked , int): if isinstance(size_unpacked_chunk, int) and isinstance(size_packed, int) and isinstance(size_unpacked, int):
logging.info("Archive is valid.") logging.info("Archive is valid.")
logging.debug(f"Archive header size information. Unpacked Chunk: {size_unpacked_chunk}({unpacked_chunk}) Full Packed: {size_packed}({packed}) Full Unpacked: {size_unpacked}({unpacked})") logging.debug(
f"Archive header size information. Unpacked Chunk: {size_unpacked_chunk}({unpacked_chunk}) Full Packed: {size_packed}({packed}) Full Unpacked: {size_unpacked}({unpacked})")
#Obtain the Archive Compression Index # Obtain the Archive Compression Index
compression_index = [] compression_index = []
size_indexed = 0 size_indexed = 0
while size_indexed < size_unpacked: while size_indexed < size_unpacked:
@ -89,26 +92,27 @@ def unpack(src, dst):
uncompressed = struct.unpack('q', raw_uncompressed)[0] uncompressed = struct.unpack('q', raw_uncompressed)[0]
compression_index.append((compressed, uncompressed)) compression_index.append((compressed, uncompressed))
size_indexed += uncompressed size_indexed += uncompressed
logging.debug(f"{len(compression_index)}: {size_indexed}/{size_unpacked} ({compressed}/{uncompressed}) - {raw_compressed} - {raw_uncompressed}") logging.debug(
f"{len(compression_index)}: {size_indexed}/{size_unpacked} ({compressed}/{uncompressed}) - {raw_compressed} - {raw_uncompressed}")
if size_unpacked != size_indexed: if size_unpacked != size_indexed:
msg = f"Header-Index mismatch. Header indicates it should only have {size_unpacked} bytes when uncompressed but the index indicates {size_indexed} bytes." msg = f"Header-Index mismatch. Header indicates it should only have {size_unpacked} bytes when uncompressed but the index indicates {size_indexed} bytes."
logging.critical(msg) logging.critical(msg)
raise CorruptUnpackException(msg) raise CorruptUnpackException(msg)
#Read the actual archive data # Read the actual archive data
data = b'' data = b''
read_data = 0 read_data = 0
for compressed, uncompressed in compression_index: for compressed, uncompressed in compression_index:
compressed_data = f.read(compressed) compressed_data = f.read(compressed)
uncompressed_data = zlib.decompress(compressed_data) uncompressed_data = zlib.decompress(compressed_data)
#Verify the size of the data is consistent with the archives index # Verify the size of the data is consistent with the archives index
if len(uncompressed_data) == uncompressed: if len(uncompressed_data) == uncompressed:
data += uncompressed_data data += uncompressed_data
read_data += 1 read_data += 1
#Verify there is only one partial chunk # Verify there is only one partial chunk
if len(uncompressed_data) != size_unpacked_chunk and read_data != len(compression_index): if len(uncompressed_data) != size_unpacked_chunk and read_data != len(compression_index):
msg = f"Index contains more than one partial chunk: was {len(uncompressed_data)} when the full chunk size is {size_unpacked_chunk}, chunk {read_data}/{len(compression_index)}" msg = f"Index contains more than one partial chunk: was {len(uncompressed_data)} when the full chunk size is {size_unpacked_chunk}, chunk {read_data}/{len(compression_index)}"
logging.critical(msg) logging.critical(msg)
@ -126,7 +130,7 @@ def unpack(src, dst):
logging.critical(msg) logging.critical(msg)
raise SignatureUnpackException(msg) raise SignatureUnpackException(msg)
#Write the extracted data to disk # Write the extracted data to disk
with open(dst, 'wb') as f: with open(dst, 'wb') as f:
f.write(data) f.write(data)
logging.info("Archive has been extracted.") logging.info("Archive has been extracted.")
@ -338,7 +342,9 @@ def config_ark(list_config=list_config):
else: else:
listen_server = True listen_server = True
yaml_create(game := "ARK", dir_server := "", cluster_server, map_s, list_config[-1], port_server, query_port, rcon_enabled, rcon_port, adminpassword_server, password_server, max_players, cluster_id, cluster_dir_override, listen_server) yaml_create(game := "ARK", dir_server := "", cluster_server, map_s, list_config[-1], port_server, query_port,
rcon_enabled, rcon_port, adminpassword_server, password_server, max_players, cluster_id,
cluster_dir_override, listen_server)
def config_7daystodie(): def config_7daystodie():
@ -361,8 +367,10 @@ def xml_parser():
print("Я не умею парсить))") print("Я не умею парсить))")
def yaml_create(game, dir_server="", cluster_server="", map_s="", name_server="", port_server="", query_port="", rcon_enabled="", rcon_port="", def yaml_create(game, dir_server="", cluster_server="", map_s="", name_server="", port_server="", query_port="",
adminpassword_server="", password_server="", max_players="", id_mods_ark="", cluster_id="", cluster_dir_override="", listen_server=""): rcon_enabled="", rcon_port="",
adminpassword_server="", password_server="", max_players="", id_mods_ark="", cluster_id="",
cluster_dir_override="", listen_server=""):
if game == "ARK": if game == "ARK":
print_line(dir_maps_ark) print_line(dir_maps_ark)
print_line(name_server) print_line(name_server)
@ -444,7 +452,8 @@ WantedBy=default.target
@hlna.command(help='Для скачивания и установки модов') @hlna.command(help='Для скачивания и установки модов')
@click.option('-g', help="Название игры для запуска. (ark, 7days") @click.option('-g', help="Название игры для запуска. (ark, 7days")
@click.option('-m', default='all', help="Название карты для запуска или all для запуска все карт") @click.option('-m', default='all', help="Название карты для запуска или all для запуска все карт")
def modinstall(g, m): @click.option("-i/-u", default=True, help="-i установить моды, -u удалить моды")
def mod(g, m, i):
if g == "ark": if g == "ark":
id_game_workshop = "346110" id_game_workshop = "346110"
if not os.path.isdir(dir_workshop_ark): if not os.path.isdir(dir_workshop_ark):
@ -452,15 +461,18 @@ def modinstall(g, m):
id_mods_ark = input("""Укажите id модов через запятую id_mods_ark = input("""Укажите id модов через запятую
:""").split(",") :""").split(",")
for id_mod in id_mods_ark: for id_mod in id_mods_ark:
os.system(f"steamcmd +login anonymous +workshop_download_item {id_game_workshop} {id_mod} +quit") dir_ark_mods = f"{dir_mods_ark}/{id_mod}"
modextract(id_mod, id_game_workshop) if i:
os.system(f"steamcmd +login anonymous +workshop_download_item {id_game_workshop} {id_mod} +quit")
modextract(id_mod, id_game_workshop, dir_ark_mods)
else:
os.system(f"rm -rf {dir_ark_mods}")
os.system(f"rm {dir_mods_ark}/{id_mod}.mod")
def modextract(id_mod, id_game_workshop): def modextract(id_mod, id_game_workshop, dir_ark_mods):
dir_steam_workshop = f"{dir_workshop_ark}/content/{id_game_workshop}/{id_mod}/WindowsNoEditor" dir_steam_workshop = f"{dir_workshop_ark}/content/{id_game_workshop}/{id_mod}/WindowsNoEditor"
dir_ark_mods = f"{dir_mods_ark}/{id_mod}"
dir_extract = dir_ark_mods dir_extract = dir_ark_mods
if id_mod == "111111111": if id_mod == "111111111":
return return
@ -483,7 +495,8 @@ def modextract(id_mod, id_game_workshop):
os.system(f"rm -rf {dir_ark_mods}") os.system(f"rm -rf {dir_ark_mods}")
os.system(f"mv -f {dir_steam_workshop} {dir_ark_mods}") os.system(f"mv -f {dir_steam_workshop} {dir_ark_mods}")
modname = subprocess.check_output(['curl', '-s', 'https://steamcommunity.com/sharedfiles/filedetails/?id={}'.format(id_mod)]).decode('utf-8') modname = subprocess.check_output(
['curl', '-s', 'https://steamcommunity.com/sharedfiles/filedetails/?id={}'.format(id_mod)]).decode('utf-8')
modname = re.search(r'<div class="workshopItemTitle">(.+)</div>', modname) modname = re.search(r'<div class="workshopItemTitle">(.+)</div>', modname)
modname = modname and modname.group(1) modname = modname and modname.group(1)
@ -494,8 +507,8 @@ def modextract(id_mod, id_game_workshop):
with open(f"{dir_extract}/mod.info", "rb") as modinfo: with open(f"{dir_extract}/mod.info", "rb") as modinfo:
data = modinfo.read() data = modinfo.read()
mapnamelen = struct.unpack_from("<L", data, 0)[0] mapnamelen = struct.unpack_from("<L", data, 0)[0]
mapname = data[4:mapnamelen+3] mapname = data[4:mapnamelen + 3]
nummaps = struct.unpack_from("<L", data, mapnamelen+4)[0] nummaps = struct.unpack_from("<L", data, mapnamelen + 4)[0]
pos = mapnamelen + 8 pos = mapnamelen + 8
modname = (modname.encode() or mapname.decode()) + b'\x00' modname = (modname.encode() or mapname.decode()) + b'\x00'
modnamelen = len(modname) modnamelen = len(modname)
@ -504,10 +517,11 @@ def modextract(id_mod, id_game_workshop):
with open(f"{dir_ark_mods}.mod", "wb") as mod: with open(f"{dir_ark_mods}.mod", "wb") as mod:
print(type(modnamelen)) print(type(modnamelen))
print(type(modpathlen)) print(type(modpathlen))
mod.write(struct.pack('<LLL{}sL{}sL'.format(modnamelen, modpathlen), int(id_mod), 0, modnamelen, modname, modpathlen, modpath, nummaps)) mod.write(struct.pack('<LLL{}sL{}sL'.format(modnamelen, modpathlen), int(id_mod), 0, modnamelen, modname,
modpathlen, modpath, nummaps))
for mapnum in range(nummaps): for mapnum in range(nummaps):
mapfilelen = struct.unpack_from("<L", data, pos)[0] mapfilelen = struct.unpack_from("<L", data, pos)[0]
mapfile = data[mapnamelen+12:mapnamelen+12+mapfilelen] mapfile = data[mapnamelen + 12:mapnamelen + 12 + mapfilelen]
mod.write(struct.pack("<L%ds" % mapfilelen, mapfilelen, mapfile)) mod.write(struct.pack("<L%ds" % mapfilelen, mapfilelen, mapfile))
pos = pos + 4 + mapfilelen pos = pos + 4 + mapfilelen
mod.write(b"\x33\xFF\x22\xFF\x02\x00\x00\x00\x01") mod.write(b"\x33\xFF\x22\xFF\x02\x00\x00\x00\x01")
@ -525,9 +539,9 @@ def modextract(id_mod, id_game_workshop):
os.makedirs(dir_ark_mods) os.makedirs(dir_ark_mods)
@ hlna.command() @hlna.command()
@ click.option("-m", required=True, help="Название Сервера") @click.option("-m", required=True, help="Название Сервера")
@ click.option("-e/-d", default=True, help="-e активировать карты, -d деактивировать") @click.option("-e/-d", default=True, help="-e активировать карты, -d деактивировать")
def enablemap(m, e): def enablemap(m, e):
"""Включение/выключение карт""" """Включение/выключение карт"""
m = m.split(",") m = m.split(",")
@ -663,7 +677,7 @@ def start_stop(action, g, m, list_config=list_config):
for ns, v in dict_mapname.items(): for ns, v in dict_mapname.items():
if v in m: if v in m:
names_serverstart.append(ns) names_serverstart.append(ns)
if list_config != []: #Перенести выше для проверки наличия конфигов if list_config != []: # Перенести выше для проверки наличия конфигов
if m == "all": if m == "all":
names_serverstart = dict_allmapname names_serverstart = dict_allmapname
print(f"Выполняется для карт(-ы) {names_serverstart}") print(f"Выполняется для карт(-ы) {names_serverstart}")
@ -671,7 +685,8 @@ def start_stop(action, g, m, list_config=list_config):
names_serverstart = choose_map(names_serverstart) names_serverstart = choose_map(names_serverstart)
for i in names_serverstart: for i in names_serverstart:
data = read_yaml(i, game="ARK") data = read_yaml(i, game="ARK")
y = os.system(f"~/git/hln-a/hlna.py rcon SaveWorld -m {i}") if action == "restart" or action == "stop" else "" y = os.system(
f"~/git/hln-a/hlna.py rcon SaveWorld -m {i}") if action == "restart" or action == "stop" else ""
x = os.system(f"systemctl --user {action} ark_{data['SessionName'].lower()}.service") x = os.system(f"systemctl --user {action} ark_{data['SessionName'].lower()}.service")
print_line(y) print_line(y)
if x == 0: if x == 0:
@ -763,7 +778,6 @@ else:
print_line(data['path_server']) print_line(data['path_server'])
dir_server = data['path_server'] dir_server = data['path_server']
dir_unit = f"{home_dir}/.config/systemd/user/" dir_unit = f"{home_dir}/.config/systemd/user/"
dir_logs = f"{dir_config}logs/" dir_logs = f"{dir_config}logs/"
@ -783,6 +797,5 @@ create_dir(dir_unit)
create_dir(dir_config) create_dir(dir_config)
create_dir(dir_logs) create_dir(dir_logs)
if __name__ == '__main__': if __name__ == '__main__':
hlna() hlna()