Skip to content

Commit

Permalink
[scripts] import changes
Browse files Browse the repository at this point in the history
* Adds script to generate auto-updating jars
* Fixes an issue with tests not accepting eula correctly
* Moves the generated pack to the `generated/pack/` directory. (Was `pack_generated/`)
  • Loading branch information
TheEpicBlock committed Sep 28, 2024
1 parent 88b1adc commit f209479
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,5 @@ jobs:
url: https://theepicblock.nl/
username: modfestghci
password: ${{ secrets.TEB_WEBDAV_PASSWORD }}
local: "./pack_generated/"
local: "./generated/pack/"
remote: "private/ModFest-1-21"
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
*.mrpack
# Output of assemble_packwiz.py
/pack_generated
# Output of assemble scripts
/generated
# run_test.py will run a minecraft server here
/run

Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ The `pack/` directory contains the bulk of the pack. The files in here can be up
Submissions are version locked using the `submission-lock.json` file. Run `scripts/pull_platform.py` to pull the latest versions from platform. This script can also be run via a manually-triggered github action.

## Compiling the final pack
Run `scripts/assemble_packwiz.py`. It will output a full packwiz pack in `pack_generated`.
Run `scripts/assemble_packwiz.py`. It will output a full packwiz pack in `generated/pack/`.

## Creating auto-updating packs
Running `scripts/assemble_unsup.py` will create two zip files in the `generated` directory.
The file without a suffix can be put loaded into prism launcher.
The `-server.zip` file contains files needed to run a server. For Fabric it will contain a full server instance. For NeoForge you should run the server installer yourself and copy these files over top.
4 changes: 3 additions & 1 deletion constants.jsonc
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
// The name used for pulling from ModFest's platform api
"event": null
"event": null,
// The subdirectory in https://github.com/ModFest/art used for pulling the icon
"art_id": "1.21"
}
1 change: 0 additions & 1 deletion platform_exclude.txt

This file was deleted.

3 changes: 2 additions & 1 deletion scripts/assemble_packwiz.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env python3
import shutil
import json
import common
Expand All @@ -10,7 +11,7 @@ def main():
repo_root = common.get_repo_root()
submission_lock_file = repo_root / "submissions-lock.json"
source_pack = repo_root / "pack"
dest_pack = repo_root / "pack_generated"
dest_pack = common.get_generated_dir() / "pack"
exclude_file = repo_root / "platform.ignore"
packwiz = common.check_packwiz()

Expand Down
166 changes: 166 additions & 0 deletions scripts/assemble_unsup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#!/usr/bin/env python3
import sys
import re
from zipfile import ZipFile
import zipfile
import io
import json
import urllib.request

from common import Ansi
import common

def main():
repo_root = common.get_repo_root()
constants_file = repo_root / "constants.jsonc"
pack_toml_file = repo_root / "pack" / "pack.toml"
generated_dir = common.get_generated_dir()

url = common.env("URL")
if url == None:
print(f"{Ansi.ERROR}Please set the URL environment variable to the public url for this pack{Ansi.RESET}")
sys.exit(1)
if not url.endswith("pack.toml"):
print(f"{Ansi.WARN}URL does not end with \"pack.toml\", please make sure it's correct{Ansi.RESET}")
unsup_v = common.env("UNSUP_VERSION", default="0.2.3")

print(f"Using unsup version {unsup_v}")

packwiz_info = common.parse_packwiz(pack_toml_file)
constants = common.jsonc_at_home(common.read_file(constants_file))

# Download unsup jar
unsup_jar_file = generated_dir / "cache" / f"unsup-{unsup_v}.jar"
if not unsup_jar_file.exists():
unsup_jar_file.parent.mkdir(exist_ok=True, parents=True)
print(f"Downloading unsup to {unsup_jar_file.relative_to(repo_root)}")
urllib.request.urlretrieve(
f"https://repo.sleeping.town/com/unascribed/unsup/{unsup_v}/unsup-{unsup_v}.jar",
unsup_jar_file
)

