CatStation/Tools/package_client_build.py
Morb0 636bea81df Merge remote-tracking branch 'upstream/master' into upstream-sync
# Conflicts:
#	.github/CODEOWNERS
#	Content.Client/Entry/EntryPoint.cs
#	Content.Server/Arcade/Components/SpaceVillainArcadeComponent.cs
#	Content.Server/Zombies/ZombifyOnDeathSystem.cs
#	Resources/Prototypes/Corvax/Roles/Jobs/Engineering/chief_engineer.yml
#	Resources/Prototypes/Datasets/Names/cargo_shuttle.yml
#	Resources/Prototypes/Datasets/tips.yml
#	Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml
#	Resources/Prototypes/Entities/Mobs/Species/base.yml
#	Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml
#	Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml
#	Resources/Prototypes/Roles/Jobs/Command/captain.yml
#	Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml
#	Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml
#	Resources/Prototypes/Roles/Jobs/Science/research_director.yml
#	Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml
#	Resources/Prototypes/Voice/speech_emotes.yml
#	Resources/ServerInfo/Guidebook/Science/Robotics.xml
#	Resources/Textures/Clothing/Head/Bandanas/brown.rsi/meta.json
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/equipped-HELMET.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/headlight-equipped-HELMET.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/headlight-inhand-left.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/headlight-inhand-right.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/headlight.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/icon.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/inhand-left.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/inhand-right.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/meta.json
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/visorlit-equipped-HELMET.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/visorlit-inhand-left.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/visorlit-inhand-right.png
#	Resources/Textures/Clothing/Head/Helmets/syndicate.rsi/visorlit.png
#	Resources/Textures/Clothing/OuterClothing/Suits/syndicate.rsi/equipped-OUTERCLOTHING.png
#	Resources/Textures/Clothing/OuterClothing/Suits/syndicate.rsi/icon.png
#	Resources/Textures/Clothing/OuterClothing/Suits/syndicate.rsi/inhand-left.png
#	Resources/Textures/Clothing/OuterClothing/Suits/syndicate.rsi/inhand-right.png
#	Resources/Textures/Effects/speech.rsi/meta.json
#	Resources/Textures/Objects/Misc/bureaucracy.rsi/meta.json
#	Resources/Textures/Objects/Misc/stock_parts.rsi/adv_capacitor.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/advanced_matter_bin.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/bluespace_matter_bin.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/capacitor.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/femto_mani.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/matter_bin.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/micro_mani.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/nano_mani.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/pico_mani.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/quadratic_capacitor.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/super_capacitor.png
#	Resources/Textures/Objects/Misc/stock_parts.rsi/super_matter_bin.png
#	Resources/Textures/Structures/Furniture/chairs.rsi/meta.json
2023-06-19 21:06:28 +03:00

193 lines
4.9 KiB
Python
Executable file

#!/usr/bin/env python3
import os
import shutil
import subprocess
import sys
import zipfile
import argparse
from typing import List, Optional
try:
from colorama import init, Fore, Style
init()
except ImportError:
# Just give an empty string for everything, no colored logging.
class ColorDummy(object):
def __getattr__(self, name):
return ""
Fore = ColorDummy()
Style = ColorDummy()
p = os.path.join
SHARED_IGNORED_RESOURCES = {
"ss13model.7z",
"ResourcePack.zip",
"buildResourcePack.py",
"CONTENT_GOES_HERE",
".gitignore",
".directory",
".DS_Store"
}
CLIENT_IGNORED_RESOURCES = {
"Maps",
"ConfigPresets",
"emotes.xml",
"Groups",
"CorvaxSecretsServer", # Corvax-Secrets
"engineCommandPerms.yml"
}
CLIENT_CONTENT_ASSEMBLIES = [
# IF YOU ADD SOMETHING HERE, ADD IT TO MANIFEST.YML TOO.
"Content.Client",
"Content.Shared",
"Content.Shared.Database"
]
def main() -> None:
parser = argparse.ArgumentParser(
description="Packages the SS14 client.")
parser.add_argument("--skip-build",
action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
skip_build = args.skip_build
if os.path.exists("release"):
pass
# print(Fore.BLUE + Style.DIM +
# "Cleaning old release packages (release/)..." + Style.RESET_ALL)
# shutil.rmtree("release")
else:
os.mkdir("release")
if not skip_build:
wipe_bin()
build(skip_build)
def wipe_bin():
print(Fore.BLUE + Style.DIM +
"Clearing old build artifacts (if any)..." + Style.RESET_ALL)
if os.path.exists("bin"):
shutil.rmtree("bin")
# Be advised this is called from package_server_build during a Hybrid-ACZ build.
def build(skip_build: bool) -> None:
# Run a full build.
print(Fore.GREEN + "Building project..." + Style.RESET_ALL)
if not skip_build:
subprocess.run([
"dotnet",
"build",
p("Content.Client", "Content.Client.csproj"),
"-c", "Release",
"--nologo",
"/v:m",
"/t:Rebuild",
"/p:FullRelease=True",
"/m"
], check=True)
print(Fore.GREEN + "Packaging client..." + Style.RESET_ALL)
client_zip = zipfile.ZipFile(
p("release", "SS14.Client.zip"), "w",
compression=zipfile.ZIP_DEFLATED)
copy_resources(client_zip)
copy_content_assemblies("Assemblies", client_zip)
# Cool we're done.
client_zip.close()
def copy_resources(zipf):
ignore_set = SHARED_IGNORED_RESOURCES.union(CLIENT_IGNORED_RESOURCES)
do_resource_copy("Resources", zipf, ignore_set)
def do_resource_copy(source, zipf, ignore_set):
for filename in os.listdir(source):
if filename in ignore_set:
continue
path = p(source, filename)
target_path = filename
if os.path.isdir(path):
copy_dir_into_zip(path, target_path, zipf)
else:
zipf.write(path, target_path)
def zip_entry_exists(zipf, name):
try:
# Trick ZipInfo into sanitizing the name for us so this awful module stops spewing warnings.
zinfo = zipfile.ZipInfo.from_file("Resources", name)
zipf.getinfo(zinfo.filename)
except KeyError:
return False
return True
def copy_dir_into_zip(directory, basepath, zipf):
if basepath and not zip_entry_exists(zipf, basepath):
zipf.write(directory, basepath)
for root, _, files in os.walk(directory):
relpath = os.path.relpath(root, directory)
if relpath != "." and not zip_entry_exists(zipf, p(basepath, relpath)):
zipf.write(root, p(basepath, relpath))
for filename in files:
zippath = p(basepath, relpath, filename)
filepath = p(root, filename)
message = "{dim}{diskroot}{sep}{zipfile}{dim} -> {ziproot}{sep}{zipfile}".format(
sep=os.sep + Style.NORMAL,
dim=Style.DIM,
diskroot=directory,
ziproot=zipf.filename,
zipfile=os.path.normpath(zippath))
print(Fore.CYAN + message + Style.RESET_ALL)
zipf.write(filepath, zippath)
def copy_content_assemblies(target, zipf):
files = []
source_dir = p("bin", "Content.Client")
base_assemblies = CLIENT_CONTENT_ASSEMBLIES
# Include content assemblies.
for asm in base_assemblies:
files.append(asm + ".dll")
# If PDB available, include it aswell.
pdb_path = asm + ".pdb"
if os.path.exists(p(source_dir, pdb_path)):
files.append(pdb_path)
# Write assemblies dir if necessary.
if not zip_entry_exists(zipf, target):
zipf.write(".", target)
for x in files:
zipf.write(p(source_dir, x), f"{target}/{x}")
if __name__ == '__main__':
main()