Skip to content

Commit

Permalink
Merge branch '1.21.0' into 1.21.3
Browse files Browse the repository at this point in the history
  • Loading branch information
rfresh2 committed Dec 8, 2024
2 parents ed9f990 + 10040dc commit a1579cc
Show file tree
Hide file tree
Showing 17 changed files with 352 additions and 86 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/act-build-launcher.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,42 @@ jobs:
name: launcher-python.sha1
path: ZenithProxy-launcher-python.sha1

# same as python package but with a custom bat script that bootstraps the python interpreter
package-windows-python:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Create Python executable zip
run: zip -j launcher-py.zip src/launcher/*.py

- name: Rename launch_windows.bat
run: cp src/launcher/launch_windows.bat launch.bat

- name: Create release zip
run: zip -j ZenithProxy-launcher-windows-python-amd64.zip launcher-py.zip src/launcher/requirements.txt launch.bat scripts/windows_help.txt

- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: launcher-windows-python-amd64
path: ZenithProxy-launcher-windows-python-amd64.zip

- name: Get Binary Hash
run: sha1sum -b launcher-py.zip | cut -d" " -f 1 > ZenithProxy-launcher-windows-python-amd64.sha1

- name: Upload Launcher Hash Version
uses: actions/upload-artifact@v4
with:
name: launcher-windows-python-amd64.sha1
path: ZenithProxy-launcher-windows-python-amd64.sha1

release-artifacts:
needs:
- build-matrix
- package-python
- package-windows-python
runs-on: ubuntu-latest
steps:
- name: Check out repository
Expand Down
76 changes: 32 additions & 44 deletions .github/workflows/release-launcher.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,49 +72,6 @@ jobs:
name: ${{ matrix.artifact-name }}.sha1
path: ZenithProxy-${{ matrix.artifact-name }}.sha1

build-windows:
runs-on: windows-2019
steps:
- name: Check out repository
uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ env.python_version }}

- name: Install Dependencies
run: |
pip install -r ./src/launcher/requirements.txt
- uses: Nuitka/Nuitka-Action@main
with:
nuitka-version: main
script-name: src/launcher/__main__.py
standalone: true
onefile: true
windows-icon-from-ico: src/launcher/icon.ico
output-file: "launch"
output-dir: "dist"

- name: Create zip
run: |
Compress-Archive -Path .\dist\launch.exe -DestinationPath .\dist\ZenithProxy-launcher-windows-amd64.zip
- name: Upload Binary
uses: actions/upload-artifact@v4
with:
name: launcher-windows-amd64
path: dist/ZenithProxy-launcher-windows-amd64.zip

- name: Get Binary Hash
run: (Get-FileHash -Path dist\launch.exe -Algorithm sha1).Hash.ToLower() > ZenithProxy-launcher-windows-amd64.sha1

- name: Upload Launcher Hash Version
uses: actions/upload-artifact@v4
with:
name: launcher-windows-amd64.sha1
path: ZenithProxy-launcher-windows-amd64.sha1

build-linux-aarch64:
runs-on: 'ubuntu-latest'
steps:
Expand Down Expand Up @@ -192,12 +149,43 @@ jobs:
name: launcher-python.sha1
path: ZenithProxy-launcher-python.sha1

# same as python package but with a custom bat script that bootstraps the python interpreter
package-windows-python:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Create Python executable zip
run: zip -j launcher-py.zip src/launcher/*.py

- name: Rename launch_windows.bat
run: cp src/launcher/launch_windows.bat launch.bat

- name: Create release zip
run: zip -j ZenithProxy-launcher-windows-python-amd64.zip launcher-py.zip src/launcher/requirements.txt launch.bat scripts/windows_help.txt

- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: launcher-windows-python-amd64
path: ZenithProxy-launcher-windows-python-amd64.zip

- name: Get Binary Hash
run: sha1sum -b launcher-py.zip | cut -d" " -f 1 > ZenithProxy-launcher-windows-python-amd64.sha1

- name: Upload Launcher Hash Version
uses: actions/upload-artifact@v4
with:
name: launcher-windows-python-amd64.sha1
path: ZenithProxy-launcher-windows-python-amd64.sha1

release-artifacts:
needs:
- build-matrix
- build-windows
- build-linux-aarch64
- package-python
- package-windows-python
runs-on: ubuntu-latest
steps:
- name: Download job artifacts
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ This project is also used for the [2b2t.vc API](https://api.2b2t.vc) and [Discor
### Launcher

1. Download [the launcher zip](https://github.com/rfresh2/ZenithProxy/releases/launcher-v3) for your system
* Windows Setup Guide: https://github.com/rfresh2/ZenithProxy/wiki/Windows-Python-Launcher-Guide
* For other systems, download the Python version (Universal). Requires [Python 3.10+](https://www.python.org/downloads/)
2. Unzip the file.
3. Double click or run the launcher executable in a terminal:
* Windows: `.\launch.exe`
3. Run the launcher executable in a terminal:
* Linux/Mac: `./launch`
* (Terminal Only) Python Universal: `./launch.sh` (Linux/Mac) or `.\launch.bat` (Windows)
* Python: `./launch.sh` (Linux/Mac) or `.\launch.bat` (Windows)

<details>
<summary>How do I download a file from a Linux terminal?</summary>
Expand Down
10 changes: 10 additions & 0 deletions scripts/windows_help.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Usage Instructions

Full Guide With Screenshots: https://github.com/rfresh2/ZenithProxy/wiki/Windows-Python-Launcher-Guide

1. Open cmd or Windows Terminal

2. Switch directories to the location of the launcher files using the "cd" command
Example: cd "C:\Users\rfresh2\Downloads\ZenithProxy-launcher-windows-python-amd64"

3. Run the launcher: ".\launch.bat"
54 changes: 36 additions & 18 deletions src/launcher/github_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import requests

from requests import Session
from requests.adapters import HTTPAdapter
from urllib3 import Retry

class GitHubAPI:
launch_config = None
Expand All @@ -22,11 +23,34 @@ def get_headers(self):
"Connection": "close",
}

def _create_session(self):
retries = Retry(
total=1,
connect=1,
read=1,
status=1,
redirect=5,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
session = Session()
adapter = HTTPAdapter(max_retries=retries)
session.mount("https://", adapter)
return session

def _send_request(self, url, headers, params=None, timeout=10, allow_redirects=False):
try:
with self._create_session() as session:
response = session.get(url, headers=headers, params=params, timeout=timeout, allow_redirects=allow_redirects)
if response.status_code == 200:
return response
raise Exception(f"Request to {url} failed with status code {response.status_code}")
except Exception as e:
raise Exception(f"Request to {url} failed with exception {e}")

def get_latest_release_and_ver(self, channel):
try:
response = requests.get(self.get_base_url(), headers=self.get_headers(), params={"per_page": 100}, timeout=10)
if response.status_code != 200:
return None
response = self._send_request(self.get_base_url(), self.get_headers(), params={"per_page": 100})
releases = response.json()
latest_release = max(
(r for r in releases if not r["draft"] and r["tag_name"].endswith("+" + channel)),
Expand All @@ -41,20 +65,18 @@ def get_latest_release_and_ver(self, channel):
def get_release_for_ver(self, tag_name):
url = f"{self.get_base_url()}/tags/{tag_name}"
try:
response = requests.get(url, headers=self.get_headers(), timeout=10)
if response.status_code == 200:
release = response.json()
return release["id"], release["tag_name"]
response = self._send_request(url, self.get_headers())
release = response.json()
return release["id"], release["tag_name"]
except Exception as e:
print("Failed to get release for version:", e)
return None

def get_asset_id(self, release_id, asset_name, tag=False):
url = f"{self.get_base_url()}/{'tags/' if tag else ''}{release_id}"
try:
response = requests.get(url, headers=self.get_headers(), timeout=10)
if response.status_code == 200:
return next((asset["id"] for asset in response.json()["assets"] if asset["name"] == asset_name), None)
response = self._send_request(url, self.get_headers())
return next((asset["id"] for asset in response.json()["assets"] if asset["name"] == asset_name), None)
except Exception as e:
print("Failed to get release asset ID:", e)
return None
Expand All @@ -70,12 +92,8 @@ def download_asset(self, asset_id):
download_headers = self.get_headers()
download_headers["Accept"] = "application/octet-stream"
try:
response = requests.get(url, headers=download_headers, allow_redirects=True, timeout=60)
if response.status_code == 200:
return response.content
else:
print("Failed to download asset:", response.status_code, response.reason)
return None
response = self._send_request(url, download_headers, allow_redirects=True, timeout=60)
return response.content
except Exception as e:
print("Failed to download asset:", e)
return None
4 changes: 4 additions & 0 deletions src/launcher/launch_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ def is_nuitka_bundle():
return "__compiled__" in globals()


def is_windows_python_bundle():
return os.path.exists("python/python.exe")


def executable_path():
if is_nuitka_bundle():
return sys.argv[0]
Expand Down
28 changes: 28 additions & 0 deletions src/launcher/launch_windows.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@echo off
setlocal

REM Check if Python is already installed
if not exist python\python.exe (
REM Download python
echo Downloading Python...
curl -L -o python.tar.gz "https://github.com/indygreg/python-build-standalone/releases/download/20241206/cpython-3.13.1+20241206-x86_64-pc-windows-msvc-shared-install_only_stripped.tar.gz"

REM Extract tarball
echo Extracting Python...
tar -xf python.tar.gz

REM Delete tarball
del python.tar.gz
) else (
echo Found existing Python installation.
)

REM Install pip requirements.txt
echo Verifying requirements...
python\python.exe -m pip install -r requirements.txt -qq --disable-pip-version-check --no-input

REM Run launcher-py.zip
echo Starting Launcher...
python\python.exe launcher-py.zip

endlocal
14 changes: 9 additions & 5 deletions src/launcher/update_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ def update_launcher_exec(config, api):
print("Checking for launcher update...")
try:
is_pyinstaller = launch_platform.is_pyinstaller_bundle() or launch_platform.is_nuitka_bundle()
is_windows_python = not is_pyinstaller and launch_platform.is_windows_python_bundle()
os_platform = launch_platform.get_platform_os()
os_arch = launch_platform.get_platform_arch()
launcher_asset_file_name = get_launcher_asset_zip_file_name(is_pyinstaller, os_platform, os_arch)
launcher_asset_file_name = get_launcher_asset_zip_file_name(is_pyinstaller, is_windows_python, os_platform, os_arch)
current_executable_name = get_current_launcher_executable_name(is_pyinstaller)
expected_executable_name = get_expected_launcher_executable_name(is_pyinstaller)
hashes_list = get_launcher_hashes(api)
Expand Down Expand Up @@ -54,15 +55,17 @@ def update_launcher_exec(config, api):
if is_pyinstaller:
relaunch_executable(os_platform, current_executable_name)
else:
replace_extra_python_launcher_files(os_platform, current_launcher_sha1)
replace_extra_python_launcher_files(os_platform, is_windows_python, current_launcher_sha1)
relaunch_python(os_platform, current_executable_name)
except Exception as e:
print("Error during launcher updater check, skipping update:", e)


def get_launcher_asset_zip_file_name(is_pyinstaller, os_platform, os_arch):
def get_launcher_asset_zip_file_name(is_pyinstaller, is_windows_python, os_platform, os_arch):
if is_pyinstaller:
return f"ZenithProxy-launcher-{os_platform.value}-{os_arch.value}.zip"
elif is_windows_python:
return "ZenithProxy-launcher-windows-python-amd64.zip"
else:
return "ZenithProxy-launcher-python.zip"

Expand Down Expand Up @@ -144,10 +147,11 @@ def replace_launcher_executable(os_platform, exec_name, new_exec_name, current_s
os.replace(new_exec_name, exec_name)


def replace_extra_python_launcher_files(os_platform, current_sha1):
def replace_extra_python_launcher_files(os_platform, is_windows_python, current_sha1):
os.replace("launcher/requirements.txt", "requirements.txt")
# todo: handle the case where users change the script's name
os.replace("launcher/launch.sh", "launch.sh")
if not is_windows_python:
os.replace("launcher/launch.sh", "launch.sh")
if os_platform == OperatingSystem.WINDOWS:
os.rename("launch.bat", tempfile.gettempdir() + "/launch-" + current_sha1 + ".bat.old")
os.rename("launcher/launch.bat", "launch.bat")
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/zenith/command/CommandManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public class CommandManager {
new UnsupportedCommand(),
new ViaVersionCommand(),
new VisualRangeCommand(),
new WanderCommand(),
new WhitelistCommand()
);
private final CommandDispatcher<CommandContext> dispatcher;
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/com/zenith/command/impl/SpammerCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ public CommandUsage commandUsage() {
asList(
"on/off",
"whisper on/off",
"whilePlayerConnected on/off",
"delayTicks <int>",
"randomOrder on/off",
"appendRandom on/off",
"list",
"clear",
"add <message>",
"addAt <index> <message>",
"del <index>"),
"del <index>"
),
asList("spam")
);
}
Expand All @@ -62,6 +64,13 @@ public LiteralArgumentBuilder<CommandContext> register() {
.title("Whisper " + toggleStrCaps(CONFIG.client.extra.spammer.whisper));
return OK;
})))
.then(literal("whilePlayerConnected")
.then(argument("toggle", toggle()).executes(c -> {
CONFIG.client.extra.spammer.whilePlayerConnected = getToggle(c, "toggle");
c.getSource().getEmbed()
.title("While Player Connected " + toggleStrCaps(CONFIG.client.extra.spammer.whilePlayerConnected));
return OK;
})))
.then(literal("delayTicks")
.then(argument("delayTicks", integer(1, 10000)).executes(c -> {
CONFIG.client.extra.spammer.delayTicks = IntegerArgumentType.getInteger(c, "delayTicks");
Expand Down Expand Up @@ -140,6 +149,7 @@ public void postPopulate(final Embed builder) {
addListDescription(builder)
.addField("Spammer", toggleStr(CONFIG.client.extra.spammer.enabled), false)
.addField("Whisper", toggleStr(CONFIG.client.extra.spammer.whisper), false)
.addField("While Player Connected", toggleStr(CONFIG.client.extra.spammer.whilePlayerConnected), false)
.addField("Delay", CONFIG.client.extra.spammer.delayTicks, false)
.addField("Random Order", toggleStr(CONFIG.client.extra.spammer.randomOrder), false)
.addField("Append Random", toggleStr(CONFIG.client.extra.spammer.appendRandom), false)
Expand Down
Loading

0 comments on commit a1579cc

Please sign in to comment.