Compare commits

..
Author SHA1 Message Date
adminandClaude Opus 4.6 6762be71b4 Add setup-node step before JS syntax check
The self-hosted runner doesn't have Node.js in PATH.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:19:13 -08:00
adminandClaude Opus 4.6 401dbb0ce0 Add JS syntax checking to CI and merge conflict pre-commit hook
A git conflict marker was accidentally left in map_editor.js after a
rebase merge, breaking the map editor in production. This adds two
safeguards:

- CI lint job: `node --check` to catch JS syntax errors
- Pre-commit: `check-merge-conflict` hook to catch conflict markers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:05:35 -08:00
5668 changed files with 316206 additions and 629240 deletions
+1 -6
View File
@@ -37,14 +37,9 @@ common:macos --host_linkopt=-Wl,-no_warn_duplicate_libraries
# See: https://github.com/grpc/grpc/issues/37619
common:macos --features=-module_maps
# Pin DEVELOPER_DIR so the apple_cc_autoconf repo rule doesn't re-evaluate
# when Xcode updates in-place. The sync script overrides this for mactools.
# Fix Xcode version caching issue - avoids need for `bazel clean --expunge` after Xcode updates
common:macos --repo_env=DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
# Xcode config for mactools builds only. Generated by scripts/sync_bazel_xcode.sh.
# Bakes the Xcode build version into action cache keys and sets DEVELOPER_DIR.
try-import %workspace%/.bazelrc.xcode
common --java_language_version=25
common --java_runtime_version=remotejdk_25
common --tool_java_language_version=25
-14
View File
@@ -5,26 +5,12 @@
*.tif filter=lfs diff=lfs merge=lfs -text
*.bytes filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.psb filter=lfs diff=lfs merge=lfs -text
# PSB meta files contain bone/sprite import data and can be very large
*.psb.meta filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
# Exclude pre-existing font files that were committed as blobs (not LFS pointers)
src/main/csharp/**/GUI[[:space:]]Pro[[:space:]]Kit*/**/*.ttf !filter !diff !merge
src/main/csharp/**/Modern[[:space:]]UI[[:space:]]Pack/**/*.ttf !filter !diff !merge
*.herodata filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.FBX filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
# Third-party asset packs: track all files via LFS (never manually edited)
src/main/csharp/**/DungeonMonsters2D/** filter=lfs diff=lfs merge=lfs -text
src/main/csharp/**/Raccoon/** filter=lfs diff=lfs merge=lfs -text
src/main/csharp/**/Polytope[[:space:]]Studio/** filter=lfs diff=lfs merge=lfs -text
src/main/csharp/**/RRFreelance-Characters/** filter=lfs diff=lfs merge=lfs -text
src/main/csharp/**/Dragon/** filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
# Unity Smart Merge - use UnityYAMLMerge for Unity files
# Requires configuring unityyamlmerge in ~/.gitconfig:
+2 -2
View File
@@ -106,7 +106,7 @@ jobs:
with:
name: test.json
path: test.json
retention-days: 3
retention-days: 5
- name: Archive failed test logs
if: always()
uses: actions/upload-artifact@v4
@@ -114,4 +114,4 @@ jobs:
name: failed-test-logs
path: failed_test_logs/
if-no-files-found: ignore
retention-days: 3
retention-days: 5
-27
View File
@@ -1,27 +0,0 @@
name: Blob Cleanup
on:
schedule:
# Run daily at 04:00 UTC
- cron: '0 4 * * *'
workflow_dispatch: # Allow manual trigger
permissions:
contents: read
jobs:
cleanup:
runs-on: [self-hosted, bazel]
steps:
- uses: actions/checkout@v4
with:
lfs: false
clean: false
- name: Clean up unreferenced blobs
env:
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
SECRET_KEY: ${{ secrets.SECRET_KEY }}
run: |
bazel run //src/main/go/net/eagle0/build/blob_cleanup:blob_cleanup -- --min-age=1h
+2 -20
View File
@@ -40,7 +40,7 @@ concurrency:
permissions:
contents: read
actions: write # Required to delete artifacts after deploy
actions: read
jobs:
# Single consolidated build job - builds all images with one bazel invocation
@@ -76,7 +76,7 @@ jobs:
- name: Fetch LFS files needed for admin server
if: steps.check-latest.outputs.skip != 'true'
run: ./ci/github_actions/fetch_lfs.sh --include="src/main/go/net/eagle0/admin_server/static/tiles/*"
run: git lfs pull --include="src/main/go/net/eagle0/admin_server/static/tiles/*"
- name: Build all Docker images
if: steps.check-latest.outputs.skip != 'true'
@@ -242,7 +242,6 @@ jobs:
DO_DROPLET_IP: ${{ secrets.DO_DROPLET_IP }}
DO_REGISTRY_TOKEN: ${{ secrets.DO_REGISTRY_TOKEN }}
NOTIFY_SECRET: ${{ secrets.EAGLE_NOTIFY_SECRET }}
GITHUB_TOKEN_FOR_ADMIN: ${{ secrets.ADMIN_GITHUB_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -367,7 +366,6 @@ jobs:
export FASTMAIL_FROM_NAME="${FASTMAIL_FROM_NAME}"
export DO_REGISTRY_TOKEN="${DO_REGISTRY_TOKEN}"
export NOTIFY_SECRET="${NOTIFY_SECRET}"
export GITHUB_TOKEN="${GITHUB_TOKEN_FOR_ADMIN}"
# Check Docker has IPv6 support
if ! cat /etc/docker/daemon.json 2>/dev/null | grep -q '"ip6tables"'; then
@@ -471,19 +469,3 @@ jobs:
# Remove images older than 24h (keeps recent images for rollback)
docker image prune -a -f --filter "until=24h" || true
DEPLOY_SCRIPT
cleanup:
needs: [build-all, deploy]
if: always()
runs-on: ubuntu-latest
steps:
- name: Delete warmup-binary artifact
env:
GH_TOKEN: ${{ github.token }}
run: |
ARTIFACT_ID=$(gh api "repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts" \
-q '.artifacts[] | select(.name == "warmup-binary") | .id')
if [ -n "$ARTIFACT_ID" ]; then
echo "Deleting warmup-binary artifact (ID: $ARTIFACT_ID)"
gh api -X DELETE "repos/${{ github.repository }}/actions/artifacts/$ARTIFACT_ID" || true
fi
+6 -21
View File
@@ -112,29 +112,14 @@ jobs:
- name: Delete all installer artifacts
if: success() && github.ref == 'refs/heads/main' && github.event_name == 'push'
env:
GITHUB_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ github.token }}
run: |
# Delete ALL eagle-installer artifacts to free up storage
echo "Fetching all eagle-installer artifacts..."
page=1
while true; do
response=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/actions/artifacts?per_page=100&page=$page")
ids=$(echo "$response" | python3 -c "
import json, sys
data = json.load(sys.stdin)
for a in data.get('artifacts', []):
if a['name'] == 'eagle-installer':
print(a['id'])
" 2>/dev/null)
if [ -z "$ids" ]; then
break
fi
for id in $ids; do
echo "Deleting artifact ID: $id"
curl -s -X DELETE -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/actions/artifacts/$id" || true
done
page=$((page + 1))
artifact_ids=$(gh api "repos/${{ github.repository }}/actions/artifacts" \
--paginate -q '.artifacts[] | select(.name == "eagle-installer") | .id')
for id in $artifact_ids; do
echo "Deleting artifact ID: $id"
gh api -X DELETE "repos/${{ github.repository }}/actions/artifacts/$id" || true
done
echo "Cleanup complete"
@@ -0,0 +1,98 @@
name: iOS Addressables Build
on:
push:
branches: [ "main" ]
paths:
- ".github/workflows/ios_addressables_build.yml"
- "src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/AddressableAssetsData/**"
- "src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/Music/**"
- "src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/Editor/BuildScript.cs"
- "ci/github_actions/build_ios_addressables.sh"
- "ci/github_actions/upload_addressables.sh"
pull_request:
paths:
- ".github/workflows/ios_addressables_build.yml"
- "src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/AddressableAssetsData/**"
- "src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/Music/**"
- "src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/Editor/BuildScript.cs"
- "ci/github_actions/build_ios_addressables.sh"
- "ci/github_actions/upload_addressables.sh"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
env:
# Runner-specific build directory to allow parallel builds on multiple runners
EAGLE0_BUILD_DIR: /tmp/eagle0-${{ github.run_id }}
jobs:
build-ios-addressables:
runs-on: [self-hosted, macOS, unity-mac]
steps:
- name: Prune stale PR refs
run: |
# Self-hosted runners persist .git between runs. When a PR is updated,
# old local refs (refs/remotes/pull/*/merge) may point to commits whose
# objects were never fetched or have been pruned. Remove these stale refs
# before checkout to prevent "missing object" errors.
if [ -d ".git" ]; then
echo "Pruning stale PR refs..."
git for-each-ref --format='%(refname)' refs/remotes/pull/ 2>/dev/null | \
xargs -r git update-ref -d 2>/dev/null || true
fi
- uses: actions/checkout@v4
with:
lfs: false # Fetch LFS after checkout to avoid stale ref issues
clean: false # Library/ persists between runs on self-hosted runners
- name: Clean stale files
run: |
git clean -ffd
rm -rf src/main/csharp/net/eagle0/clients/unity/eagle0/Library/Bee/
- name: Fetch LFS files
run: |
git lfs install
git lfs pull
- name: Ensure Unity version installed
run: ./ci/github_actions/ensure_unity_installed.sh ios
- name: Build iOS Addressables
run: ./ci/github_actions/build_ios_addressables.sh "$EAGLE0_BUILD_DIR/editor_ios_addressables.log"
- name: Upload Addressables to CDN
if: success() && github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
env:
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
SECRET_KEY: ${{ secrets.SECRET_KEY }}
run: ./ci/github_actions/upload_addressables.sh iOS
- name: Purge CDN cache for iOS addressables
if: success() && github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
env:
DO_CDN_PAT: ${{ secrets.DO_CDN_PAT }}
run: |
curl -s -X DELETE "https://api.digitalocean.com/v2/cdn/endpoints/8c98df29-6f0c-4704-8e82-ca40a2b81aa8/cache" \
-H "Authorization: Bearer $DO_CDN_PAT" \
-H "Content-Type: application/json" \
-d '{"files": ["addressables/iOS/*"]}' \
--fail || echo "Warning: CDN purge failed (non-fatal)"
- name: Archive Build Log
if: success() || failure()
uses: actions/upload-artifact@v4
with:
name: editor_ios_addressables.log
path: ${{ env.EAGLE0_BUILD_DIR }}/editor_ios_addressables.log
retention-days: 5
- name: Cleanup build directory
if: always()
run: rm -rf "${{ env.EAGLE0_BUILD_DIR }}"
+4 -100
View File
@@ -1,8 +1,6 @@
name: iOS TestFlight
on:
schedule:
- cron: '0 5 * * *' # 9 PM Pacific (UTC-8) / 10 PM PDT (UTC-7)
workflow_dispatch:
inputs:
skip_upload:
@@ -13,7 +11,6 @@ on:
permissions:
contents: read
actions: read
env:
# Runner-specific build directory to allow parallel builds on multiple runners
@@ -22,92 +19,7 @@ env:
KEYCHAIN_NAME: ios-build-${{ github.run_id }}.keychain
jobs:
check-changes:
# Skip nightly builds when nothing has changed since the last successful
# scheduled run. Manual workflow_dispatch always builds.
runs-on: ubuntu-latest
outputs:
should_build: ${{ steps.check.outputs.should_build }}
steps:
- name: Check for relevant changes since last successful run
id: check
uses: actions/github-script@v8
with:
script: |
if (context.eventName === 'workflow_dispatch') {
core.setOutput('should_build', 'true');
console.log('Manual trigger — building');
return;
}
const { data: { workflow_runs: runs } } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'ios_testflight.yml',
status: 'success',
event: 'schedule',
per_page: 1,
});
if (runs.length === 0) {
core.setOutput('should_build', 'true');
console.log('No previous successful scheduled run — building');
return;
}
const lastSha = runs[0].head_sha;
console.log(`Last successful scheduled run: ${lastSha}`);
console.log(`Current SHA: ${context.sha}`);
if (lastSha === context.sha) {
core.setOutput('should_build', 'false');
console.log('No changes since last successful run — skipping');
return;
}
// Paths that can affect the iOS Unity build.
const relevantPrefixes = [
'src/main/csharp/', // Unity project
'src/main/protobuf/', // Generates C# code
'src/main/resources/', // Game data & maps
'scripts/', // Build scripts
'ci/', // CI scripts & workflows
'.github/workflows/ios_testflight.yml',
'MODULE.bazel',
'.bazelrc',
];
const { data: comparison } = await github.rest.repos.compareCommitsWithBasehead({
owner: context.repo.owner,
repo: context.repo.repo,
basehead: `${lastSha}...${context.sha}`,
per_page: 1, // We only need the file list, not patches
});
// If the diff is too large, build to be safe
if (comparison.files === undefined) {
core.setOutput('should_build', 'true');
console.log('Could not retrieve file list — building to be safe');
return;
}
const relevant = comparison.files.filter(f =>
relevantPrefixes.some(p => f.filename.startsWith(p))
);
if (relevant.length > 0) {
core.setOutput('should_build', 'true');
console.log(`${relevant.length} relevant file(s) changed:`);
relevant.slice(0, 20).forEach(f => console.log(` ${f.filename}`));
if (relevant.length > 20) console.log(` ... and ${relevant.length - 20} more`);
} else {
core.setOutput('should_build', 'false');
console.log(`${comparison.files.length} file(s) changed, none in relevant paths — skipping`);
}
build-unity:
needs: check-changes
if: needs.check-changes.outputs.should_build == 'true'
runs-on: [self-hosted, macOS, testflight]
steps:
@@ -134,7 +46,9 @@ jobs:
rm -rf src/main/csharp/net/eagle0/clients/unity/eagle0/Library/Bee/
- name: Fetch LFS files
run: ./ci/github_actions/fetch_lfs.sh
run: |
git lfs install
git lfs pull
- name: Ensure Unity version installed
run: ./ci/github_actions/ensure_unity_installed.sh ios
@@ -168,7 +82,7 @@ jobs:
with:
name: editor_ios.log
path: ${{ env.EAGLE0_BUILD_DIR }}/editor_ios.log
retention-days: 3
retention-days: 5
archive-and-upload:
needs: build-unity
@@ -226,20 +140,10 @@ jobs:
- name: Archive and Export IPA
env:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
run: |
# Write API key to file for xcodebuild
API_KEY_PATH=$(mktemp)
echo "$APP_STORE_CONNECT_API_KEY" > "$API_KEY_PATH"
export APP_STORE_CONNECT_API_KEY_PATH="$API_KEY_PATH"
chmod +x ./ci/github_actions/archive_ios.sh
./ci/github_actions/archive_ios.sh "$EAGLE0_BUILD_DIR/eagle0iOS" "$EAGLE0_BUILD_DIR/archive" "$APPLE_TEAM_ID" "$PROFILE_UUID"
rm -f "$API_KEY_PATH"
- name: Upload to TestFlight
if: ${{ github.event.inputs.skip_upload != 'true' }}
env:
+4 -9
View File
@@ -32,7 +32,6 @@ on:
- "src/main/go/net/eagle0/build/mac_build_handler/**"
- "scripts/build_mac_plugin.sh"
- "scripts/build_sparkle_plugin.sh"
- "src/main/objc/net/eagle0/clients/unity/sparkle/**"
- "scripts/inject_sparkle.sh"
- "scripts/codesign_mac_app.sh"
- "scripts/notarize_submit.sh"
@@ -109,14 +108,13 @@ jobs:
fi
- name: Fetch LFS files
run: ./ci/github_actions/fetch_lfs.sh
run: |
git lfs install
git lfs pull
- name: Ensure Unity version installed
run: ./ci/github_actions/ensure_unity_installed.sh mac
- name: Sync Bazel Xcode config
run: ./scripts/sync_bazel_xcode.sh
- name: Build Mac Unity
run: ./ci/github_actions/build_unity_mac.sh "${{ env.EAGLE0_BUILD_DIR }}/eagle0MAC"
@@ -239,7 +237,7 @@ jobs:
with:
name: editor_mac.log
path: ${{ env.EAGLE0_BUILD_DIR }}/editor_mac.log
retention-days: 3
retention-days: 5
- name: Cleanup build directory
if: always()
run: rm -rf "${{ env.EAGLE0_BUILD_DIR }}"
@@ -322,9 +320,6 @@ jobs:
ditto -x -k eagle0.app.zip .
rm eagle0.app.zip
- name: Sync Bazel Xcode config
run: ./scripts/sync_bazel_xcode.sh
- name: Deploy Mac Build
id: deploy-mac
env:
+16 -6
View File
@@ -96,7 +96,9 @@ jobs:
fi
- name: Fetch LFS files
run: ./ci/github_actions/fetch_lfs.sh
run: |
git lfs install
git lfs pull
- name: Ensure Unity version installed
run: ./ci/github_actions/ensure_unity_installed.sh windows
- name: Build Windows unity
@@ -113,14 +115,14 @@ jobs:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
run: ./ci/github_actions/upload_addressables.sh StandaloneWindows64
- name: Deploy Windows unity
if: success() && github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
if: success() && github.ref == 'refs/heads/main' && github.event_name == 'push'
env:
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
SECRET_KEY: ${{ secrets.SECRET_KEY }}
run: bazel run //src/main/go/net/eagle0/build/unity3d_windows_build_handler:unity3d_windows_build_handler -- "${{ env.EAGLE0_BUILD_DIR }}/eagle0WIN" "/tmp/unity_manifest.txt"
- name: Update unified manifest
if: success() && github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
if: success() && github.ref == 'refs/heads/main' && github.event_name == 'push'
env:
ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }}
SECRET_KEY: ${{ secrets.SECRET_KEY }}
@@ -145,7 +147,7 @@ jobs:
- name: Export deployed version
id: get-version
if: success() && github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
if: success() && github.ref == 'refs/heads/main' && github.event_name == 'push'
run: |
VERSION=$(grep "^version=" /tmp/unity_manifest.txt | cut -d= -f2 || date +%Y.%m.%d)
echo "deployed_version=$VERSION" >> $GITHUB_OUTPUT
@@ -156,7 +158,7 @@ jobs:
with:
name: editor_win.log
path: ${{ env.EAGLE0_BUILD_DIR }}/editor_win.log
retention-days: 3
retention-days: 5
- name: Cleanup build directory
if: always()
run: rm -rf "${{ env.EAGLE0_BUILD_DIR }}"
@@ -166,10 +168,18 @@ jobs:
if: needs.windows-unity.outputs.deployed_version != ''
runs-on: ubuntu-latest
steps:
- name: Notify clients of update
- name: Purge CDN cache and notify clients
env:
NOTIFY_SECRET: ${{ secrets.EAGLE_NOTIFY_SECRET }}
DO_CDN_PAT: ${{ secrets.DO_CDN_PAT }}
run: |
# Purge CDN cache so clients get the latest files immediately
curl -s -X DELETE "https://api.digitalocean.com/v2/cdn/endpoints/8c98df29-6f0c-4704-8e82-ca40a2b81aa8/cache" \
-H "Authorization: Bearer $DO_CDN_PAT" \
-H "Content-Type: application/json" \
-d '{"files": ["windows/*", "addressables/StandaloneWindows64/*"]}' \
--fail || echo "Warning: CDN purge failed (non-fatal)"
curl -X POST "https://admin.eagle0.net/notify-update?platform=windows&version=${{ needs.windows-unity.outputs.deployed_version }}&required=false" \
-H "X-Notify-Secret: $NOTIFY_SECRET" \
--fail --silent --show-error || echo "Warning: Failed to notify clients (non-fatal)"
-1
View File
@@ -23,7 +23,6 @@ bazel-bin
bazel-eagle0*
bazel-out
bazel-testlogs
.bazelrc.xcode
.ijwb
.clwb
buildWin.sh
+1 -10
View File
@@ -14,16 +14,7 @@ repos:
- id: clang-format
args: [-i, --no-diff]
types_or: ["c++", "c#"]
exclude: >-
(?x)^src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/(
Plugins|
DungeonMonsters2D|
Dragon|
ithappy|
Polytope\ Studio|
RRFreelance-Characters|
Raccoon
)/
exclude: ^src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/Plugins
- repo: https://github.com/yoheimuta/protolint
rev: v0.42.2
hooks:
-6
View File
@@ -1,13 +1,7 @@
# CLAUDE.md
## CRITICAL BASH RULES (NEVER VIOLATE)
**NEVER chain bash commands.** Do not use `&&`, `||`, or `;` to combine commands. Each command must be a separate Bash tool call. Use parallel tool calls when commands are independent.
## CRITICAL GIT RULES (NEVER VIOLATE)
**NEVER use `git -C`.** Instead, cd to the repo root and run git commands from there.
**NEVER push directly to main/master.** No exceptions. Not for "small changes." Not for docs. Not ever.
**NEVER merge PRs.** You create PRs. The user merges them. No exceptions.
+18 -47
View File
@@ -149,54 +149,38 @@ use_repo(crate, "map_generator_crates")
#
# Platform Support - Apple/iOS
#
# Note: rules_apple is NOT included in the main workspace due to rules_swift
# version conflicts with grpc. SparklePlugin (which needs rules_apple) is built
# in a separate workspace at sparkle_workspace/ to isolate the conflict.
#
bazel_dep(name = "apple_support", version = "1.24.1", repo_name = "build_bazel_apple_support")
bazel_dep(name = "rules_apple", version = "4.3.3", repo_name = "build_bazel_rules_apple")
# rules_swift is a transitive dep of grpc and flatbuffers with conflicting versions:
# - grpc 1.76.0.bcr.1 requires rules_swift 3.x (compatibility level 3)
# - flatbuffers requires rules_swift 2.x (compatibility level 2)
# We don't use Swift directly, but we need to force a single version.
# Force 3.x since grpc is more complex and harder to downgrade.
single_version_override(
module_name = "rules_swift",
version = "3.1.2",
)
# Register Apple CC toolchain for Objective-C compilation
apple_cc_configure = use_extension(
"@build_bazel_apple_support//crosstool:setup.bzl",
"apple_cc_configure_extension",
)
use_repo(apple_cc_configure, "local_config_apple_cc", "local_config_apple_cc_toolchains")
use_repo(apple_cc_configure, "local_config_apple_cc")
#
# Protocol Buffers & RPC
#
bazel_dep(name = "protobuf", version = "33.5", repo_name = "com_google_protobuf")
# Use pre-built protoc binaries instead of compiling from source.
# See: https://protobuf.dev/reference/cpp/cpp-generated/#invocation
prebuilt_protoc = use_extension("@com_google_protobuf//bazel/private:prebuilt_protoc_extension.bzl", "protoc")
use_repo(
prebuilt_protoc,
"prebuilt_protoc.linux_aarch_64",
"prebuilt_protoc.linux_ppcle_64",
"prebuilt_protoc.linux_s390_64",
"prebuilt_protoc.linux_x86_32",
"prebuilt_protoc.linux_x86_64",
"prebuilt_protoc.osx_aarch_64",
"prebuilt_protoc.osx_x86_64",
"prebuilt_protoc.win32",
"prebuilt_protoc.win64",
)
bazel_dep(name = "rules_proto", version = "7.1.0")
bazel_dep(name = "rules_cc", version = "0.2.14")
bazel_dep(name = "grpc", version = "1.78.0")
# Patch grpc 1.78.0 to fix rules_python incompatibility: grpc requests Python
# 3.14.0b2 toolchain but rules_python >= 1.6.0 removed it in favor of 3.14.
# Upstream fix: https://github.com/grpc/grpc/commit/459279b
# TODO: Remove this override once a fixed grpc version is published to BCR.
single_version_override(
module_name = "grpc",
patch_strip = 1,
patches = ["//third_party/patches:grpc_fix_python_version.patch"],
version = "1.78.0",
)
bazel_dep(name = "grpc", version = "1.74.1")
bazel_dep(name = "grpc-java", version = "1.78.0")
bazel_dep(name = "rules_proto_grpc_csharp", version = "5.8.0")
bazel_dep(name = "flatbuffers", version = "25.12.19")
@@ -400,16 +384,8 @@ http_archive(
],
)
# Sparkle framework for macOS auto-updates
SPARKLE_VERSION = "2.6.4"
http_archive(
name = "sparkle",
build_file = "//src/main/objc/net/eagle0/clients/unity/sparkle/external:BUILD.sparkle",
sha256 = "50612a06038abc931f16011d7903b8326a362c1074dabccb718404ce8e585f0b",
strip_prefix = "",
url = "https://github.com/sparkle-project/Sparkle/releases/download/%s/Sparkle-%s.tar.xz" % (SPARKLE_VERSION, SPARKLE_VERSION),
)
# Note: Sparkle framework is defined in sparkle_workspace/MODULE.bazel
# (not in main workspace due to rules_swift version conflicts)
# Busybox static binary for Docker health checks (provides nc, wget, etc.)
# Primary: DigitalOcean Spaces (public, reliable)
@@ -499,11 +475,6 @@ register_toolchains(
"@rules_scala//testing:scalatest_toolchain",
)
# Apple CC toolchain for Objective-C compilation (SparklePlugin).
# Registered before LLVM so it has higher priority; Apple constraint matching
# ensures it's only used for Apple-platform targets (objc_library, macos_bundle).
register_toolchains("@local_config_apple_cc_toolchains//:all")
# Set dev_dependency so we can turn this off for swift MacOS builds
register_toolchains(
"@llvm_toolchain//:all",
+236 -185
View File
@@ -4,12 +4,15 @@
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
"https://bcr.bazel.build/modules/abseil-cpp/20220623.1/MODULE.bazel": "73ae41b6818d423a11fd79d95aedef1258f304448193d4db4ff90e5e7a0f076c",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.0/MODULE.bazel": "98dc378d64c12a4e4741ad3362f87fb737ee6a0886b2d90c3cdbb4d93ea3e0bf",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
"https://bcr.bazel.build/modules/abseil-cpp/20240722.0/MODULE.bazel": "88668a07647adbdc14cb3a7cd116fb23c9dda37a90a1681590b6c9d8339a5b84",
"https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5",
"https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
"https://bcr.bazel.build/modules/abseil-cpp/20250512.0/MODULE.bazel": "c4d02dd22cd87458516655a45512060246ee2a4732f1fbe948a5bd9eb614e626",
@@ -22,7 +25,7 @@
"https://bcr.bazel.build/modules/apple_support/1.13.0/MODULE.bazel": "7c8cdea7e031b7f9f67f0b497adf6d2c6a2675e9304ca93a9af6ed84eef5a524",
"https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
"https://bcr.bazel.build/modules/apple_support/1.17.1/MODULE.bazel": "655c922ab1209978a94ef6ca7d9d43e940cd97d9c172fb55f94d91ac53f8610b",
"https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1",
"https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e",
"https://bcr.bazel.build/modules/apple_support/1.23.0/MODULE.bazel": "317d47e3f65b580e7fb4221c160797fda48e32f07d2dfff63d754ef2316dcd25",
"https://bcr.bazel.build/modules/apple_support/1.23.1/MODULE.bazel": "53763fed456a968cf919b3240427cf3a9d5481ec5466abc9d5dc51bc70087442",
"https://bcr.bazel.build/modules/apple_support/1.24.1/MODULE.bazel": "f46e8ddad60aef170ee92b2f3d00ef66c147ceafea68b6877cb45bd91737f5f8",
@@ -64,7 +67,6 @@
"https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a",
"https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
"https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
"https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
"https://bcr.bazel.build/modules/bazel_features/1.32.0/MODULE.bazel": "095d67022a58cb20f7e20e1aefecfa65257a222c18a938e2914fd257b5f1ccdc",
"https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6",
@@ -100,6 +102,7 @@
"https://bcr.bazel.build/modules/bazel_worker_api/0.0.4/MODULE.bazel": "460aa12d01231a80cce03c548287b433b321d205b0028ae596728c35e5ee442e",
"https://bcr.bazel.build/modules/bazel_worker_java/0.0.4/MODULE.bazel": "82494a01018bb7ef06d4a17ec4cd7a758721f10eb8b6c820a818e70d669500db",
"https://bcr.bazel.build/modules/bazel_worker_java/0.0.4/source.json": "a2d30458fd86cf022c2b6331e652526fa08e17573b2f5034a9dbcacdf9c2583c",
"https://bcr.bazel.build/modules/boringssl/0.0.0-20211025-d4f1ab9/MODULE.bazel": "6ee6353f8b1a701fe2178e1d925034294971350b6d3ac37e67e5a7d463267834",
"https://bcr.bazel.build/modules/boringssl/0.0.0-20230215-5c22014/MODULE.bazel": "4b03dc0d04375fa0271174badcd202ed249870c8e895b26664fd7298abea7282",
"https://bcr.bazel.build/modules/boringssl/0.0.0-20240530-2db0eb3/MODULE.bazel": "d0405b762c5e87cd445b7015f2b8da5400ef9a8dbca0bfefa6c1cea79d528a97",
"https://bcr.bazel.build/modules/boringssl/0.20240913.0/MODULE.bazel": "fcaa7503a5213290831a91ed1eb538551cf11ac0bc3a6ad92d0fef92c5bd25fb",
@@ -107,12 +110,14 @@
"https://bcr.bazel.build/modules/boringssl/0.20241024.0/source.json": "d843092e682b84188c043ac742965d7f96e04c846c7e338187e03238674909a9",
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
"https://bcr.bazel.build/modules/c-ares/1.15.0/MODULE.bazel": "ba0a78360fdc83f02f437a9e7df0532ad1fbaa59b722f6e715c11effebaa0166",
"https://bcr.bazel.build/modules/c-ares/1.19.1/MODULE.bazel": "73bca21720772370ff91cc8e88bbbaf14897720c6473e87c1ddc0f848284c313",
"https://bcr.bazel.build/modules/c-ares/1.19.1/source.json": "56bfa95b01e4e0012e90eaa9f1bab823c48c3af4454286b889b9cc74f5098da1",
"https://bcr.bazel.build/modules/cel-spec/0.15.0/MODULE.bazel": "e1eed53d233acbdcf024b4b0bc1528116d92c29713251b5154078ab1348cb600",
"https://bcr.bazel.build/modules/cel-spec/0.15.0/source.json": "ab7dccdf21ea2261c0f809b5a5221a4d7f8b580309f285fdf1444baaca75d44a",
"https://bcr.bazel.build/modules/civetweb/1.16/MODULE.bazel": "46a38f9daeb57392e3827fce7d40926be0c802bd23cdd6bfd3a96c804de42fae",
"https://bcr.bazel.build/modules/civetweb/1.16/source.json": "ba8b9585adb8355cb51b999d57172fd05e7a762c56b8d4bac6db42c99de3beb7",
"https://bcr.bazel.build/modules/curl/8.4.0/MODULE.bazel": "0bc250aa1cb69590049383df7a9537c809591fcf876c620f5f097c58fdc9bc10",
"https://bcr.bazel.build/modules/curl/8.7.1/MODULE.bazel": "088221c35a2939c555e6e47cb31a81c15f8b59f4daa8009b1e9271a502d33485",
"https://bcr.bazel.build/modules/curl/8.8.0/MODULE.bazel": "7da3b3e79b0b4ee8f8c95d640bc6ad7b430ce66ef6e9c9d2bc29b3b5ef85f6fe",
"https://bcr.bazel.build/modules/curl/8.8.0/source.json": "d7d138b6878cf38891692fee0649ace35357fd549b425614d571786f054374d4",
@@ -137,33 +142,36 @@
"https://bcr.bazel.build/modules/gazelle/0.47.0/source.json": "aeb2e5df14b7fb298625d75d08b9c65bdb0b56014c5eb89da9e5dd0572280ae6",
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/google_benchmark/1.8.4/MODULE.bazel": "c6d54a11dcf64ee63545f42561eda3fd94c1b5f5ebe1357011de63ae33739d5e",
"https://bcr.bazel.build/modules/google_benchmark/1.8.4/source.json": "84590f7bc5a1fd99e1ef274ee16bb41c214f705e62847b42e705010dfa81fe53",
"https://bcr.bazel.build/modules/googleapis-cc/1.0.0/MODULE.bazel": "cf01757e7590c56140a4b81638ff2b3e7074769e6271720bbf738fcda25b6fc2",
"https://bcr.bazel.build/modules/googleapis-cc/1.0.0/source.json": "ab0e3a2ee9968a8848f59872fbbfa3e1f768597d71d2229e6caa319d357967c7",
"https://bcr.bazel.build/modules/googleapis-grpc-cc/1.0.0/MODULE.bazel": "3553358a9d8d96026c9e28d9fb6c268574950d0be7fa9b4c0aeaf3c37c73f2d3",
"https://bcr.bazel.build/modules/googleapis-grpc-cc/1.0.0/source.json": "fa7b79043b3c82bf74f1f2fa45af289e19b247375868d0752db2c114a1c7366c",
"https://bcr.bazel.build/modules/googleapis-python/1.0.0/MODULE.bazel": "0ccd1614a914fb524b3ac267f9c97f9a5cd5412b027f0176b81a725882ec42ff",
"https://bcr.bazel.build/modules/googleapis-python/1.0.0/source.json": "24364f075ec5e6d5e0cfc5d651bd833b119e0cea1a45d51330c93461e3586e42",
"https://bcr.bazel.build/modules/googleapis-rules-registry/1.0.0/MODULE.bazel": "97c6a4d413b373d4cc97065da3de1b2166e22cbbb5f4cc9f05760bfa83619e24",
"https://bcr.bazel.build/modules/googleapis-rules-registry/1.0.0/source.json": "cf611c836a60e98e2e2ab2de8004f119e9f06878dcf4ea2d95a437b1b7a89fe9",
"https://bcr.bazel.build/modules/google_benchmark/1.8.5/MODULE.bazel": "9ba9b31b984022828a950e3300410977eda2e35df35584c6b0b2d0c2e52766b7",
"https://bcr.bazel.build/modules/google_benchmark/1.8.5/source.json": "2c9c685f9b496f125b9e3a9c696c549d1ed2f33b75830a2fb6ac94fab23c0398",
"https://bcr.bazel.build/modules/googleapis/0.0.0-20240326-1c8d509c5/MODULE.bazel": "a4b7e46393c1cdcc5a00e6f85524467c48c565256b22b5fae20f84ab4a999a68",
"https://bcr.bazel.build/modules/googleapis/0.0.0-20240819-fe8ba054a/MODULE.bazel": "117b7c7be7327ed5d6c482274533f2dbd78631313f607094d4625c28203cacdf",
"https://bcr.bazel.build/modules/googleapis/0.0.0-20241220-5e258e33.bcr.1/MODULE.bazel": "ee6c30f82ecd476e61f019fb1151aaab380ea419958ff274ef2f0efca7969f5c",
"https://bcr.bazel.build/modules/googleapis/0.0.0-20241220-5e258e33.bcr.1/source.json": "d6f66e3d95ec52821e994015e83ed194f8888c655068e192659e55a8987dfe77",
"https://bcr.bazel.build/modules/googleapis/0.0.0-20240819-fe8ba054a/source.json": "b31fc7eb283a83f71d2e5bfc3d1c562d2994198fa1278409fbe8caec3afc1d3e",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
"https://bcr.bazel.build/modules/googletest/1.16.0/MODULE.bazel": "a175623c69e94fca4ca7acbc12031e637b0c489318cd4805606981d4d7adb34a",
"https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
"https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713",
"https://bcr.bazel.build/modules/grpc-java/1.62.2/MODULE.bazel": "99b8771e8c7cacb130170fed2a10c9e8fed26334a93e73b42d2953250885a158",
"https://bcr.bazel.build/modules/grpc-java/1.66.0/MODULE.bazel": "86ff26209fac846adb89db11f3714b3dc0090fb2fb81575673cc74880cda4e7e",
"https://bcr.bazel.build/modules/grpc-java/1.69.0/MODULE.bazel": "53887af6a00b3b406d70175d3d07e84ea9362016ff55ea90b9185f0227bfaf98",
"https://bcr.bazel.build/modules/grpc-java/1.78.0/MODULE.bazel": "48f790fbb95625245295df1283e0dba344a4e30b4a9a9cefbabfa92bd84f3691",
"https://bcr.bazel.build/modules/grpc-java/1.78.0/source.json": "36c3a83c5ddeb864d7a4b97801456c464077f80a8216354ac1a71f7ce8699771",
"https://bcr.bazel.build/modules/grpc-proto/0.0.0-20240627-ec30f58/MODULE.bazel": "88de79051e668a04726e9ea94a481ec6f1692086735fd6f488ab908b3b909238",
"https://bcr.bazel.build/modules/grpc-proto/0.0.0-20240627-ec30f58/source.json": "5035d379c61042930244ab59e750106d893ec440add92ec0df6a0098ca7f131d",
"https://bcr.bazel.build/modules/grpc/1.78.0/MODULE.bazel": "6a72f0b2fe950342fe63b231c76197df6d117a8ea1ac338dac40b053020f586a",
"https://bcr.bazel.build/modules/grpc/1.78.0/source.json": "c988abfe519ef5ace8cd27c80c0a66e68e501e5902b623722fcbf6694b355693",
"https://bcr.bazel.build/modules/grpc/1.41.0/MODULE.bazel": "5bcbfc2b274dabea628f0649dc50c90cf36543b1cfc31624832538644ad1aae8",
"https://bcr.bazel.build/modules/grpc/1.56.3.bcr.1/MODULE.bazel": "cd5b1eb276b806ec5ab85032921f24acc51735a69ace781be586880af20ab33f",
"https://bcr.bazel.build/modules/grpc/1.62.1/MODULE.bazel": "2998211594b8a79a6b459c4e797cfa19f0fb8b3be3149760ec7b8c99abfd426f",
"https://bcr.bazel.build/modules/grpc/1.63.1.bcr.1/MODULE.bazel": "d7b9fef03bd175e6825237b521b18a3c29f1ac15f8aa52c8a1a0f3bd8f33d54b",
"https://bcr.bazel.build/modules/grpc/1.66.0.bcr.2/MODULE.bazel": "0fa2b0fd028ce354febf0fe90f1ed8fecfbfc33118cddd95ac0418cc283333a0",
"https://bcr.bazel.build/modules/grpc/1.66.0.bcr.3/MODULE.bazel": "f6047e89faf488f5e3e65cb2594c6f5e86992abec7487163ff6b623526e543b0",
"https://bcr.bazel.build/modules/grpc/1.69.0/MODULE.bazel": "4e26e05c9e1ef291ccbc96aad8e457b1b8abedbc141623831629da2f8168eef6",
"https://bcr.bazel.build/modules/grpc/1.70.1/MODULE.bazel": "b800cd8e3e7555c1e61cba2e02d3a2fcf0e91f66e800db286d965d3b7a6a721a",
"https://bcr.bazel.build/modules/grpc/1.71.0/MODULE.bazel": "7fcab2c05530373f1a442c362b17740dd0c75b6a2a975eec8f5bf4c70a37928a",
"https://bcr.bazel.build/modules/grpc/1.74.1/MODULE.bazel": "09523be10ba2bfd999683671d0f8f22fb5b20ec77ad89b05ef58ff19a1b65c82",
"https://bcr.bazel.build/modules/grpc/1.74.1/source.json": "8508bcf9bae1b7c647a594e13461ce192240fcdbb409c2741444322d47d01f98",
"https://bcr.bazel.build/modules/helly25_bzl/0.3.1/MODULE.bazel": "3a4be20f6fc13be32ad44643b8252ef5af09eee936f1d943cd4fd7867fa92826",
"https://bcr.bazel.build/modules/helly25_bzl/0.3.1/source.json": "b129ab1828492de2c163785bbeb4065c166de52d932524b4317beb5b7f917994",
"https://bcr.bazel.build/modules/jq.bzl/0.1.0/MODULE.bazel": "2ce69b1af49952cd4121a9c3055faa679e748ce774c7f1fda9657f936cae902f",
@@ -180,13 +188,18 @@
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
"https://bcr.bazel.build/modules/opencensus-cpp/0.0.0-20230502-50eb5de.bcr.2/MODULE.bazel": "cc18734138dd18c912c6ce2a59186db28f85d8058c99c9f21b46ca3e0aba0ebe",
"https://bcr.bazel.build/modules/opencensus-cpp/0.0.0-20230502-50eb5de.bcr.2/source.json": "7c135f9d42bb3b045669c3c6ab3bb3c208e00b46aca4422eea64c29811a5b240",
"https://bcr.bazel.build/modules/opencensus-cpp/0.0.0-20230502-50eb5de/MODULE.bazel": "02201d2921dadb4ec90c4980eca4b2a02904eddcf6fa02f3da7594fb7b0d821c",
"https://bcr.bazel.build/modules/opencensus-proto/0.4.1.bcr.2/MODULE.bazel": "789706a714855f92c5c8cfcf1ef32bbb64dcd3b7c9066756ad7986ec59709d29",
"https://bcr.bazel.build/modules/opencensus-proto/0.4.1.bcr.2/source.json": "aadf3f53e08b72376506b7c4ea3d167010c9efb160d7d6e1e304ed646bac1b36",
"https://bcr.bazel.build/modules/opencensus-proto/0.4.1/MODULE.bazel": "4a2e8b4d0b544002502474d611a5a183aa282251e14f6a01afe841c0c1b10372",
"https://bcr.bazel.build/modules/openssl/3.3.1.bcr.1/MODULE.bazel": "49c0c07e8fb87b480bccb842cfee1b32617f11dac590f732573c69058699a3d1",
"https://bcr.bazel.build/modules/openssl/3.3.1.bcr.1/source.json": "0c0872e048bbea052a9c541fb47019481a19201ba5555a71d762ad591bf94e1f",
"https://bcr.bazel.build/modules/opentelemetry-cpp/1.14.2/MODULE.bazel": "089a5613c2a159c7dfde098dabfc61e966889c7d6a81a98422a84c51535ed17d",
"https://bcr.bazel.build/modules/opentelemetry-cpp/1.16.0/MODULE.bazel": "b7379a140f538cea3f749179a2d481ed81942cc6f7b05a6113723eb34ac3b3e7",
"https://bcr.bazel.build/modules/opentelemetry-cpp/1.19.0/MODULE.bazel": "3455326c08b28415648a3d60d8e3c811847ebdbe64474f75b25878f25585aea1",
"https://bcr.bazel.build/modules/opentelemetry-cpp/1.19.0/source.json": "4e48137e4c3ecb99401ff99876df8fa330598d7da051869bec643446e8a8ff95",
"https://bcr.bazel.build/modules/opentelemetry-proto/1.1.0/MODULE.bazel": "a49f406e99bf05ab43ed4f5b3322fbd33adfd484b6546948929d1316299b68bf",
"https://bcr.bazel.build/modules/opentelemetry-proto/1.3.1/MODULE.bazel": "0141a50e989576ee064c11ce8dd5ec89993525bd9f9a09c5618e4dacc8df9352",
"https://bcr.bazel.build/modules/opentelemetry-proto/1.4.0.bcr.1/MODULE.bazel": "5ceaf25e11170d22eded4c8032728b4a3f273765fccda32f9e94f463755c4167",
"https://bcr.bazel.build/modules/opentelemetry-proto/1.5.0/MODULE.bazel": "7543d91a53b98e7b5b37c5a0865b93bff12c1ee022b1e322cd236b968894b030",
"https://bcr.bazel.build/modules/opentelemetry-proto/1.5.0/source.json": "046b721ce203e88cdaad44d7dd17a86b7200eab9388b663b234e72e13ff7b143",
@@ -206,6 +219,7 @@
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
"https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580",
"https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96",
"https://bcr.bazel.build/modules/prometheus-cpp/1.2.4/MODULE.bazel": "0fbe5dcff66311947a3f6b86ebc6a6d9328e31a28413ca864debc4a043f371e5",
"https://bcr.bazel.build/modules/prometheus-cpp/1.3.0.bcr.1/MODULE.bazel": "116ad46e97c1d2aeb020fe2899a342a7e703574ce7c0faf7e4810f938c974a9a",
"https://bcr.bazel.build/modules/prometheus-cpp/1.3.0.bcr.1/source.json": "e813cce2d450708cfcb26e309c5172583a7440776edf354e83e6788c768e5cca",
"https://bcr.bazel.build/modules/prometheus-cpp/1.3.0/MODULE.bazel": "ce82e086bbc0b60267e970f6a54b2ca6d0f22d3eb6633e00e2cc2899c700f3d8",
@@ -213,6 +227,8 @@
"https://bcr.bazel.build/modules/protobuf/23.1/MODULE.bazel": "88b393b3eb4101d18129e5db51847cd40a5517a53e81216144a8c32dfeeca52a",
"https://bcr.bazel.build/modules/protobuf/24.4/MODULE.bazel": "7bc7ce5f2abf36b3b7b7c8218d3acdebb9426aeb35c2257c96445756f970eb12",
"https://bcr.bazel.build/modules/protobuf/25.6/MODULE.bazel": "fc0ae073b47c7ede88b825ff79e64f1c058967c7a87a86cdf4abecd9e0516625",
"https://bcr.bazel.build/modules/protobuf/26.0.bcr.1/MODULE.bazel": "8f04d38c2da40a3715ff6bdce4d32c5981e6432557571482d43a62c31a24c2cf",
"https://bcr.bazel.build/modules/protobuf/26.0.bcr.2/MODULE.bazel": "62e0b84ca727bdeb55a6fe1ef180e6b191bbe548a58305ea1426c158067be534",
"https://bcr.bazel.build/modules/protobuf/26.0/MODULE.bazel": "8402da964092af40097f4a205eec2a33fd4a7748dc43632b7d1629bfd9a2b856",
"https://bcr.bazel.build/modules/protobuf/27.0-rc2/MODULE.bazel": "b2b0dbafd57b6bec0ca9b251da02e628c357dab53a097570aa7d79d020f107cf",
"https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
@@ -236,6 +252,7 @@
"https://bcr.bazel.build/modules/protoc-gen-validate/1.0.4/MODULE.bazel": "b8913c154b16177990f6126d2d2477d187f9ddc568e95ee3e2d50fc65d2c494a",
"https://bcr.bazel.build/modules/protoc-gen-validate/1.2.1.bcr.1/MODULE.bazel": "4bf09676b62fa587ae07e073420a76ec8766dcce7545e5f8c68cfa8e484b5120",
"https://bcr.bazel.build/modules/protoc-gen-validate/1.2.1.bcr.1/source.json": "c19071ebc4b53b5f1cfab9c66eefaf6e4179eb8a998970d07b1077687e777f29",
"https://bcr.bazel.build/modules/protoc-gen-validate/1.2.1/MODULE.bazel": "52b51f50533ec4fbd5d613cd093773f979ac2e035d954e02ca11de383f502505",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680",
@@ -252,8 +269,8 @@
"https://bcr.bazel.build/modules/rules_android/0.6.6/source.json": "a9d8dc2d5a102dc03269a94acc886a4cab82cdcb9ccbc77b0f665d6d17a6ae09",
"https://bcr.bazel.build/modules/rules_apple/3.13.0/MODULE.bazel": "b4559a2c6281ca3165275bb36c1f0ac74666632adc5bdb680e366de7ce845f43",
"https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a",
"https://bcr.bazel.build/modules/rules_apple/4.3.3/MODULE.bazel": "c5c2c4adeeac5f3f2f9b7f16abfa8be7ffefa596171d0d92bed4cae9ade0a498",
"https://bcr.bazel.build/modules/rules_apple/4.3.3/source.json": "3cb1d69c8243ffcc42ecbf84ae8b9cccd7b1e2f091b0aee5a3e9c9a45267f312",
"https://bcr.bazel.build/modules/rules_apple/3.16.0/source.json": "d8b5fe461272018cc07cfafce11fe369c7525330804c37eec5a82f84cd475366",
"https://bcr.bazel.build/modules/rules_apple/3.5.1/MODULE.bazel": "3d1bbf65ad3692003d36d8a29eff54d4e5c1c5f4bfb60f79e28646a924d9101c",
"https://bcr.bazel.build/modules/rules_buf/0.1.1/MODULE.bazel": "6189aec18a4f7caff599ad41b851ab7645d4f1e114aa6431acf9b0666eb92162",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
@@ -296,6 +313,7 @@
"https://bcr.bazel.build/modules/rules_go/0.59.0/MODULE.bazel": "b7e43e7414a3139a7547d1b4909b29085fbe5182b6c58cbe1ed4c6272815aeae",
"https://bcr.bazel.build/modules/rules_go/0.59.0/source.json": "1df17bb7865cfc029492c30163cee891d0dd8658ea0d5bfdf252c4b6db5c1ef6",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/5.1.0/MODULE.bazel": "324b6478b0343a3ce7a9add8586ad75d24076d6d43d2f622990b9c1cfd8a1b15",
"https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
"https://bcr.bazel.build/modules/rules_java/5.5.0/MODULE.bazel": "486ad1aa15cdc881af632b4b1448b0136c76025a1fe1ad1b65c5899376b83a50",
"https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
@@ -373,18 +391,18 @@
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.29.0/MODULE.bazel": "2ac8cd70524b4b9ec49a0b8284c79e4cd86199296f82f6e0d5da3f783d660c82",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.32.2/MODULE.bazel": "01052470fc30b49de91fb8483d26bea6f664500cfad0b078d4605b03e3a83ed4",
"https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
"https://bcr.bazel.build/modules/rules_python/0.37.1/MODULE.bazel": "3faeb2d9fa0a81f8980643ee33f212308f4d93eea4b9ce6f36d0b742e71e9500",
"https://bcr.bazel.build/modules/rules_python/0.37.2/MODULE.bazel": "b5ffde91410745750b6c13be1c5dc4555ef5bc50562af4a89fd77807fdde626a",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
"https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43",
"https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
"https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6",
"https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8",
"https://bcr.bazel.build/modules/rules_python/1.6.3/MODULE.bazel": "a7b80c42cb3de5ee2a5fa1abc119684593704fcd2fec83165ebe615dec76574f",
"https://bcr.bazel.build/modules/rules_python/1.6.3/source.json": "f0be74977e5604a6526c8a416cda22985093ff7d5d380d41722d7e44015cc419",
"https://bcr.bazel.build/modules/rules_python/1.6.0/source.json": "e980f654cf66ec4928672f41fc66c4102b5ea54286acf4aecd23256c84211be6",
"https://bcr.bazel.build/modules/rules_robolectric/4.14.1.2/MODULE.bazel": "d44fec647d0aeb67b9f3b980cf68ba634976f3ae7ccd6c07d790b59b87a4f251",
"https://bcr.bazel.build/modules/rules_robolectric/4.14.1.2/source.json": "37c10335f2361c337c5c1f34ed36d2da70534c23088062b33a8bdaab68aa9dea",
"https://bcr.bazel.build/modules/rules_rust/0.45.1/MODULE.bazel": "a69d0db3a958fab2c6520961e1b2287afcc8b36690fd31bbc4f6f7391397150d",
@@ -402,10 +420,8 @@
"https://bcr.bazel.build/modules/rules_shell/0.5.0/MODULE.bazel": "8c8447370594d45539f66858b602b0bb2cb2d3401a4ebb9ad25830c59c0f366d",
"https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b",
"https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
"https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
"https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
"https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd",
"https://bcr.bazel.build/modules/rules_swift/2.4.0/source.json": "a6577f57f9febbdc015a01f2a8f3487422032f134d6c61d18ed8e8ca3b9acc7c",
"https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400",
"https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66",
"https://bcr.bazel.build/modules/stardoc/0.5.0/MODULE.bazel": "f9f1f46ba8d9c3362648eea571c6f9100680efc44913618811b58cc9c02cd678",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
@@ -416,8 +432,8 @@
"https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
"https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
"https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b",
"https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468",
"https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351",
"https://bcr.bazel.build/modules/tar.bzl/0.6.0/MODULE.bazel": "a3584b4edcfafcabd9b0ef9819808f05b372957bbdff41601429d5fd0aac2e7c",
@@ -426,18 +442,23 @@
"https://bcr.bazel.build/modules/toolchains_llvm/1.6.0/source.json": "6bd3ef95a288dd2bb1582eca332af850c9a5428a23bb92cb1c57c2dfe6cb7369",
"https://bcr.bazel.build/modules/toolchains_protoc/0.5.0/MODULE.bazel": "e649dcd74790d8b186517588c827a777dfa67acfc4cbd733721c4be143ea107f",
"https://bcr.bazel.build/modules/toolchains_protoc/0.5.0/source.json": "9152bf33827a44f796f94f486252fc0128d9efc2413246ebb09a234bb628a846",
"https://bcr.bazel.build/modules/upb/0.0.0-20211020-160625a/MODULE.bazel": "6cced416be2dc5b9c05efd5b997049ba795e5e4e6fafbe1624f4587767638928",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9",
"https://bcr.bazel.build/modules/upb/0.0.0-20230907-e7430e6/MODULE.bazel": "3a7dedadf70346e678dc059dbe44d05cbf3ab17f1ce43a1c7a42edc7cbf93fd9",
"https://bcr.bazel.build/modules/xds/0.0.0-20240423-555b57e/MODULE.bazel": "cea509976a77e34131411684ef05a1d6ad194dd71a8d5816643bc5b0af16dc0f",
"https://bcr.bazel.build/modules/xds/0.0.0-20240423-555b57e/source.json": "7227e1fcad55f3f3cab1a08691ecd753cb29cc6380a47bc650851be9f9ad6d20",
"https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072",
"https://bcr.bazel.build/modules/yq.bzl/0.1.1/source.json": "2d2bad780a9f2b9195a4a370314d2c17ae95eaa745cefc2e12fbc49759b15aa3",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
"https://bcr.bazel.build/modules/zlib/1.2.13/MODULE.bazel": "aa6deb1b83c18ffecd940c4119aff9567cd0a671d7bba756741cb2ef043a29d5",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.1/MODULE.bazel": "6a9fe6e3fc865715a7be9823ce694ceb01e364c35f7a846bf0d2b34762bc066b",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198",
"https://bcr.bazel.build/modules/zlib/1.3/MODULE.bazel": "6a9c02f19a24dcedb05572b2381446e27c272cd383aed11d41d99da9e3167a72"
},
"selectedYankedVersions": {},
"moduleExtensions": {
@@ -1138,12 +1159,168 @@
},
"@@googleapis+//:extensions.bzl%switched_rules": {
"general": {
"bzlTransitiveDigest": "liqpEiZfQn8ycdEspyJt6J+baY9GQOl+9/prJJz2wTA=",
"usagesDigest": "AtKnJVSfl4DFbEt1Zhzwc971VYZMgmyRYK8WMKrwA7o=",
"bzlTransitiveDigest": "vG6fuTzXD8MMvHWZEQud0MMH7eoC4GXY0va7VrFFh04=",
"usagesDigest": "tB2/BAROtqvrfaBweAJxJpqqnx85mOx/aupy9bEK4Ss=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {},
"generatedRepoSpecs": {
"com_google_googleapis_imports": {
"repoRuleId": "@@googleapis+//:repository_rules.bzl%switched_rules",
"attributes": {
"rules": {
"proto_library_with_info": [
"",
""
],
"moved_proto_library": [
"",
""
],
"java_proto_library": [
"",
""
],
"java_grpc_library": [
"",
""
],
"java_gapic_library": [
"",
""
],
"java_gapic_test": [
"",
""
],
"java_gapic_assembly_gradle_pkg": [
"",
""
],
"py_proto_library": [
"",
""
],
"py_grpc_library": [
"",
""
],
"py_gapic_library": [
"",
""
],
"py_test": [
"",
""
],
"py_gapic_assembly_pkg": [
"",
""
],
"py_import": [
"",
""
],
"go_proto_library": [
"",
""
],
"go_grpc_library": [
"",
""
],
"go_library": [
"",
""
],
"go_test": [
"",
""
],
"go_gapic_library": [
"",
""
],
"go_gapic_assembly_pkg": [
"",
""
],
"cc_proto_library": [
"",
""
],
"cc_grpc_library": [
"",
""
],
"cc_gapic_library": [
"",
""
],
"php_proto_library": [
"",
"php_proto_library"
],
"php_grpc_library": [
"",
"php_grpc_library"
],
"php_gapic_library": [
"",
"php_gapic_library"
],
"php_gapic_assembly_pkg": [
"",
"php_gapic_assembly_pkg"
],
"nodejs_gapic_library": [
"",
"typescript_gapic_library"
],
"nodejs_gapic_assembly_pkg": [
"",
"typescript_gapic_assembly_pkg"
],
"ruby_proto_library": [
"",
""
],
"ruby_grpc_library": [
"",
""
],
"ruby_ads_gapic_library": [
"",
""
],
"ruby_cloud_gapic_library": [
"",
""
],
"ruby_gapic_assembly_pkg": [
"",
""
],
"csharp_proto_library": [
"",
""
],
"csharp_grpc_library": [
"",
""
],
"csharp_gapic_library": [
"",
""
],
"csharp_gapic_assembly_pkg": [
"",
""
]
}
}
}
},
"recordedRepoMappingEntries": []
}
},
@@ -1243,6 +1420,34 @@
"recordedRepoMappingEntries": []
}
},
"@@rules_apple+//apple:extensions.bzl%non_module_deps": {
"general": {
"bzlTransitiveDigest": "UsflLeiazyu2v5pvibcvOeIdDV95S25rT96h4XU1nhY=",
"usagesDigest": "M3VqFpeTCo4qmrNKGZw0dxBHvTYDrfV3cscGzlSAhQ4=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"xctestrunner": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/google/xctestrunner/archive/b7698df3d435b6491b4b4c0f9fc7a63fbed5e3a6.tar.gz"
],
"strip_prefix": "xctestrunner-b7698df3d435b6491b4b4c0f9fc7a63fbed5e3a6",
"sha256": "ae3a063c985a8633cb7eb566db21656f8db8eb9a0edb8c182312c7f0db53730d"
}
}
},
"recordedRepoMappingEntries": [
[
"rules_apple+",
"bazel_tools",
"bazel_tools"
]
]
}
},
"@@rules_dotnet+//dotnet:extensions.bzl%dotnet": {
"general": {
"bzlTransitiveDigest": "fd+R6GHICVvxgxz6YGDAcp7EbUx26nq9MWH1unOHz9I=",
@@ -2193,7 +2398,7 @@
"@@rules_python+//python/uv:uv.bzl%uv": {
"general": {
"bzlTransitiveDigest": "8vT1ddXtljNxYD0tJkksqzeKE6xqx4Ix+tXthAppjTI=",
"usagesDigest": "icnInV8HDGrRQf9x8RMfxWfBHgT3OgRlYovS/9POEJw=",
"usagesDigest": "p80sy6cYQuWxx5jhV3fOTu+N9EyIUFG9+F7UC/nhXic=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
@@ -3528,160 +3733,6 @@
]
]
}
},
"@@rules_swift+//swift:extensions.bzl%non_module_deps": {
"general": {
"bzlTransitiveDigest": "gITmwZkwiDAjxHDTZA8AxJiD5JGajyGl/ExE3dyszB0=",
"usagesDigest": "9w18ec4dj90mX/JqpR2tBU2YVc1GU9yNxi/d7q6lLVA=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"com_github_apple_swift_protobuf": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-protobuf/archive/1.20.2.tar.gz"
],
"sha256": "3fb50bd4d293337f202d917b6ada22f9548a0a0aed9d9a4d791e6fbd8a246ebb",
"strip_prefix": "swift-protobuf-1.20.2/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_protobuf/BUILD.overlay"
}
},
"com_github_grpc_grpc_swift": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/grpc/grpc-swift/archive/1.16.0.tar.gz"
],
"sha256": "58b60431d0064969f9679411264b82e40a217ae6bd34e17096d92cc4e47556a5",
"strip_prefix": "grpc-swift-1.16.0/",
"build_file": "@@rules_swift+//third_party:com_github_grpc_grpc_swift/BUILD.overlay"
}
},
"com_github_apple_swift_docc_symbolkit": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-docc-symbolkit/archive/refs/tags/swift-5.10-RELEASE.tar.gz"
],
"sha256": "de1d4b6940468ddb53b89df7aa1a81323b9712775b0e33e8254fa0f6f7469a97",
"strip_prefix": "swift-docc-symbolkit-swift-5.10-RELEASE",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_docc_symbolkit/BUILD.overlay"
}
},
"com_github_apple_swift_nio": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio/archive/2.42.0.tar.gz"
],
"sha256": "e3304bc3fb53aea74a3e54bd005ede11f6dc357117d9b1db642d03aea87194a0",
"strip_prefix": "swift-nio-2.42.0/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio/BUILD.overlay"
}
},
"com_github_apple_swift_nio_http2": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-http2/archive/1.26.0.tar.gz"
],
"sha256": "f0edfc9d6a7be1d587e5b403f2d04264bdfae59aac1d74f7d974a9022c6d2b25",
"strip_prefix": "swift-nio-http2-1.26.0/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_http2/BUILD.overlay"
}
},
"com_github_apple_swift_nio_transport_services": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-transport-services/archive/1.15.0.tar.gz"
],
"sha256": "f3498dafa633751a52b9b7f741f7ac30c42bcbeb3b9edca6d447e0da8e693262",
"strip_prefix": "swift-nio-transport-services-1.15.0/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_transport_services/BUILD.overlay"
}
},
"com_github_apple_swift_nio_extras": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-extras/archive/1.4.0.tar.gz"
],
"sha256": "4684b52951d9d9937bb3e8ccd6b5daedd777021ef2519ea2f18c4c922843b52b",
"strip_prefix": "swift-nio-extras-1.4.0/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_extras/BUILD.overlay"
}
},
"com_github_apple_swift_log": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-log/archive/1.4.4.tar.gz"
],
"sha256": "48fe66426c784c0c20031f15dc17faf9f4c9037c192bfac2f643f65cb2321ba0",
"strip_prefix": "swift-log-1.4.4/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_log/BUILD.overlay"
}
},
"com_github_apple_swift_nio_ssl": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-ssl/archive/2.23.0.tar.gz"
],
"sha256": "4787c63f61dd04d99e498adc3d1a628193387e41efddf8de19b8db04544d016d",
"strip_prefix": "swift-nio-ssl-2.23.0/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_ssl/BUILD.overlay"
}
},
"com_github_apple_swift_collections": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-collections/archive/1.0.4.tar.gz"
],
"sha256": "d9e4c8a91c60fb9c92a04caccbb10ded42f4cb47b26a212bc6b39cc390a4b096",
"strip_prefix": "swift-collections-1.0.4/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_collections/BUILD.overlay"
}
},
"com_github_apple_swift_atomics": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-atomics/archive/1.1.0.tar.gz"
],
"sha256": "1bee7f469f7e8dc49f11cfa4da07182fbc79eab000ec2c17bfdce468c5d276fb",
"strip_prefix": "swift-atomics-1.1.0/",
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_atomics/BUILD.overlay"
}
},
"build_bazel_rules_swift_index_import": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"build_file": "@@rules_swift+//third_party:build_bazel_rules_swift_index_import/BUILD.overlay",
"canonical_id": "index-import-5.8",
"urls": [
"https://github.com/MobileNativeFoundation/index-import/releases/download/5.8.0.1/index-import.tar.gz"
],
"sha256": "28c1ffa39d99e74ed70623899b207b41f79214c498c603915aef55972a851a15"
}
},
"build_bazel_rules_swift_local_config": {
"repoRuleId": "@@rules_swift+//swift/internal:swift_autoconfiguration.bzl%swift_autoconfiguration",
"attributes": {}
}
},
"recordedRepoMappingEntries": [
[
"rules_swift+",
"bazel_tools",
"bazel_tools"
]
]
}
}
},
"facts": {
+2 -44
View File
@@ -40,19 +40,6 @@ if [ -f "$INFO_PLIST" ]; then
/usr/libexec/PlistBuddy -c "Set :ITSAppUsesNonExemptEncryption false" "$INFO_PLIST" 2>/dev/null \
|| /usr/libexec/PlistBuddy -c "Add :ITSAppUsesNonExemptEncryption bool false" "$INFO_PLIST"
echo "Set ITSAppUsesNonExemptEncryption=false in Info.plist"
# Remove UIApplicationSceneManifest if present.
# Unity 6 generates this key, which opts the app into the iOS scene-based
# lifecycle. This breaks Application.deepLinkActivated because iOS routes
# deep link URLs through UISceneDelegate instead of UIApplicationDelegate,
# and Unity doesn't implement the scene delegate path.
# See: https://issuetracker.unity3d.com/issues/in-135632
if /usr/libexec/PlistBuddy -c "Print :UIApplicationSceneManifest" "$INFO_PLIST" 2>/dev/null; then
echo "Found UIApplicationSceneManifest in Info.plist — removing to fix deep link handling"
/usr/libexec/PlistBuddy -c "Delete :UIApplicationSceneManifest" "$INFO_PLIST"
else
echo "No UIApplicationSceneManifest in Info.plist (deep links should work)"
fi
fi
# Unity always generates "Unity-iPhone" as the main app scheme
@@ -101,16 +88,6 @@ EOF
echo "Exporting IPA..."
# Restore keychain search list before export.
# xcodebuild archive can reset the user keychain search list during long
# builds, dropping the temporary CI keychain that holds the signing cert.
# Re-add it here so xcodebuild -exportArchive can find the certificate.
if [ -n "${KEYCHAIN_NAME:-}" ]; then
echo "Restoring keychain search list (adding $KEYCHAIN_NAME)"
security list-keychains -d user -s "$KEYCHAIN_NAME" login.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME"
fi
# Debug: List available keychains and signing identities
echo "=== Debug: Available keychains ==="
security list-keychains -d user
@@ -120,24 +97,11 @@ echo "=== Debug: Export options plist ==="
cat "$EXPORT_OPTIONS_PLIST"
echo "=== End debug ==="
# Export IPA with App Store Connect API key authentication.
# Without the API key, xcodebuild falls back to the Xcode-Token in the
# keychain, which expires periodically and breaks headless CI builds.
EXPORT_AUTH_ARGS=()
if [ -n "${APP_STORE_CONNECT_API_KEY_PATH:-}" ] && [ -n "${APP_STORE_CONNECT_API_KEY_ID:-}" ] && [ -n "${APP_STORE_CONNECT_API_ISSUER_ID:-}" ]; then
echo "Using App Store Connect API key for export authentication"
EXPORT_AUTH_ARGS=(
-authenticationKeyPath "$APP_STORE_CONNECT_API_KEY_PATH"
-authenticationKeyID "$APP_STORE_CONNECT_API_KEY_ID"
-authenticationKeyIssuerID "$APP_STORE_CONNECT_API_ISSUER_ID"
)
fi
# Export IPA (removed -allowProvisioningUpdates as we're using manual signing)
xcodebuild -exportArchive \
-archivePath "$ARCHIVE_PATH" \
-exportPath "$EXPORT_PATH" \
-exportOptionsPlist "$EXPORT_OPTIONS_PLIST" \
"${EXPORT_AUTH_ARGS[@]}"
-exportOptionsPlist "$EXPORT_OPTIONS_PLIST"
# Find and rename the IPA to a consistent name
IPA_FILE=$(find "$EXPORT_PATH" -name "*.ipa" | head -1)
@@ -147,9 +111,3 @@ fi
echo "Export complete: $EXPORT_PATH/eagle0.ipa"
ls -la "$EXPORT_PATH"
# Clean up DerivedData for Unity-iPhone builds.
# Each build creates a new ~3.6GB folder (Unity-iPhone-<random>) that
# accumulates and wastes disk space on the build runner.
echo "Cleaning up Unity-iPhone DerivedData..."
find ~/Library/Developer/Xcode/DerivedData -maxdepth 1 -name 'Unity-iPhone-*' -type d -exec rm -rf {} + 2>/dev/null || true
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env bash
# Build iOS Addressables only (no player build)
# This switches Unity to iOS target and builds addressables for CDN upload
set -euxo pipefail
# Read Unity version from project file
UNITY_VERSION=$(grep "m_EditorVersion:" src/main/csharp/net/eagle0/clients/unity/eagle0/ProjectSettings/ProjectVersion.txt | head -1 | sed 's/m_EditorVersion: //')
# Use runner-specific build directory if EAGLE0_BUILD_DIR is set, otherwise default
BUILD_BASE="${EAGLE0_BUILD_DIR:-/tmp/eagle0}"
WORKSPACE=$(pwd)
echo "Building protos"
./scripts/build_protos.sh
UNITY_INSTALL_PATH="/Applications/Unity/Hub/Editor"
LOG_PATH=${1:-"${BUILD_BASE}/editor_ios_addressables.log"}
echo "Building iOS Addressables"
mkdir -p "$(dirname "$LOG_PATH")"
# Build Addressables for iOS target
# Uses BuildiOSAddressables which explicitly switches build target
# Capture exit code to show log on failure
set +e
${UNITY_INSTALL_PATH}/${UNITY_VERSION}/Unity.app/Contents/MacOS/Unity \
-nographics \
-batchmode \
-quit \
-executeMethod BuildScript.BuildiOSAddressables \
-logFile "$LOG_PATH" \
-projectPath "$WORKSPACE/src/main/csharp/net/eagle0/clients/unity/eagle0"
UNITY_EXIT_CODE=$?
set -e
if [ $UNITY_EXIT_CODE -ne 0 ]; then
echo ""
echo "Unity build failed with exit code $UNITY_EXIT_CODE"
echo "=== Unity Editor Log (last 200 lines) ==="
tail -200 "$LOG_PATH" || echo "Could not read log file at $LOG_PATH"
echo "=== End of Unity Editor Log ==="
exit $UNITY_EXIT_CODE
fi
echo "iOS Addressables build complete"
echo "Bundles should be in: $WORKSPACE/src/main/csharp/net/eagle0/clients/unity/eagle0/ServerData/iOS/"
-35
View File
@@ -1,35 +0,0 @@
#!/bin/bash
# Fetch LFS files from Gitea mirror with retry.
#
# Gitea's mirror-sync API is async — the webhook fires on push but the
# actual sync may still be in progress when CI starts. Retry with backoff
# to bridge the gap.
#
# Usage:
# ./ci/github_actions/fetch_lfs.sh # full pull
# ./ci/github_actions/fetch_lfs.sh --include="path/to/*" # selective pull
set -euo pipefail
MAX_ATTEMPTS=5
RETRY_DELAY=15
git lfs install
echo "LFS objects before pull:"
git lfs ls-files | wc -l
for i in $(seq 1 $MAX_ATTEMPTS); do
if git lfs pull "$@"; then
echo "LFS objects after pull:"
git lfs ls-files | wc -l
exit 0
fi
if [ "$i" -lt "$MAX_ATTEMPTS" ]; then
echo "LFS pull attempt $i/$MAX_ATTEMPTS failed, retrying in ${RETRY_DELAY}s..."
sleep $RETRY_DELAY
fi
done
echo "LFS pull failed after $MAX_ATTEMPTS attempts"
exit 1
-2
View File
@@ -217,8 +217,6 @@ services:
DO_SPACES_ENDPOINT: "${DO_SPACES_ENDPOINT:-https://sfo3.digitaloceanspaces.com}"
DO_SPACES_ACCESS_KEY: "${ADMIN_S3_ACCESS_KEY:-}"
DO_SPACES_SECRET_KEY: "${ADMIN_S3_SECRET_KEY:-}"
# GitHub PAT for map editor PR creation (scoped to contents:write + pull_requests:write)
GITHUB_TOKEN: "${GITHUB_TOKEN:-}"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# No external port - accessed via nginx at admin.eagle0.net
-281
View File
@@ -1,281 +0,0 @@
# Allied Victory: Battle Resolution Flow
How allied victories work end-to-end, from Shardok tactical resolution through Eagle strategic
processing to player-facing aftermath decisions.
## 1. Battle Setup (Eagle -> Shardok)
When Eagle sends a battle to Shardok via `RequestBattlesAction`, each player gets specific victory
conditions:
| Player | Victory Conditions |
|-------------|-----------------------------------------------------------------------|
| Attacker(s) | `HoldsCriticalTiles`, `LastPlayerStanding`, `LastAllianceStanding` |
| Defender | `LastPlayerStanding`, `WinAfterMaxRounds` |
This is set in `RequestBattlesAction.shardokPlayers`.
Alliance information is sent separately in `PlayerSetupInfo.allies`. Eagle reads each player's
`factionRelationships` and includes all non-HOSTILE factions as allies
(`ShardokInterfaceGrpcClient.scala:75-80`).
## 2. Victory Condition Evaluation (Shardok)
Victory conditions are checked in `UpdateGameStatusAction.cpp` in priority order:
### Check 1: LastPlayerStanding (any time)
If exactly **one** player has surviving units and has `LastPlayerStanding`:
- That player is the sole winner.
- This applies to solo victories only (1 survivor).
### Check 2: LastAllianceStanding (any time)
If **multiple** players survive, check if they form a winning alliance:
- ALL survivors must have `LastAllianceStanding` condition
- ALL survivors must be **mutually** allied (every pair checks both directions)
- If yes: all survivors are winners
This triggers for AssaultProvince battles when allied attackers eliminate all defenders. Since the
defender does **not** have `LastAllianceStanding`, the check correctly requires that only the
allied attackers remain alive.
### Check 3: WinAfterMaxRounds (end-of-round only)
If the round counter exceeds `max_rounds`:
- Find the player with `WinAfterMaxRounds` (always the defender)
- That player wins, even if they have no surviving units
- Eagle validates exactly 1 player has this condition (`internalRequire` in `RequestBattlesAction`)
### Check 4: HoldsCriticalTiles (end-of-round only)
**Single-player castle control**: If one player with `HoldsCriticalTiles` occupies ALL critical
tiles with hero-bearing units, that player wins. Additionally, any other player who:
- Has `HoldsCriticalTiles`
- Is **mutually** allied with the castle holder
is also added to `winning_shardok_ids` as a co-winner.
**Allied castle control**: If multiple players collectively occupy all critical tiles with
hero-bearing units, AND:
- All occupants have `HoldsCriticalTiles`
- All occupants are mutually allied
Then all occupants are winners together.
## 3. EndGameCondition Assignment Per Player (Shardok -> Eagle)
Shardok assigns each player a `Victory` or `Loss`. All winners receive `Victory`; there is no
`AllyVictory` distinction. The `EndGameCondition` proto reserves fields 2 (`ally_victory`) and
3 (`draw`) for backwards compatibility but Eagle rejects both.
`GameOverResponsePopulator` validates that any player allied to a winner is also in
`winning_shardok_ids`. If an ally is missing from the winners list, it throws an internal error.
**Known issue**: This validation is too strict for `LastPlayerStanding`. When one allied attacker
is the sole survivor, their dead co-attacker is allied to the winner but legitimately not in
`winning_shardok_ids` (they're dead). The throw should be changed to `Loss` for dead allies, or
the check should only apply when the ally has surviving units.
| Condition | Criterion |
|-----------|-----------|
| `Victory(type)` | Player is in `winning_shardok_ids` |
| `Loss(type)` | Player is not in `winning_shardok_ids` |
The `type` is the VictoryCondition that caused the game to end (e.g., `HoldsCriticalTiles`).
### When do multiple players get Victory?
In standard AssaultProvince battles:
1. **Allied attackers jointly hold all castles** -> both get `Victory(HoldsCriticalTiles)`.
2. **One attacker holds all castles alone, ally has `HoldsCriticalTiles` and is mutually allied**
-> both get `Victory(HoldsCriticalTiles)`. The ally is added to `winning_shardok_ids` by
`UpdateGameStatusAction`.
3. **Allied attackers eliminate all defenders** -> both get `Victory(LastAllianceStanding)`.
This triggers because both have `LastAllianceStanding` and are mutually allied.
4. **One attacker holds all castles, co-attacker is NOT allied** -> only the castle holder
gets `Victory(HoldsCriticalTiles)`; the non-allied co-attacker gets `Loss`.
## 4. Eagle Processes Battle Results
`ResolveBattleAction.scala` receives `BattleResolution` containing each player's
`EndGameCondition` and resolved units.
### Winner/Loser Partition
Players are split by `isVictory` (line 383-386):
- `winningResolvedPlayers`: Victory
- `losingResolvedPlayers`: Loss
### The `unitReturned` Function (line 765-788)
Determines which units go home vs stay at the battle province:
| Unit Status | Returned? | Notes |
|---------------|-----------|-------|
| `Fled` | Always | Sent to their army's flee province |
| `NeverEntered`| Conditional | Only if: attacker AND has flee province AND did NOT win (`!isVictory`) |
| `Captured` | Never | |
| `Normal` | Never | |
| `Retreated` | Never | |
| `Outlawed` | Never | Becomes unaffiliated hero |
Key point: `NeverEntered` units from **winning** factions stay at the battle province rather than
being sent home. This is important for bounced co-attackers who are allied with the actual winner.
### Withdrawn/Fled Unit Routing (line 690-706)
For units that ARE returned, `armyFromResolvedArmy` builds a returning army with
`fleeProvinceId = None`. If the army has no `fleeProvinceId`, it becomes "shattered" (units
become outlaws in the battle province). If the original army had a `fleeProvinceId` set, returned
units are sent there as incoming armies.
### Battle Resolution Branching (line 397-552)
Three branches based on who won:
#### Branch A: Defender Won
Triggered when: `winningShardokPlayers.exists(_.isDefender)`
- Executes `ProvinceHeldAction`
- All non-defender, non-returned, non-outlawed units are **captured**
- Province stays with the defending faction
#### Branch B: Single Attacker Won
Triggered when: exactly 1 attacking winner
- Executes `ProvinceConqueredAction` immediately
- Winning attacker's non-fled units occupy the province
- Losing defenders' non-fled units are captured
- Province transfers to the attacker
#### Branch C: Multiple Allied Attackers Won
Triggered when: 2+ attacking winners
- Executes `MultiVictorBattleSetupAction`
- Creates `PendingConquestInfo` with aftermath claimants
- Province enters the **Battle Aftermath** phase
## 5. Battle Aftermath (Multi-Victor Only)
When multiple allied attackers win, the province enters an aftermath decision phase where players
decide who keeps it.
### Claimant Setup
Each attacking winner becomes an `AftermathClaimant` with:
- `units`: their non-fled, non-outlawed units still at the battle province
- `armySize`: total troop count of those units
- `broughtGold` / `broughtFood`: supplies their armies carried
Claimants are **sorted by army size descending** (largest army decides first).
### Decision Phase
Claimants are presented with a choice **one at a time**, in order:
**If no one has chosen "Keep" yet:**
- **Keep Province**: claim the province for your faction
- **Withdraw To**: pick an adjacent province to march your army to, optionally carrying up to
the gold/food you brought
**If someone already chose "Keep":**
- **Withdraw To** is the only option (can't have two keepers)
**Last undecided claimant:**
- If no one has chosen "Keep" yet, the last claimant **automatically keeps** (no command shown,
resolved by `AutoResolveBattleAftermathAction`)
- This guarantees someone always claims the province
### Finalization
Once all claimants have decided (`FinalizeAftermathAction`):
1. The keeper's units run through `ProvinceConqueredAction` -- province transfers to their faction
2. Withdrawing claimants' units become incoming armies to their chosen adjacent province,
arriving next round, carrying the specified supplies
3. `PendingConquestInfo` is cleared from the province
## 6. Summary: Who Gets What
### Two allied attackers jointly hold all castles
- Shardok: Both get `Victory(HoldsCriticalTiles)` (both in `winning_shardok_ids`)
- Eagle: Both are attacking winners -> MultiVictorBattleSetupAction
- Players: Largest army picks first: Keep or Withdraw. Last player auto-keeps if no one chose Keep.
### One attacker holds all castles, allied attacker doesn't
- Shardok: Castle-holder gets `Victory(HoldsCriticalTiles)`. Mutually-allied co-attacker with
`HoldsCriticalTiles` is added to `winning_shardok_ids` -> also gets `Victory(HoldsCriticalTiles)`.
- Eagle: Both are attacking winners -> MultiVictorBattleSetupAction -> Battle Aftermath.
- Players: Largest army picks first: Keep or Withdraw.
### Allied attackers eliminate all defenders
- Shardok: Both attackers have `LastAllianceStanding` and are mutually allied -> both get
`Victory(LastAllianceStanding)`.
- Eagle: Both are attacking winners -> MultiVictorBattleSetupAction -> Battle Aftermath.
- Players: Largest army picks first: Keep or Withdraw.
### Non-allied co-attackers: one holds all castles
- Shardok: Castle-holder gets `Victory(HoldsCriticalTiles)`, non-allied co-attacker gets
`Loss(HoldsCriticalTiles)`.
- Eagle: Single attacker won -> ProvinceConqueredAction. Non-allied co-attacker's units are
captured along with the defender's.
### One allied attacker is sole survivor (LastPlayerStanding)
- Shardok: Sole survivor gets `Victory(LastPlayerStanding)`. Dead ally should get `Loss`.
- **BUG**: `GameOverResponsePopulator` currently throws because dead ally is allied to winner
but not in `winning_shardok_ids`. Needs fix — see known issue in Section 3.
- Eagle (once fixed): Single attacker won -> ProvinceConqueredAction. Dead ally's units were
already destroyed in battle.
### Single attacker wins (any condition, no co-attackers)
- No alliance considerations. ProvinceConqueredAction immediately.
### Defender wins (WinAfterMaxRounds or LastPlayerStanding)
- ProvinceHeldAction. All non-returned attacker units are captured.
## 7. Edge Cases and Known Issues
### BUG: Dead ally causes crash via LastPlayerStanding
When one allied attacker is the sole survivor (both the co-attacker and defender are dead),
`LastPlayerStanding` fires and only the survivor is in `winning_shardok_ids`. The
`GameOverResponsePopulator` then sees the dead co-attacker is allied to the winner but not in
`winning_shardok_ids`, and throws `ShardokInternalErrorException`. Fix: dead allies should
receive `Loss`, not trigger a validation error.
### Non-allied co-attackers eliminate all defenders
Two non-allied attackers who both survive after eliminating the defender cannot win via
`LastAllianceStanding` (they aren't mutually allied). The game continues until max rounds,
at which point the defender wins via `WinAfterMaxRounds`. They must capture all critical tiles.
### Non-allied co-attackers: one holds all castles
Only the castle holder wins. The non-allied co-attacker gets `Loss` and their units are captured
along with the defender's. The mutual-alliance check in `UpdateGameStatusAction` prevents
non-allied players from being added to `winning_shardok_ids`.
## Key File References
| Component | File |
|-----------|------|
| Victory condition checking | `src/main/cpp/net/eagle0/shardok/library/actions/UpdateGameStatusAction.cpp` |
| Per-player EndGameCondition | `src/main/cpp/net/eagle0/shardok/server/GameOverResponsePopulator.cpp` |
| Battle setup (victory conditions) | `src/main/scala/.../library/actions/impl/action/RequestBattlesAction.scala` |
| Alliance communication | `src/main/scala/.../shardok_interface/ShardokInterfaceGrpcClient.scala:75-80` |
| Battle result processing | `src/main/scala/.../library/actions/impl/action/ResolveBattleAction.scala` |
| Unit return logic | `ResolveBattleAction.scala:765-788` (`unitReturned`) |
| Multi-victor setup | `src/main/scala/.../library/actions/impl/action/MultiVictorBattleSetupAction.scala` |
| Aftermath availability | `src/main/scala/.../library/actions/availability/AvailableBattleAftermathDecisionCommandFactory.scala` |
| Aftermath command | `src/main/scala/.../library/actions/impl/command/BattleAftermathDecisionCommand.scala` |
| Auto-resolve last claimant | `src/main/scala/.../library/actions/impl/action/AutoResolveBattleAftermathAction.scala` |
| Finalize aftermath | `src/main/scala/.../library/actions/impl/action/FinalizeAftermathAction.scala` |
| EndGameCondition enum | `src/main/scala/.../model/state/shardok_battle/EndGameCondition.scala` |
+1 -25
View File
@@ -12,7 +12,7 @@ This document catalogs all media assets in the Unity project for licensing revie
|----------|-------|-------|
| Images | 10,637 | Mostly PNG icons and UI sprites |
| Audio | 1,778 | 26 music tracks + 1,752 sound effects |
| 3D Models | 66+ | Bridge pack, Animal pack deluxe, Honey Badger |
| 3D Models | 52 | Bridge pack only |
| Fonts | 16 | TTF files |
---
@@ -55,30 +55,6 @@ These are commercial Unity Asset Store purchases tied to your account:
- **Contents:** Bridge construction pieces
- **License:** Unity Asset Store
### Animal pack deluxe
- **Location:** `Assets/Animal pack deluxe/`
- **Publisher:** janpec
- **Asset Store Link:** https://assetstore.unity.com/packages/3d/characters/animals/animal-pack-deluxe-99702
- **Contents:** 26 rigged and animated 3D animal models (bear, boar, crocodile, wolf, frog, crab, rabbit, scorpion, snake, stag, deer, rat, goat, pig, etc.) with idle, walk, run, eat, attack, and die animations
- **Used for:** Beast province effects on the strategic map (AnimalEffect)
- **License:** Unity Asset Store
### 2D Monster Pack: Basic Bundle (+PSB)
- **Location:** `Assets/DungeonMonsters2D/`
- **Publisher:** SP1
- **Asset Store Link:** https://assetstore.unity.com/packages/2d/characters/2d-monster-pack-basic-bundle-psb-328637
- **Contents:** 2D animated monster sprites with PSB (Photoshop) source files. Characters: SkeletonWarrior, SkeletonArcher, SkeletonMage, Zombie, ZombieWarrior, Demon, Succubus, Imp, Spider, Rat, Vampire, DragonRed, Butcher
- **Used for:** Beast province effects (MonsterEffect, DragonEffect) and human-type beast effects on the strategic map
- **License:** Unity Asset Store
### Honey Badger 3D Model
- **Location:** `Assets/HoneyBadger/`
- **Creator:** WildMesh 3D (@WildMesh_3D)
- **Source:** https://sketchfab.com/3d-models/realistic-honey-badger-3d-model-09751ed5383c4afb924cfb6485d313f1
- **Contents:** Rigged 3D honey badger model (FBX) with 63 animations and PBR texture
- **Used for:** Honey badger beast province effect (AnimalEffect)
- **License:** Purchased via Sketchfab/Patreon
### Fantasy Interface Sounds
- **Location:** `Assets/Fantasy Interface Sounds/`
- **Count:** 320 WAV files
-246
View File
@@ -1,246 +0,0 @@
# Adding Beast-Type-Specific Effects
When a province has a `BeastsEvent`, `ProvinceBeastsController` spawns a visual effect at the province centroid. By default this is the generic `BeastsEffect` (circling vultures/crows). Beast-specific effects can override this based on `BeastInfo.SingularName`.
## Architecture
```
ProvinceBeastsController
├── GetBeastName(province) → reads BeastsEvent.BeastInfo.SingularName
├── GetEffectPrefab(beastName) → switch on name → returns prefab
└── SpawnBeastsEffect(provinceId, beastName) → instantiates at centroid
```
**Key files:**
| File | Purpose |
|------|---------|
| `Assets/Eagle/ProvinceBeastsController.cs` | Routes beast names to prefabs, positions effects |
| `Assets/Eagle/BeastsEffect.cs` | Generic effect (circling birds via particle system) |
| `Assets/Eagle/DragonEffect.cs` | Dragon-specific effect (3D model with flying/ground modes) |
| `Assets/Eagle/MonsterEffect.cs` | Wandering 2D monster group (DungeonMonsters2D prefabs) |
| `Assets/Eagle/AnimalEffect.cs` | Wandering 3D animal group (Animal Pack Deluxe prefabs) |
| `Assets/Eagle/Effects/` | All effect prefabs |
## Adding a new beast type
### 1. Create the effect MonoBehaviour (or reuse an existing one)
Three effect scripts exist for different asset types:
**MonsterEffect** (2D sprites, DungeonMonsters2D): Spawns a group of wandering 2D monsters. Uses PascalCase animator states (`Idle`, `Move`) and triggers (`AttackTrigger`, `SpecialATrigger`). Flips sprite X scale for facing direction. Best for DungeonMonsters2D prefabs.
**AnimalEffect** (3D models, Animal Pack Deluxe): Spawns a group of wandering 3D animals. Uses lowercase animator states (`idle`, `walk`, `eat`, `attack`) with `Animator.Play()`. Rotates model on Y axis for facing. Sets `sortingOrder=103`, `renderQueue=4000`, and `ZTest=Always` to render above the map. Best for Animal Pack Deluxe prefabs.
**DragonEffect** (single animated 3D creature): Spawns a 3D dragon that alternates between flying (circling at altitude with fly actions) and grounded (wandering with ground actions) modes. Uses `Animator.Play()` with DragonMapAnims controller. Best for large creatures with flight capabilities.
**Particle-based** (like `BeastsEffect.cs`): Good for simple effects like swarms or atmospheric particles.
To create a new effect script, use `[RequireComponent(typeof(RectTransform))]` for UI canvas positioning and accept tuning parameters as public fields.
### 2. Create the prefab
1. Create an empty GameObject in `Assets/Eagle/Effects/`
2. Add a `RectTransform` component
3. Add your effect MonoBehaviour
4. Wire up any references (animated prefab, textures, materials)
5. Save as prefab
### 3. Register in ProvinceBeastsController
Add a prefab field and a case in `GetEffectPrefab()`:
```csharp
// In ProvinceBeastsController.cs
// Add inspector field alongside existing ones:
public GameObject wolfEffectPrefab;
// Add case in GetEffectPrefab(), keyed by singularName from beasts.tsv:
private GameObject GetEffectPrefab(string beastName) {
switch (beastName) {
case "dragon": return dragonEffectPrefab;
case "wolf": return wolfEffectPrefab;
default: return beastsEffectPrefab;
}
}
```
### 4. Wire up in the scene
In `Gameplay.unity`, find the `ProvinceBeastsController` component and assign your new prefab to the new field.
### 5. Test
Use `[ContextMenu]` methods on `ProvinceBeastsController` to test:
- "Test Dragon in Motcia (ID 2)" spawns a dragon effect
- Add similar methods for your beast type
- "Clear All Effects" removes all active effects
## Beast name matching
Beast names come from `BeastInfo.SingularName` in the proto, which uses the canonical `singularName` from `src/main/resources/net/eagle0/eagle/beasts.tsv`. The switch in `GetEffectPrefab` uses exact string matching on this canonical name (e.g. `"dragon"`, `"wolf"`, `"skeleton"`).
Human-type beasts (pirates, bandits, etc.) are matched via a `HumanBeastNames` HashSet in `ProvinceBeastsController` rather than individual switch cases.
## Beast animation coverage
### Custom animations
| Beast | Effect Type | Asset Pack | Prefabs Used |
|---|---|---|---|
| dragon | DragonEffect | 3dFoin Dragon | dragon_skin.FBX (w/ DragonMapAnims controller) |
| skeleton | MonsterEffect | DungeonMonsters2D | SkeletonWarrior, SkeletonArcher, SkeletonMage |
| zombie | MonsterEffect | DungeonMonsters2D | Zombie, ZombieWarrior |
| rat | MonsterEffect + AnimalEffect | DungeonMonsters2D + Animal Pack Deluxe | Rat (2D), Rat (3D) |
| spider | MonsterEffect | DungeonMonsters2D | Spider |
| demon | MonsterEffect | DungeonMonsters2D | Demon, Succubus |
| orc | MonsterEffect | DungeonMonsters2D | Imp |
| vampire | MonsterEffect | DungeonMonsters2D | Vampire |
| knight types (6 names) | AnimalEffect | Polytope Studio | PT_Male_Knight_01/02, PT_Female_Knight_01/02 (w/ HumanMapAnims controller) |
| soldier types (8 names) | AnimalEffect | Polytope Studio | PT_Male_Soldier_01/02, PT_Female_Soldier_01/02 (w/ HumanMapAnims controller) |
| archer types (3 names) | AnimalEffect | Polytope Studio | PT_Male_Archer_01/02, PT_Female_Archer_01/02 (w/ HumanMapAnims controller) |
| militia types (8 names) | AnimalEffect | Polytope Studio | PT_Male_Militia_01/02, PT_Female_Militia_01/02 (w/ HumanMapAnims controller) |
| peasant types (9 names) | AnimalEffect | Polytope Studio | PT_Male_Peasant_01, PT_Female_Peasant_01_a (w/ HumanMapAnims controller) |
| clown | AnimalEffect | Clown Pack | Clown, Fat Clown (w/ per-prefab controller overrides) |
| giant | AnimalEffect | Polytope Studio | PT_Male/Female_Peasant at 3x scale (w/ HumanMapAnims controller) |
| ogre, troll | AnimalEffect | Orc-Ogre Pack | OrcOgre_Animated (w/ OgreMapAnims controller) |
| bear | AnimalEffect | Animal Pack Deluxe | Brown_bear |
| boar | AnimalEffect | Animal Pack Deluxe | Wild_boar |
| crocodile | AnimalEffect | Animal Pack Deluxe | Crocodile |
| snake | AnimalEffect | Animal Pack Deluxe | Viper |
| crab | AnimalEffect | Animal Pack Deluxe | Crab |
| frog | AnimalEffect | Animal Pack Deluxe | Common_frog, Common_frog_v2, Common_frog_v3 |
| rabbit | AnimalEffect | Animal Pack Deluxe | Wild_rabbit, Wild_rabbit_v2 |
| salamander | AnimalEffect | Animal Pack Deluxe | Fire_salamander |
| scorpion | AnimalEffect | Animal Pack Deluxe | Scorpion, Yellow_fattail_scorpion |
| stag | AnimalEffect | Animal Pack Deluxe | Deer, Deer_male |
| wild goat | AnimalEffect | Animal Pack Deluxe | Goat, Ibex |
| wild pig | AnimalEffect | Animal Pack Deluxe | Iron_age_pig, Iron_age_pig_v2 |
| wolf, wolverine | AnimalEffect | Animal Pack Deluxe | Wolf |
| honey badger | AnimalEffect | HoneyBadger (Sketchfab) | HoneyBadger (w/ HoneyBadgerMapAnims controller) |
| raccoon | AnimalEffect | Raccoon (Sketchfab) | Raccoon (w/ RaccoonMapAnims controller) |
| tiger | AnimalEffect | ithappy Animals FREE | Tiger_001 (w/ TigerMapAnims controller) |
| elephant | AnimalEffect | Animal Pack Deluxe v2 | African_elephant, Indian_elephant (w/ ElephantMapAnims controller) |
| mammoth | AnimalEffect | Animal Pack Deluxe v2 | African_elephant, Indian_elephant (w/ ElephantMapAnims controller) |
| hippopotamus | AnimalEffect | Africa Animals Pack Low Poly V2 | Hippopotamus (w/ HippopotamusMapAnims controller) |
| lion | AnimalEffect | Africa Animals Pack Low Poly V1 | Lion, Lioness (w/ LionMapAnims controller) |
| velociraptor | AnimalEffect | Dino Pack Low Poly V1 | VelociraptorColor1, VelociraptorColor2 (w/ VelociraptorMapAnims controller) |
| black panther | AnimalEffect | Africa Animals Pack Low Poly V1 | BlackPanther (w/ BlackPantherMapAnims controller) |
| rhinoceros | AnimalEffect | Africa Animals Pack Low Poly V1 | Rhinoceros (w/ RhinocerosMapAnims controller) |
| gorilla | AnimalEffect | Africa Animals Pack Low Poly V2 | Gorilla (w/ GorillaMapAnims controller) |
| hyena | AnimalEffect | Africa Animals Pack Low Poly V2 | Hyena (w/ HyenaMapAnims controller) |
| leopard | AnimalEffect | Africa Animals Pack Low Poly V2 | Leopard (w/ LeopardMapAnims controller) |
| warthog | AnimalEffect | Africa Animals Pack Low Poly V2 | Phacochoerus (w/ WarthogMapAnims controller) |
| emu | AnimalEffect | Australia Animals Pack V1 | Emu (w/ EmuMapAnims controller) |
| kangaroo | AnimalEffect | Australia Animals Pack V1 | Kangaroo (w/ KangarooMapAnims controller) |
| tasmanian devil | AnimalEffect | Australia Animals Pack V1 | TasmanianDevil (w/ TasmanianDevilMapAnims controller) |
| hippogryph | DragonEffect | Heroic Fantasy Creatures Full Pack Vol 2 | Hippogriff_PBR (w/ HippogryphMapAnims controller) |
### Human-type beasts
34 human-type beast names use 3D Polytope Studio characters grouped into 5 archetypes. Each archetype uses a shared `HumanMapAnims.controller` that retargets Clown animation clips (idle, walk, attack, damage) via Unity's Humanoid system. One additional human type (psychopath) uses the 2D Butcher sprite from DungeonMonsters2D.
| Archetype | Polytope Type | Beast Names (count) |
|---|---|---|
| **Knight** (heavy armor) | Knight M/F x2 | cultist, heretic, cannibal, terrorist, cossack, desperado (6) |
| **Soldier** (medium armor) | Soldier M/F x2 | bandit, brigand, robber, highwayman, marauder, dacoit, freebooter, mobster (8) |
| **Archer** (light armor, ranged) | Archer M/F x2 | thief, pirate, buccaneer (3) |
| **Militia** (light armed) | Militia M/F x2 | hooligan, street tough, ruffian, scalawag, ne'er-do-well, crook, miscreant, asshole (8) |
| **Peasant** (unarmed) | Peasant M/F | agitator, instigator, rabble-rouser, separatist, particularist, nihilist, proud boy, rebel, traitor (9) |
Asset packs: Polytope Studio - Lowpoly Medieval Characters (Soldiers, Knights, Militia, Archers, Peasants)
| **Butcher** (armed loner) | DungeonMonsters2D Butcher | psychopath (1) |
### No custom animation (falls back to generic vultures)
Ordered by spawn likelihood (most common first):
| Beast | Likelihood | Notes |
|---|---|---|
| chimpanzee | 0.04 | Primate |
| unknown | 0.00 | Intentional fallback |
## Using low-poly animal packs (Africa Animals, Dino Pack)
Assets from these packs (by the same author) require extra setup because they ship with **Legacy** animation import and include physics components that conflict with AnimalEffect. The workflow below applies to all of them:
- Africa Animals Pack Low Poly V1 (Lion, Lioness, Black Panther, Crocodile, Elephant, Giraffe, Rhinoceros, Tiger, Zebra)
- Africa Animals Pack Low Poly V2 (Hippopotamus, Antelope, Gorilla, Hyena, Leopard, Phacochoerus/Warthog)
- Dino Pack Low Poly V1 (Velociraptor, Brontosaurus, Pteranodon, Stegosaurus, T-Rex, Triceratops)
- Australia Animals Pack V1 (Chlamydosaurus/Frilled Lizard, Echidna, Emu, Kangaroo, Koala, Platypus, Tasmanian Devil)
### Per-animal setup steps
1. **Switch FBX import to Generic animation type.**
In the `.fbx.meta` file (location varies by pack):
- Change `animationType: 1` to `animationType: 2`
- Change `avatarSetup: 0` to `avatarSetup: 1` (newer format) — older metas without `avatarSetup` will auto-create an avatar at runtime
- Set `loopTime: 1` on looping clips (idle, walk, eat, run) but NOT one-shot clips (attack, death, hurt)
Unity will re-import the FBX with Mecanim-compatible clips when it next opens.
2. **Create an AnimatorController** in `Assets/Eagle/Effects/` named `<Animal>MapAnims.controller`.
Use the same 4-state pattern (idle, walk, eat, attack) as ElephantMapAnims. Reference the animation clips by their fileIDs from the FBX meta's `internalIDToNameTable` (type 74 entries) or `fileIDToRecycleName` (older format, type 7400000+). These IDs are stable across import type changes. Note: if the FBX names its idle clip `idle1`, create the controller state as `idle` but reference the `idle1` clip by fileID.
3. **Create an AnimalEffect prefab** in `Assets/Eagle/Effects/` named `<Animal>Effect.prefab`.
Reference the pack's prefab as the animal prefab, and wire up the new AnimatorController. Multiple color/sex variants from the same or similar FBX can share one controller (e.g., Lion and Lioness). AnimalEffect will automatically strip the pack's legacy Animation, Rigidbody, and Collider components at spawn time, and add an Animator if the prefab doesn't already have one.
4. **Register in ProvinceBeastsController** with a case in `GetEffectPrefab()` and a test ContextMenu method.
5. **Mark the effect prefab as Addressable** with the `beast-effects` label in the Unity editor (Window > Asset Management > Addressables > Groups).
### Notes
- The packs include both SingleTexture and TextureAtlas variants; use SingleTexture for best visual quality.
- Hippos have water-specific animations (idlewater, deathwater) that could be used for future water-province effects.
- The packs' prefabs include Rigidbody/BoxCollider components intended for gameplay use. AnimalEffect strips these automatically since it controls position directly.
### Available animals not yet set up as beasts
These animals exist in the imported packs and could be set up as in-game beasts using the workflow above:
**Africa Animals Pack V1** (already imported):
| Animal | Good fit for | Notes |
|---|---|---|
| Giraffe (x2 variants) | giraffe beast | Tall model, may need larger scale |
| Zebra | zebra beast | Herd animal; good with higher animalCount |
(Black Panther, Rhinoceros, Crocodile, Elephant, and Tiger already have effects.)
**Africa Animals Pack V2** (already imported):
| Animal | Good fit for | Notes |
|---|---|---|
| Antelope | antelope/gazelle beast | Fast-moving; good with higher moveSpeed |
(Gorilla, Hyena, Leopard, Warthog, and Hippopotamus already have effects.)
**Dino Pack Low Poly V1** (already imported):
| Animal | Good fit for | Notes |
|---|---|---|
| Brontosaurus | brontosaurus/sauropod beast | Very large; needs big scale, low count |
| Pteranodon | pteranodon/flying beast | Has fly animation; could use DragonEffect-style flight |
| Stegosaurus | stegosaurus beast | Large herbivore |
| T-Rex | tyrannosaurus beast | Iconic predator; good as a solo beast |
| Triceratops | triceratops beast | Large herbivore; good for tough beast |
(Velociraptor already has an effect.)
**Australia Animals Pack V1** (already imported):
| Animal | Good fit for | Notes |
|---|---|---|
| Koala | koala beast | Peaceful; good for low-threat province events |
| Echidna | echidna beast | Small, spiny |
| Chlamydosaurus (Frilled Lizard) | lizard beast | Has threat display animation |
| Platypus (Ornitorinco) | platypus beast | Semi-aquatic; unique |
(Emu, Kangaroo, and Tasmanian Devil already have effects.)
None of the remaining animals above are currently in `beasts.tsv`.
## Tips
- Keep effects lightweight; multiple provinces may have beasts simultaneously
- Use `ParticleSystemScalingMode.Hierarchy` so effects scale with the map zoom
- Set appropriate `sortingOrder` on renderers (existing effects use 102-104)
- For animated prefabs, set `AnimatorCullingMode.AlwaysAnimate` since UI elements may be considered offscreen by the culling system
- For 3D models (AnimalEffect), set `renderQueue=4000` and `ZTest=Always` on materials to prevent clipping behind the map
-27
View File
@@ -129,33 +129,6 @@ std::vector<ActionResult> CheckAndExecuteEvents(
- Create `TutorialHeroJoined` action results adding reinforcement heroes to player faction
- Set appropriate loyalty, vigor, location for joined heroes
### Phase 7: Post-Battle Strategic Dialogue
After the battle ends and the player returns to the strategic map, narrative dialogues guide them through the next steps.
**Dialogue 1: Battle Aftermath** (trigger: `tutorial_battle_ended`)
- Old Marek reflects on the close call
- Tarn has vanished — rumors of sorcery or escape, no one knows
- Captured lieutenants: they followed orders, not to blame for Tarn's madness
- Player should try to recruit them or hold them
- No instruction text needed — Handle Captured Heroes UI is self-explanatory
**Dialogue 2: Rebuild Support** (trigger: `tutorial_rebuild_support`)
- Fires when available commands no longer include HandleCapturedHeroCommand
- Marek explains the province needs support rebuilt after the battle
- Engineers (John Ranil) can **Improve** the province — build infrastructure, develop economy
- Paladins (Elena Fyar) can **Give Alms** — distribute food to win hearts
- Instructions highlight **Improve** and **Give Alms** buttons
- Goal: get Support to **40** before January for tax revenue
**Implementation:**
- Dialogues defined in `tutorial_strategic.json`
- `tutorial_battle_ended`: fire when tutorial battle is removed from `RunningShardokGameModels`
- `tutorial_rebuild_support`: fire when available commands no longer include `HandleCapturedHeroCommand`
- Register `ImproveButton` and `AlmsButton` as highlight targets in `TutorialTargetRegistry`
See `TUTORIAL_CONTENT.md` for full dialogue text.
---
## File Summary
-46
View File
@@ -149,52 +149,6 @@ Triggered during battles when players encounter spells, terrain, or abilities.
---
## Post-Battle Dialogue (Narrative Dialogues)
These fire after the first tutorial battle ends and the player returns to the strategic map. They use the narrative dialogue system (`DialogueManager` / `tutorial_strategic.json`) rather than the modal tutorial system.
### Battle Aftermath
| Field | Value |
|-------|-------|
| ID | `post_battle_aftermath` |
| Trigger | `tutorial_battle_ended` (battle removed from RunningShardokGameModels) |
| Speaker | Old Marek the Learned |
| Panel Position | top |
**Dialogue (Marek):**
> That was closer than I'd like to admit. We held — barely. But Tarn... Tarn is gone. Not retreated — *gone*. The men say he vanished from the field. Some claim sorcery. Others say he slipped away in the chaos. Whatever the truth, no one can find him.
>
> But we captured some of his lieutenants. These are soldiers, Sadar — they followed orders, same as we once did. They're not to blame for Tarn's madness. See if you can bring them to our cause, or at least hold them until they come around.
**Instructions:** *(none — Handle Captured Heroes UI is self-explanatory)*
### Rebuild Support
| Field | Value |
|-------|-------|
| ID | `post_battle_rebuild` |
| Trigger | `tutorial_rebuild_support` (fires when available commands no longer include HandleCapturedHeroCommand) |
| Speaker | Old Marek the Learned |
| Panel Position | top |
**Dialogue (Marek):**
> Good. Now we need to rebuild our support here in Onmaa. The people are shaken — a battle on their doorstep will do that. We need them behind us if we're going to hold this province.
>
> Any of our heroes can develop the land or give alms to the people — nothing wins hearts faster than a full belly. Engineers like John Ranil are especially effective at improving a province, and paladins like Elena Fyar are the best at winning hearts. Either way, we need the people's support before the tax collectors come round in January.
**Instructions:** Use **Improve** and **Give Alms** to raise Support. You must have at least **40** support in the province by January in order to collect gold and food in taxes.
**Highlight targets:** `SupportField`
### Implementation Notes
- Both dialogues go in `tutorial_strategic.json`
- Need new trigger events: `tutorial_battle_ended` and `tutorial_rebuild_support`
- `tutorial_battle_ended` should fire when the tutorial battle is removed from `RunningShardokGameModels` in `EagleGameModel.ApplyGameStateViewDiff`
- `tutorial_rebuild_support` should fire when available commands no longer include `HandleCapturedHeroCommand` (i.e. the captured heroes phase is done and the player has regular commands available)
- The "rebuild" dialogue should highlight the Improve and Give Alms buttons in the command panel (requires registering them as highlight targets)
---
## Display Modes
| Mode | Description | Use For |
-19
View File
@@ -1,19 +0,0 @@
# Two-Stage Animation Implementation Pattern
Actions with server-determined success/failure outcomes use a two-stage system:
1. **Attempt phase**: Animation + sound plays immediately when the command is issued
2. **Result phase**: A distinct success or failure animation + sound plays when the server responds
## Adding a New Two-Stage Action
To add distinct success/failure animations for an action (using `ExtinguishFire` as an example):
1. **AnimationType enum** (`ShardokGameController.cs`): Add `ExtinguishFireFailed`
2. **AnimationTypeForAction()**: Map `ActionType.ExtinguishFireFailed` to new type
3. **AttemptAnimationType()**: Map `ExtinguishFireFailed` back to `ExtinguishFire`
4. **ActionTypeForSound()**: Map new type to `ActionType.ExtinguishFireFailed`
5. **PlayAnimation()**: Add dispatch case calling the new animator method
6. **Animator**: Add `AnimateExtinguishFailed()` method
7. **SoundManager**: Ensure result sound is mapped (usually already done)
See FearAnimator and FleeAnimator for reference implementations.
+1 -1
View File
@@ -12,7 +12,7 @@ require (
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/uuid v1.6.0
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6
golang.org/x/sys v0.30.0
golang.org/x/sys v0.28.0
google.golang.org/grpc v1.68.0
google.golang.org/protobuf v1.36.3
)
+2 -2
View File
@@ -43,8 +43,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6 h1:VQpB2SpK88C6B5lPHTuSZKb2Qee1QWwiFlC5CKY4AW0=
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6/go.mod h1:yE65LFCeWf4kyWD5re+h4XNvOHJEXOCOuJZ4v8l5sgk=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+8 -4
View File
@@ -2,6 +2,9 @@
#
# Build the SparklePlugin native library for Unity using Bazel
#
# The SparklePlugin is built in a separate Bazel workspace (sparkle_workspace/)
# to avoid rules_swift version conflicts between grpc and rules_apple.
#
# Usage: build_sparkle_plugin.sh [output_dir]
set -euo pipefail
@@ -11,13 +14,14 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OUTPUT_DIR="${1:-$PROJECT_ROOT/src/main/csharp/net/eagle0/clients/unity/eagle0/Assets/Plugins/macOS}"
echo "=== Building SparklePlugin with Bazel ==="
echo "=== Building SparklePlugin with Bazel (from sparkle_workspace) ==="
cd "$PROJECT_ROOT"
bazel build //src/main/objc/net/eagle0/clients/unity/sparkle:SparklePlugin
# Build in the separate sparkle_workspace to avoid dependency conflicts
cd "$PROJECT_ROOT/sparkle_workspace"
bazel build //:SparklePlugin
# Get the zip path from bazel
ZIP_PATH=$(bazel cquery --output=files //src/main/objc/net/eagle0/clients/unity/sparkle:SparklePlugin 2>/dev/null)
ZIP_PATH=$(bazel cquery --output=files //:SparklePlugin 2>/dev/null)
echo "=== Extracting SparklePlugin.bundle ==="
mkdir -p "$OUTPUT_DIR"
-54
View File
@@ -1,54 +0,0 @@
#!/usr/bin/env bash
# Keeps Bazel mactools builds in sync with the installed Xcode version.
#
# Only needed on runners that do mactools builds (Mac/Sparkle). Non-Mac builds
# don't run this script; their apple_cc_autoconf stays cached because none of
# its environ vars change, so they're unaffected by Xcode version changes.
#
# 1. Writes .bazelrc.xcode with mactools-scoped flags:
# - action_env for remote cache key invalidation
# - DEVELOPER_DIR pointing to the active Xcode
#
# 2. Runs `bazel clean --expunge` when the version actually changes, because
# local_config_apple_cc (a cached repository rule) bakes in the old version
# and can only be refreshed by clearing the output base.
#
# .bazelrc imports the generated file via: try-import %workspace%/.bazelrc.xcode
set -euo pipefail
XCODE_BUILD_VERSION=$(xcodebuild -version 2>/dev/null | awk '/Build version/ {print $3}')
if [ -z "$XCODE_BUILD_VERSION" ]; then
echo "Warning: Could not detect Xcode build version, skipping"
exit 0
fi
DEVELOPER_DIR=$(xcode-select -p 2>/dev/null)
BAZELRC_XCODE=".bazelrc.xcode"
EXPECTED_LINE="common:mactools --action_env=XCODE_BUILD_VERSION=${XCODE_BUILD_VERSION}"
# Check if the file already has the right version (first line is the version marker)
if [ -f "$BAZELRC_XCODE" ]; then
CURRENT_FIRST_LINE=$(head -1 "$BAZELRC_XCODE")
if [ "$CURRENT_FIRST_LINE" = "$EXPECTED_LINE" ]; then
exit 0
fi
fi
# Xcode version changed (or first run) — expunge local cache to clear
# stale local_config_apple_cc, then write the new config
OLD_VERSION="unknown"
if [ -f "$BAZELRC_XCODE" ]; then
OLD_VERSION=$(sed -n 's/.*XCODE_BUILD_VERSION=//p' "$BAZELRC_XCODE" | head -1)
fi
echo "Xcode build version changed: ${OLD_VERSION} -> ${XCODE_BUILD_VERSION}"
echo "Running bazel clean --expunge to clear stale toolchain config..."
bazel clean --expunge 2>/dev/null || true
cat > "$BAZELRC_XCODE" << EOF
${EXPECTED_LINE}
common:mactools --repo_env=DEVELOPER_DIR=${DEVELOPER_DIR}
EOF
echo "Updated ${BAZELRC_XCODE} — next mactools build will rebuild with Xcode ${XCODE_BUILD_VERSION}"
+1
View File
@@ -0,0 +1 @@
7.7.1
+2
View File
@@ -0,0 +1,2 @@
# Bazel symlinks
bazel-*
+28
View File
@@ -0,0 +1,28 @@
module(name = "sparkle_workspace")
# Minimal dependencies for building SparklePlugin
# This workspace is isolated from the main workspace to avoid
# rules_swift version conflicts between grpc and rules_apple
bazel_dep(name = "apple_support", version = "1.21.1", repo_name = "build_bazel_apple_support")
bazel_dep(name = "rules_apple", version = "4.3.3", repo_name = "build_bazel_rules_apple")
# Register Apple CC toolchain for Objective-C compilation
apple_cc_configure = use_extension(
"@build_bazel_apple_support//crosstool:setup.bzl",
"apple_cc_configure_extension",
)
use_repo(apple_cc_configure, "local_config_apple_cc")
# Sparkle framework for macOS auto-updates
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
SPARKLE_VERSION = "2.6.4"
http_archive(
name = "sparkle",
build_file = "//:external/BUILD.sparkle",
sha256 = "50612a06038abc931f16011d7903b8326a362c1074dabccb718404ce8e585f0b",
strip_prefix = "",
url = "https://github.com/sparkle-project/Sparkle/releases/download/%s/Sparkle-%s.tar.xz" % (SPARKLE_VERSION, SPARKLE_VERSION),
)
+451
View File
@@ -0,0 +1,451 @@
{
"lockFileVersion": 13,
"registryFileHashes": {
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
"https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896",
"https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
"https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1",
"https://bcr.bazel.build/modules/apple_support/1.23.1/MODULE.bazel": "53763fed456a968cf919b3240427cf3a9d5481ec5466abc9d5dc51bc70087442",
"https://bcr.bazel.build/modules/apple_support/1.23.1/source.json": "d888b44312eb0ad2c21a91d026753f330caa48a25c9b2102fae75eb2b0dcfdd2",
"https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
"https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
"https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
"https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
"https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
"https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
"https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
"https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc",
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
"https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
"https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
"https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
"https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
"https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
"https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
"https://bcr.bazel.build/modules/protobuf/29.0-rc3/source.json": "c16a6488fb279ef578da7098e605082d72ed85fc8d843eaae81e7d27d0f4625d",
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
"https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
"https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
"https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
"https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
"https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
"https://bcr.bazel.build/modules/rules_apple/4.3.3/MODULE.bazel": "c5c2c4adeeac5f3f2f9b7f16abfa8be7ffefa596171d0d92bed4cae9ade0a498",
"https://bcr.bazel.build/modules/rules_apple/4.3.3/source.json": "3cb1d69c8243ffcc42ecbf84ae8b9cccd7b1e2f091b0aee5a3e9c9a45267f312",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
"https://bcr.bazel.build/modules/rules_cc/0.0.11/MODULE.bazel": "9f249c5624a4788067b96b8b896be10c7e8b4375dc46f6d8e1e51100113e0992",
"https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
"https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0",
"https://bcr.bazel.build/modules/rules_cc/0.1.2/source.json": "53fcb09b5816c83ca60d9d7493faf3bfaf410dfc2f15deb52d6ddd146b8d43f0",
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
"https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
"https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
"https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1",
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
"https://bcr.bazel.build/modules/rules_java/8.5.1/source.json": "db1a77d81b059e0f84985db67a22f3f579a529a86b7997605be3d214a0abe38e",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
"https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
"https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
"https://bcr.bazel.build/modules/rules_proto/6.0.2/source.json": "17a2e195f56cb28d6bbf763e49973d13890487c6945311ed141e196fb660426d",
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7",
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
"https://bcr.bazel.build/modules/rules_python/1.3.0/source.json": "25932f917cd279c7baefa6cb1d3fa8750a7a29de522024449b19af6eab51f4a0",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
"https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
"https://bcr.bazel.build/modules/rules_shell/0.3.0/source.json": "c55ed591aa5009401ddf80ded9762ac32c358d2517ee7820be981e2de9756cf3",
"https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
"https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd",
"https://bcr.bazel.build/modules/rules_swift/2.4.0/source.json": "a6577f57f9febbdc015a01f2a8f3487422032f134d6c61d18ed8e8ca3b9acc7c",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
"https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
"https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
"https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
},
"selectedYankedVersions": {},
"moduleExtensions": {
"@@rules_java~//java:rules_java_deps.bzl%compatibility_proxy": {
"general": {
"bzlTransitiveDigest": "C4xqrMy1wN4iuTN6Z2eCm94S5XingHhD6uwrIXvCxVI=",
"usagesDigest": "pwHZ+26iLgQdwvdZeA5wnAjKnNI3y6XO2VbhOTeo5h8=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"compatibility_proxy": {
"bzlFile": "@@rules_java~//java:rules_java_deps.bzl",
"ruleClassName": "_compatibility_proxy_repo_rule",
"attributes": {}
}
},
"recordedRepoMappingEntries": [
[
"rules_java~",
"bazel_tools",
"bazel_tools"
]
]
}
},
"@@rules_kotlin~//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "eecmTsmdIQveoA97hPtH3/Ej/kugbdCI24bhXIXaly8=",
"usagesDigest": "aJF6fLy82rR95Ff5CZPAqxNoFgOMLMN5ImfBS0nhnkg=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"com_github_jetbrains_kotlin_git": {
"bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl",
"ruleClassName": "kotlin_compiler_git_repository",
"attributes": {
"urls": [
"https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
],
"sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
}
},
"com_github_jetbrains_kotlin": {
"bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl",
"ruleClassName": "kotlin_capabilities_repository",
"attributes": {
"git_repository_name": "com_github_jetbrains_kotlin_git",
"compiler_version": "1.9.23"
}
},
"com_github_google_ksp": {
"bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:ksp.bzl",
"ruleClassName": "ksp_compiler_plugin_repository",
"attributes": {
"urls": [
"https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
],
"sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
"strip_version": "1.9.23-1.0.20"
}
},
"com_github_pinterest_ktlint": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_file",
"attributes": {
"sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
"urls": [
"https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
],
"executable": true
}
},
"rules_android": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
"strip_prefix": "rules_android-0.1.1",
"urls": [
"https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
]
}
}
},
"recordedRepoMappingEntries": [
[
"rules_kotlin~",
"bazel_tools",
"bazel_tools"
]
]
}
},
"@@rules_python~//python/uv:uv.bzl%uv": {
"general": {
"bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=",
"usagesDigest": "qI5PVlIum/YAnGJg5oXGHzDkMFWt2aNSUZY4G8PBbic=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"uv": {
"bzlFile": "@@rules_python~//python/uv/private:uv_toolchains_repo.bzl",
"ruleClassName": "uv_toolchains_repo",
"attributes": {
"toolchain_type": "'@@rules_python~//python/uv:uv_toolchain_type'",
"toolchain_names": [
"none"
],
"toolchain_implementations": {
"none": "'@@rules_python~//python:none'"
},
"toolchain_compatible_with": {
"none": [
"@platforms//:incompatible"
]
},
"toolchain_target_settings": {}
}
}
},
"recordedRepoMappingEntries": [
[
"rules_python~",
"platforms",
"platforms"
]
]
}
},
"@@rules_swift~//swift:extensions.bzl%non_module_deps": {
"general": {
"bzlTransitiveDigest": "l+Zu+SMObRQy3DG2LEw0eGVPkYRnyVj+M1QyR5AAFmM=",
"usagesDigest": "l2vIL7SL4tJqHIVLWd78Y/ym+r0II64lmvoX8o+0Bb0=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"com_github_apple_swift_protobuf": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-protobuf/archive/1.20.2.tar.gz"
],
"sha256": "3fb50bd4d293337f202d917b6ada22f9548a0a0aed9d9a4d791e6fbd8a246ebb",
"strip_prefix": "swift-protobuf-1.20.2/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_protobuf/BUILD.overlay"
}
},
"com_github_grpc_grpc_swift": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/grpc/grpc-swift/archive/1.16.0.tar.gz"
],
"sha256": "58b60431d0064969f9679411264b82e40a217ae6bd34e17096d92cc4e47556a5",
"strip_prefix": "grpc-swift-1.16.0/",
"build_file": "@@rules_swift~//third_party:com_github_grpc_grpc_swift/BUILD.overlay"
}
},
"com_github_apple_swift_docc_symbolkit": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-docc-symbolkit/archive/refs/tags/swift-5.10-RELEASE.tar.gz"
],
"sha256": "de1d4b6940468ddb53b89df7aa1a81323b9712775b0e33e8254fa0f6f7469a97",
"strip_prefix": "swift-docc-symbolkit-swift-5.10-RELEASE",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_docc_symbolkit/BUILD.overlay"
}
},
"com_github_apple_swift_nio": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio/archive/2.42.0.tar.gz"
],
"sha256": "e3304bc3fb53aea74a3e54bd005ede11f6dc357117d9b1db642d03aea87194a0",
"strip_prefix": "swift-nio-2.42.0/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio/BUILD.overlay"
}
},
"com_github_apple_swift_nio_http2": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-http2/archive/1.26.0.tar.gz"
],
"sha256": "f0edfc9d6a7be1d587e5b403f2d04264bdfae59aac1d74f7d974a9022c6d2b25",
"strip_prefix": "swift-nio-http2-1.26.0/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_http2/BUILD.overlay"
}
},
"com_github_apple_swift_nio_transport_services": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-transport-services/archive/1.15.0.tar.gz"
],
"sha256": "f3498dafa633751a52b9b7f741f7ac30c42bcbeb3b9edca6d447e0da8e693262",
"strip_prefix": "swift-nio-transport-services-1.15.0/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_transport_services/BUILD.overlay"
}
},
"com_github_apple_swift_nio_extras": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-extras/archive/1.4.0.tar.gz"
],
"sha256": "4684b52951d9d9937bb3e8ccd6b5daedd777021ef2519ea2f18c4c922843b52b",
"strip_prefix": "swift-nio-extras-1.4.0/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_extras/BUILD.overlay"
}
},
"com_github_apple_swift_log": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-log/archive/1.4.4.tar.gz"
],
"sha256": "48fe66426c784c0c20031f15dc17faf9f4c9037c192bfac2f643f65cb2321ba0",
"strip_prefix": "swift-log-1.4.4/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_log/BUILD.overlay"
}
},
"com_github_apple_swift_nio_ssl": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-nio-ssl/archive/2.23.0.tar.gz"
],
"sha256": "4787c63f61dd04d99e498adc3d1a628193387e41efddf8de19b8db04544d016d",
"strip_prefix": "swift-nio-ssl-2.23.0/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_nio_ssl/BUILD.overlay"
}
},
"com_github_apple_swift_collections": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-collections/archive/1.0.4.tar.gz"
],
"sha256": "d9e4c8a91c60fb9c92a04caccbb10ded42f4cb47b26a212bc6b39cc390a4b096",
"strip_prefix": "swift-collections-1.0.4/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_collections/BUILD.overlay"
}
},
"com_github_apple_swift_atomics": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"urls": [
"https://github.com/apple/swift-atomics/archive/1.1.0.tar.gz"
],
"sha256": "1bee7f469f7e8dc49f11cfa4da07182fbc79eab000ec2c17bfdce468c5d276fb",
"strip_prefix": "swift-atomics-1.1.0/",
"build_file": "@@rules_swift~//third_party:com_github_apple_swift_atomics/BUILD.overlay"
}
},
"build_bazel_rules_swift_index_import": {
"bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
"ruleClassName": "http_archive",
"attributes": {
"build_file": "@@rules_swift~//third_party:build_bazel_rules_swift_index_import/BUILD.overlay",
"canonical_id": "index-import-5.8",
"urls": [
"https://github.com/MobileNativeFoundation/index-import/releases/download/5.8.0.1/index-import.tar.gz"
],
"sha256": "28c1ffa39d99e74ed70623899b207b41f79214c498c603915aef55972a851a15"
}
},
"build_bazel_rules_swift_local_config": {
"bzlFile": "@@rules_swift~//swift/internal:swift_autoconfiguration.bzl",
"ruleClassName": "swift_autoconfiguration",
"attributes": {}
}
},
"recordedRepoMappingEntries": [
[
"rules_swift~",
"bazel_tools",
"bazel_tools"
]
]
}
}
}
}
+3
View File
@@ -0,0 +1,3 @@
# This file marks sparkle_workspace as a separate Bazel workspace.
# It prevents Bazel from looking up to the parent directory's workspace.
# The actual dependencies are defined in MODULE.bazel (bzlmod).
@@ -95,16 +95,9 @@ auto ConvertUnit(
shardokUnit.mutate_stun_rounds_remaining(0);
for (const PlayerId pid : allPlayerIds) {
int8_t initialKnowledge = 0;
for (const auto visibleToPid : unit.visible_to_player_ids()) {
if (visibleToPid == pid) {
initialKnowledge = 100;
break;
}
}
shardokUnit.mutable_opponent_knowledge()->Mutate(
static_cast<flatbuffers::uoffset_t>(pid),
initialKnowledge);
0);
}
shardokUnit.mutate_has_moved_in_zoc(false);
@@ -13,7 +13,6 @@
#include <cstring>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
@@ -148,9 +147,6 @@ public:
static auto FromPath(const string& path) -> byte_vector {
std::ifstream inputFileStream(path, std::ios::binary | std::ios::ate);
if (!inputFileStream.is_open()) {
throw std::runtime_error("Failed to open file: " + path);
}
const std::streamsize size = inputFileStream.tellg();
inputFileStream.seekg(0, std::ios::beg);
byte_vector serializedGame((size_t(size)));
@@ -32,32 +32,6 @@ CoordsSet AICommandFilter::BuildEnemyLocations(const GameStateW& gameState, Play
return enemyLocations;
}
std::vector<size_t> AICommandFilter::FilterLoopingCommands(
const CommandListSPtr& commands,
const GameStateW& gameState) {
std::vector<size_t> filteredIndices;
filteredIndices.reserve(commands->size());
for (size_t i = 0; i < commands->size(); ++i) {
const auto& cmd = (*commands)[i];
bool shouldFilter = false;
if (cmd->GetCommandType() == CommandType::METEOR_TARGET_COMMAND ||
cmd->GetCommandType() == CommandType::METEOR_CANCEL_COMMAND) {
const int unitId = cmd->GetActorUnitId();
const Unit* unit = gameState->units()->Get(unitId);
if (unit->attached_hero().profession_info().cast_target().row() > -1) {
shouldFilter = true;
}
}
if (!shouldFilter) { filteredIndices.push_back(i); }
}
return filteredIndices;
}
std::vector<size_t> AICommandFilter::FilterCommands(
const CommandListSPtr& commands,
PlayerId pid,
@@ -164,17 +138,6 @@ bool AICommandFilter::IsWastefulAction(
break;
}
case CommandType::METEOR_TARGET_COMMAND:
case CommandType::METEOR_CANCEL_COMMAND: {
// Filter out re-target/cancel when the mage already has a target.
// Re-targeting exists for human misclick correction; the AI commits
// to its first target choice and doesn't need to reconsider.
const int unitId = cmd.GetActorUnitId();
const Unit* unit = gameState->units()->Get(unitId);
if (unit->attached_hero().profession_info().cast_target().row() > -1) { return true; }
break;
}
case CommandType::START_FIRE_COMMAND: {
// Fire spell filtering - be very restrictive for attackers
// Fire only affects adjacent tiles and lasts multiple rounds
@@ -44,18 +44,6 @@ public:
const APDCache& apdCache,
const BattalionTypeGetter& battalionTypeLookup);
/**
* Lightweight filter for the root of the search tree.
* Only removes commands that are genuinely never useful (e.g. meteor
* re-targeting when a target is already set), as opposed to the full
* heuristic filter which aggressively prunes for lookahead performance.
* The full filter could miss good moves at the root that only look
* bad locally but prove worthwhile with deeper search.
*/
static std::vector<size_t> FilterLoopingCommands(
const CommandListSPtr& commands,
const GameStateW& gameState);
private:
// Helper to build enemy locations once for efficiency
static CoordsSet BuildEnemyLocations(const GameStateW& gameState, PlayerId pid);
@@ -11,7 +11,6 @@
#include "AIAttackerStrategySelector.hpp"
#include "AICommandEvaluator.hpp"
#include "AICommandFilter.hpp"
#include "TranspositionTable.hpp"
#include "src/main/cpp/net/eagle0/shardok/ai/score/AIScoreCalculator.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokEngine.hpp"
@@ -60,12 +59,6 @@ auto IterativeDeepeningAI::IterativeSearch(
return result;
}
// Lightweight root filter: only remove genuinely never-useful commands
// (e.g. meteor re-targeting). The full aggressive filter is reserved for
// lookahead where pruning is a performance optimization, not a decision.
const std::vector<size_t> rootFilteredIndices =
AICommandFilter::FilterLoopingCommands(commands, state);
// Check if we're in SET_UP phase and enforce maximum depth limit
bool isSetupPhase =
(state->status()->state() ==
@@ -97,8 +90,7 @@ auto IterativeDeepeningAI::IterativeSearch(
std::vector<size_t> sortedIndices = GetCommandsSortedByPreviousDepth(
currentDepth,
scoresByDepth,
highestDepthCompleted,
rootFilteredIndices);
highestDepthCompleted);
size_t evaluatedCount = 0;
bool allEvaluated = true;
@@ -352,14 +344,14 @@ auto IterativeDeepeningAI::SearchCommandAtDepthWithEngine(
auto IterativeDeepeningAI::GetCommandsSortedByPreviousDepth(
const size_t currentDepth,
const std::vector<std::vector<ScoreValue>>& scoresByDepth,
const std::vector<size_t>& highestDepthCompleted,
const std::vector<size_t>& filteredIndices) -> std::vector<size_t> {
if (currentDepth == 1) {
// For depth 1, return filtered indices in natural order
return filteredIndices;
}
const std::vector<size_t>& highestDepthCompleted) -> std::vector<size_t> {
std::vector<size_t> indices(scoresByDepth.size());
std::iota(indices.begin(), indices.end(), 0);
std::vector<size_t> indices = filteredIndices;
if (currentDepth == 1) {
// For depth 1, return natural order
return indices;
}
// Sort by score at previous depth
const size_t prevDepth = currentDepth - 1;
@@ -101,8 +101,7 @@ private:
[[nodiscard]] static std::vector<size_t> GetCommandsSortedByPreviousDepth(
size_t currentDepth,
const std::vector<std::vector<ScoreValue>>& scoresByDepth,
const std::vector<size_t>& highestDepthCompleted,
const std::vector<size_t>& filteredIndices);
const std::vector<size_t>& highestDepthCompleted);
[[nodiscard]] static SearchResult SelectBestResult(
const std::vector<std::vector<ScoreValue>>& scoresByDepth,
@@ -8,8 +8,6 @@
#include "ShardokGameController.hpp"
#include <execinfo.h>
#include <algorithm>
#include <iterator>
#include <ranges>
@@ -155,48 +153,28 @@ void ShardokGameController::DoAIThread() {
continue;
}
try {
// Phase 2: AI thinks (NO LOCK - this is the slow part)
const auto results = aiClient->ChooseCommandIndex(settings, gsv, availableCommands);
// Phase 2: AI thinks (NO LOCK - this is the slow part)
const auto results = aiClient->ChooseCommandIndex(settings, gsv, availableCommands);
// Phase 3: Post the command (brief lock)
{
unique_lock lk(masterLock);
// Phase 3: Post the command (brief lock)
{
unique_lock lk(masterLock);
// Verify state hasn't changed while we were thinking
if (engine->GetUnfilteredHistoryCount() != expectedHistoryCount) {
// State changed (e.g., human posted command) - re-evaluate
printf("AI: State changed while thinking, re-evaluating\n");
continue;
}
if (engine->GameIsOver()) {
aiThreadKeepGoing = false;
continue;
}
engine->PostCommand(playerId, results.chosenIndex);
LockedNotifyClients();
aiThreadKeepGoing = !engine->GameIsOver();
// Verify state hasn't changed while we were thinking
if (engine->GetUnfilteredHistoryCount() != expectedHistoryCount) {
// State changed (e.g., human posted command) - re-evaluate
printf("AI: State changed while thinking, re-evaluating\n");
continue;
}
} catch (const std::exception &e) {
fprintf(stderr,
"AI thread exception in game %s, player %d, round %d: %s\n",
cachedGameId.c_str(),
playerId,
gsv.current_round(),
e.what());
void *backtraceArray[20];
const int backtraceSize = backtrace(backtraceArray, 20);
backtrace_symbols_fd(backtraceArray, backtraceSize, STDERR_FILENO);
if (engine->GameIsOver()) {
aiThreadKeepGoing = false;
continue;
}
aiThreadErrorMessage = "AI error in game " + cachedGameId + ", player " +
std::to_string(playerId) + ", round " +
std::to_string(gsv.current_round()) + ": " + e.what();
aiThreadFailed.store(true);
updateCondition.notify_all();
break;
engine->PostCommand(playerId, results.chosenIndex);
LockedNotifyClients();
aiThreadKeepGoing = !engine->GameIsOver();
}
}
printf("Exiting AI thread.\n");
@@ -396,39 +374,31 @@ void ShardokGameController::UnregisterSubscriber(const StreamSubscriber *subscri
auto ShardokGameController::WaitForUpdatesAndPush(
std::shared_ptr<StreamSubscriber> subscriber,
int64_t startingActionId) -> WaitResult {
int64_t startingActionId) -> bool {
int64_t lastPushedActionId = startingActionId;
while (subscriber->IsActive()) {
bool gameOver = false;
bool tutorialReset = false;
GameOverInfo gameOverInfo{};
{
unique_lock<mutex> guard(masterLock);
// Wait for updates, game over, or AI thread failure
// Wait for updates or game over
updateCondition.wait(guard, [this, lastPushedActionId] {
return engine->GetUnfilteredHistoryCount() >
static_cast<size_t>(lastPushedActionId) ||
engine->GameIsOver() || aiThreadFailed.load();
engine->GameIsOver();
});
if (!subscriber->IsActive()) { return WaitResult::DISCONNECTED; }
if (aiThreadFailed.load()) { return WaitResult::DISCONNECTED; }
if (!subscriber->IsActive()) { return false; }
gameOver = engine->GameIsOver();
if (gameOver) {
// Check if this is a tutorial battle where the defender lost
tutorialReset = engine->IsTutorialBattleEnabled() && engine->DidDefenderLose();
if (!tutorialReset) {
gameOverInfo.gameStatus = fb::ToProto(engine->GetGameStatus());
gameOverInfo.playerInfos = engine->GetPlayerInfos();
gameOverInfo.endGameUnits = engine->EndGameUnits();
}
gameOverInfo.gameStatus = fb::ToProto(engine->GetGameStatus());
gameOverInfo.playerInfos = engine->GetPlayerInfos();
gameOverInfo.endGameUnits = engine->EndGameUnits();
}
}
// Lock released - GetUpdates will acquire its own lock
@@ -448,20 +418,14 @@ auto ShardokGameController::WaitForUpdatesAndPush(
updates.currentGameState);
}
// Tutorial battle reset: defender lost, signal reset instead of game over
if (tutorialReset) {
subscriber->OnBattleReset();
return WaitResult::BATTLE_RESET;
}
// Now send gameOver notification after all updates have been sent
if (gameOver) {
subscriber->OnGameOver(gameOverInfo);
return WaitResult::GAME_OVER;
return true;
}
}
return WaitResult::DISCONNECTED; // Subscriber disconnected
return false; // Subscriber disconnected
}
} // namespace shardok
@@ -9,7 +9,6 @@
#ifndef ShardokGameController_hpp
#define ShardokGameController_hpp
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
@@ -56,13 +55,6 @@ struct OnePlayerUpdates {
availableCommands(acs) {}
};
/// Result of WaitForUpdatesAndPush indicating how the wait ended
enum class WaitResult {
GAME_OVER, // Game ended normally
DISCONNECTED, // Subscriber disconnected
BATTLE_RESET // Tutorial battle reset (defender lost)
};
/// Interface for subscribers that receive streaming updates from a game
class StreamSubscriber {
public:
@@ -78,9 +70,6 @@ public:
/// Called when the game ends
virtual void OnGameOver(const GameOverInfo& info) = 0;
/// Called when a tutorial battle resets (defender lost, battle will restart)
virtual void OnBattleReset() = 0;
/// Returns true if this subscriber is still active and should receive updates
[[nodiscard]] virtual auto IsActive() const -> bool = 0;
};
@@ -111,10 +100,6 @@ private:
const string mapName;
const string logFilePath;
// AI thread error state - written once by AI thread before setting atomic flag
std::atomic<bool> aiThreadFailed{false};
std::string aiThreadErrorMessage;
vector<shared_ptr<ShardokAIClient>> aiClients;
std::thread aiThread;
@@ -184,9 +169,6 @@ public:
[[nodiscard]] auto GetLogFilePath() const -> string { return logFilePath; }
[[nodiscard]] auto HasAIThreadError() const -> bool { return aiThreadFailed.load(); }
[[nodiscard]] auto GetAIThreadError() const -> std::string { return aiThreadErrorMessage; }
/// Register a subscriber to receive streaming updates for this game.
/// The subscriber will receive updates until it becomes inactive or is unregistered.
void RegisterSubscriber(std::shared_ptr<StreamSubscriber> subscriber);
@@ -195,10 +177,11 @@ public:
void UnregisterSubscriber(const StreamSubscriber* subscriber);
/// Wait for game updates, pushing them to the given subscriber.
/// Blocks until the game ends, subscriber disconnects, or tutorial battle resets.
/// Blocks until the game ends or the subscriber becomes inactive.
/// Returns true if the game ended normally, false if subscriber disconnected.
auto WaitForUpdatesAndPush(
std::shared_ptr<StreamSubscriber> subscriber,
int64_t startingActionId) -> WaitResult;
int64_t startingActionId) -> bool;
};
} // namespace shardok
@@ -29,17 +29,6 @@ class AvailableCommandsFactoryImpl : public AvailableCommandsFactory {
private:
const SettingsGetter settings;
static auto CannotBecomeOutlaw(const GameStateW &gameState, PlayerId pid) -> bool {
if (pid == UNCONTROLLED_PLAYER_ID) return false;
const auto &player = std::find_if(
begin(*gameState->player_infos()),
end(*gameState->player_infos()),
[pid](const PlayerInfoFb *pi) { return pi->player_id() == pid; });
return (player != end(*gameState->player_infos()) && player->cannot_become_outlaw());
}
static auto IsAttacker(const GameStateW &gameState, PlayerId pid) -> bool {
if (pid == UNCONTROLLED_PLAYER_ID) return false;
@@ -109,7 +98,6 @@ void AvailableCommandsFactoryImpl::AddAvailableCommandsForOneUnit(
const bool hasHero = unit->has_attached_hero();
const auto allyPids = AlliedPids(gameState, unit->player_id());
const bool isAttacker = IsAttacker(gameState, unit->player_id());
const bool cannotBecomeOutlaw = CannotBecomeOutlaw(gameState, unit->player_id());
const bool unitMovedIntoZoc = unit->has_moved_in_zoc();
const ActionPoints remainingActionPoints = unit->remaining_action_points();
@@ -146,7 +134,6 @@ void AvailableCommandsFactoryImpl::AddAvailableCommandsForOneUnit(
.units = gameState->units(),
.allyPids = allyPids,
.isAttacker = isAttacker,
.cannotBecomeOutlaw = cannotBecomeOutlaw,
.unitMovedIntoZoc = unitMovedIntoZoc};
for (const auto &commandFactory : commandFactories) {
@@ -219,27 +219,6 @@ public:
}
[[nodiscard]] inline auto GameIsOver() const -> bool { return GameIsOver(GetGameStatus()); }
[[nodiscard]] auto IsTutorialBattleEnabled() const -> bool {
return tutorialController_.IsEnabled();
}
/// Returns true if the game is over and the defender lost (not in winning_shardok_ids).
[[nodiscard]] auto DidDefenderLose() const -> bool {
if (!GameIsOver()) return false;
const auto *status = GetGameStatus();
const auto *winIds = status->winning_shardok_ids();
for (const auto *pi : *GetCurrentGameState()->player_infos()) {
if (pi->is_defender()) {
if (!winIds) return true;
for (const auto wid : *winIds) {
if (wid == pi->player_id()) return false;
}
return true;
}
}
return false;
}
};
} // namespace shardok
@@ -29,6 +29,7 @@ using Unit = net::eagle0::shardok::storage::fb::Unit;
inline auto GetMutableUnit(GameState *state, UnitId unitId) -> Unit * {
return const_cast<Unit *>(state->mutable_units()->GetMutableObject(unitId));
}
using net::eagle0::shardok::storage::fb::DrawType;
using net::eagle0::shardok::storage::fb::VictoryCondition;
using net::eagle0::shardok::storage::fb::VictoryType;
@@ -258,6 +259,23 @@ void MutatingApplyResult(
->mutable_end_game_condition()
->mutate_victory_type(VictoryType::VictoryType_UNKNOWN_VICTORY_TYPE);
break;
case net::eagle0::shardok::common::EndGameCondition::kAllyVictory:
mutatingGameState->mutable_status()
->mutable_end_game_condition()
->mutate_victory_type(VictoryType::VictoryType_ALLY_VICTORY);
mutatingGameState->mutable_status()
->mutable_end_game_condition()
->mutate_victory_details(static_cast<VictoryCondition>(
result.game_status().end_game_condition().ally_victory()));
break;
case net::eagle0::shardok::common::EndGameCondition::kDraw:
mutatingGameState->mutable_status()
->mutable_end_game_condition()
->mutate_victory_type(VictoryType::VictoryType_DRAW);
mutatingGameState->mutable_status()
->mutable_end_game_condition()
->mutate_draw_details(static_cast<DrawType>(
result.game_status().end_game_condition().draw()));
case net::eagle0::shardok::common::EndGameCondition::kLoss:
mutatingGameState->mutable_status()
->mutable_end_game_condition()
@@ -211,13 +211,21 @@ auto UpdateGameStatusAction::InternalExecute(
}
}
throw ShardokInternalErrorException(
"No player has WIN_AFTER_MAX_ROUNDS but max rounds exceeded");
results.emplace_back();
results[0].set_type(net::eagle0::shardok::common::GAME_OVER);
results[0].mutable_game_status()->set_state(GameStatusProto::DRAW);
results[0].mutable_game_status()->clear_winning_shardok_ids();
results[0].mutable_game_status()->mutable_end_game_condition()->set_draw(
net::eagle0::shardok::common::DRAW_AFTER_MAX_ROUNDS);
results[0].mutable_game_status()->set_description(
"Draw! No victory after " + std::to_string(settingsGetter.Backing().max_rounds()) +
" rounds");
return results;
}
// check for castle occupation
if (!criticalTileLocations.empty()) {
// First check: single player holding all critical tiles
for (const auto* pi : *gameState->player_infos()) {
if (HasVictoryCondition(
pi,
@@ -253,30 +261,6 @@ auto UpdateGameStatusAction::InternalExecute(
results[0].mutable_game_status()->set_state(
GameStatusProto::State::GameStatus_State_VICTORY);
results[0].mutable_game_status()->add_winning_shardok_ids(pi->player_id());
// Also add mutually-allied players with HoldsCriticalTiles
for (const auto* otherPi : *gameState->player_infos()) {
if (otherPi->player_id() == pi->player_id()) continue;
if (!HasVictoryCondition(
otherPi,
net::eagle0::shardok::storage::fb::
VictoryCondition_VICTORY_CONDITION_HOLDS_CRITICAL_TILES))
continue;
bool mutuallyAllied =
std::ranges::any_of(
*pi->allies(),
[otherPi](const auto* ap) {
return ap->player_id() == otherPi->player_id();
}) &&
std::ranges::any_of(*otherPi->allies(), [pi](const auto* ap) {
return ap->player_id() == pi->player_id();
});
if (mutuallyAllied) {
results[0].mutable_game_status()->add_winning_shardok_ids(
otherPi->player_id());
}
}
results[0].mutable_game_status()->mutable_end_game_condition()->set_victory(
net::eagle0::shardok::common::VICTORY_CONDITION_HOLDS_CRITICAL_TILES);
results[0].mutable_game_status()->set_description(
@@ -286,71 +270,6 @@ auto UpdateGameStatusAction::InternalExecute(
}
}
}
// Second check: allied players collectively holding all critical tiles
unordered_set<PlayerId> occupantPlayerIds{};
bool allTilesOccupiedWithHeroes = true;
for (const auto& criticalTile : criticalTileLocations) {
const auto* possibleOccupant = currentState.GetOccupant(criticalTile);
if (!possibleOccupant || !possibleOccupant->has_attached_hero()) {
allTilesOccupiedWithHeroes = false;
break;
}
occupantPlayerIds.insert(possibleOccupant->player_id());
}
if (allTilesOccupiedWithHeroes && occupantPlayerIds.size() > 1) {
// All occupants must have the HOLDS_CRITICAL_TILES victory condition
bool allHaveCondition = true;
for (const PlayerId pid : occupantPlayerIds) {
const auto* pi = GetPlayerInfo(pid);
if (!HasVictoryCondition(
pi,
net::eagle0::shardok::storage::fb::
VictoryCondition_VICTORY_CONDITION_HOLDS_CRITICAL_TILES)) {
allHaveCondition = false;
break;
}
}
if (allHaveCondition) {
// Check mutual alliance among all occupants
bool allAllied = true;
for (const PlayerId pid1 : occupantPlayerIds) {
const auto* p1Info = GetPlayerInfo(pid1);
for (const PlayerId pid2 : occupantPlayerIds) {
if (pid1 == pid2) continue;
if (!std::ranges::any_of(
*p1Info->allies(),
[pid2](const net::eagle0::shardok::storage::fb::AlliedPlayer*
alliedPlayer) {
return alliedPlayer->player_id() == pid2;
})) {
allAllied = false;
break;
}
}
if (!allAllied) break;
}
if (allAllied) {
results.emplace_back();
results[0].set_type(net::eagle0::shardok::common::GAME_OVER);
results[0].mutable_game_status()->set_state(
GameStatusProto::State::GameStatus_State_VICTORY);
*results[0].mutable_game_status()->mutable_winning_shardok_ids() = {
std::begin(occupantPlayerIds),
std::end(occupantPlayerIds)};
results[0].mutable_game_status()->mutable_end_game_condition()->set_victory(
net::eagle0::shardok::common::VICTORY_CONDITION_HOLDS_CRITICAL_TILES);
results[0].mutable_game_status()->set_description(
"Alliance victory! Allied attackers collectively control all "
"critical tiles");
ResolveHiddenLosers(results[0]);
return results;
}
}
}
}
// If we got all the way through, keep the status as it is
@@ -10,7 +10,6 @@ cc_library(
"//src/test/cpp/net/eagle0/shardok/library:__subpackages__",
],
deps = [
":blow_bridge_command_factory",
":brave_water_command_factory",
":build_bridge_command_factory",
":challenge_duel_command_factory",
@@ -39,25 +38,6 @@ cc_library(
],
)
cc_library(
name = "blow_bridge_command_factory",
srcs = ["BlowBridgeCommandFactory.cpp"],
hdrs = ["BlowBridgeCommandFactory.hpp"],
copts = COPTS,
visibility = [
"//src/main/cpp/net/eagle0/shardok/library:__subpackages__",
"//src/test/cpp/net/eagle0/shardok/library:__subpackages__",
],
deps = [
":command_factory",
"//src/main/cpp/net/eagle0/shardok/library:shardok_command",
"//src/main/cpp/net/eagle0/shardok/library/commands:blow_bridge_command",
"//src/main/cpp/net/eagle0/shardok/library/settings:game_settings",
"//src/main/cpp/net/eagle0/shardok/library/util:combat_utils",
"//src/main/cpp/net/eagle0/shardok/library/util:hex_map_utils",
],
)
cc_library(
name = "brave_water_command_factory",
srcs = [
@@ -1,104 +0,0 @@
//
// Created by Claude on 3/14/26.
//
#include "BlowBridgeCommandFactory.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/commands/BlowBridgeCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"
namespace shardok {
[[nodiscard]] auto GetBlowBridgeOdds(
const SettingsGetter& settings,
double strength,
double agility,
double intelligence,
bool hasForestAccess) -> PercentileRollOdds;
void BlowBridgeCommandFactory::AddAvailableBlowBridgeCommands(
CommandList& commands,
const Unit* unit,
const ActionPoints remainingActionPoints,
const Coords& position,
const HexMap* hexMap,
const Units* units,
const vector<PlayerId>& allyPids) const {
const PlayerId playerId = unit->player_id();
if (!unit->has_attached_hero()) return;
const auto& hero = unit->attached_hero();
if (hero.profession_info().profession() !=
net::eagle0::shardok::storage::fb::Profession_ENGINEER)
return;
// Must be on a bridge tile
const auto* currentTerrain = GetTerrain(hexMap, position);
if (!currentTerrain->modifier().bridge().present()) return;
const ActionCost cost =
settings.ActionCostFor(settings.Backing().blow_bridge_action_point_cost());
if (!cost.IsPossible(remainingActionPoints)) return;
const bool nearbyForest = HasForestAccess(position, units, hexMap, allyPids, playerId);
const auto odds = GetBlowBridgeOdds(
settings,
hero.strength(),
hero.agility(),
hero.wisdom(),
nearbyForest);
for (const Coords& adjCoords : HexMapUtils::GetAdjacentCoords(hexMap, position)) {
if (IsTraversible(*GetTerrain(hexMap, adjCoords)) && !Occupant(units, adjCoords)) {
commands.push_back(std::make_shared<BlowBridgeCommand>(
settings.ActionCostFor(settings.Backing().blow_bridge_action_point_cost()),
unit->player_id(),
unit->unit_id(),
adjCoords,
position,
*currentTerrain,
nearbyForest,
settings.Backing().blow_bridge_agility_xp(),
settings.Backing().blow_bridge_strength_xp(),
settings.Backing().minimum_knowledge_for_profession(),
odds));
}
}
}
void BlowBridgeCommandFactory::AddAvailableCommands(
CommandList& commands,
const CommandParams& params) const {
AddAvailableBlowBridgeCommands(
commands,
params.unit,
params.remainingActionPoints,
params.position,
params.hexMap,
params.units,
params.allyPids);
}
auto GetBlowBridgeOdds(
const SettingsGetter& settings,
const double strength,
const double agility,
const double intelligence,
const bool hasForestAccess) -> PercentileRollOdds {
const int16_t base = settings.Backing().blow_bridge_base_odds();
constexpr int16_t terrainFactor = 0;
constexpr int16_t weatherFactor = 0;
constexpr int16_t windFactor = 0;
const std::vector stats = {strength, agility, intelligence};
std::vector<OtherFactor> otherFactors;
if (hasForestAccess) {
otherFactors.push_back(
MakeOtherFactor(settings.Backing().blow_bridge_forest_bonus(), "forest nearby"));
}
return MakeOdds(base, terrainFactor, weatherFactor, windFactor, stats, otherFactors);
}
} // namespace shardok
@@ -1,37 +0,0 @@
//
// Created by Claude on 3/14/26.
//
#ifndef EAGLE0_BLOWBRIDGECOMMANDFACTORY_HPP
#define EAGLE0_BLOWBRIDGECOMMANDFACTORY_HPP
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/CommandFactory.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/Coordinates.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
namespace shardok {
class BlowBridgeCommandFactory : public CommandFactory {
private:
const SettingsGetter settings;
public:
explicit BlowBridgeCommandFactory(const SettingsGetter& getter) : settings(getter){};
void AddAvailableBlowBridgeCommands(
CommandList& commands,
const Unit* unit,
ActionPoints remainingActionPoints,
const Coords& position,
const HexMap* hexMap,
const Units* units,
const vector<PlayerId>& allyPids) const;
void AddAvailableCommands(CommandList& commands, const CommandParams& params) const override;
};
} // namespace shardok
#endif // EAGLE0_BLOWBRIDGECOMMANDFACTORY_HPP
@@ -4,7 +4,6 @@
#include "CommandFactoriesList.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/BlowBridgeCommandFactory.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/BraveWaterCommandFactory.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/BuildBridgeCommandFactory.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/ChallengeDuelCommandFactory.hpp"
@@ -42,7 +41,6 @@ auto MakeFactories(const SettingsGetter& settings) -> vector<shared_ptr<const Co
return {make_shared<MeteorTargetCommandFactory>(settings),
make_shared<ControlCommandFactory>(settings),
make_shared<ArcheryCommandFactory>(settings),
make_shared<BlowBridgeCommandFactory>(settings),
make_shared<BraveWaterCommandFactory>(settings),
make_shared<BuildBridgeCommandFactory>(settings),
make_shared<ChallengeDuelCommandFactory>(settings),
@@ -35,7 +35,6 @@ public:
const Units* units;
const vector<PlayerId>& allyPids;
const bool isAttacker;
const bool cannotBecomeOutlaw;
const bool unitMovedIntoZoc;
};
@@ -25,8 +25,7 @@ void FleeCommandFactory::AddAvailableFleeCommands(
const Units *allUnits,
const HexMap *map,
const vector<PlayerId> &allyPids,
const ActionPoints remainingActionPoints,
const bool cannotBecomeOutlaw) const {
const ActionPoints remainingActionPoints) const {
if (!settings.ActionCostFor(settings.Backing().flee_action_point_cost())
.IsPossible(remainingActionPoints))
return;
@@ -84,7 +83,7 @@ void FleeCommandFactory::AddAvailableFleeCommands(
unit->player_id(),
unit->unit_id(),
odds));
} else if (!cannotBecomeOutlaw) {
} else {
commands.push_back(std::make_shared<BecomeOutlawCommand>(
settings.ActionCostFor(settings.Backing().flee_action_point_cost()),
unit->player_id(),
@@ -101,8 +100,7 @@ void FleeCommandFactory::AddAvailableCommands(
params.units,
params.hexMap,
params.allyPids,
params.remainingActionPoints,
params.cannotBecomeOutlaw);
params.remainingActionPoints);
}
} // namespace shardok
@@ -27,8 +27,7 @@ public:
const Units *allUnits,
const HexMap *map,
const vector<PlayerId> &allyPids,
ActionPoints remainingActionPoints,
bool cannotBecomeOutlaw) const;
ActionPoints remainingActionPoints) const;
void AddAvailableCommands(CommandList &commands, const CommandParams &params) const override;
@@ -21,18 +21,13 @@ auto MeteorTargetCommandFactory::AddAvailableMeteorTargetCommands(
if (unit->attached_hero().profession_info().meteor_cast_state() !=
net::eagle0::shardok::storage::fb::MultiroundMagicState_TARGET)
return;
// If the mage already has a target, these commands are optional (re-targeting).
// If no target yet, the player must choose before ending their turn.
const bool isRetarget = unit->attached_hero().profession_info().cast_target().row() > -1;
const bool requiredToEndTurn = !isRetarget;
if (unit->attached_hero().profession_info().cast_target().row() > -1) return;
existingCommands.emplace_back(std::make_shared<MeteorCancelCommand>(
settings.ActionCostFor(settings.Backing().meteor_cancel_action_point_cost()),
settings,
unit->player_id(),
unit->unit_id(),
requiredToEndTurn));
unit->unit_id()));
const Coords &unitLocation = unit->location();
for (const Coords &meteorCoords : CoordsInMeteorRange(map, unitLocation, settings)) {
@@ -42,8 +37,7 @@ auto MeteorTargetCommandFactory::AddAvailableMeteorTargetCommands(
unit->player_id(),
unit->unit_id(),
meteorCoords,
settings.Backing().minimum_knowledge_for_profession(),
requiredToEndTurn));
settings.Backing().minimum_knowledge_for_profession()));
}
}
void MeteorTargetCommandFactory::AddAvailableCommands(
@@ -49,10 +49,10 @@ auto ReduceCommandFactory::AddAvailableReduceCommands(
const auto *terrain = GetTerrain(map, reduceCoords);
// Allow reducing if there's a castle with integrity > 0, OR an enemy
// Allow reducing if there's a bridge or castle with integrity > 0, OR an enemy
// occupant. We already continued in the case of friendly occupants.
// Note: bridges are no longer valid reduce targets (use Blow Bridge instead).
if ((terrain->modifier().castle().present() &&
if (terrain->modifier().bridge().present() ||
(terrain->modifier().castle().present() &&
terrain->modifier().castle().integrity() > 0.0) ||
enemyOccupant) {
existingCommands.push_back(std::make_shared<ReduceCommand>(
@@ -84,25 +84,6 @@ void ArcheryCommandFactory::AddAvailableArcheryCommands(
targetCoords += HexMapUtils::GetAdjacentCoords(hexMap, position);
}
// Wind-assisted range 3 for longbowmen
if (battalionType->alwaysArcheryCapable &&
weather->wind().speed_in_mph() >=
settings.Backing().longbow_wind_bonus_range_min_speed()) {
const int windDir = (int)weather->wind().direction();
for (const Coords &farCoords : TilesWithExactDistance(hexMap, position, 3)) {
auto dirTo = DirectionsTo(hexMap, position, farCoords);
int relMain = ((int)dirTo.main - windDir + 6) % 6;
bool inCone = (relMain == 0 || relMain == 1 || relMain == 5);
if (!inCone && dirTo.usesSecondary) {
int relSec = ((int)dirTo.secondary - windDir + 6) % 6;
inCone = (relSec == 0 || relSec == 1 || relSec == 5);
}
if (inCone && !HexMapUtils::LineIsBlockedByMountains(hexMap, position, farCoords)) {
targetCoords.Add(farCoords);
}
}
}
for (const Coords &archeryCoords : targetCoords) {
const auto *const enemyOccupant =
KnownEnemyOccupant(unit->player_id(), units, allyPids, archeryCoords);
@@ -39,28 +39,6 @@ cc_library(
],
)
cc_library(
name = "blow_bridge_command",
srcs = ["BlowBridgeCommand.cpp"],
hdrs = ["BlowBridgeCommand.hpp"],
copts = COPTS,
visibility = [
"//src/main/cpp/net/eagle0/shardok/library:__subpackages__",
"//src/test/cpp/net/eagle0/shardok/ai:__subpackages__",
"//src/test/cpp/net/eagle0/shardok/library:__subpackages__",
],
deps = [
"//src/main/cpp/net/eagle0/shardok/library:action_cost",
"//src/main/cpp/net/eagle0/shardok/library:shardok_command",
"//src/main/cpp/net/eagle0/shardok/library/actions:action_requires_hero_exception",
"//src/main/cpp/net/eagle0/shardok/library/map:tile_modifier_with_coords",
"//src/main/cpp/net/eagle0/shardok/library/unit",
"//src/main/cpp/net/eagle0/shardok/library/util:action_result_flatbuffer_helpers",
"//src/main/cpp/net/eagle0/shardok/library/view_filters:odds_filter",
"//src/main/protobuf/net/eagle0/shardok/common:terrain_cc_proto",
],
)
cc_library(
name = "build_bridge_command",
srcs = ["BuildBridgeCommand.cpp"],
@@ -1,82 +0,0 @@
//
// Created by Claude on 3/14/26.
//
#include "BlowBridgeCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/actions/ActionRequiresHeroException.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/TileModifierWithCoords.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/util/ActionResultFlatbufferHelpers.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/view_filters/OddsFilter.hpp"
#include "src/main/protobuf/net/eagle0/shardok/common/tile_modifier.pb.h"
namespace shardok {
using net::eagle0::shardok::common::ActionType;
auto BlowBridgeCommand::InternalExecuteWithRoll(
const GameStateW& currentState,
const std::shared_ptr<RandomGenerator>& generator,
const std::optional<int32_t> roll) const -> vector<ActionResult> {
const auto successRoll = 101 - roll.value_or(generator->Percentile());
return ExecuteWithRoll(currentState, successRoll);
}
auto BlowBridgeCommand::ExecuteWithRoll(const GameStateW& currentState, double roll) const
-> vector<ActionResult> {
const auto* actor = currentState->units()->Get(actorId);
if (!actor->has_attached_hero()) { throw ActionRequiresHeroException("blow bridge"); }
auto actorAfter = *actor;
MutatingSpendActionPoints(&actorAfter, cost);
MutatingBumpAgilityXp(&actorAfter, agilityXp);
MutatingBumpStrengthXp(&actorAfter, strengthXp);
MutatingBumpAllKnowledgeToMinimum(&actorAfter, minimumKnowledgeAfter);
// Always move engineer to target tile
actorAfter.mutable_location() = target;
ActionResult result{};
result.mutable_player()->set_value(GetPlayerId());
result.mutable_actor()->set_value(actorAfter.unit_id());
*result.mutable_target_coords() = ToCoordsProto(target);
result.mutable_roll()->set_value(roll);
*result.mutable_odds() = successOdds;
if (PercentileRollSucceeds(successOdds, roll)) {
result.set_type(ActionType::BLOW_BRIDGE);
auto newTileModifier = targetTerrain.modifier();
SetBridge(newTileModifier, 0.0);
*result.add_changed_tile_modifiers() = MakeTmc(bridgeCoords, newTileModifier);
} else {
result.set_type(ActionType::BLOW_BRIDGE_FAILED);
}
AddChangedUnit(result, actorAfter);
return {result};
}
auto BlowBridgeCommand::GetCommandProto() const -> CommandProto {
CommandProto proto{};
proto.set_player(GetPlayerId());
proto.set_type(net::eagle0::shardok::common::BLOW_BRIDGE_COMMAND);
proto.mutable_actor()->set_value(actorId);
*proto.mutable_target() = ToCoordsProto(target);
proto.mutable_roll_request()->set_roll_type(net::eagle0::shardok::api::ROLL_TYPE_D100);
proto.mutable_roll_request()->set_command_type(
net::eagle0::shardok::common::BLOW_BRIDGE_COMMAND);
proto.mutable_roll_request()->set_acting_unit_id(actorId);
*proto.mutable_odds() = OddsFilteredForPlayer(successOdds, GetPlayerId());
return proto;
}
auto BlowBridgeCommand::GetOddsPercentile() const -> int32_t {
return OddsFilteredForPlayer(successOdds, GetPlayerId()).success_chance();
}
} // namespace shardok
@@ -1,82 +0,0 @@
//
// Created by Claude on 3/14/26.
//
#ifndef EAGLE0_BLOWBRIDGECOMMAND_HPP
#define EAGLE0_BLOWBRIDGECOMMAND_HPP
#include <utility>
#include "src/main/cpp/net/eagle0/shardok/library/ActionCost.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCommand.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/map/Coordinates.hpp"
namespace shardok {
using Terrain = net::eagle0::shardok::storage::fb::Terrain;
using Unit = net::eagle0::shardok::storage::fb::Unit;
class BlowBridgeCommand : public ShardokCommand {
protected:
[[nodiscard]] auto InternalExecuteWithRoll(
const GameStateW& currentState,
const std::shared_ptr<RandomGenerator>& generator,
std::optional<int32_t> roll) const -> vector<ActionResult> override;
const ActionCost cost;
const UnitId actorId;
const Coords target;
const Coords bridgeCoords;
const Terrain targetTerrain;
const bool hasNearbyForest;
const int agilityXp;
const int strengthXp;
int minimumKnowledgeAfter;
const PercentileRollOdds successOdds;
public:
BlowBridgeCommand(
const ActionCost& cost,
PlayerId playerId,
UnitId actorId,
Coords target,
Coords bridgeCoords,
const Terrain& targetTerrain,
bool hasNearbyForest,
int agilityXp,
int strengthXp,
int opponentKnowledgeIncrease,
PercentileRollOdds successOdds)
: ShardokCommand(playerId),
cost(cost),
actorId(actorId),
target(std::move(target)),
bridgeCoords(std::move(bridgeCoords)),
targetTerrain(std::move(targetTerrain)),
hasNearbyForest(hasNearbyForest),
agilityXp(agilityXp),
strengthXp(strengthXp),
minimumKnowledgeAfter(opponentKnowledgeIncrease),
successOdds(std::move(successOdds)){};
auto ExecuteWithRoll(const GameStateW& currentState, double roll) const -> vector<ActionResult>;
~BlowBridgeCommand() override = default;
[[nodiscard]] auto GetCommandType() const -> CommandType override {
return net::eagle0::shardok::common::BLOW_BRIDGE_COMMAND;
}
[[nodiscard]] auto CanUseClientRoll() const -> bool override { return true; }
[[nodiscard]] auto GetCommandProto() const -> CommandProto override;
[[nodiscard]] auto HasOdds() const -> bool override { return true; }
[[nodiscard]] auto GetOddsPercentile() const -> int32_t override;
[[nodiscard]] int GetActorUnitId() const override { return actorId; }
[[nodiscard]] MapIndex GetTargetRow() const override { return target.row(); }
[[nodiscard]] MapIndex GetTargetColumn() const override { return target.column(); }
};
} // namespace shardok
#endif // EAGLE0_BLOWBRIDGECOMMAND_HPP
@@ -16,13 +16,11 @@ MeteorCancelCommand::MeteorCancelCommand(
const ActionCost& cost,
const SettingsGetter& settingsGetter,
const PlayerId playerId,
const UnitId casterId,
const bool requiredToEndTurn)
const UnitId casterId)
: ShardokCommand(playerId),
cost(cost),
settings(settingsGetter),
casterId(casterId),
requiredToEndTurn(requiredToEndTurn) {}
casterId(casterId) {}
auto MeteorCancelCommand::InternalExecute(
const GameStateW& currentState,
@@ -21,15 +21,13 @@ protected:
const ActionCost cost;
const SettingsGetter settings;
const UnitId casterId;
const bool requiredToEndTurn;
public:
MeteorCancelCommand(
const ActionCost &cost,
const SettingsGetter &settingsGetter,
PlayerId playerId,
UnitId casterId,
bool requiredToEndTurn = true);
UnitId casterId);
~MeteorCancelCommand() override = default;
@@ -38,7 +36,7 @@ public:
}
auto GetCommandProto() const -> CommandProto override;
[[nodiscard]] auto IsRequiredToEndTurn() const -> bool override { return requiredToEndTurn; }
[[nodiscard]] auto IsRequiredToEndTurn() const -> bool override { return true; }
[[nodiscard]] auto CanDoWithLowMorale() const -> bool override { return true; }
[[nodiscard]] auto CanDoWithLowVigor() const -> bool override { return true; }
@@ -41,15 +41,13 @@ MeteorTargetCommand::MeteorTargetCommand(
const PlayerId playerId,
const UnitId casterId,
Coords target,
const int minimumKnowledge,
const bool requiredToEndTurn)
const int minimumKnowledge)
: ShardokCommand(playerId),
cost(cost),
settings(settingsGetter),
casterId(casterId),
target(std::move(target)),
minimumKnowledge(minimumKnowledge),
requiredToEndTurn(requiredToEndTurn) {}
minimumKnowledge(minimumKnowledge) {}
auto MeteorTargetCommand::GetCommandProto() const -> CommandProto {
CommandProto proto{};
@@ -24,7 +24,6 @@ protected:
const UnitId casterId;
const Coords target;
const int minimumKnowledge;
const bool requiredToEndTurn;
public:
MeteorTargetCommand(
@@ -33,8 +32,7 @@ public:
PlayerId playerId,
UnitId casterId,
Coords target,
int minimumKnowledge,
bool requiredToEndTurn = true);
int minimumKnowledge);
~MeteorTargetCommand() override = default;
@@ -43,7 +41,7 @@ public:
}
auto GetCommandProto() const -> CommandProto override;
[[nodiscard]] auto IsRequiredToEndTurn() const -> bool override { return requiredToEndTurn; }
[[nodiscard]] auto IsRequiredToEndTurn() const -> bool override { return true; }
[[nodiscard]] auto CanDoWithLowMorale() const -> bool override { return true; }
[[nodiscard]] auto CanDoWithLowVigor() const -> bool override { return true; }
@@ -62,7 +62,6 @@ auto FromPlayerInfoProto(flatbuffers::FlatBufferBuilder& fbb, const PlayerInfoPr
pib.add_allies(alliesOffset);
pib.add_victory_conditions(vcOffset);
pib.add_starting_food(piProto.starting_food());
pib.add_cannot_become_outlaw(piProto.cannot_become_outlaw());
return pib.Finish();
}
@@ -240,12 +239,14 @@ auto ToProto(const GameStatus* fbStatus) -> GameStatusProto {
fbStatus->end_game_condition()->victory_details()));
break;
case net::eagle0::shardok::storage::fb::VictoryType_ALLY_VICTORY:
protoStatus.mutable_end_game_condition()->set_victory(
protoStatus.mutable_end_game_condition()->set_ally_victory(
static_cast<net::eagle0::shardok::common::VictoryCondition>(
fbStatus->end_game_condition()->victory_details()));
break;
case net::eagle0::shardok::storage::fb::VictoryType_DRAW:
throw InvalidProtoException("Draw victory type is no longer supported");
protoStatus.mutable_end_game_condition()->set_draw(
static_cast<net::eagle0::shardok::common::DrawType>(
fbStatus->end_game_condition()->draw_details()));
break;
case net::eagle0::shardok::storage::fb::VictoryType_LOSS:
protoStatus.mutable_end_game_condition()->set_loss(
@@ -277,7 +278,6 @@ auto ToPlayerInfoProto(const PlayerInfo* fbPI) -> PlayerInfoProto {
}
piProto.set_is_ai(fbPI->is_ai());
piProto.set_eagle_faction_id(fbPI->eagle_faction_id());
piProto.set_cannot_become_outlaw(fbPI->cannot_become_outlaw());
return piProto;
}
@@ -260,13 +260,7 @@ auto TutorialBattleController::ExecuteReinforcementsAction(
}
}
// Build set of eagle hero IDs for this specific reinforcement event
std::set<int32_t> expectedHeroIds;
for (const auto& commonUnit : reinforcementsAction.units()) {
if (commonUnit.has_hero()) { expectedHeroIds.insert(commonUnit.hero().eagle_hero_id()); }
}
// Place only the PENDING_REINFORCEMENT units that belong to this event
// Place PENDING_REINFORCEMENT units directly at available positions as NORMAL_UNIT
ActionResult reinforcementsResult{};
reinforcementsResult.set_type(ActionType::TUTORIAL_REINFORCEMENTS_ARRIVED);
reinforcementsResult.mutable_player()->set_value(playerId);
@@ -274,10 +268,6 @@ auto TutorialBattleController::ExecuteReinforcementsAction(
size_t posIndex = 0;
for (const auto* unit : *state->units()) {
if (unit->status() != UnitStatusFB::UnitStatus_PENDING_REINFORCEMENT) { continue; }
if (!unit->has_attached_hero() ||
!expectedHeroIds.contains(unit->attached_hero().eagle_hero_id())) {
continue;
}
if (posIndex >= availablePositions.size()) { break; }
net::eagle0::shardok::storage::fb::Unit changedUnit = *unit;
@@ -188,6 +188,22 @@ auto GameStateGuesser::GuessedState(
gameStateView.status().end_game_condition().victory()));
break;
case net::eagle0::shardok::common::EndGameCondition::ConditionCase::kAllyVictory:
endGameCondition.mutate_victory_type(
net::eagle0::shardok::storage::fb::VictoryType_ALLY_VICTORY);
endGameCondition.mutate_victory_details(
static_cast<net::eagle0::shardok::storage::fb::VictoryCondition>(
gameStateView.status().end_game_condition().ally_victory()));
break;
case net::eagle0::shardok::common::EndGameCondition::ConditionCase::kDraw:
endGameCondition.mutate_victory_type(
net::eagle0::shardok::storage::fb::VictoryType_DRAW);
endGameCondition.mutate_draw_details(
static_cast<net::eagle0::shardok::storage::fb::DrawType>(
gameStateView.status().end_game_condition().draw()));
break;
case net::eagle0::shardok::common::EndGameCondition::ConditionCase::kLoss:
endGameCondition.mutate_victory_type(
net::eagle0::shardok::storage::fb::VictoryType_LOSS);
@@ -47,25 +47,6 @@ cc_library(
],
)
cc_library(
name = "game_over_response_populator",
srcs = ["GameOverResponsePopulator.cpp"],
hdrs = ["GameOverResponsePopulator.hpp"],
copts = COPTS,
visibility = ["//visibility:public"],
deps = [
"//src/main/cpp/net/eagle0/shardok/library:shardok_c_types",
"//src/main/cpp/net/eagle0/shardok/library:shardok_exception",
"//src/main/flatbuffer/net/eagle0/shardok/storage:unit_cc_fbs",
"//src/main/protobuf/net/eagle0/common:common_unit_cc_proto",
"//src/main/protobuf/net/eagle0/common:shardok_internal_interface_cc_grpc",
"//src/main/protobuf/net/eagle0/common:victory_condition_cc_proto",
"//src/main/protobuf/net/eagle0/shardok/common:game_status_cc_proto",
"//src/main/protobuf/net/eagle0/shardok/common:player_info_cc_proto",
"//src/main/protobuf/net/eagle0/shardok/storage:action_result_cc_proto",
],
)
cc_library(
name = "eagle_interface_grpc_server",
srcs = ["EagleInterfaceGrpcServer.cpp"],
@@ -73,7 +54,6 @@ cc_library(
copts = COPTS,
visibility = ["//src/main/cpp/net/eagle0/shardok:__subpackages__"],
deps = [
":game_over_response_populator",
":games_manager",
":token_auth",
"//src/main/cpp/net/eagle0/common:unit_conversions",
@@ -19,7 +19,6 @@
#include "src/main/cpp/net/eagle0/common/UnitConversions.hpp"
#include "src/main/cpp/net/eagle0/shardok/controller/ShardokGameController.hpp"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokEngine.hpp"
#include "src/main/cpp/net/eagle0/shardok/server/GameOverResponsePopulator.hpp"
#include "src/main/cpp/net/eagle0/shardok/util/MapLoader.hpp"
#include "src/main/protobuf/net/eagle0/common/victory_condition.pb.h"
@@ -46,16 +45,6 @@ public:
auto EagleInterfaceImpl::ControllerForGame(const GameId &gameId, const GameSetupInfo &setupInfo)
-> std::shared_ptr<ShardokGameController> {
auto controller = gamesManager->GetController(gameId);
// If game exists but Eagle is requesting a fresh start with no prior history
// (happens after admin rewind), replace the old game
if (controller != nullptr && setupInfo.has_new_game_request() &&
setupInfo.known_result_count() == 0) {
printf("Replacing existing game %s with fresh game (rewind detected)\n", gameId.c_str());
gamesManager->RemoveController(gameId);
controller = nullptr;
}
if (controller == nullptr) {
if (setupInfo.current_game_state().empty()) {
StartGame(setupInfo.new_game_request());
@@ -74,6 +63,22 @@ auto EagleInterfaceImpl::ControllerForGame(const GameId &gameId, const GameSetup
return controller;
}
static auto PopulateGameOverResponse(
const string &gameId,
const GameStatus &gameStatus,
const vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
const vector<net::eagle0::shardok::storage::ResolvedUnit> &resolvedUnits,
net::eagle0::common::GameOverResponse *gameOverResponse) -> bool;
static auto IncludeUnitProtoInReturn(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus &internalStatus) -> bool;
static auto FromUnitFb(const Unit &unit) -> net::eagle0::common::CommonUnit;
static auto FromInternalStatus(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus internalStatus)
-> net::eagle0::common::UnitStatus;
const std::string &kShardokGameRequestExtension = *(new string(".e0gr"));
EagleInterfaceImpl::EagleInterfaceImpl(
@@ -138,8 +143,7 @@ auto ConvertPlayerInfo(
pi.food(),
victoryConditions,
alliedPids,
shardokUnits,
pi.cannot_become_outlaw());
shardokUnits);
}
void EagleInterfaceImpl::StartGame(const NewGameRequest &request) {
@@ -171,21 +175,7 @@ void EagleInterfaceImpl::StartGame(const NewGameRequest &request) {
playersInfo.push_back(ConvertPlayerInfo(request.user_infos(), (PlayerId)i));
}
// Validate that exactly one player has WIN_AFTER_MAX_ROUNDS
int winAfterMaxRoundsCount = 0;
for (const auto &psi : playersInfo) {
for (const auto &vc : psi.playerInfo.victory_conditions()) {
if (vc == net::eagle0::shardok::common::VICTORY_CONDITION_WIN_AFTER_MAX_ROUNDS) {
winAfterMaxRoundsCount++;
}
}
}
if (winAfterMaxRoundsCount != 1) {
throw NewGameException(
StatusCode::INVALID_ARGUMENT,
"Exactly one player must have WIN_AFTER_MAX_ROUNDS victory condition, found " +
std::to_string(winAfterMaxRoundsCount));
}
// FIXME: validate sanity of the victory conditions
// Grab the nonempty gameId
const string &gameId = request.game_id();
@@ -361,6 +351,177 @@ auto EagleInterfaceImpl::GetHexMapNames(
return Status::OK;
}
auto PopulateGameOverResponse(
const string &gameId,
const GameStatus &gameStatus,
const vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
const vector<net::eagle0::shardok::storage::ResolvedUnit> &resolvedUnits,
net::eagle0::common::GameOverResponse *gameOverResponse) -> bool {
const auto &endCondition = gameStatus.end_game_condition();
int32_t winningFactionId = -1;
for (const auto &rpi : resolvedPlayerInfos) {
// for (int shardokPid = 0; shardokPid < request.user_infos_size(); shardokPid++) {
auto shardokPid = rpi.player_id();
const int32_t eagleFactionId = rpi.eagle_faction_id();
// const net::eagle0::common::PlayerSetupInfo &playerSetupInfo =
// request.user_infos(shardokPid);
auto *resolutionInfo = gameOverResponse->add_user_infos();
// Set the endgame condition (win/lose/draw) appropriately
resolutionInfo->set_eagle_faction_id(eagleFactionId);
if (endCondition.condition_case() == EndGameCondition::kDraw) {
// Everyone gets a draw
resolutionInfo->mutable_end_game_condition()->set_draw(
net::eagle0::common::DrawType(endCondition.draw()));
} else if (std::ranges::contains(gameStatus.winning_shardok_ids(), shardokPid)) {
// The winning player gets the victory set
resolutionInfo->mutable_end_game_condition()->set_victory(
net::eagle0::common::VictoryCondition(endCondition.victory()));
winningFactionId = eagleFactionId;
} else if (std::ranges::any_of(
gameStatus.winning_shardok_ids(),
[&rpi, shardokPid](const PlayerId /*pid*/) {
return std::ranges::any_of(
rpi.allies(),
[shardokPid](const net::eagle0::shardok::common::AlliedPlayer
&ap) {
return ap.player_id() == shardokPid;
});
})) {
// Allies of the winning player get an allied victory set
resolutionInfo->mutable_end_game_condition()->set_ally_victory(
net::eagle0::common::VictoryCondition(endCondition.victory()));
} else {
resolutionInfo->mutable_end_game_condition()->set_loss(
net::eagle0::common::VictoryCondition(endCondition.victory()));
}
// copy in all the resolvedUnits that correspond to this player
for (const auto &internalRu : resolvedUnits) {
const auto unit = (Unit *)internalRu.unit_bytes().data();
if (!unit->has_attached_hero()) continue;
if (!IncludeUnitProtoInReturn(internalRu.status())) continue;
if (unit->player_id() != shardokPid) continue;
auto *ru = resolutionInfo->add_units();
*ru->mutable_unit() = FromUnitFb(*unit);
ru->set_status(FromInternalStatus(internalRu.status()));
}
}
printf("Finishing game %s: ", gameId.c_str());
if (endCondition.condition_case() == EndGameCondition::kDraw) {
printf("It's a draw!\n");
} else {
printf("%d wins\n", winningFactionId);
}
return true;
}
auto IncludeUnitProtoInReturn(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus &internalStatus) -> bool {
switch (internalStatus) {
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_CAPTURED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NORMAL_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_FLED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_RETREATED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NEVER_ENTERED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_OUTLAWED_UNIT: return true;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_DESTROYED_SUMMONED_UNIT:
return false;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_UNKNOWN_UNIT:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
throw ShardokInternalErrorException("Bad unit status on resolved unit");
}
return true;
}
auto FromUnitFb(const Unit &unit) -> net::eagle0::common::CommonUnit {
net::eagle0::common::CommonUnit commonUnit{};
commonUnit.set_eagle_player_id(unit.eagle_player_id());
commonUnit.mutable_hero()->set_eagle_hero_id(unit.attached_hero().eagle_hero_id());
commonUnit.mutable_hero()->set_profession(
(net::eagle0::common::CommonProfession)unit.attached_hero()
.profession_info()
.profession());
commonUnit.mutable_hero()->set_strength(unit.attached_hero().strength());
commonUnit.mutable_hero()->set_strength_xp(unit.attached_hero().strength_xp());
commonUnit.mutable_hero()->set_agility(unit.attached_hero().agility());
commonUnit.mutable_hero()->set_agility_xp(unit.attached_hero().agility_xp());
commonUnit.mutable_hero()->set_constitution(unit.attached_hero().constitution());
commonUnit.mutable_hero()->set_constitution_xp(unit.attached_hero().constitution_xp());
commonUnit.mutable_hero()->set_charisma(unit.attached_hero().charisma());
commonUnit.mutable_hero()->set_charisma_xp(unit.attached_hero().charisma_xp());
commonUnit.mutable_hero()->set_wisdom(unit.attached_hero().wisdom());
commonUnit.mutable_hero()->set_wisdom_xp(unit.attached_hero().wisdom_xp());
commonUnit.mutable_hero()->set_integrity(unit.attached_hero().integrity());
commonUnit.mutable_hero()->set_ambition(unit.attached_hero().ambition());
commonUnit.mutable_hero()->set_gregariousness(unit.attached_hero().gregariousness());
commonUnit.mutable_hero()->set_bravery(unit.attached_hero().bravery());
commonUnit.mutable_hero()->set_vigor(unit.attached_hero().vigor());
commonUnit.mutable_hero()->set_spent_vigor(unit.attached_hero().spent_vigor());
commonUnit.mutable_battalion()->set_eagle_battalion_id(unit.battalion().eagle_battalion_id());
commonUnit.mutable_battalion()->set_size(unit.battalion().size());
commonUnit.mutable_battalion()->set_type(
static_cast<net::eagle0::common::CommonBattalionTypeId>(unit.battalion().type()));
commonUnit.mutable_battalion()->set_armament(unit.battalion().armament());
commonUnit.mutable_battalion()->set_training(unit.battalion().training());
return commonUnit;
}
auto FromInternalStatus(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus internalStatus)
-> net::eagle0::common::UnitStatus {
switch (internalStatus) {
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_CAPTURED_UNIT:
return net::eagle0::common::UnitStatus::CAPTURED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NORMAL_UNIT:
return net::eagle0::common::UnitStatus::NORMAL_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_FLED_UNIT:
return net::eagle0::common::UnitStatus::FLED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_RETREATED_UNIT:
return net::eagle0::common::UnitStatus::RETREATED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NEVER_ENTERED_UNIT:
return net::eagle0::common::UnitStatus::NEVER_ENTERED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_OUTLAWED_UNIT:
return net::eagle0::common::UnitStatus::OUTLAWED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_DESTROYED_SUMMONED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_UNKNOWN_UNIT:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
throw ShardokInternalErrorException("Bad unit status on resolved unit");
}
throw ShardokInternalErrorException("Bad unit status on resolved unit");
}
auto EagleInterfaceImpl::SubscribeToGame(
ServerContext *context,
const GameSubscriptionRequest *request,
@@ -371,16 +532,7 @@ auto EagleInterfaceImpl::SubscribeToGame(
shared_ptr<ShardokGameController> controller;
try {
controller = ControllerForGame(request->game_id(), request->game_setup_info());
} catch (NewGameException &e) { return e.GetStatus(); } catch (ShardokClientErrorException &e) {
std::cerr << "Bad request from client: " << e.what() << std::endl;
return Status(StatusCode::INVALID_ARGUMENT, e.what());
} catch (ShardokInternalErrorException &e) {
std::cerr << "Internal error: " << e.what() << std::endl;
return Status(StatusCode::INTERNAL, e.what());
} catch (std::exception &e) {
std::cerr << "Unknown exception in SubscribeToGame: " << e.what() << std::endl;
return Status(StatusCode::INTERNAL, e.what());
}
} catch (NewGameException &e) { return e.GetStatus(); }
if (!controller) { return Status(StatusCode::NOT_FOUND, "Game not found"); }
@@ -472,16 +624,6 @@ auto EagleInterfaceImpl::SubscribeToGame(
active_ = false;
}
void OnBattleReset() override {
if (!active_) return;
GameStatusResponse response;
response.set_game_id(gameId_);
response.mutable_battle_reset_response();
if (!writer_->Write(response)) { active_ = false; }
}
[[nodiscard]] auto IsActive() const -> bool override {
return active_ && !context_->IsCancelled();
}
@@ -492,63 +634,13 @@ auto EagleInterfaceImpl::SubscribeToGame(
controller->RegisterSubscriber(subscriber);
// Wait for updates and push them until game ends or subscriber disconnects.
// For tutorial battles, a BATTLE_RESET result means the defender lost and we
// should restart the game from the original request.
int64_t actionCount = countAfterInitialResponse;
WaitResult result = WaitResult::GAME_OVER;
while (true) {
result = controller->WaitForUpdatesAndPush(subscriber, actionCount);
if (result != WaitResult::BATTLE_RESET) break;
printf("SubscribeToGame: Tutorial battle reset, restarting game %s\n",
controller->GetGameId().c_str());
// Save the serialized request before removing the controller
const std::string savedRequest = controller->SerializedRequest();
const GameId gameId = controller->GetGameId();
controller->UnregisterSubscriber(subscriber.get());
gamesManager->RemoveController(gameId);
// Deserialize and restart the game from the original request
NewGameRequest newGameRequest;
newGameRequest.ParseFromString(savedRequest);
StartGame(newGameRequest);
controller = gamesManager->GetController(gameId);
if (!controller) {
printf("SubscribeToGame: Failed to restart game after reset\n");
return Status(StatusCode::INTERNAL, "Failed to restart tutorial battle");
}
// Send initial state from the new game
GameStatusResponse resetInitialResponse;
PopulateGameStatusResponse(controller, 0, &resetInitialResponse);
if (!writer->Write(resetInitialResponse)) break;
// Reset action count based on the new game's state
actionCount =
resetInitialResponse.has_game_update_response()
? resetInitialResponse.game_update_response().total_action_result_count()
: 0;
// Re-register subscriber with the new controller
controller->RegisterSubscriber(subscriber);
}
// Wait for updates and push them until game ends or subscriber disconnects
// Use countAfterInitialResponse to avoid re-sending results already in initial response
bool gameEnded = controller->WaitForUpdatesAndPush(subscriber, countAfterInitialResponse);
controller->UnregisterSubscriber(subscriber.get());
if (controller->HasAIThreadError()) {
std::cerr << "SubscribeToGame: AI thread error: " << controller->GetAIThreadError()
<< std::endl;
return Status(StatusCode::INTERNAL, controller->GetAIThreadError());
}
if (result == WaitResult::GAME_OVER) {
if (gameEnded) {
printf("SubscribeToGame: Game ended normally\n");
} else {
printf("SubscribeToGame: Subscriber disconnected\n");
@@ -1,176 +0,0 @@
#include "GameOverResponsePopulator.hpp"
#include <algorithm>
#include <ranges>
#include <string>
#include <vector>
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
#include "src/main/cpp/net/eagle0/shardok/library/ShardokException.hpp"
#include "src/main/protobuf/net/eagle0/common/victory_condition.pb.h"
namespace shardok {
using net::eagle0::common::VictoryCondition;
using std::string;
using std::vector;
auto PopulateGameOverResponse(
const string &gameId,
const net::eagle0::shardok::common::GameStatus &gameStatus,
const vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
const vector<net::eagle0::shardok::storage::ResolvedUnit> &resolvedUnits,
net::eagle0::common::GameOverResponse *gameOverResponse) -> bool {
const auto &endCondition = gameStatus.end_game_condition();
int32_t winningFactionId = -1;
for (const auto &rpi : resolvedPlayerInfos) {
auto shardokPid = rpi.player_id();
const int32_t eagleFactionId = rpi.eagle_faction_id();
auto *resolutionInfo = gameOverResponse->add_user_infos();
// Set the endgame condition (win/lose) appropriately
resolutionInfo->set_eagle_faction_id(eagleFactionId);
if (std::ranges::contains(gameStatus.winning_shardok_ids(), shardokPid)) {
// The winning player gets the victory set
resolutionInfo->mutable_end_game_condition()->set_victory(
net::eagle0::common::VictoryCondition(endCondition.victory()));
winningFactionId = eagleFactionId;
} else if (std::ranges::any_of(
gameStatus.winning_shardok_ids(),
[&rpi](const PlayerId pid) {
return std::ranges::any_of(
rpi.allies(),
[pid](const net::eagle0::shardok::common::AlliedPlayer &ap) {
return ap.player_id() == pid;
});
})) {
// Allied to a winner — their side won, so they get victory too
resolutionInfo->mutable_end_game_condition()->set_victory(
net::eagle0::common::VictoryCondition(endCondition.victory()));
} else {
resolutionInfo->mutable_end_game_condition()->set_loss(
net::eagle0::common::VictoryCondition(endCondition.victory()));
}
// copy in all the resolvedUnits that correspond to this player
for (const auto &internalRu : resolvedUnits) {
const auto unit = (Unit *)internalRu.unit_bytes().data();
if (!unit->has_attached_hero()) continue;
if (!IncludeUnitProtoInReturn(internalRu.status())) continue;
if (unit->player_id() != shardokPid) continue;
auto *ru = resolutionInfo->add_units();
*ru->mutable_unit() = FromUnitFb(*unit);
ru->set_status(FromInternalStatus(internalRu.status()));
}
}
printf("Finishing game %s: %d wins\n", gameId.c_str(), winningFactionId);
return true;
}
auto IncludeUnitProtoInReturn(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus &internalStatus) -> bool {
switch (internalStatus) {
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_CAPTURED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NORMAL_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_FLED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_RETREATED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NEVER_ENTERED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_OUTLAWED_UNIT: return true;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_DESTROYED_SUMMONED_UNIT:
return false;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_UNKNOWN_UNIT:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
throw ShardokInternalErrorException("Bad unit status on resolved unit");
}
return true;
}
auto FromUnitFb(const Unit &unit) -> net::eagle0::common::CommonUnit {
net::eagle0::common::CommonUnit commonUnit{};
commonUnit.set_eagle_player_id(unit.eagle_player_id());
commonUnit.mutable_hero()->set_eagle_hero_id(unit.attached_hero().eagle_hero_id());
commonUnit.mutable_hero()->set_profession(
(net::eagle0::common::CommonProfession)unit.attached_hero()
.profession_info()
.profession());
commonUnit.mutable_hero()->set_strength(unit.attached_hero().strength());
commonUnit.mutable_hero()->set_strength_xp(unit.attached_hero().strength_xp());
commonUnit.mutable_hero()->set_agility(unit.attached_hero().agility());
commonUnit.mutable_hero()->set_agility_xp(unit.attached_hero().agility_xp());
commonUnit.mutable_hero()->set_constitution(unit.attached_hero().constitution());
commonUnit.mutable_hero()->set_constitution_xp(unit.attached_hero().constitution_xp());
commonUnit.mutable_hero()->set_charisma(unit.attached_hero().charisma());
commonUnit.mutable_hero()->set_charisma_xp(unit.attached_hero().charisma_xp());
commonUnit.mutable_hero()->set_wisdom(unit.attached_hero().wisdom());
commonUnit.mutable_hero()->set_wisdom_xp(unit.attached_hero().wisdom_xp());
commonUnit.mutable_hero()->set_integrity(unit.attached_hero().integrity());
commonUnit.mutable_hero()->set_ambition(unit.attached_hero().ambition());
commonUnit.mutable_hero()->set_gregariousness(unit.attached_hero().gregariousness());
commonUnit.mutable_hero()->set_bravery(unit.attached_hero().bravery());
commonUnit.mutable_hero()->set_vigor(unit.attached_hero().vigor());
commonUnit.mutable_hero()->set_spent_vigor(unit.attached_hero().spent_vigor());
commonUnit.mutable_battalion()->set_eagle_battalion_id(unit.battalion().eagle_battalion_id());
commonUnit.mutable_battalion()->set_size(unit.battalion().size());
commonUnit.mutable_battalion()->set_type(
static_cast<net::eagle0::common::CommonBattalionTypeId>(unit.battalion().type()));
commonUnit.mutable_battalion()->set_armament(unit.battalion().armament());
commonUnit.mutable_battalion()->set_training(unit.battalion().training());
return commonUnit;
}
auto FromInternalStatus(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus internalStatus)
-> net::eagle0::common::UnitStatus {
switch (internalStatus) {
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_CAPTURED_UNIT:
return net::eagle0::common::UnitStatus::CAPTURED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NORMAL_UNIT:
return net::eagle0::common::UnitStatus::NORMAL_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_FLED_UNIT:
return net::eagle0::common::UnitStatus::FLED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_RETREATED_UNIT:
return net::eagle0::common::UnitStatus::RETREATED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_NEVER_ENTERED_UNIT:
return net::eagle0::common::UnitStatus::NEVER_ENTERED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_OUTLAWED_UNIT:
return net::eagle0::common::UnitStatus::OUTLAWED_UNIT;
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_DESTROYED_SUMMONED_UNIT:
case net::eagle0::shardok::storage::ResolvedUnit_UnitStatus_UNKNOWN_UNIT:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
case net::eagle0::shardok::storage::
ResolvedUnit_UnitStatus_ResolvedUnit_UnitStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
throw ShardokInternalErrorException("Bad unit status on resolved unit");
}
throw ShardokInternalErrorException("Bad unit status on resolved unit");
}
} // namespace shardok
@@ -1,36 +0,0 @@
#ifndef GameOverResponsePopulator_hpp
#define GameOverResponsePopulator_hpp
#include <string>
#include <vector>
#include "src/main/flatbuffer/net/eagle0/shardok/storage/unit.hpp"
#include "src/main/protobuf/net/eagle0/common/common_unit.pb.h"
#include "src/main/protobuf/net/eagle0/common/shardok_internal_interface.pb.h"
#include "src/main/protobuf/net/eagle0/shardok/common/game_status.pb.h"
#include "src/main/protobuf/net/eagle0/shardok/common/player_info.pb.h"
#include "src/main/protobuf/net/eagle0/shardok/storage/action_result.pb.h"
namespace shardok {
using net::eagle0::shardok::storage::fb::Unit;
auto PopulateGameOverResponse(
const std::string &gameId,
const net::eagle0::shardok::common::GameStatus &gameStatus,
const std::vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
const std::vector<net::eagle0::shardok::storage::ResolvedUnit> &resolvedUnits,
net::eagle0::common::GameOverResponse *gameOverResponse) -> bool;
auto IncludeUnitProtoInReturn(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus &internalStatus) -> bool;
auto FromUnitFb(const Unit &unit) -> net::eagle0::common::CommonUnit;
auto FromInternalStatus(
const net::eagle0::shardok::storage::ResolvedUnit::UnitStatus internalStatus)
-> net::eagle0::common::UnitStatus;
} // namespace shardok
#endif /* GameOverResponsePopulator_hpp */
@@ -57,11 +57,6 @@ auto ShardokGamesManager::GetController(const GameId &gameId)
return existing->second;
}
void ShardokGamesManager::RemoveController(const GameId &gameId) {
std::unique_lock<std::shared_mutex> lk(runningControllersLock);
runningControllers.erase(gameId);
}
auto ShardokGamesManager::UnlockedCreateFromGameStateBytes(
const byte_vector &gameStateBytes,
int32_t startingHistoryCount,
@@ -154,24 +149,6 @@ auto SetUpController(
for (auto up : units) {
up.mutate_unit_id(nextUnitId++);
up.mutate_status(net::eagle0::shardok::storage::fb::UnitStatus_RESERVE_UNIT);
// Apply initial visibility settings from tutorial config
if (tutorialConfig.enabled() && up.has_attached_hero()) {
const int heroId = up.attached_hero().eagle_hero_id();
for (const auto &visibility : tutorialConfig.initial_visibilities()) {
if (visibility.eagle_hero_id() == heroId) {
for (const int playerId : visibility.visible_to_player_ids()) {
if (playerId >= 0 && playerId < 10) {
up.mutable_opponent_knowledge()->Mutate(
static_cast<flatbuffers::uoffset_t>(playerId),
100);
}
}
break;
}
}
}
unplacedUnits.push_back(up);
}
@@ -203,15 +180,8 @@ auto SetUpController(
}
}
// For tutorial battles, override settings so duels are always accepted
auto effectiveSettings = gameSettings;
if (tutorialConfig.enabled()) {
effectiveSettings = std::make_shared<GameSettings>(*gameSettings);
effectiveSettings->GetSetter().SetInt(kSettingsKeys.duelBaseAcceptOdds, 200);
}
unique_ptr<ShardokEngine> engine = std::make_unique<ShardokEngine>(
effectiveSettings,
gameSettings,
std::move(unplacedUnits),
customMapBytes.empty() ? LoadMap(mapName) : LoadMapFromBytes(customMapBytes),
month,
@@ -47,8 +47,7 @@ public:
const vector<VictoryConditionProto> &victoryConditions,
const vector<PlayerId> &alliedPids,
const int32_t eagleFactionId,
const bool isAi,
const bool cannotBecomeOutlaw) -> PlayerInfoProto {
const bool isAi) -> PlayerInfoProto {
PlayerInfoProto pi;
pi.set_player_id(pid);
pi.set_is_defender(def);
@@ -57,7 +56,6 @@ public:
for (const PlayerId alliedPid : alliedPids) { pi.add_allies()->set_player_id(alliedPid); }
pi.set_eagle_faction_id(eagleFactionId);
pi.set_is_ai(isAi);
pi.set_cannot_become_outlaw(cannotBecomeOutlaw);
return pi;
}
@@ -70,8 +68,7 @@ public:
const int food,
const vector<VictoryConditionProto> &victoryConditions,
const vector<PlayerId> &alliedPids,
vector<Unit> us,
const bool cannotBecomeOutlaw)
vector<Unit> us)
: playerInfo(MakePlayerInfo(
pid,
def,
@@ -79,8 +76,7 @@ public:
victoryConditions,
alliedPids,
eagleFactionId,
isAi,
cannotBecomeOutlaw)),
isAi)),
units(std::move(us)) {}
};
@@ -101,8 +97,6 @@ public:
auto GetController(const GameId &gameId) -> std::shared_ptr<ShardokGameController>;
void RemoveController(const GameId &gameId);
auto UnlockedCreateSpecifiedGame(
const GameId &gameId,
const vector<PlayerInfoWithUnits> &playerSetupInfos,
@@ -41,12 +41,4 @@ sysinfo.txt
mono_crash.*
# Local server data
ServerData/
# Unity FBX import artifacts (auto-generated duplicates of textures/materials)
*.fbm/
*.fbm.meta
Assets/HoneyBadger/Materials/
Assets/HoneyBadger/Materials.meta
Assets/HoneyBadger/M_Honey_Badger.mat
Assets/HoneyBadger/M_Honey_Badger.mat.meta
ServerData/
@@ -13,8 +13,4 @@ MonoBehaviour:
m_Name: AddressableAssetGroupSortSettings
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.AddressableAssetGroupSortSettings
sortOrder:
- b7e3a1c4d5f6928a0b1c2d3e4f5a6b7c
- e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
- f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6
- a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
- 4458439bbfafa478b905417eff3c5741
@@ -61,10 +61,6 @@ MonoBehaviour:
m_overridePlayerVersion: '[UnityEditor.PlayerSettings.bundleVersion]'
m_GroupAssets:
- {fileID: 11400000, guid: e57932396135345fe98cb0c17cfc1d9d, type: 2}
- {fileID: 11400000, guid: aa899846fdf64bddb09e7af6c73d3bfa, type: 2}
- {fileID: 11400000, guid: f8a2b3c4d5e6f7089a1b2c3d4e5f6a7b, type: 2}
- {fileID: 11400000, guid: e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6, type: 2}
- {fileID: 11400000, guid: f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7, type: 2}
m_BuildSettings:
m_LogResourceManagerExceptions: 1
m_BundleBuildPath: Temp/com.unity.addressables/AssetBundles
@@ -104,29 +100,6 @@ MonoBehaviour:
m_LabelTable:
m_LabelNames:
- default
- beast-effects
- hex-castle
- hex-forest
- hex-forest-full-snow
- hex-forest-partial-snow
- hex-hills
- hex-hills-full-snow
- hex-hills-partial-snow
- hex-ice
- hex-mountain
- hex-mountain-snow
- hex-ocean
- hex-plains
- hex-plains-full-snow
- hex-plains-partial-snow
- hex-river
- hex-swamp
- hex-thawing-ice
- hex-winter-castle
- hex-winter-forest
- hex-winter-hills
- hex-winter-mountain
- hex-winter-plains
- music-autumn
- music-battle
- music-spring
@@ -134,10 +107,6 @@ MonoBehaviour:
- music-travel
- music-victory
- music-winter
- sfx-combat
- tactical-bridge-constructed
- tactical-bridge-permanent
- tactical-fire
m_SchemaTemplates: []
m_GroupTemplateObjects:
- {fileID: 11400000, guid: b712027ecfc3d47d1a2e0b33ee77c970, type: 2}
@@ -1,311 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Beast Effects
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
m_GroupName: Beast Effects
m_GUID: b7e3a1c4d5f6928a0b1c2d3e4f5a6b7c
m_SerializeEntries:
- m_GUID: 03fd458f13534496b0eb92f162f7ce5f
m_Address: Assets/Eagle/Effects/LeopardEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 06da0d48df3fc4cabb095b2bbc803307
m_Address: Assets/Eagle/Effects/SpiderEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0c9aa291ec03459290d22dbbb0cd95ac
m_Address: Assets/Eagle/Effects/WildGoatEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 18aa417cee344c3fbffdcc91e6fd43f5
m_Address: Assets/Eagle/Effects/LionEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 19b67a77bb2da43f9bd72a801f63109f
m_Address: Assets/Eagle/Effects/RatEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 1c093deb39df94fbca5faa9f015a2331
m_Address: Assets/Eagle/Effects/BeastsEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 1d7aec11b391453ebfe35a8f583402e0
m_Address: Assets/Eagle/Effects/FrogEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 22544e03efcd549b7945b13227eda25b
m_Address: Assets/Eagle/Effects/DemonEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 259d7f63b86154a41850db255b9e7c87
m_Address: Assets/Eagle/Effects/SkeletonEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 33d0f131e30ba466daed422c25ecfd45
m_Address: Assets/Eagle/Effects/ButcherEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3c2a18fce1d449bab74c89612b707c3f
m_Address: Assets/Eagle/Effects/HyenaEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3dea4965da3644dc38efcfadf7247812
m_Address: Assets/Eagle/Effects/OrcEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4be580a24d1d4ce3baff4fe4c8323498
m_Address: Assets/Eagle/Effects/PeasantEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 53e3e2ac7f7334bdeaa3a3608835bb2a
m_Address: Assets/Eagle/Effects/SnakeEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 56b0ba99866443ee8afdc6267320b5b0
m_Address: Assets/Eagle/Effects/StagEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 57c9c29cba614bc1ac6357b3357471c5
m_Address: Assets/Eagle/Effects/ElephantEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5865a698f1e404c8c923b10c218e3d99
m_Address: Assets/Eagle/Effects/BearEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5bc3a25d850c4ee98ce500b8e36e5e72
m_Address: Assets/Eagle/Effects/RhinocerosEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 60dcf531b61b143cfb2e87c519fac2f7
m_Address: Assets/Eagle/Effects/ZombieEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 67b96421193d84127b509e9cbd38dea4
m_Address: Assets/Eagle/Effects/BoarEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 6c9c00cb423a5469ab2754670303b578
m_Address: Assets/Eagle/Effects/DragonEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 6f1fb8d0b51543dd900afb7b19ca78ce
m_Address: Assets/Eagle/Effects/CrabEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 70a840086c9c4e6e80c6257eebc5a4e0
m_Address: Assets/Eagle/Effects/ArcherEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 79be05674fd8c4592afd392bc933a94a
m_Address: Assets/Eagle/Effects/RaccoonEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7dd589d0a0a04aaba2d7bae09ac2eee9
m_Address: Assets/Eagle/Effects/HippopotamusEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7f3a8b2c1d4e5f6a9b0c1d2e3f4a5b6c
m_Address: Assets/Eagle/Effects/OgreEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7ff85a8d11264353a1d99ecc0c9434a8
m_Address: Assets/Eagle/Effects/WarthogEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8e8f6f335c1243f4adaff7671fdc8f96
m_Address: Assets/Eagle/Effects/RabbitEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8f4f4c81c6f4f43d7a8a7705a2e8c827
m_Address: Assets/Eagle/Effects/HoneyBadgerEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9d4aac80ed1064b1da97b0c2da35375c
m_Address: Assets/Eagle/Effects/WolfEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9e75de33a5fd4739a256803a2401f207
m_Address: Assets/Eagle/Effects/KnightEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a085cb31c5f941a0b556b41d26095606
m_Address: Assets/Eagle/Effects/TasmanianDevilEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a728345b1fa74d63aa663e8e91451280
m_Address: Assets/Eagle/Effects/GorillaEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ac80a968b9a4486f93ba638fc4a5635a
m_Address: Assets/Eagle/Effects/KangarooEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b3910b25697e4e9a9f8151f41365175e
m_Address: Assets/Eagle/Effects/SalamanderEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b5d8f2a4c6e1930785f4b2d7a9e3c6f1
m_Address: Assets/Eagle/Effects/TigerEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: babbd2190f224e23bd4096d7bee215dd
m_Address: Assets/Eagle/Effects/VelociraptorEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c168eb3d59d6147ae90a6b6ce18b8627
m_Address: Assets/Eagle/Effects/ClownEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c994b958199c49d9ac81649fff6c4466
m_Address: Assets/Eagle/Effects/ScorpionEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c41416ab59544c898fe780f2625a45e8
m_Address: Assets/Eagle/Effects/HippogryphEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: cfe71c4bf1ca4d959895c806e89237d0
m_Address: Assets/Eagle/Effects/BlackPantherEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: cfee0ee5fb3247489f134c8b56c9c624
m_Address: Assets/Eagle/Effects/WildPigEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d4e7a1b3c5f8926074e3d1a9b6c2f8e5
m_Address: Assets/Eagle/Effects/GiantEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d7a726f04b1147659c3e98e93efd3d0e
m_Address: Assets/Eagle/Effects/SoldierEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e6e96fdb4b8d45349175545a8ca20620
m_Address: Assets/Eagle/Effects/EmuEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ebb57129016f47f8921dd89ef0af65e7
m_Address: Assets/Eagle/Effects/MilitiaEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ec1077fb62f34407b4457b0eb662e3ed
m_Address: Assets/Eagle/Effects/VampireEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f7868077fb93b49dd876e9ee457b2f79
m_Address: Assets/Eagle/Effects/CrocodileEffect.prefab
m_ReadOnly: 0
m_SerializedLabels:
- beast-effects
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: bffc3d84835754ce69a78a771fc85002, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: 9f4d7a2d75b949ed9b23d8cdce64f5a3, type: 2}
- {fileID: 11400000, guid: 55c4dbefaf9f489eb87477e8be24558f, type: 2}
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: aa899846fdf64bddb09e7af6c73d3bfa
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,731 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Hex Tiles
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
m_GroupName: Hex Tiles
m_GUID: e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
m_SerializeEntries:
- m_GUID: 044723fb45720f445bc879c27830312f
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnowCave00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0659693fd618c29459a38fb5f87db2ff
m_Address: Assets/Hex Tiles/Winter/PlainsFullSnow/hexSnowField01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0a727f19f459f2548b66c213b218970b
m_Address: Assets/Hex Tiles/Winter/HillsFullSnow/hexHillsColdSnowCovered02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0c2b586abf4e73f44b7bfb1e12e1a17d
m_Address: Assets/Hex Tiles/Winter/ForestPartialSnow/hexForestPineSnowTransition03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0ca21d4977ad29a4b811f13279d350fb
m_Address: Assets/Hex Tiles/Winter/HillsPartialSnow/hexHillsColdSnowTransitionCave00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0ca718c5d9817db45b4eb366839d46f8
m_Address: Assets/Hex Tiles/Winter/Hills/hexHillsCold03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0d554013fdb222b4abfcecec3451a6d1
m_Address: Assets/Hex Tiles/Castle/hexMarshCastleRuins00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0dc38b5f4b39658458a7cc60c66ea7c3
m_Address: Assets/Hex Tiles/Mountain/hexMountainCave00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 126ce036e072c684d91a0d7b6de98d0a
m_Address: Assets/Hex Tiles/Forest/hexForestBroadleafForester00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 142c8b443c69b7d4a85fa09583bf9b8b
m_Address: Assets/Hex Tiles/Winter/Plains/hexDirtCold03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 142f54e386f41f349aee4b43944fef36
m_Address: Assets/Hex Tiles/Plains/hexDirt03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 159f2c9c5e018fe4a8a1ffaaf708e9a1
m_Address: Assets/Hex Tiles/Winter/ForestPartialSnow/hexForestPineSnowTransition01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 15b02911c45836a4b8a8c152ba4efb0a
m_Address: Assets/Hex Tiles/ThawingIce/hexOceanIceBergs03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-thawing-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 1b7999dd006d48646acd8dd7091281ab
m_Address: Assets/Hex Tiles/Winter/ForestPartialSnow/hexForestPineSnowTransition02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 1dc0982d61478ea48958f5284aca407b
m_Address: Assets/Hex Tiles/Castle/hexDirtCastle00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 20dd0501b96ef474c87fb3961c7384ba
m_Address: Assets/Hex Tiles/Winter/HillsFullSnow/hexHillsColdSnowCovered00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 222aae9b94ca9b748a0dd182a2ec47f3
m_Address: Assets/Hex Tiles/Forest/hexForestBroadleaf00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 2357431a2f3d74968841c787076eb4f1
m_Address: Assets/Hex Tiles/Winter/Castle/hexMountainFortress00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 242f9e2d40993184b86a5f6612cdf9ff
m_Address: Assets/Hex Tiles/Plains/hexPlains00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 25227b9be5940bb4f9ad3e364b75c03b
m_Address: Assets/Hex Tiles/Winter/HillsPartialSnow/hexHillsColdSnowTransition00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 287398353e291dc49b41b3a8c9fc68b0
m_Address: Assets/Hex Tiles/Winter/Plains/hexDirtCold00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 2dfdf104f9636a1438c05f8d56bebbfc
m_Address: Assets/Hex Tiles/Winter/Hills/hexHillsCold01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 2ebd9aa864bd1b44b8d69a29e95a7042
m_Address: Assets/Hex Tiles/Plains/hexScrublands03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 2edb23c572ce88e46a7ce0761186bb2b
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnow03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 30a58a43a543d96499f8ddec24c3b68a
m_Address: Assets/Hex Tiles/Plains/hexPlains01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 348aaecda7dc730409a47ee97507de4b
m_Address: Assets/Hex Tiles/Plains/hexPlains03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 36e28e9a7cc78af43a888f18418460c8
m_Address: Assets/Hex Tiles/Ice/hexPlainsColdSnowCoveredPond00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 394f3b43fd4840d43aefb9d89bcb7f99
m_Address: Assets/Hex Tiles/Winter/ForestFullSnow/hexForestPineSnowCovered02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3a8668307a2df7c4ca4b3297b13d43d7
m_Address: Assets/Hex Tiles/Castle/hexPlainsCastle00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3c09622509d98b8429ce8655a374a69e
m_Address: Assets/Hex Tiles/Plains/hexScrublands00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3db91d7ceab395541a01cf284b246374
m_Address: Assets/Hex Tiles/Swamp/hexMarsh02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-swamp
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3ecb578a1427c814495c76f9f06aacaa
m_Address: Assets/Hex Tiles/Winter/PlainsFullSnow/hexSnowField00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 427c33bd4c21f3d419142c6acf2dc74e
m_Address: Assets/Hex Tiles/Ice/hexPlainsColdSnowCovered00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 464c392f8cea6b4418032a2396872c57
m_Address: Assets/Hex Tiles/Plains/hexDirt01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 478f81a4eaff7b94587117c799469761
m_Address: Assets/Hex Tiles/Winter/HillsPartialSnow/hexHillsColdSnowTransition03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 48f7d88a0e1de164084679af70de3921
m_Address: Assets/Hex Tiles/Castle/hexPlainsCastle00_green.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4cf49ef0171fa014c93cd8ee9fa5b070
m_Address: Assets/Hex Tiles/Winter/Forest/hexForestPine02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4e30581d44e8de74b8cef8615a827296
m_Address: Assets/Hex Tiles/River/hexOcean01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-river
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4fd806597af36dc418ff94aba10c90a6
m_Address: Assets/Hex Tiles/Plains/hexDirt00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 507cddba3b6244c42a01691f16437057
m_Address: Assets/Hex Tiles/Ice/hexPlainsColdSnowCovered01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 54b244acd42c8014ba7d2bce2878813a
m_Address: Assets/Hex Tiles/Winter/ForestFullSnow/hexForestPineSnowCovered01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 54db42620c434d245ad358deb6074623
m_Address: Assets/Hex Tiles/Winter/HillsFullSnow/hexHillsColdSnowCovered01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 57a883222952fc545b0b20c785dab3eb
m_Address: Assets/Hex Tiles/Castle/hexMountainFortress00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5a25225203fe60f419098ec25f4bd63e
m_Address: Assets/Hex Tiles/Winter/Plains/hexPlainsCold03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5ad37662d488fc14a9c5c854022b9e06
m_Address: Assets/Hex Tiles/Forest/hexForestBroadleaf03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5b435480152a64072aa3e5074400f43b
m_Address: Assets/Hex Tiles/Winter/Mountain/hexMountain00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5def67db41110a24fbb3e5cca9569377
m_Address: Assets/Hex Tiles/Swamp/hexMarsh03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-swamp
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5f2031dee052c4dbebaa2a8009927f41
m_Address: Assets/Hex Tiles/Winter/Castle/hexMountainCastle00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5f80ab8898b7b0743850c4ee3cbe87ff
m_Address: Assets/Hex Tiles/Forest/hexForestBroadleaf02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 6788042007d1a8e40868e02293a4d34a
m_Address: Assets/Hex Tiles/Winter/Hills/hexHillsCold00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 682be8ec61cc93647a66884775462e27
m_Address: Assets/Hex Tiles/Winter/ForestFullSnow/hexForestPineSnowCovered03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 6982d72ce07e4a84f95578ccf94ed73b
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnowCave01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 6c614b019a2398643a16e651c5a05e75
m_Address: Assets/Hex Tiles/Winter/ForestFullSnow/hexForestPineSnowCoveredClearing00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 6cec2c36e84a1e9439609728d3bf42da
m_Address: Assets/Hex Tiles/Winter/PlainsPartialSnow/hexPlainsColdSnowTransition02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 703d03304b902d2409e05058fb241b97
m_Address: Assets/Hex Tiles/Winter/Plains/hexDirtCold02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 74d0636b98695ee4cbbfdb48f2ed3b21
m_Address: Assets/Hex Tiles/Winter/PlainsPartialSnow/hexPlainsColdSnowTransitionPond00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7b4560f1902d54da1a7eed9dd958ca56
m_Address: Assets/Hex Tiles/Winter/Mountain/hexMountain03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7b67d17dfc98d5848af25c32dd1051cd
m_Address: Assets/Hex Tiles/River/hexOcean03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-river
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7bc0e87bc47dd21468fb04e60af44207
m_Address: Assets/Hex Tiles/Winter/HillsPartialSnow/hexHillsColdSnowTransition01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 802241df539ac3a43b720ca0f9321915
m_Address: Assets/Hex Tiles/Winter/ForestPartialSnow/hexForestPineSnowTransition00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 815b6513bb139da43812570ecdd9b9fe
m_Address: Assets/Hex Tiles/Castle/hexPlainsCastle00_blue.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 83733db5e78b0a8478114b45c4a54f31
m_Address: Assets/Hex Tiles/ThawingIce/hexOceanIceBergs02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-thawing-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 85980b2265ff45344b1513252dd5d6ef
m_Address: Assets/Hex Tiles/Ocean/hexOcean00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-ocean
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8a8dacd9ee5f6b848b27a5129f6f4238
m_Address: Assets/Hex Tiles/Winter/Plains/hexPlainsCold00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8abfc7f22352b6a4d87a7d9763d6c27b
m_Address: Assets/Hex Tiles/Winter/Hills/hexHillsColdCave00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8b1abd64669c6ac47a92c3bb04a026c2
m_Address: Assets/Hex Tiles/Winter/Plains/hexPlainsCold02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8be08a2e1863c7f43a0abfb06179c682
m_Address: Assets/Hex Tiles/Castle/hexMountainDwarfFortress00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 912605f6db2a9234bb7feafc3a0655b5
m_Address: Assets/Hex Tiles/Plains/hexDirt02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 91aab815eba2a704e97aa7ff2be26ef8
m_Address: Assets/Hex Tiles/Winter/PlainsPartialSnow/hexPlainsColdSnowTransition00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 926371c6928788a40a04edc29f911931
m_Address: Assets/Hex Tiles/Hills/hexHills03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 92e9b8d12c2b3cf409874d0c5d862b26
m_Address: Assets/Hex Tiles/Winter/Plains/hexDirtCold01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 930869bc0c618d446a525c196a58129d
m_Address: Assets/Hex Tiles/Mountain/hexMountain01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 93312d4222ad61446be900d97031204b
m_Address: Assets/Hex Tiles/Forest/hexForestBroadleaf01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9537a3e60336d914f889c96773ec204f
m_Address: Assets/Hex Tiles/Winter/ForestFullSnow/hexForestPineSnowCovered00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 96001be02960c3f4d9c77b399fc5cd58
m_Address: Assets/Hex Tiles/Winter/PlainsPartialSnow/hexPlainsColdSnowTransition03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 962993f07e510f74ca65d36de42dcafa
m_Address: Assets/Hex Tiles/Winter/HillsFullSnow/hexHillsColdSnowCoveredCave00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9695be27a28e22b47af841545bf58f95
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnow01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 994e2eeeb8c163c4aa41b134e73d0ea5
m_Address: Assets/Hex Tiles/Swamp/hexMarsh01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-swamp
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 999118f269ad1a94bb8439efd6c11e8f
m_Address: Assets/Hex Tiles/Hills/hexHills02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 99a934cad7542ed41819255942968a1d
m_Address: Assets/Hex Tiles/Hills/hexHills01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9abe58259b12c274385553b94ca3b706
m_Address: Assets/Hex Tiles/Winter/Forest/hexForestPine00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9bb20f0a522c6e44c8b18f7a8e5ccba2
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnowCave02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9c01e0b6f0d489945aaed9fa35a602d8
m_Address: Assets/Hex Tiles/Plains/hexPlains02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9f2e9e51d64083349847cc81d03e1d96
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnow00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a00eb4fdd0412a7479dd32a392bfab29
m_Address: Assets/Hex Tiles/Winter/Plains/hexPlainsCold01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a1a4802555e68594f8f222281cf25910
m_Address: Assets/Hex Tiles/Castle/hexPlainsWalledCity00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a1e0821356939824cbf62c3491463fe2
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnow02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a574bb28797e67646805085db5d5c8b0
m_Address: Assets/Hex Tiles/Mountain/hexMountain02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a83dc6b61e9ec4d1c9394d23392d22ab
m_Address: Assets/Hex Tiles/Winter/Mountain/hexMountainCave00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: aa4da2ce1a6f8e94ab8b03da8ca83ff2
m_Address: Assets/Hex Tiles/Castle/hexDirtWalledCity00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: aa6cf94b55cfc4f7f99c96f0ddfa54a7
m_Address: Assets/Hex Tiles/Winter/Mountain/hexMountain02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ab70bf8144a18754abd362d192e839a6
m_Address: Assets/Hex Tiles/Plains/hexScrublands01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b182e2c192e8ebe44a08ed807c66e42c
m_Address: Assets/Hex Tiles/Winter/HillsPartialSnow/hexHillsColdSnowTransition02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b2a74a4a0a89bc04cb935bf78b9b6af4
m_Address: Assets/Hex Tiles/Plains/hexScrublands02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b6e872dbce137d842a2fdb5d58fc9b91
m_Address: Assets/Hex Tiles/Ice/hexPlainsColdSnowCovered02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: bbe8b026b8a5b4b8baa9a15a063132bf
m_Address: Assets/Hex Tiles/Winter/Mountain/hexMountain01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: beeeac2b04c45d141930d1ecbab37f33
m_Address: Assets/Hex Tiles/Winter/Forest/hexForestPine03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: bf6abd5babf09854d9d2c9f56a17df7f
m_Address: Assets/Hex Tiles/Mountain/hexMountainCave01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c03d7b7abe5f59f4291f0920a780f088
m_Address: Assets/Hex Tiles/ThawingIce/hexOceanIceBergs00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-thawing-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c0cc93cce6b27744e85f7ccc6b3db00a
m_Address: Assets/Hex Tiles/Mountain/hexMountain00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c5eddc2322a2329438f370a635f47223
m_Address: Assets/Hex Tiles/Winter/Hills/hexHillsCold02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-hills
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c71963927a62933459606789f53c0a98
m_Address: Assets/Hex Tiles/Winter/PlainsFullSnow/hexSnowField03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c8f1796d2e32f4830bbff97cc7299584
m_Address: Assets/Hex Tiles/Winter/Mountain/hexMountainCave01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: cd02e9c75e59137488f9c9a9de504361
m_Address: Assets/Hex Tiles/Winter/ForestPartialSnow/hexForestPineSnowTransitionClearing00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d09aa48433c41cf4b99a84d9820e9979
m_Address: Assets/Hex Tiles/Swamp/hexMarsh00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-swamp
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d3e4776064cbc6146878357184615ad0
m_Address: Assets/Hex Tiles/Winter/PlainsPartialSnow/hexPlainsColdSnowTransition01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-partial-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d80dd964f2ad6d24ea7cd8bf6c8cfdeb
m_Address: Assets/Hex Tiles/Forest/hexForestBroadleafForester01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e3753902ee88aa94d82c2b27d0fd26e0
m_Address: Assets/Hex Tiles/Winter/MountainSnow/hexMountainSnowCave03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e4997a0e2994c6d42bdbf42209172883
m_Address: Assets/Hex Tiles/Winter/HillsFullSnow/hexHillsColdSnowCovered03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e51d401b0ad3bfa458c17e39fa1d0fe2
m_Address: Assets/Hex Tiles/Ocean/hexOcean02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-ocean
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e63b4b157c3cca24db2143b4df4f67b0
m_Address: Assets/Hex Tiles/Winter/Forest/hexForestPineClearing00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e687450362cef744684faaf8d4a7032d
m_Address: Assets/Hex Tiles/ThawingIce/hexOceanIceBergs01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-thawing-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e792d3719cbd10b4e8b4f296beffd5c9
m_Address: Assets/Hex Tiles/Winter/PlainsFullSnow/hexSnowField02.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-plains-full-snow
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e811ff7d176db66489a5e51e09524082
m_Address: Assets/Hex Tiles/Mountain/hexMountain03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-mountain
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ed5516dfaa0865342a3c193cdc3347ae
m_Address: Assets/Hex Tiles/Castle/hexMountainCastle00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-castle
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: eef22687bc5f0fc4b8e4599f29affaad
m_Address: Assets/Hex Tiles/Ice/hexPlainsColdSnowCovered03.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-ice
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: fad09dbc7076adf4db4b4ae1aff1139c
m_Address: Assets/Hex Tiles/Winter/Forest/hexForestPine01.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-winter-forest
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ff82e10631e5ed542880eebb5bcfed3a
m_Address: Assets/Hex Tiles/Hills/hexHills00.png
m_ReadOnly: 0
m_SerializedLabels:
- hex-hills
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: bffc3d84835754ce69a78a771fc85002, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4, type: 2}
- {fileID: 11400000, guid: b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6, type: 2}
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f8a2b3c4d5e6f7089a1b2c3d4e5f6a7b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,48 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
m_Name: Beast Effects_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: aa899846fdf64bddb09e7af6c73d3bfa, type: 2}
m_InternalBundleIdMode: 1
m_Compression: 1
m_IncludeAddressInCatalog: 1
m_IncludeGUIDInCatalog: 1
m_IncludeLabelsInCatalog: 1
m_InternalIdNamingMode: 0
m_CacheClearBehavior: 0
m_IncludeInBuild: 1
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_StripDownloadOptions: 0
m_ForceUniqueProvider: 0
m_UseAssetBundleCache: 1
m_UseAssetBundleCrc: 1
m_UseAssetBundleCrcForCachedBundles: 1
m_UseUWRForLocalBundles: 0
m_Timeout: 0
m_ChunkedTransfer: 0
m_RedirectLimit: -1
m_RetryCount: 0
m_BuildPath:
m_Id: 2af7f42f684fd4296a199c9e60624f6f
m_LoadPath:
m_Id: 55b13501972b540abb7332a5bad98342
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 9f4d7a2d75b949ed9b23d8cdce64f5a3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,16 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
m_Name: Beast Effects_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: aa899846fdf64bddb09e7af6c73d3bfa, type: 2}
m_StaticContent: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 55c4dbefaf9f489eb87477e8be24558f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,48 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
m_Name: Hex Tiles_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: f8a2b3c4d5e6f7089a1b2c3d4e5f6a7b, type: 2}
m_InternalBundleIdMode: 1
m_Compression: 1
m_IncludeAddressInCatalog: 1
m_IncludeGUIDInCatalog: 1
m_IncludeLabelsInCatalog: 1
m_InternalIdNamingMode: 0
m_CacheClearBehavior: 0
m_IncludeInBuild: 1
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_StripDownloadOptions: 0
m_ForceUniqueProvider: 0
m_UseAssetBundleCache: 1
m_UseAssetBundleCrc: 1
m_UseAssetBundleCrcForCachedBundles: 1
m_UseUWRForLocalBundles: 0
m_Timeout: 0
m_ChunkedTransfer: 0
m_RedirectLimit: -1
m_RetryCount: 0
m_BuildPath:
m_Id: 2af7f42f684fd4296a199c9e60624f6f
m_LoadPath:
m_Id: 55b13501972b540abb7332a5bad98342
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,16 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
m_Name: Hex Tiles_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: f8a2b3c4d5e6f7089a1b2c3d4e5f6a7b, type: 2}
m_StaticContent: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ac8d5c261438f4bd68e68c2f37fd4ea7
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,48 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
m_Name: Sound Effects_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7, type: 2}
m_InternalBundleIdMode: 1
m_Compression: 1
m_IncludeAddressInCatalog: 1
m_IncludeGUIDInCatalog: 1
m_IncludeLabelsInCatalog: 1
m_InternalIdNamingMode: 0
m_CacheClearBehavior: 0
m_IncludeInBuild: 1
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_StripDownloadOptions: 0
m_ForceUniqueProvider: 0
m_UseAssetBundleCache: 1
m_UseAssetBundleCrc: 1
m_UseAssetBundleCrcForCachedBundles: 1
m_UseUWRForLocalBundles: 0
m_Timeout: 0
m_ChunkedTransfer: 0
m_RedirectLimit: -1
m_RetryCount: 0
m_BuildPath:
m_Id: 2af7f42f684fd4296a199c9e60624f6f
m_LoadPath:
m_Id: 55b13501972b540abb7332a5bad98342
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,16 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
m_Name: Sound Effects_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7, type: 2}
m_StaticContent: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,48 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
m_Name: Tactical Assets_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6, type: 2}
m_InternalBundleIdMode: 1
m_Compression: 1
m_IncludeAddressInCatalog: 1
m_IncludeGUIDInCatalog: 1
m_IncludeLabelsInCatalog: 1
m_InternalIdNamingMode: 0
m_CacheClearBehavior: 0
m_IncludeInBuild: 1
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_StripDownloadOptions: 0
m_ForceUniqueProvider: 0
m_UseAssetBundleCache: 1
m_UseAssetBundleCrc: 1
m_UseAssetBundleCrcForCachedBundles: 1
m_UseUWRForLocalBundles: 0
m_Timeout: 0
m_ChunkedTransfer: 0
m_RedirectLimit: -1
m_RetryCount: 0
m_BuildPath:
m_Id: 2af7f42f684fd4296a199c9e60624f6f
m_LoadPath:
m_Id: 55b13501972b540abb7332a5bad98342
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,16 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
m_Name: Tactical Assets_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6, type: 2}
m_StaticContent: 0
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -1,467 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Sound Effects
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
m_GroupName: Sound Effects
m_GUID: f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6
m_SerializeEntries:
- m_GUID: 0b253d5f05dd344728f60f2d81fb9363
m_Address: Assets/Shardok/soundEffects/archery.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 0deae9bdb045eff4d95fe05a60ea5185
m_Address: Assets/Medieval Combat Sounds/Weapons/Weapon Draw Metal 5.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 187809f233dd149efbaf7d21918e45a3
m_Address: Assets/Shardok/soundEffects/repair_failed.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 207d1c2948a494738ae0cefc69cf8eaf
m_Address: Assets/Shardok/soundEffects/melee.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 23168a0bd1f9949a8bdac2551a72ea78
m_Address: Assets/Shardok/soundEffects/undead_break_control.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 23d505a858948614bb825caca37094c0
m_Address: Assets/Magic Spells Sound Effects LITE/General Spell/Negative Effect 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 24fabc88cd2a549e4847f3e2d0b5e31d
m_Address: Assets/Shardok/soundEffects/fire_start_failure.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 261478c4105a6894eb07080d90ab1170
m_Address: Assets/Magic Spells Sound Effects LITE/General Spell/Negative Effect 14.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 2f8d73a5b4a2b45c2ab94ade33b4d252
m_Address: Assets/Shardok/soundEffects/build_bridge.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3059dbcfcd54d4cb39e3ac902c8f187e
m_Address: Assets/Shardok/soundEffects/raise_undead.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 324eca04cae0a4781b5c1bd6a7a5955b
m_Address: Assets/Shardok/soundEffects/lightning.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 356df74eca2df4f4b81f2f0cc7e564cd
m_Address: Assets/Fantasy Interface Sounds/Magic Chimes 03.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 393c5e9cb43f946c3a46ba3af4c8cb15
m_Address: Assets/Shardok/soundEffects/charge.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3a230106bce0c43e590be59b8e13c49a
m_Address: Assets/Shardok/soundEffects/fire_start.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3b9c8d7e6f5a4b2c1d0e9f8a7b6c5d4e
m_Address: Assets/Shardok/Sounds/rain_loop.ogg
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3dc5691a8d3ee4cf2bb9f5f5ca6c74bc
m_Address: Assets/Shardok/soundEffects/fire_spread.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3f7410e4edbe60146942448ebc7c17b9
m_Address: Assets/Medieval Combat Sounds/Swings and Whoosh/Sword Swing 1_1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4064ef3ae368341488c7f0d431d06397
m_Address: Assets/Shardok/soundEffects/fire_extinguish.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4866a803aaa6d894997ab3e078a4db36
m_Address: Assets/Magic Spells Sound Effects LITE/General Spell/Buff Defense 08.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 4c0d9e8f7a6b5c3d2e1f0a9b8c7d6e5f
m_Address: Assets/Shardok/Sounds/blizzard_wind_loop.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 54297a87ade01a14d983f869be713bd4
m_Address: Assets/Fantasy Interface Sounds/Potion and Alchemy 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5aa9e3d34242bee4c840f3ce7790b3c4
m_Address: Assets/Fantasy Interface Sounds/Foley Armour 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 5b9f05a7789c14a7f89df76ce7a875d5
m_Address: Assets/Shardok/soundEffects/runaway_new.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 61f7e6c569a209649b82dd21edc87d20
m_Address: Assets/Fantasy Interface Sounds/Writing 1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 643eab6675cd7504b95693e88638e107
m_Address: Assets/Medieval Combat Sounds/Magic/Magic Debuffl 02.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 682711ac987ab45f6947be359521c1a6
m_Address: Assets/Shardok/soundEffects/flee_attempt.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 71492767c077742f182f8f3118d40b23
m_Address: Assets/Shardok/soundEffects/repair.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 738aebeadbbdc6c4c86258226634e4ab
m_Address: Assets/Medieval Combat Sounds/Magic/Magic Negative 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7696580094909f54684e881971773723
m_Address: Assets/Magic Spells Sound Effects LITE/Element Scholls/Fire/Fire Spelll 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 77ed6a2cdc66c46a38e348a2f5638d62
m_Address: Assets/Shardok/Sounds/thunder_loud.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7bbdef360a86e4240b0fa165a7feb29f
m_Address: Assets/Shardok/soundEffects/fear attempt.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7f6c7ea917ad64dd6971ff7a2bb0a706
m_Address: Assets/Shardok/soundEffects/meteor.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 80c545af22a74804ad6617be59fef458
m_Address: Assets/Shardok/soundEffects/feast_cheer.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 80148791db78ea24cb4f091ba98c80b1
m_Address: Assets/Magic Spells Sound Effects LITE/Element Scholls/Fire/Fire Spelll 02.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 81a95ab34bee142c9b904132fc181566
m_Address: Assets/Shardok/soundEffects/move.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 820314ba2c927d244a00d1dcf4c27830
m_Address: Assets/Fantasy Interface Sounds/Stone 08.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 844c8c9f821651d438eaeff4e21b1c84
m_Address: Assets/Medieval Combat Sounds/Magic/Magic Buff 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8703f41a6fcc94af6b4e20187a361423
m_Address: Assets/Shardok/soundEffects/burnination.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8756d07bb49104cd0bf32d870dd6f226
m_Address: Assets/Shardok/soundEffects/holy_wave_damage.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9089af59ccc9f3844bcb4a6f1c1fd094
m_Address: Assets/Fantasy Interface Sounds/UI Tight 02.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 965f48a3dbd3f4d4098bfc2699a6b119
m_Address: Assets/Shardok/soundEffects/anybody.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 98df6d9680a1d0948852a7bf91f167d6
m_Address: Assets/Medieval Combat Sounds/Weapons/Metal Weapon Hit Stone 2_1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9b7f0cbc69cdc95458e379dc0403e7f0
m_Address: Assets/Fantasy Interface Sounds/Locker 1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9e2192e93722ed043b59edfd6188721a
m_Address: Assets/Magic Spells Sound Effects LITE/Element Scholls/Wind/Wind Spell 1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9edd53f46d5c05c42931d1c6d8a9afb1
m_Address: Assets/Medieval Combat Sounds/Footsteps/Armored Grass Surface/Heavy Armor Grass Walking 1_01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9f06d48acebbb4785abae075ffff5c0a
m_Address: Assets/Shardok/soundEffects/dismiss_unit.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a1b7bb8017f6149bf8df60af9c17786a
m_Address: Assets/Shardok/soundEffects/jail_door.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a8bff7f82ebf744c988efe621d929d26
m_Address: Assets/Shardok/Sounds/thunder_clap.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: aab3a37b168aa45b1bc0c1915b92b326
m_Address: Assets/Shardok/Sounds/thunder_distant.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ad788f28ae846864fa7e6980c35e21d5
m_Address: Assets/Medieval Combat Sounds/Weapons/Arrow Hit Stone 1_2.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ae854c089c217d841acdbc304a74e5af
m_Address: Assets/Fantasy Interface Sounds/Magic Chimes 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b56606a67754c472b9e327fb538fdf4f
m_Address: Assets/Shardok/soundEffects/battle_shout.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b6c393d275ec3a54896db3987fa3c8df
m_Address: Assets/Medieval Combat Sounds/Weapons/Metal Weapon Hit Metal 1_1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: bf2bc9c55ed0e6240afe76a1ed889857
m_Address: Assets/Fantasy Interface Sounds/Bag 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c43b41f3acf6689449422f3ea9547975
m_Address: Assets/Magic Spells Sound Effects LITE/General Spell/Negative Effect 04.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c4e4a16ec1a025a40917a97f0026bd51
m_Address: Assets/Fantasy Interface Sounds/Whoosh 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: cdb6ada03a86044a1b3fe4078d494dc8
m_Address: Assets/Shardok/soundEffects/boo.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d10f8d9a69796324099077705d5862c8
m_Address: Assets/Medieval Combat Sounds/Swings and Whoosh/Dash Heavy Armor 1_01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d17b12f9ec69d44dab329950970bbb42
m_Address: Assets/Shardok/soundEffects/freeze.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d180d9fab29d3465d83cd5f30cbdd55e
m_Address: Assets/Shardok/soundEffects/raging_fire.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d20ba1e2f250d411cb4a402ce7d8201b
m_Address: Assets/Shardok/soundEffects/braved_water.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d31d7ceb406c544358b013833291e4f6
m_Address: Assets/Shardok/soundEffects/reduce.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d4b6b622ffce24e469f75722f266ddef
m_Address: Assets/Fantasy Interface Sounds/Coins 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: df294057e81c740fd9bee9d9bd6fbfb9
m_Address: Assets/Shardok/soundEffects/undead_grew.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e0d38576140e948b7b006e617fa4b44a
m_Address: Assets/Shardok/soundEffects/holy_wave.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e480e2182aa2b49cbad019fe89d6e9ca
m_Address: Assets/Shardok/soundEffects/mind_control.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: e68cd340e1a424f28a7adebe50287232
m_Address: Assets/Shardok/Sounds/thunder_crack.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f321f83128583f84c8964cddb405182d
m_Address: Assets/Magic Spells Sound Effects LITE/Element Scholls/Holy/Holy Spell 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f5a74fde83300445e825e4ab9251d383
m_Address: Assets/Shardok/soundEffects/splash.mp3
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f7f8c4e324017c341b4bc820961c201c
m_Address: Assets/Magic Spells Sound Effects LITE/Element Scholls/Ice/Ice Spelll 06.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f8167a5229da99740a43bbb92bf385e0
m_Address: Assets/Fantasy Interface Sounds/Special Click 01.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f94699714bc34a24583886479fb97e74
m_Address: Assets/Medieval Combat Sounds/Punch and Melee/Body Fall 1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: fc0ee2e934f6046459bbcbc60219946f
m_Address: Assets/Magic Spells Sound Effects LITE/General Spell/Positive Effect 1.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ff7723b1d7f5ec942801185de588f85b
m_Address: Assets/Magic Spells Sound Effects LITE/General Spell/Positive Effect 6.wav
m_ReadOnly: 0
m_SerializedLabels:
- sfx-combat
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: bffc3d84835754ce69a78a771fc85002, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7, type: 2}
- {fileID: 11400000, guid: b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8, type: 2}

Some files were not shown because too many files have changed in this diff Show More