Merge branch 'rewrite/master' into bugfix/remove-kickstarter-backers

This commit is contained in:
Cameron Taylor 2024-04-16 13:33:02 -04:00
commit 2d5153cdbf
25 changed files with 749 additions and 426 deletions

135
.github/actions/setup-haxe/action.yml vendored Normal file
View file

@ -0,0 +1,135 @@
name: setup-haxeshit
description: "sets up haxe shit, using HMM!"
inputs:
haxe:
description: 'Version of haxe to install'
required: true
default: '4.3.4'
hxcpp-cache:
description: 'Whether to use a shared hxcpp compile cache'
required: true
default: 'true'
hxcpp-cache-path:
description: 'Path to create hxcpp cache in'
required: true
default: ${{ runner.temp }}/hxcpp_cache
targets:
description: 'Targets we plan to compile to. Installs native dependencies needed.'
required: true
runs:
using: "composite"
steps:
- name: Setup timers
shell: bash
run: |
echo "TIMER_HAXE=$(date +%s)" >> "$GITHUB_ENV"
- name: Install Haxe
uses: funkincrew/ci-haxe@v3.1.0
with:
haxe-version: ${{ inputs.haxe }}
- name: Install native dependencies
if: ${{ runner.os == 'Linux' }}
shell: bash
run: |
ls -lah /usr/lib/x86_64-linux-gnu/
apt-get update
apt-get install -y \
g++ \
libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev \
libgl-dev libgl1-mesa-dev \
libasound2-dev
ln -s /usr/lib/x86_64-linux-gnu/libffi.so.8 /usr/lib/x86_64-linux-gnu/libffi.so.6 || true
- name: Install linux-specific dependencies
if: ${{ runner.os == 'Linux' && contains(inputs.targets, 'linux') }}
shell: bash
run: |
apt-get install -y libvlc-dev libvlccore-dev
- name: Config haxelib
shell: bash
run: |
echo "TIMER_HAXELIB=$(date +%s)" >> "$GITHUB_ENV"
haxelib --debug --never install haxelib 4.1.0 --global
haxelib --debug --never deleterepo || true
haxelib --debug --never newrepo
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
haxelib --debug --never git haxelib https://github.com/HaxeFoundation/haxelib.git master
haxelib --debug --global install hmm
echo "TIMER_DEPS=$(date +%s)" >> "$GITHUB_ENV"
- name: Restore cached dependencies
id: cache-hmm
uses: actions/cache@v4
with:
path: .haxelib
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
- if: ${{ steps.cache-hmm.outputs.cache-hit != 'true' }}
name: Install dependencies
shell: bash
run: |
haxelib --debug --global run hmm install
echo "TIMER_DONE=$(date +%s)" >> "$GITHUB_ENV"
# by default use a shared hxcpp cache
- if: ${{ inputs.hxcpp-cache == 'true' }}
name: Restore hxcpp cache
uses: actions/cache@v4
with:
path: ${{ inputs.hxcpp-cache-path }}
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}
# export env for it to reuse in builds
- if: ${{ inputs.hxcpp-cache == 'true' }}
name: Persist env for hxcpp cache
shell: bash
run: |
echo "HXCPP_COMPILE_CACHE=${{ inputs.hxcpp-cache-path }}" >> "$GITHUB_ENV"
echo 'HXCPP_CACHE_MB="4096"' >> "$GITHUB_ENV"
# if it's explicitly disabled, still cache export/ since that then contains the builds
- if: ${{ inputs.hxcpp-cache != 'true' }}
name: Restore export cache
uses: actions/cache@v4
with:
path: ${{ inputs.hxcpp-cache-path }}
key: haxe-export-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: haxe-export-${{ runner.os }}-${{ github.ref_name }}
- name: Print debug info
shell: bash
run: |
cat << EOF
runner:
kernel: $(uname -a)
haxe:
version: $(haxe -version)
which: $(which haxe)
haxepath: $HAXEPATH
took: $((TIMER_HAXELIB - TIMER_HAXE))s
haxelib:
version: $(haxelib version)
which: $(which haxelib)
local:
config: $(haxelib config)
path: $(haxelib path haxelib || true)
global
config: $(haxelib config --global)
path: $(haxelib path haxelib --global || true)
system
version: $(haxelib --system version)
local:
config: $(haxelib --system config)
global:
config: $(haxelib --system config --global)
took: $((TIMER_DEPS - TIMER_HAXELIB))s
deps:
took: $((TIMER_DONE - TIMER_DEPS))s
hxcpp_cache: |
$(haxelib run hxcpp cache list || true)
EOF

View file