# Create prism zip
prism = generated_dir / f"{packwiz_info.name}.zip"
with ZipFile(prism, "w", compression=zipfile.ZIP_DEFLATED) as output_zip:
icon_key = packwiz_info.safe_name()

with output_zip.open("instance.cfg", mode="w") as cfg:
cfg.write(create_instance_config(packwiz_info, icon_key).encode("utf-8"))

with output_zip.open("mmc-pack.json", mode="w") as packjson:
packjson.write(create_mmc_meta(packwiz_info, unsup_v).encode("utf-8"))

art_id = constants["art_id"]
with urllib.request.urlopen(f'https://github.com/ModFest/art/blob/v2/icon/64w/{art_id}/transparent.png?raw=true') as icon:
with output_zip.open(f"{icon_key}.png", mode="w") as icon_out:
icon_out.write(icon.read())

with output_zip.open("patches/com.unascribed.unsup.json", mode="w") as patch:
patch.write(create_unsup_patch(unsup_v).encode("utf-8"))

with output_zip.open(".minecraft/unsup.jar", mode="w") as unsup_out:
with open(unsup_jar_file, "rb") as unsup_src:
unsup_out.write(unsup_src.read())

with output_zip.open(".minecraft/unsup.ini", mode="w") as unsupini:
unsupini.write(create_unsup_ini(url).encode("utf-8"))
print(f"Wrote to \"{prism.relative_to(generated_dir)}\"")

server_zip = generated_dir / f"{packwiz_info.safe_name()}-server.zip"
with ZipFile(server_zip, "w", compression=zipfile.ZIP_DEFLATED) as output_zip:
if packwiz_info.loader == "fabric":
print(f"{Ansi.WARN}Fabric server zips are not supported yet{Ansi.RESET}")
elif packwiz_info.loader == "neoforge":
with output_zip.open("user_jvm_args.txt", mode="w") as jvm_args:
jvm_args.write("-javaagent:unsup.jar".encode("utf-8"))

with output_zip.open("unsup.jar", mode="w") as unsup_out:
with open(unsup_jar_file, "rb") as unsup_src:
unsup_out.write(unsup_src.read())

with output_zip.open("unsup.ini", mode="w") as unsupini:
unsupini.write(create_unsup_ini(url).encode("utf-8"))
print(f"Wrote to \"{server_zip.relative_to(generated_dir)}\"")

# Creates a patch file which tells prism to
# load unsup as an agent
def create_unsup_patch(unsup_version):
patch = {
"formatVersion": 1,
"name": "Una's Simple Updater",
"uid": "com.unascribed.unsup",
"version": unsup_version,
"+agents": [
{
"name": f"com.unascribed:unsup:{unsup_version}",
"url": "https://repo.sleeping.town"
}
]
}
return json.dumps(patch)

# Creates the mmc-pack.json file, which stores "dependency" information for prism/multimc
# The most important thing is that it defines the minecraft version and launcher used
def create_mmc_meta(packwiz_info, unsup_version):
meta = {}
meta["formatVersion"] = 1

components = []
# Add mc component
components.append({
"important": True,
"uid": "net.minecraft",
"version": packwiz_info.minecraft_version
})

# Add unsup component
components.append({
"cachedName": "Una's Simple Updater",
"cachedVersion": unsup_version,
"uid": "com.unascribed.unsup"
})

# Add loader component
if packwiz_info.loader == "neoforge":
components.append({
"uid": "net.neoforged",
"version": packwiz_info.loader_version
})
elif packwiz_info.loader == "fabric":
components.append({
"uid": "net.fabricmc.fabric-loader",
"version": packwiz_info.loader_version
})
else:
raise RuntimeError(f"Unknown loader {packwiz_info.loader}")

meta["components"] = components
return json.dumps(meta)

# Creates the instance.cfg, which defines basic information about the pack
# to prism/multimc
def create_instance_config(packwiz_info, icon_name):
return instance_cfg_template.replace("{iconKey}", icon_name).replace("{name}", packwiz_info.name)

