Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import clr
- from System.IO import Directory, File, Path, SearchOption
- from System import Environment, PlatformID, String, Exception
- from System.Text.RegularExpressions import Regex, RegexOptions, Match
- extractedcount=0
- totalfilecount=0
- lastfileprogress=0
- ########################################
- # https://github.com/TheCherry/ark-server-manager #
- ########################################
- import struct
- import zlib
- import sys
- def str_to_l(st):
- return struct.unpack('q', st)[0]
- def z_unpack(src, dst):
- global extractedcount, totalfilecount, lastfileprogress
- with open(src, 'rb') as f_src:
- with open(dst, 'wb') as f_dst:
- f_src.read(8)
- size1 = str_to_l(f_src.read(8))
- f_src.read(8)
- size2 = str_to_l(f_src.read(8))
- if(size1 == -1641380927):
- size1 = 131072L
- runs = (size2 + size1 - 1L) / size1
- array = []
- for i in range(runs):
- array.append(f_src.read(8))
- f_src.read(8)
- for i in range(runs):
- to_read = array[i]
- compressed = f_src.read(str_to_l(to_read))
- decompressed = zlib.decompress(compressed)
- f_dst.write(decompressed)
- Script.WriteToConsole("Extracted " + dst.Replace(ThisService.RootDirectory, ""))
- File.Delete(src)
- File.Delete(src + ".uncompressed_size")
- extractedcount=extractedcount+1
- progress=round((float(extractedcount)/totalfilecount)*100,0)
- if progress > lastfileprogress + 4:
- lastfileprogress=progress
- ThisTaskStep.UpdateProgress(progress)
- #######################################################################
- # https://github.com/barrycarey/Ark_Mod_Downloader/blob/master/Ark_Mod_Downloader.py #
- #######################################################################
- import os
- import struct
- from collections import OrderedDict
- map_names = []
- map_count=0
- temp_mod_path = os.path.join(ThisService.RootDirectory, "ShooterGame/Content/Mods")
- meta_data = OrderedDict([])
- def parse_base_info(modid):
- Script.WriteToConsole("[+] Collecting Mod Details From mod.info")
- mod_info = os.path.join(temp_mod_path, modid, "mod.info")
- if not os.path.isfile(mod_info):
- Script.WriteToConsole("[x] Failed to locate mod.info. Cannot Continue. Aborting")
- return False
- with open(mod_info, "rb") as f:
- read_ue4_string(f)
- map_count = struct.unpack('i', f.read(4))[0]
- for i in range(map_count):
- cur_map = read_ue4_string(f)
- if cur_map:
- map_names.append(cur_map)
- return True
- def parse_meta_data(modid):
- """
- Parse the modmeta.info files and extract the key value pairs need to for the .mod file.
- How To Parse modmeta.info:
- 1. Read 4 bytes to tell how many key value pairs are in the file
- 2. Read next 4 bytes tell us how many bytes to read ahead to get the key
- 3. Read ahead by the number of bytes retrieved from step 2
- 4. Read next 4 bytes to tell how many bytes to read ahead to get value
- 5. Read ahead by the number of bytes retrieved from step 4
- 6. Start at step 2 again
- :return: Dict
- """
- print("[+] Collecting Mod Meta Data From modmeta.info")
- print("[+] Located The Following Meta Data:")
- mod_meta = os.path.join(temp_mod_path, modid, "modmeta.info")
- if not os.path.isfile(mod_meta):
- Script.WriteToConsole("[x] Failed To Locate modmeta.info. Cannot continue without it. Aborting")
- return False
- with open(mod_meta, "rb") as f:
- total_pairs = struct.unpack('i', f.read(4))[0]
- for i in range(total_pairs):
- key, value = "", ""
- key_bytes = struct.unpack('i', f.read(4))[0]
- key_flag = False
- if key_bytes < 0:
- key_flag = True
- key_bytes -= 1
- if not key_flag and key_bytes > 0:
- raw = f.read(key_bytes)
- key = raw[:-1].decode()
- value_bytes = struct.unpack('i', f.read(4))[0]
- value_flag = False
- if value_bytes < 0:
- value_flag = True
- value_bytes -= 1
- if not value_flag and value_bytes > 0:
- raw = f.read(value_bytes)
- value = raw[:-1].decode()
- # TODO This is a potential issue if there is a key but no value
- if key and value:
- Script.WriteToConsole("[!] " + key + ":" + value)
- meta_data[key] = value
- return True
- def create_mod_file(modid):
- """
- Create the .mod file.
- This code is an adaptation of the code from Ark Server Launcher. All credit goes to Face Wound on Steam
- :return:
- """
- if not parse_base_info(modid) or not parse_meta_data(modid):
- return False
- print("[+] Writing .mod File")
- with open(os.path.join(temp_mod_path, modid + ".mod"), "w+b") as f:
- modid = int(modid)
- if modid > 2147483647:
- diff = modid-2147483647
- modid = -2147483647 + diff - 2
- f.write(struct.pack('ixxxx', modid)) # Needs 4 pad bits
- write_ue4_string("ModName", f)
- write_ue4_string("", f)
- map_count = len(map_names)
- f.write(struct.pack("i", map_count))
- for m in map_names:
- write_ue4_string(m, f)
- # Not sure of the reason for this
- num2 = 4280483635
- f.write(struct.pack('I', num2))
- num3 = 2
- f.write(struct.pack('i', num3))
- if "ModType" in meta_data:
- mod_type = b'1'
- else:
- mod_type = b'0'
- # TODO The packing on this char might need to be changed
- f.write(struct.pack('p', mod_type))
- meta_length = len(meta_data)
- f.write(struct.pack('i', meta_length))
- for k, v in meta_data.items():
- write_ue4_string(k, f)
- write_ue4_string(v, f)
- return True
- def read_ue4_string(file):
- count = struct.unpack('i', file.read(4))[0]
- flag = False
- if count < 0:
- flag = True
- count -= 1
- if flag or count <= 0:
- return ""
- return file.read(count)[:-1].decode()
- def write_ue4_string(string_to_write, file):
- string_length = len(string_to_write) + 1
- file.write(struct.pack('i', string_length))
- barray = bytearray(string_to_write, "utf-8")
- file.write(barray)
- file.write(struct.pack('p', b'0'))
- ###########################################
- ###########################################
- ###########################################
- # If the content folder doesn't exist use downloads
- if not Directory.Exists(InstallPath) :
- InstallPath=InstallPath.Replace("/content/", "/downloads/")
- # Always use Windows files. Linux files cause the game server to crash at startup.
- oseditor="WindowsNoEditor"
- noeditor=Path.Combine(InstallPath, oseditor )
- # Extract and delete all .z files
- zfiles=Directory.GetFiles(noeditor, "*.z", SearchOption.AllDirectories);
- totalfilecount=zfiles.Count
- for zfile in zfiles:
- file=Path.Combine(Path.GetDirectoryName(zfile), Path.GetFileNameWithoutExtension(zfile))
- z_unpack(zfile, file)
- Script.WriteToConsole("Extracted " + file)
- File.Delete(zfile)
- File.Delete(zfile + ".uncompressed_size")
- # Move folder to correct location. Delete if it already exists.
- # Define modid before FileId is altered so we write the correct id to inifile
- modid = FileId
- if FileId > 2147483647:
- diff = FileId-2147483647
- FileId = -2147483647 + diff - 2
- modfolder=Path.Combine(ThisService.RootDirectory, String.Format("ShooterGame/Content/Mods/{0}", FileId))
- if Directory.Exists(modfolder) :
- Directory.Delete(modfolder, True)
- Directory.Move(Path.Combine(InstallPath, oseditor), modfolder)
- # Update ini file
- serveros = "WindowsServer" if Environment.OSVersion.Platform == PlatformID.Win32NT else "LinuxServer"
- inifile = Path.Combine(ThisService.RootDirectory, String.Format("ShooterGame/Saved/Config/{0}/GameUserSettings.ini", serveros))
- pattern="ActiveMods[ \t]*=[ \t]*(?<ActiveMods>[0-9, \t]*)"
- filecontents = File.ReadAllText(inifile)
- match = Regex.Match(filecontents, pattern, RegexOptions.IgnoreCase)
- if match.Success :
- activemods = match.Groups["ActiveMods"].Value
- if String.IsNullOrEmpty(activemods) or activemods.IndexOf(modid.ToString()) == -1 :
- if activemods.Length > 0 :
- activemods = activemods + ","
- activemods = activemods + modid.ToString()
- filecontents=filecontents.Replace(match.Groups["ActiveMods"].Value, activemods)
- else :
- activemods = modid.ToString()
- filecontents = filecontents.Substring(0, match.Groups["ActiveMods"].Index) + activemods + filecontents.Substring(match.Groups["ActiveMods"].Index)
- File.WriteAllText(inifile, filecontents)
- #Create .mod
- parse_base_info(FileId.ToString())
- parse_meta_data(FileId.ToString())
- create_mod_file(FileId.ToString())
- # Delete folder
- if Directory.Exists(InstallPath) :
- Directory.Delete(InstallPath, True)
Add Comment
Please, Sign In to add comment