Skip to content

Commit 7c7dc99

Browse files
Merge branch 'dev' into no-arh-or-debug-map-portrait-reload
2 parents 220bce7 + 2ae1df7 commit 7c7dc99

File tree

22 files changed

+855
-147
lines changed

22 files changed

+855
-147
lines changed

.azure-pipelines/prebuild.ps1

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
# Make the Everest version match the build number.
22
$BuildNumber = [string]([int]$env:BUILD_BUILDID + [int]$env:BUILD_BUILDIDOFFSET)
33
$EverestPath = [io.path]::combine($env:BUILD_SOURCESDIRECTORY, 'Celeste.Mod.mm', 'Mod', 'Everest', 'Everest.cs')
4-
(Get-Content $EverestPath) -replace '(?<=public readonly static string VersionString = ")[^"]*', "1.$BuildNumber.0-azure-$(($env:BUILD_SOURCEVERSION).Substring(0, 5))" | Set-Content $EverestPath
4+
# Get the branch name from Azure Pipelines
5+
if ($env:SYSTEM_PULLREQUEST_PULLREQUESTID -ne $null) {
6+
# Build triggered by a PR
7+
$BranchName = "pr$env:SYSTEM_PULLREQUEST_PULLREQUESTNUMBER"
8+
} else {
9+
# Build triggered by a regular push
10+
$BranchName = $env:BUILD_SOURCEBRANCHNAME
11+
}
12+
# Compose the version string with branch info
13+
$SourceVersionShort = $env:BUILD_SOURCEVERSION.Substring(0, 5)
14+
$VersionString = "1.$BuildNumber.0-azure-$SourceVersionShort-$BranchName"
15+
16+
# Set Version String
17+
(Get-Content $EverestPath) -replace '(?<=public readonly static string VersionString = ")[^"]*', $VersionString | Set-Content $EverestPath
518

619
# Currently unstable/in development
720
$HelperPath = [io.path]::combine($env:BUILD_SOURCESDIRECTORY, 'Celeste.Mod.mm', 'Mod', 'Helpers', 'EverestVersion.cs')

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "daily"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
# Waits for Azure to be finished building, and writes the download link to /tmp/everest-pr-tas-check/download-link.txt.
3+
# Parameter: commit SHA
4+
5+
set -xeo pipefail
6+
7+
get_build_id() {
8+
curl 'https://dev.azure.com/EverestAPI/Everest/_apis/build/builds?definitions=3&statusFilter=completed' \
9+
| jq -r ".value | map(select(.sourceVersion == \"${1}\")) | .[].id"
10+
}
11+
12+
BUILD_ID=`get_build_id "$1"`
13+
while [ "${BUILD_ID}" == "" ]; do
14+
sleep 60
15+
BUILD_ID=`get_build_id "$1"`
16+
done
17+
18+
mkdir -p /tmp/everest-pr-tas-check
19+
echo -n "https://dev.azure.com/EverestAPI/Everest/_apis/build/builds/${BUILD_ID}/artifacts?artifactName=main&api-version=5.0&%24format=zip" > /tmp/everest-pr-tas-check/download-link.txt