@ -1,55 +0,0 @@
name: setup-haxeshit
description: "sets up haxe shit, using HMM!"
runs:
using: "composite"
steps:
- name: Install Haxe lol
uses: funkincrew/ci-haxe@v3.1.0
with:
haxe-version: 4.3.3
- name: Config haxelib
run: |
haxelib --never install haxelib 4.1.0 --global
haxelib --never deleterepo || true
haxelib --never newrepo
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
haxelib --never git haxelib https://github.com/HaxeFoundation/haxelib.git master
shell: bash
- name: Gather debug info
run: |
cat << EOF >> "$GITHUB_STEP_SUMMARY"
## haxe
- version: \`$(haxe -version)\`
- exe: \`$(which haxe)\`
## haxelib
- version: \`$(haxelib version)\`
- exe: \`$(which haxelib)\`
- path: \`$HAXEPATH\`
### local
- config: \`$(haxelib config)\`
- path: \`$(haxelib path haxelib || true)\`
### global
- config: \`$(haxelib config --global)\`
- path: \`$(haxelib path haxelib --global || true)\`
### system
- version: \`$(haxelib --system version)\`
- local: \`$(haxelib --system config)\`
- global: \`$(haxelib --system config --global)\`
EOF
shell: bash
- name: Install hmm
# hmm only supports global installs
run: |
haxelib --global install hmm
shell: bash
- name: Restore cached dependencies
id: cache-hmm
uses: actions/cache@v4
with:
path: .haxelib
key: ${{ runner.os }}-hmm-${{ hashFiles('**/hmm.json') }}
- if: ${{ steps.cache-hmm.outputs.cache-hit != 'true' }}
name: hmm install
run: |
haxelib --global run hmm install
shell: bash

View file

@ -1,44 +1,124 @@
name: upload-itch
description: "installs Butler, and uploads to itch.io!"
inputs:
butler-key:
description: "Butler API secret key"
required: true
itch-repo:
description: "Where to upload the game to"
required: true
default: "ninja-muffin24/funkin-secret"
build-dir:
description: "Directory of the game build"
required: true
required: false
target:
description: "Target (html5, win, linux, mac)"
description: "Target (html5, windows, linux, macos)"
required: true
runs:
using: "composite"
steps:
- name: Install butler Windows
if: runner.os == 'Windows'
run: |
curl -L -o butler.zip https://broth.itch.ovh/butler/windows-amd64/LATEST/archive/default
7z x butler.zip
./butler -v
shell: bash
- name: Install butler Mac
if: runner.os == 'macOS'
run: |
curl -L -o butler.zip https://broth.itch.ovh/butler/darwin-amd64/LATEST/archive/default
unzip butler.zip
./butler -V
shell: bash
- name: Install butler Linux
if: runner.os == 'Linux'
run: |
curl -L -o butler.zip https://broth.itch.ovh/butler/linux-amd64/LATEST/archive/default
unzip butler.zip
chmod +x butler
./butler -V
shell: bash
- name: Upload game to itch.io
env:
BUTLER_API_KEY: ${{inputs.butler-key}}
run: |
./butler login
./butler push ${{inputs.build-dir}} ninja-muffin24/funkin-secret:${{inputs.target}}-${GITHUB_REF_NAME}
shell: bash
# RUNNER_OS = Windows | macOS | Linux
# TARGET_BUILD = windows | macos | linux
# TARGET_ITCH = win | macos | linux
# TARGET_BUTLER_DOWNLOAD = windows-amd64 | darwin-amd64 | linux-amd64
- name: Setup variables
shell: bash
run: |
TARGET_OS=${{ inputs.target }}
RUNNER=${RUNNER_OS@L}
TARGET=${TARGET_OS@L}
case "$TARGET" in
"windows")
TARGET_ITCH=win
;;
*)
TARGET_ITCH=$TARGET
;;
esac
case "$RUNNER" in
"macos")
OS_NODE=darwin
;;
*)
OS_NODE=$RUNNER
;;
esac
BUTLER_PATH=$RUNNER_TEMP/butler
echo BUILD_DIR="export/release/$TARGET/bin" >> "$GITHUB_ENV"
echo ITCH_TAG=${{ inputs.itch-repo }}:$TARGET_ITCH-$GITHUB_REF_NAME >> "$GITHUB_ENV"
echo OS_AND_ARCH=$OS_NODE-amd64 >> "$GITHUB_ENV"
echo BUTLER_API_KEY=${{ inputs.butler-key }} >> "$GITHUB_ENV"
echo BUTLER_INSTALL_PATH=$BUTLER_PATH >> "$GITHUB_ENV"
echo TIMER_BUTLER=$(date +%s) >> "$GITHUB_ENV"
echo TARGET_ITCH=$TARGET_ITCH >> "$GITHUB_ENV"
echo "$BUTLER_PATH" >> "$GITHUB_PATH"
- name: Get latest butler version
shell: bash
run: |
LATEST=$(curl -sfL https://broth.itch.ovh/butler/$OS_AND_ARCH/LATEST)
echo BUTLER_LATEST=$LATEST >> "$GITHUB_ENV"
command -v butler \
&& echo BUTLER_CURRENT=$(butler -V 2>&1 | cut -d ',' -f 1) >> "$GITHUB_ENV" \
|| echo BUTLER_CURRENT=none >> "$GITHUB_ENV"
- name: Try to get butler from cache
id: cache-butler
uses: actions/cache@v4
with:
path: ${{ env.BUTLER_INSTALL_PATH }}
key: butler-${{ runner.os }}-${{ env.BUTLER_LATEST }}
- if: steps.cache-butler.outputs.cache-hit == 'true'
name: Make sure butler is executable
shell: bash
run: |
chmod +x $BUTLER_INSTALL_PATH/butler
- if: steps.cache-butler.outputs.cache-hit != 'true'
name: Install butler
shell: bash
run: |
mkdir -p $BUTLER_INSTALL_PATH
cd $BUTLER_INSTALL_PATH
curl -L -o butler.zip https://broth.itch.ovh/butler/$OS_AND_ARCH/LATEST/archive/default
unzip butler.zip
chmod +x butler
- name: Upload game to itch.io
shell: bash
run: |
echo "TIMER_UPLOAD=$(date +%s)" >> "$GITHUB_ENV"
butler login
butler push $BUILD_DIR $ITCH_TAG
echo "TIMER_DONE=$(date +%s)" >> "$GITHUB_ENV"
- name: Print debug info
shell: bash
run: |
cat << EOF
butler:
version: $(
if [[ "$BUTLER_CURRENT" == "$BUTLER_LATEST" ]]
then
echo $BUTLER_CURRENT
else
echo $BUTLER_CURRENT -> $BUTLER_LATEST
fi
)
install:
took: $(($TIMER_UPLOAD-$TIMER_BUTLER))s
upload:
tag: $TARGET_ITCH/$GITHUB_REF_NAME
took: $(($TIMER_DONE-$TIMER_UPLOAD))s
EOF
cat << EOF >> "$GITHUB_STEP_SUMMARY"
### open in launcher: [$TARGET_ITCH/$GITHUB_REF_NAME](https://run.funkin.me/$TARGET_ITCH/$GITHUB_REF_NAME)
EOF

View file

@ -0,0 +1,53 @@
name: Create and publish Docker image
on:
workflow_dispatch:
push:
paths:
- '**/Dockerfile'
- '.github/workflows/build-docker-image.yml'
jobs:
build-and-push-image:
runs-on: build-set
permissions:
contents: read
packages: write
steps:
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: false
token: ${{ steps.app_token.outputs.token }}
- name: Log into GitHub Container Registry
uses: docker/login-action@v3.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5.3.0
with:
context: ./build
push: true
tags: |
ghcr.io/funkincrew/build-dependencies:latest
ghcr.io/funkincrew/build-dependencies:${{ github.sha }}
labels: |
org.opencontainers.image.description=precooked haxe build-dependencies
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.title=${{ github.repository_owner }}/build-dependencies
org.opencontainers.image.url=https://github.com/${{ github.repository }}
org.opencontainers.image.version=${{ github.sha }}

125
.github/workflows/build-game.yml vendored Normal file
View file

@ -0,0 +1,125 @@
name: Build and Upload nightly game builds
on:
workflow_dispatch:
push:
paths-ignore:
- '**/Dockerfile'
- '.github/workflows/build-docker-image.yml'
jobs:
build-game-on-host:
strategy:
matrix:
include:
- target: windows
- target: macos
runs-on:
- ${{ matrix.target }}
defaults:
run:
shell: bash
steps:
- name: Make git happy
if: ${{ matrix.target == 'macos' }}
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
- name: Setup build environment
uses: ./.github/actions/setup-haxe
- name: Build game
if: ${{ matrix.target == 'windows' }}
run: |
haxelib run lime build windows -v -release -DGITHUB_BUILD
timeout-minutes: 120
- name: Build game
if: ${{ matrix.target != 'windows' }}
run: |
haxelib run lime build ${{ matrix.target }} -v -release --times -DGITHUB_BUILD
timeout-minutes: 120
- name: Upload build artifacts
uses: ./.github/actions/upload-itch
with:
butler-key: ${{ secrets.BUTLER_API_KEY}}
target: ${{ matrix.target }}
build-game-in-container:
runs-on: build-set
container: ghcr.io/funkincrew/build-dependencies:latest
strategy:
matrix:
include:
- target: linux
- target: html5
defaults:
run:
shell: bash
steps:
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
- name: Config haxelib
run: |
haxelib --never newrepo
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
- name: Restore cached dependencies
id: cache-hmm
uses: actions/cache@v4
with:
path: .haxelib
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
- if: ${{ steps.cache-hmm.outputs.cache-hit != 'true' }}
name: Install dependencies
run: |
haxelib --global run hmm install
- if: ${{ matrix.target != 'html5' }}
name: Restore hxcpp cache
uses: actions/cache@v4
with:
path: /usr/share/hxcpp
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}
- name: Build game
run: |
haxelib run lime build ${{ matrix.target }} -v -release --times -DGITHUB_BUILD
timeout-minutes: 120
- name: Upload build artifacts
uses: ./.github/actions/upload-itch
with:
butler-key: ${{ secrets.BUTLER_API_KEY}}
target: ${{ matrix.target }}

View file

@ -1,136 +0,0 @@
name: build-upload
on:
workflow_dispatch:
push:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
create-nightly-html5:
runs-on: [self-hosted, linux]
container: ubuntu:23.10
steps:
- name: Install tools missing in container
run: |
apt update
apt install -y sudo git curl unzip
- name: Fix git config on posix runner
# this can't be {{ github.workspace }} because that's not docker-aware
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
- name: Install Haxe, dependencies
uses: ./.github/actions/setup-haxeshit
- name: Install native dependencies
run: |
apt install -y \
libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev \
libgl-dev libgl1-mesa-dev \
libasound2-dev
- name: Build game
run: |
haxelib run lime build html5 -release --times -DGITHUB_BUILD
- name: Upload build artifacts
uses: ./.github/actions/upload-itch
with:
butler-key: ${{ secrets.BUTLER_API_KEY}}
build-dir: export/release/html5/bin
target: html5
create-nightly-win:
runs-on: [self-hosted, windows]
defaults:
run:
shell: bash
steps:
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
- name: Install Haxe, dependencies
uses: ./.github/actions/setup-haxeshit
- name: Setup build cache
run: |
mkdir -p ${{ runner.temp }}/hxcpp_cache
- name: Restore build cache
id: cache-build-win
uses: actions/cache@v4
with:
path: |
export
${{ runner.temp }}/hxcpp_cache
key: ${{ runner.os }}-build-win-${{ github.ref_name }}
- name: Build game
run: |
haxelib run lime build windows -v -release -DGITHUB_BUILD
env:
HXCPP_COMPILE_CACHE: "${{ runner.temp }}\\hxcpp_cache"
- name: Upload build artifacts
uses: ./.github/actions/upload-itch
with:
butler-key: ${{ secrets.BUTLER_API_KEY }}
build-dir: export/release/windows/bin
target: win
create-nightly-mac:
runs-on: [self-hosted, macos]
steps:
- name: Fix git config on posix runner
# this can't be {{ github.workspace }} because that's not docker-aware
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Get checkout token
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PEM }}
owner: ${{ github.repository_owner }}
- name: Checkout repo
uses: funkincrew/ci-checkout@v6
with:
submodules: 'recursive'
token: ${{ steps.app_token.outputs.token }}
- name: Install Haxe, dependencies
uses: ./.github/actions/setup-haxeshit
- name: Setup build cache
run: |
mkdir -p ${{ runner.temp }}/hxcpp_cache
- name: Restore build cache
id: cache-build-win
uses: actions/cache@v4
with:
path: |
export
${{ runner.temp }}/hxcpp_cache
key: ${{ runner.os }}-build-mac-${{ github.ref_name }}
- name: Build game
run: |
haxelib run lime build macos -release --times -DGITHUB_BUILD
env:
HXCPP_COMPILE_CACHE: "${{ runner.temp }}/hxcpp_cache"
- name: Upload build artifacts
uses: ./.github/actions/upload-itch
with:
butler-key: ${{ secrets.BUTLER_API_KEY}}
build-dir: export/release/macos/bin
target: macos

View file

@ -1,35 +1,38 @@
name: cancel-merged-branches
name: Cancel queued workflows on PR merge
on:
pull_request:
types:
- closed
jobs:
cancel_stuff:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
runs-on: build-set
permissions:
actions: write
steps:
- uses: actions/github-script@v7
id: cancel-runs
with:
result-encoding: string
retries: 3
script: |
let branch_workflows = await github.rest.actions.listWorkflowRuns({
- name: Cancel queued workflows for ${{ github.event.pull_request.head.ref }}
uses: actions/github-script@v7
with:
result-encoding: string
retries: 3
script: |
let branch_workflows = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: "build-shit.yml",
status: "queued",
branch: "${{ github.event.pull_request.head.ref }}"
});
let runs = branch_workflows.data.workflow_runs;
runs.forEach((run) => {
github.rest.actions.cancelWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: "build-shit.yml",
status: "queued",
branch: "${{ github.event.pull_request.head.ref }}"
run_id: run.id
});
let runs = branch_workflows.data.workflow_runs;
runs.forEach((run) => {
github.rest.actions.cancelWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: run.id
});
});
console.log(runs);
});
console.log(runs);

10
.vscode/settings.json vendored
View file

@ -96,6 +96,11 @@
"target": "windows",
"args": ["-debug", "-DFORCE_DEBUG_VERSION"]
},
{
"label": "Linux / Debug",
"target": "linux",
"args": ["-debug", "-DFORCE_DEBUG_VERSION"]
},
{
"label": "HashLink / Debug",
"target": "hl",
@ -130,6 +135,11 @@
"-DFORCE_DEBUG_VERSION"
]
},
{
"label": "Windows / Debug (Straight to Play - 2hot)",
"target": "windows",
"args": ["-debug", "-DSONG=2hot", "-DFORCE_DEBUG_VERSION"]
},
{
"label": "HashLink / Debug (Straight to Play - Bopeebo Normal)",
"target": "hl",

View file

@ -45,6 +45,7 @@
<library name="week6" preload="true" />
<library name="week7" preload="true" />
<library name="weekend1" preload="true" />
<library name="videos" preload="true" />
</section>
<section if="NO_PRELOAD_ALL">
<library name="songs" preload="false" />
@ -58,10 +59,13 @@
<library name="week6" preload="false" />
<library name="week7" preload="false" />
<library name="weekend1" preload="false" />
<library name="videos" preload="false" />
</section>
<library name="art" preload="false" />
<assets path="assets/songs" library="songs" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/songs" library="songs" exclude="*.fla|*.mp3|*.wav" unless="web" />
<!-- Videos go in their own library because web never needs to preload them, they can just be streamed. -->
<assets path="assets/videos" library="videos" />
<assets path="assets/shared" library="shared" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/shared" library="shared" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.ogg|*.wav" if="web" />

2
assets

@ -1 +1 @@
Subproject commit 40d946207aa14b996b152800f285f94b7a679ba4
Subproject commit 1b12b6c6666af6c84addf5aa0795546aa0d04185

185
build/Dockerfile Normal file
View file

@ -0,0 +1,185 @@
FROM ubuntu:mantic
ARG haxe_version=4.3.4
ARG haxelib_version=4.1.0
ARG neko_version=2.3.0
# prepare runner
ENV GITHUB_HOME="/github/home"
RUN <<EOF
mkdir -p "$GITHUB_HOME"
mkdir -p /opt
mkdir -p /usr/share/hxcpp
mkdir -p /usr/local/bin
chmod -R 777 /opt
chmod -R 777 /usr/share
chmod -R 777 /usr/local/bin
EOF
# Prepare Ubuntu
# https://github.com/actions/runner-images/blob/main/images/ubuntu/scripts/build/configure-environment.sh
# https://github.com/actions/runner-images/blob/main/images/ubuntu/scripts/build/configure-system.sh
RUN <<EOF
echo 'vm.max_map_count=262144' | tee -a /etc/sysctl.conf
echo 'fs.inotify.max_user_watches=655360' | tee -a /etc/sysctl.conf
echo 'fs.inotify.max_user_instances=1280' | tee -a /etc/sysctl.conf
EOF
ENV DEBIAN_FRONTEND="noninteractive"
# Prepare APT
RUN <<EOF
cat <<EOC >> /etc/apt/apt.conf.d/10apt-autoremove
APT::Get::AutomaticRemove "0";
APT::Get::HideAutoRemove "1";
EOC
echo <<EOC >> /etc/apt/apt.conf.d/80retries
"APT::Acquire::Retries \"10\";"
EOC
echo <<EOC >> /etc/apt/apt.conf.d/90assumeyes
"APT::Get::Assume-Yes \"true\";"
EOC
EOF
# Prepare apt-fast
RUN <<EOF
apt-get update
apt-get install -y --no-install-recommends software-properties-common
add-apt-repository -y ppa:apt-fast/stable
apt-get -y install apt-fast
echo debconf apt-fast/maxdownloads string 8 | debconf-set-selections
echo debconf apt-fast/dlflag boolean true | debconf-set-selections
echo debconf apt-fast/aptmanager string apt-get | debconf-set-selections
EOF
# Base packages
# https://github.com/actions/runner-images/blob/main/images/ubuntu/toolsets/toolset-2204.json#L114
RUN <<EOF
apt-fast install -y --no-install-recommends \
ca-certificates \
bzip2 curl g++ gcc make jq tar unzip wget \
sudo git openssh-client
EOF
# Prepare git
RUN <<EOF
cat <<EOC >> /etc/gitconfig
[safe]
directory = *
EOC
ssh-keyscan -t rsa,ecdsa,ed25519 github.com >> /etc/ssh/ssh_known_hosts
ssh-keyscan -t rsa,ecdsa,ed25519 ravy.dev >> /etc/ssh/ssh_known_hosts
EOF
# Haxe native dependencies
RUN <<EOF
apt-fast install -y --no-install-recommends \
libc6-dev libffi-dev \
libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev \
libgl-dev libgl1-mesa-dev \
libasound2-dev \
libvlc-dev libvlccore-dev
EOF
# Janky libffi.6 fix
RUN <<EOF
ln -s \
/usr/lib/x86_64-linux-gnu/libffi.so.8 \
/usr/lib/x86_64-linux-gnu/libffi.so.6 \
|| true
EOF
# neko
# https://github.com/HaxeFoundation/neko/releases/download/v2-3-0/neko-2.3.0-linux64.tar.gz
RUN <<EOF
neko_url=$(curl https://api.github.com/repos/HaxeFoundation/neko/releases -sfL \
| jq '.[] | select(.name == "'"$neko_version"'")' \
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
| jq -r '.browser_download_url')
curl -sfL "$neko_url" | tar -xz -C /usr/local
EOF
RUN <<EOF
neko_path="$(find /usr/local -maxdepth 1 -type d -name 'neko*')"
ln -s "$neko_path" /usr/local/neko
EOF
ENV NEKOPATH="/usr/local/neko"
ENV LD_LIBRARY_PATH="$NEKOPATH:$LD_LIBRARY_PATH"
ENV PATH="$NEKOPATH:$PATH"
# haxe
# https://github.com/HaxeFoundation/haxe/releases/download/4.0.5/haxe-4.0.5-linux64.tar.gz
RUN <<EOF
haxe_url=$(curl https://api.github.com/repos/HaxeFoundation/haxe/releases -sfL \
| jq '.[] | select(.name == "'"$haxe_version"'")' \
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
| jq -r '.browser_download_url')
curl -sfL "$haxe_url" | tar -xz -C /usr/local
EOF
RUN <<EOF
haxe_path="$(find /usr/local -maxdepth 1 -type d -name 'haxe*')"
ln -s "$haxe_path" /usr/local/haxe
EOF
ENV HAXEPATH="/usr/local/haxe"
ENV HAXE_STD_PATH="$HAXEPATH/std"
ENV PATH="$HAXEPATH:$PATH"
# haxelib
RUN <<EOF
HOME=/etc haxelib setup "$HAXEPATH/lib"
haxelib --global --never install haxelib $haxelib_version
haxelib --global --never git haxelib https://github.com/HaxeFoundation/haxelib.git master
haxelib --global --never install hmm
EOF
# hxcpp
ENV HXCPP_COMPILE_CACHE="/usr/share/hxcpp"
ENV HXCPP_CACHE_MB="4096"
# Clean up
# https://github.com/actions/runner-images/blob/main/images/ubuntu/scripts/build/cleanup.sh
RUN <<EOF
rm -r /var/cache/apt/apt-fast
apt-get clean
if [ -d /var/lib/apt/lists ]; then
rm -rf /var/lib/apt/lists/*
fi
if [ -d /tmp ]; then
rm -rf /tmp/*
fi
if [ -d /root/.cache ]; then
rm -rf /root/.cache
fi
if command -v journalctl; then
journalctl --rotate
journalctl --vacuum-time=1s
fi
if [ -d /var/log ]; then
find /var/log -type f -regex ".*\.gz$" -delete
find /var/log -type f -regex ".*\.[0-9]$" -delete
find /var/log/ -type f -exec cp /dev/null {} \;
fi
if [ -f /usr/local/bin/invoke_tests ]; then
rm -rf /usr/local/bin/invoke_tests
fi
EOF
# Print debug info
RUN <<EOF
echo "/root"
ls -la /root
cat /root/.haxelib && echo
id
env
EOF

View file

@ -104,7 +104,7 @@
"name": "lime",
"type": "git",
"dir": null,
"ref": "1359fe6ad52e91175dc636a516d460bd54ea22ed",
"ref": "43ebebdd8119936b99f23407057025c7849c5f5b",
"url": "https://github.com/FunkinCrew/lime"
},
{

View file

@ -261,6 +261,35 @@ class InitState extends FlxState
return;
}
// TODO: Rework loading behavior so we don't have to do this.
switch (songId)
{
case 'tutorial' | 'bopeebo' | 'fresh' | 'dadbattle':
Paths.setCurrentLevel('week1');
PlayStatePlaylist.campaignId = 'week1';
case 'spookeez' | 'south' | 'monster':
Paths.setCurrentLevel('week2');
PlayStatePlaylist.campaignId = 'week2';
case 'pico' | 'philly-nice' | 'blammed':
Paths.setCurrentLevel('week3');
PlayStatePlaylist.campaignId = 'week3';
case 'high' | 'satin-panties' | 'milf':
Paths.setCurrentLevel('week4');
PlayStatePlaylist.campaignId = 'week4';
case 'cocoa' | 'eggnog' | 'winter-horrorland':
Paths.setCurrentLevel('week5');
PlayStatePlaylist.campaignId = 'week5';
case 'senpai' | 'roses' | 'thorns':
Paths.setCurrentLevel('week6');
PlayStatePlaylist.campaignId = 'week6';
case 'ugh' | 'guns' | 'stress':
Paths.setCurrentLevel('week7');
PlayStatePlaylist.campaignId = 'week7';
case 'darnell' | 'lit-up' | '2hot' | 'blazin':
Paths.setCurrentLevel('weekend1');
PlayStatePlaylist.campaignId = 'weekend1';
}
LoadingState.loadPlayState(
{
targetSong: songData,
@ -283,6 +312,10 @@ class InitState extends FlxState
return;
}
// TODO: Rework loading behavior so we don't have to do this.
Paths.setCurrentLevel(levelId);
PlayStatePlaylist.campaignId = levelId;
PlayStatePlaylist.playlistSongIds = currentLevel.getSongs();
PlayStatePlaylist.isStoryMode = true;
PlayStatePlaylist.campaignScore = 0;

View file

@ -113,7 +113,7 @@ class Paths
public static function videos(key:String, ?library:String):String
{
return getPath('videos/$key.${Constants.EXT_VIDEO}', BINARY, library);
return getPath('videos/$key.${Constants.EXT_VIDEO}', BINARY, library ?? 'videos');
}
public static function voices(song:String, ?suffix:String = ''):String

View file

@ -240,8 +240,8 @@ class PolymodHandler
{
return {
assetLibraryPaths: [
'default' => 'preload', 'shared' => 'shared', 'songs' => 'songs', 'tutorial' => 'tutorial', 'week1' => 'week1', 'week2' => 'week2',
'week3' => 'week3', 'week4' => 'week4', 'week5' => 'week5', 'week6' => 'week6', 'week7' => 'week7', 'weekend1' => 'weekend1',
'default' => 'preload', 'shared' => 'shared', 'songs' => 'songs', 'videos' => 'videos', 'tutorial' => 'tutorial', 'week1' => 'week1',
'week2' => 'week2', 'week3' => 'week3', 'week4' => 'week4', 'week5' => 'week5', 'week6' => 'week6', 'week7' => 'week7', 'weekend1' => 'weekend1',
],
coreAssetRedirect: CORE_FOLDER,
}

View file

@ -2388,13 +2388,6 @@ class PlayState extends MusicBeatSubState
// Display the combo meter and add the calculation to the score.
popUpScore(note, event.score, event.judgement, event.healthChange);
if (note.isHoldNote && note.holdNoteSprite != null)
{
playerStrumline.playNoteHoldCover(note.holdNoteSprite);
}
vocals.playerVolume = 1;
}
/**
@ -2676,6 +2669,13 @@ class PlayState extends MusicBeatSubState
}
comboPopUps.displayRating(daRating);
if (Highscore.tallies.combo >= 10 || Highscore.tallies.combo == 0) comboPopUps.displayCombo(Highscore.tallies.combo);
if (daNote.isHoldNote && daNote.holdNoteSprite != null)
{
playerStrumline.playNoteHoldCover(daNote.holdNoteSprite);
}
vocals.playerVolume = 1;
}
/**
@ -2786,7 +2786,7 @@ class PlayState extends MusicBeatSubState
// adds current song data into the tallies for the level (story levels)
Highscore.talliesLevel = Highscore.combineTallies(Highscore.tallies, Highscore.talliesLevel);
if (Save.instance.isSongHighScore(currentSong.id, currentDifficulty, data))
if (!isPracticeMode && !isBotPlayMode && Save.instance.isSongHighScore(currentSong.id, currentDifficulty, data))
{
Save.instance.setSongScore(currentSong.id, currentDifficulty, data);
#if newgrounds
@ -3072,18 +3072,18 @@ class PlayState extends MusicBeatSubState
title: PlayStatePlaylist.isStoryMode ? ('${PlayStatePlaylist.campaignTitle}') : ('${currentChart.songName} by ${currentChart.songArtist}'),
scoreData:
{
score: songScore,
score: PlayStatePlaylist.isStoryMode ? PlayStatePlaylist.campaignScore : songScore,
tallies:
{
sick: Highscore.tallies.sick,
good: Highscore.tallies.good,
bad: Highscore.tallies.bad,
shit: Highscore.tallies.shit,
missed: Highscore.tallies.missed,
combo: Highscore.tallies.combo,
maxCombo: Highscore.tallies.maxCombo,
totalNotesHit: Highscore.tallies.totalNotesHit,
totalNotes: Highscore.tallies.totalNotes,
sick: talliesToUse.sick,
good: talliesToUse.good,
bad: talliesToUse.bad,
shit: talliesToUse.shit,
missed: talliesToUse.missed,
combo: talliesToUse.combo,
maxCombo: talliesToUse.maxCombo,
totalNotesHit: talliesToUse.totalNotesHit,
totalNotes: talliesToUse.totalNotes,
},
accuracy: Highscore.tallies.totalNotesHit / Highscore.tallies.totalNotes,
},

View file

@ -67,8 +67,13 @@ class VideoCutscene
if (!openfl.Assets.exists(filePath))
{
// Display a popup.
lime.app.Application.current.window.alert('Video file does not exist: ${filePath}', 'Error playing video');
return;
// lime.app.Application.current.window.alert('Video file does not exist: ${filePath}', 'Error playing video');
// return;
// TODO: After moving videos to their own library,
// this function ALWAYS FAILS on web, but the video still plays.
// I think that's due to a weird quirk with how OpenFL libraries work.
trace('Video file does not exist: ${filePath}');
}
var rawFilePath = Paths.stripLibrary(filePath);

View file

@ -693,7 +693,7 @@ class Save
trace("[SAVE] Checking for legacy save data...");
var legacySave:FlxSave = new FlxSave();
legacySave.bind(SAVE_NAME_LEGACY, SAVE_PATH_LEGACY);
if (legacySave?.data == null)
if (legacySave.isEmpty())
{
trace("[SAVE] No legacy save data found.");
return null;

View file

@ -95,12 +95,19 @@ class CreditsDataHandler
static function fetchCreditsData():funkin.data.JsonFile
{
#if !macro
var rawJson:String = openfl.Assets.getText(CREDITS_DATA_PATH).trim();
return {
fileName: CREDITS_DATA_PATH,
contents: rawJson
};
#else
return {
fileName: CREDITS_DATA_PATH,
contents: null
};
#end
}
static function parseCreditsData(file:JsonFile):Null<CreditsData>

View file

@ -117,12 +117,6 @@ class ChartEditorNoteSprite extends FlxSprite
{
noteFrameCollection.pushFrame(frame);
}
var frameCollectionNormal2:FlxAtlasFrames = Paths.getSparrowAtlas('NoteHoldNormal');
for (frame in frameCollectionNormal2.frames)
{
noteFrameCollection.pushFrame(frame);
}
// Pixel notes
var graphicPixel = FlxG.bitmap.add(Paths.image('weeb/pixelUI/arrows-pixels', 'week6'), false, null);

View file

@ -37,8 +37,8 @@ class AlbumRoll extends FlxSpriteGroup
}
var newAlbumArt:FlxAtlasSprite;
var difficultyStars:DifficultyStars;
// var difficultyStars:DifficultyStars;
var _exitMovers:Null<FreeplayState.ExitMoverData>;
var albumData:Album;
@ -65,9 +65,9 @@ class AlbumRoll extends FlxSpriteGroup
add(newAlbumArt);
difficultyStars = new DifficultyStars(140, 39);
difficultyStars.stars.visible = false;
add(difficultyStars);
// difficultyStars = new DifficultyStars(140, 39);
// difficultyStars.stars.visible = false;
// add(difficultyStars);
}
function onAlbumFinish(animName:String):Void
@ -86,7 +86,7 @@ class AlbumRoll extends FlxSpriteGroup
{
if (albumId == null)
{
difficultyStars.stars.visible = false;
// difficultyStars.stars.visible = false;
return;
}
@ -132,13 +132,6 @@ class AlbumRoll extends FlxSpriteGroup
speed: 0.4,
wait: 0
});
exitMovers.set([difficultyStars],
{
x: FlxG.width * 1.2,
speed: 0.2,
wait: 0.3
});
}
var titleTimer:Null<FlxTimer> = null;
@ -151,10 +144,10 @@ class AlbumRoll extends FlxSpriteGroup
newAlbumArt.visible = true;
newAlbumArt.playAnimation(animNames.get('$albumId-active'), false, false, false);
difficultyStars.stars.visible = false;
// difficultyStars.stars.visible = false;
new FlxTimer().start(0.75, function(_) {
// showTitle();
showStars();
// showStars();
});
}
@ -163,18 +156,16 @@ class AlbumRoll extends FlxSpriteGroup
newAlbumArt.playAnimation(animNames.get('$albumId-trans'), false, false, false);
}
public function setDifficultyStars(?difficulty:Int):Void
{
if (difficulty == null) return;
difficultyStars.difficulty = difficulty;
}
/**
* Make the album stars visible.
*/
public function showStars():Void
{
difficultyStars.stars.visible = false; // true;
}
// public function setDifficultyStars(?difficulty:Int):Void
// {
// if (difficulty == null) return;
// difficultyStars.difficulty = difficulty;
// }
// /**
// * Make the album stars visible.
// */
// public function showStars():Void
// {
// difficultyStars.stars.visible = false; // true;
// }
}

View file

@ -1,106 +0,0 @@
package funkin.ui.freeplay;
import flixel.group.FlxSpriteGroup;
import funkin.graphics.adobeanimate.FlxAtlasSprite;
import funkin.graphics.shaders.HSVShader;
class DifficultyStars extends FlxSpriteGroup
{
/**
* Internal handler var for difficulty... ranges from 0... to 15
* 0 is 1 star... 15 is 0 stars!
*/
var curDifficulty(default, set):Int = 0;
/**
* Range between 0 and 15
*/
public var difficulty(default, set):Int = 1;
public var stars:FlxAtlasSprite;
var flames:FreeplayFlames;
var hsvShader:HSVShader;
public function new(x:Float, y:Float)
{
super(x, y);
hsvShader = new HSVShader();
flames = new FreeplayFlames(0, 0);
add(flames);
stars = new FlxAtlasSprite(0, 0, Paths.animateAtlas("freeplay/freeplayStars"));
stars.anim.play("diff stars");
add(stars);
stars.shader = hsvShader;
for (memb in flames.members)
memb.shader = hsvShader;
}
override function update(elapsed:Float):Void
{
super.update(elapsed);
// "loops" the current animation
// for clarity, the animation file looks like
// frame : stars
// 0-99: 1 star
// 100-199: 2 stars
// ......
// 1300-1499: 15 stars
// 1500 : 0 stars
if (curDifficulty < 15 && stars.anim.curFrame >= (curDifficulty + 1) * 100)
{
stars.anim.play("diff stars", true, false, curDifficulty * 100);
}
}
function set_difficulty(value:Int):Int
{
difficulty = value;
if (difficulty <= 0)
{
difficulty = 0;
curDifficulty = 15;
}
else if (difficulty <= 15)
{
difficulty = value;
curDifficulty = difficulty - 1;
}
else
{
difficulty = 15;
curDifficulty = difficulty - 1;
}
if (difficulty > 10) flames.flameCount = difficulty - 10;
else
flames.flameCount = 0;
return difficulty;
}
function set_curDifficulty(value:Int):Int
{
curDifficulty = value;
if (curDifficulty == 15)
{
stars.anim.play("diff stars", true, false, 1500);
stars.anim.pause();
}
else
{
stars.anim.curFrame = Std.int(curDifficulty * 100);
stars.anim.play("diff stars", true, false, curDifficulty * 100);
}
return curDifficulty;
}
}

View file

@ -469,6 +469,10 @@ class FreeplayState extends MusicBeatSubState
albumRoll.playIntro();
new FlxTimer().start(0.75, function(_) {
// albumRoll.showTitle();
});
FlxTween.tween(grpDifficulties, {x: 90}, 0.6, {ease: FlxEase.quartOut});
var diffSelLeft:DifficultySelector = new DifficultySelector(20, grpDifficulties.y - 10, false, controls);
@ -634,14 +638,7 @@ class FreeplayState extends MusicBeatSubState
funnyMenu.favIcon.visible = tempSongs[i].isFav;
funnyMenu.hsvShader = hsvShader;
if (i < 8)
{
funnyMenu.initJumpIn(Math.min(i, 4), force);
}
else
{
funnyMenu.forcePosition();
}
funnyMenu.forcePosition();
grpCapsules.add(funnyMenu);
}
@ -1039,9 +1036,6 @@ class FreeplayState extends MusicBeatSubState
}
}
// Set the difficulty star count on the right.
albumRoll.setDifficultyStars(daSong?.songRating);
// Set the album graphic and play the animation if relevant.
var newAlbumId:String = daSong?.albumId;
if (albumRoll.albumId != newAlbumId)
@ -1161,10 +1155,6 @@ class FreeplayState extends MusicBeatSubState
{
currentDifficulty = rememberedDifficulty;
}
// Set the difficulty star count on the right.
var daSong:Null<FreeplaySongData> = grpCapsules.members[curSelected]?.songData;
albumRoll.setDifficultyStars(daSong?.songRating ?? 0);
}
function changeSelection(change:Int = 0):Void

View file

@ -1,5 +1,6 @@
package funkin.ui.mainmenu;
import funkin.graphics.FunkinSprite;
import flixel.addons.transition.FlxTransitionableState;
import funkin.ui.debug.DebugMenuSubState;
import flixel.FlxObject;
@ -56,7 +57,12 @@ class MainMenuState extends MusicBeatState
persistentUpdate = false;
persistentDraw = true;
var bg:FlxSprite = new FlxSprite(Paths.image('menuBG'));
var bg = FunkinSprite.create('menuDesat');
bg.color = 0xFFFDE871;
// This line accounts for the fact that the base color of menuDesat is #EFEFEF.
flixel.util.FlxColorTransformUtil.setOffsets(bg.colorTransform, 30, 27, 13, 0.0);
bg.scrollFactor.x = 0;
bg.scrollFactor.y = 0.17;
bg.setGraphicSize(Std.int(bg.width * 1.2));

View file

@ -281,7 +281,6 @@ class LoadingState extends MusicBeatSubState
{
// TODO: This section is a hack! Redo this later when we have a proper asset caching system.
FunkinSprite.preparePurgeCache();
FunkinSprite.cacheTexture(Paths.image('combo'));
FunkinSprite.cacheTexture(Paths.image('healthBar'));
FunkinSprite.cacheTexture(Paths.image('menuDesat'));
FunkinSprite.cacheTexture(Paths.image('combo'));