# Creates the unsup config file, which tells unsup where
# to download mods from
def create_unsup_ini(url):
return unsup_ini_template.replace("{url}", url)

instance_cfg_template = """
[General]
ConfigVersion=1.2
iconKey={iconKey}
name={name}
InstanceType=OneSix
""".strip()

unsup_ini_template = """
version=1
source_format=packwiz
source={url}
preset=minecraft
""".strip()

if __name__ == "__main__":
main()
55 changes: 54 additions & 1 deletion scripts/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
from pathlib import Path
import hashlib
import tomllib
from dataclasses import dataclass
import re

class Ansi:
BOLD = '\033[1m'
ITALIC = '\033[3m'
YELLOW_FG = '\033[33m'
RED_FG = '\033[31m'
WARN = YELLOW_FG+BOLD
ERROR = RED_FG+BOLD
RESET = '\033[0m'

def check_packwiz():
Expand Down Expand Up @@ -38,6 +42,12 @@ def get_repo_root():
# is one directory up from this one
return Path(os.path.join(os.path.dirname(__file__), '..'))

def get_generated_dir():
dir = env("OUTPUT_DIR", default=(get_repo_root() / "generated"))
if not dir.exists():
dir.mkdir(exist_ok=True, parents=True)
return dir

def read_file(path):
with open(path, "r") as f:
return f.read()
Expand Down Expand Up @@ -79,4 +89,47 @@ def __init__(self, time):

def limit(self):
time.sleep(max(0, self.wait_time - (time.time() - self.last_action)))
self.last_action = time.time()
self.last_action = time.time()

def parse_packwiz(pack_toml_file):
pack_toml = tomllib.loads(read_file(pack_toml_file))

version_data = pack_toml["versions"]
if not "minecraft" in version_data:
raise Exception("pack.toml doesn't define a minecraft version")

# detect loader
supported_loaders = ["fabric", "neoforge"]
loaders = {k:v for k, v in version_data.items() if k in supported_loaders}
if len(loaders) >= 2:
raise Exception("pack is using multiple loaders, unsure which one to use: ["+", ".join(loaders.keys())+"]")
if len(loaders) == 0:
raise Exception("pack does not seem to define a loader")

loader = list(loaders.keys())[0]
loader_version = list(loaders.values())[0]

for v in version_data:
if v != "minecraft" and v not in supported_loaders:
raise Exception(f"pack is using unsupported software: {v}")

return PackwizPackInfo(
pack_toml.get("name"),
pack_toml.get("author"),
pack_toml.get("version"),
version_data["minecraft"],
loader,
loader_version
)

@dataclass
class PackwizPackInfo:
name: str
author: str
pack_version: str
minecraft_version: str
loader: str
loader_version: str

def safe_name(self):
return re.sub("[^a-zA-Z0-9]+", "-", self.name)
1 change: 1 addition & 0 deletions scripts/pull_platform.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env python3
import urllib.request
import json
import subprocess
Expand Down
12 changes: 8 additions & 4 deletions scripts/run_test.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env python3
import tomllib
import os
import urllib.request
Expand All @@ -10,7 +11,7 @@
def main():
repo_root = common.get_repo_root()
java = common.check_java()
pack = repo_root / "pack_generated"
pack = common.get_generated_dir() / "pack"
pack_toml_file = pack / "pack.toml"
test_server_working = Path(common.env("WORK_DIR", default=(repo_root / "run")))

Expand Down Expand Up @@ -79,10 +80,13 @@ def main():

# Accept eula
if loader == "fabric":
with open(game_dir / "eula.txt", "w") as f:
f.write("eula=true")
eula = game_dir / "eula.txt"
elif loader == "neoforge":
with open(minecraft_dir / "eula.txt", "w") as f:
eula = minecraft_dir / "eula.txt"
if not eula.exists():
eula.parent.mkdir(exist_ok=True, parents=True)
eula.touch()
with open(eula, "w") as f:
f.write("eula=true")

# Set up the packwiz and game dir
Expand Down

0 comments on commit f209479

Please sign in to comment.