.github/tas-check/2-1-install.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
# Installs Everest from the branch to test, CelesteTAS and the mod that is going to be TASed.
3+
# Parameters: URL of the TAS files, URL of the mod bundle
4+
5+
set -xeo pipefail
6+
7+
docker build \
8+
--build-arg "MAIN_BUILD_URL=`cat /tmp/everest-pr-tas-check/download-link.txt`" \
9+
--build-arg "TAS_FILES_URL=$1" \
10+
--build-arg "BUNDLE_DOWNLOAD_URL=$2" \
11+
-t celeste .
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
# Installs Everest from the branch to test, CelesteTAS and the mod that is going to be TASed.
3+
# Run from within the Docker image, where Celeste is installed at /home/ubuntu/celeste.
4+
5+
set -xeo pipefail
6+
7+
# download Everest
8+
cd /home/ubuntu
9+
curl --fail -Lo everest.zip "${MAIN_BUILD_URL}"
10+
unzip everest.zip
11+
rm -v everest.zip
12+
13+
# copy Everest files to Celeste install
14+
mv -fv main/* celeste/
15+
rm -rfv main
16+
17+
# install Everest in headless mode
18+
cd celeste
19+
chmod -v u+x MiniInstaller-linux
20+
./MiniInstaller-linux headless
21+
22+
# download TAS files
23+
cd ..
24+
curl --fail -Lo t.zip "${TAS_FILES_URL}"
25+
unzip t.zip
26+
rm -v t.zip
27+
28+
# install CelesteTAS
29+
cd celeste/Mods
30+
curl --fail -Lo CelesteTAS.zip "https://github.com/EverestAPI/CelesteTAS-EverestInterop/releases/download/v3.45.1/CelesteTAS.zip"
31+
32+
# install the mod that is going to be TASed, downloaded as a bundle zip containing the mod zip
33+
# and all of its dependencies (https://maddie480.ovh/celeste/bundle-download?id=${TAS_TO_RUN})
34+
if ! [ "${BUNDLE_DOWNLOAD_URL}" == "" ]; then
35+
curl --fail -Lo t.zip "${BUNDLE_DOWNLOAD_URL}"
36+
unzip t.zip
37+
rm -v t.zip
38+
fi

.github/tas-check/3-run.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
# Runs the requested TAS and checks the result.
3+
# Parameter: path of the TAS to run
4+
5+
set -xeo pipefail
6+
7+
docker run \
8+
--volume "/tmp/everest-pr-tas-check:/home/ubuntu/tas" \
9+
--rm \
10+
--name celeste celeste \
11+
--sync-check-file "/home/ubuntu/$1" \
12+
--sync-check-result /home/ubuntu/tas/result.json
13+
14+
[ "`jq -r '.entries[].status' /tmp/everest-pr-tas-check/result.json`" == "success" ]

.github/tas-check/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM max480/everest:vanilla
2+
3+
ARG MAIN_BUILD_URL TAS_FILES_URL BUNDLE_DOWNLOAD_URL
4+
COPY 2-2-install-inner.sh /tmp
5+
RUN /tmp/2-2-install-inner.sh && rm /tmp/2-2-install-inner.sh

.github/tas-check/run-locally.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/bash
2+
# Builds and runs the TAS locally, calling the same scripts as the pipeline in order to test them.
3+
# Requires Docker and jq.
4+
5+
if [ "$1" == "" ] || [ "$2" == "" ]; then
6+
echo "Usage: ./run-locally.sh [Celeste|StrawberryJam2021] [commit SHA]"
7+
exit 1
8+
fi
9+
10+
set -xeo pipefail
11+
12+
case "$1" in
13+
"Celeste")
14+
TAS_URL="https://github.com/VampireFlower/CelesteTAS/archive/60b1680e61e43ec4681d7c9053d249491e0fe905.zip"
15+
TAS_PATH="CelesteTAS-60b1680e61e43ec4681d7c9053d249491e0fe905/0 - 100%.tas"
16+
;;
17+
18+
"StrawberryJam2021")
19+
TAS_URL="https://github.com/VampireFlower/StrawberryJamTAS/archive/c9c589a8ef225def5aca869cc1ed3eedf588ec14.zip"
20+
TAS_PATH="StrawberryJamTAS-c9c589a8ef225def5aca869cc1ed3eedf588ec14/0-SJ All Levels.tas"
21+
BUNDLE_DOWNLOAD="https://celestemodupdater.0x0a.de/pinned-mods/StrawberryJam2021-Bundle-134df0f4.zip"
22+
;;
23+
24+
*)
25+
echo "Unknown TAS: $1"
26+
exit 1
27+
esac
28+
29+
cd "`dirname "$0"`"
30+
./1-get-build-url.sh "$2"
31+
./2-1-install.sh "${TAS_URL}" "${BUNDLE_DOWNLOAD}"
32+
./3-run.sh "${TAS_PATH}"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: TAS Sync Check
2+
3+
on:
4+
pull_request:
5+
branches: [dev]
6+
7+
jobs:
8+
check:
9+
strategy:
10+
matrix:
11+
tas:
12+
- name: Celeste 100%
13+
url: "https://github.com/VampireFlower/CelesteTAS/archive/60b1680e61e43ec4681d7c9053d249491e0fe905.zip"
14+
path: "CelesteTAS-60b1680e61e43ec4681d7c9053d249491e0fe905/0 - 100%.tas"
15+
16+
- name: Strawberry Jam All Levels
17+
url: "https://github.com/VampireFlower/StrawberryJamTAS/archive/c9c589a8ef225def5aca869cc1ed3eedf588ec14.zip"
18+
path: "StrawberryJamTAS-c9c589a8ef225def5aca869cc1ed3eedf588ec14/0-SJ All Levels.tas"
19+
bundle: "https://celestemodupdater.0x0a.de/pinned-mods/StrawberryJam2021-Bundle-134df0f4.zip"
20+
21+
runs-on: ubuntu-latest
22+
timeout-minutes: 60
23+
name: ${{ matrix.tas.name }}
24+
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- name: Set up Docker Buildx
29+
uses: docker/setup-buildx-action@v3
30+
31+
- name: Wait for Azure build on commit ${{ github.sha }}
32+
run: cd .github/tas-check && ./1-get-build-url.sh "${{ github.sha }}"
33+
34+
- name: Install Everest and required mods
35+
run: cd .github/tas-check && ./2-1-install.sh "${{ matrix.tas.url }}" "${{ matrix.tas.bundle }}"
36+
37+
- name: Run TAS at ${{ matrix.tas.path }}
38+
run: cd .github/tas-check && ./3-run.sh "${{ matrix.tas.path }}"

Celeste.Mod.mm/Mod/Everest/Everest.Loader.cs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
using Celeste.Mod.Backdrops;
1+
using Celeste.Mod.Backdrops;
22
using Celeste.Mod.Core;
33
using Celeste.Mod.Entities;
44
using Celeste.Mod.Helpers;
5+
using Celeste.Mod.Registry;
56
using MAB.DotIgnore;
67
using Microsoft.Xna.Framework;
78
using Monocle;
@@ -208,6 +209,7 @@ internal static void LoadAuto() {
208209

209210
watch.Stop();
210211
Logger.Verbose("loader", $"ALL MODS LOADED IN {watch.ElapsedMilliseconds}ms");
212+
Logger.Info("loader", $"Loaded {Everest._Modules.Count} modules");
211213

212214
try {
213215
Watcher = new FileSystemWatcher {
@@ -609,36 +611,68 @@ internal static void ProcessAssembly(EverestModuleMetadata meta, Assembly asm, T
609611

610612
patch_Level.EntityLoader loader = null;
611613

612-
ConstructorInfo ctor;
614+
ConstructorInfo ctor = null;
613615
MethodInfo gen;
614616

615617
gen = type.GetMethod(genName, new Type[] { typeof(Level), typeof(LevelData), typeof(Vector2), typeof(EntityData) });
616618
if (gen != null && gen.IsStatic && gen.ReturnType.IsCompatible(typeof(Entity))) {
617-
loader = (level, levelData, offset, entityData) => (Entity) gen.Invoke(null, new object[] { level, levelData, offset, entityData });
619+
loader = (level, levelData, offset, entityData) => {
620+
var entityId = ((patch_Level)level).CreateEntityId(levelData, entityData);
621+
var entity = (patch_Entity) gen.Invoke(null, new object[] { level, levelData, offset, entityData });
622+
if (entity != null) {
623+
entity.SourceData = entityData;
624+
entity.SourceId = entityId;
625+
}
626+
627+
return entity;
628+
};
618629
goto RegisterEntityLoader;
619630
}
620631

621632
ctor = type.GetConstructor(new Type[] { typeof(EntityData), typeof(Vector2), typeof(EntityID) });
622633
if (ctor != null) {
623-
loader = (level, levelData, offset, entityData) => (Entity) ctor.Invoke(new object[] { entityData, offset, new EntityID(levelData.Name, entityData.ID + (patch_Level._isLoadingTriggers ? 10000000 : 0)) });
634+
loader = (level, levelData, offset, entityData) => {
635+
var entityId = ((patch_Level)level).CreateEntityId(levelData, entityData);
636+
var entity = (patch_Entity) ctor.Invoke(new object[] { entityData, offset, entityId });
637+
entity.SourceData = entityData;
638+
entity.SourceId = entityId;
639+
640+
return entity;
641+
};
624642
goto RegisterEntityLoader;
625643
}
626644

627645
ctor = type.GetConstructor(new Type[] { typeof(EntityData), typeof(Vector2) });
628646
if (ctor != null) {
629-
loader = (level, levelData, offset, entityData) => (Entity) ctor.Invoke(new object[] { entityData, offset });
647+
loader = (level, levelData, offset, entityData) => {
648+
var entity = (patch_Entity)ctor.Invoke(new object[] { entityData, offset });
649+
entity.SourceData = entityData;
650+
entity.SourceId = ((patch_Level)level).CreateEntityId(levelData, entityData);
651+
652+
return entity;
653+
};
630654
goto RegisterEntityLoader;
631655
}
632656

633657
ctor = type.GetConstructor(new Type[] { typeof(Vector2) });
634658
if (ctor != null) {
635-
loader = (level, levelData, offset, entityData) => (Entity) ctor.Invoke(new object[] { offset });
659+
loader = (level, levelData, offset, entityData) => {
660+
var entity = (patch_Entity)ctor.Invoke(new object[] { offset });
661+
entity.SourceData = entityData;
662+
entity.SourceId = ((patch_Level)level).CreateEntityId(levelData, entityData);
663+
return entity;
664+
};
636665
goto RegisterEntityLoader;
637666
}
638667

639668
ctor = type.GetConstructor(Type.EmptyTypes);
640669
if (ctor != null) {
641-
loader = (level, levelData, offset, entityData) => (Entity) ctor.Invoke(null);
670+
loader = (level, levelData, offset, entityData) => {
671+
var entity = (patch_Entity)ctor.Invoke(null);
672+
entity.SourceData = entityData;
673+
entity.SourceId = ((patch_Level)level).CreateEntityId(levelData, entityData);
674+
return entity;
675+
};
642676
goto RegisterEntityLoader;
643677
}
644678

@@ -647,6 +681,13 @@ internal static void ProcessAssembly(EverestModuleMetadata meta, Assembly asm, T
647681
Logger.Warn("core", $"Found custom entity without suitable constructor / {genName}(Level, LevelData, Vector2, EntityData): {id} ({type.FullName})");
648682
continue;
649683
}
684+
685+
// Immediately register the connection when we're calling the ctor,
686+
// since we know the return type upfront.
687+
if (ctor != null) {
688+
EntityRegistry.RegisterSidToTypeConnection(id, ctor.DeclaringType);
689+
}
690+
650691
patch_Level.EntityLoaders[id] = loader;
651692
}
652693
}

0 commit comments

Comments
 (0)