mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-29 08:55:42 +00:00
Compare commits
50
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
415acf27cd | ||
|
|
c4ad4529d8 | ||
|
|
44e87fbe49 | ||
|
|
4b5897210c | ||
|
|
d1191cf494 | ||
|
|
f4250d2b82 | ||
|
|
1a4656992c | ||
|
|
8b67adbe00 | ||
|
|
6e8c683d9f | ||
|
|
fb5ed2365f | ||
|
|
44ae2f36a7 | ||
|
|
41407d4ad0 | ||
|
|
78d92fee37 | ||
|
|
4e32bd7c51 | ||
|
|
2227cce8a6 | ||
|
|
3e618b1e6f | ||
|
|
c392895e12 | ||
|
|
f86fb86870 | ||
|
|
3cacfc5225 | ||
|
|
6e94c82098 | ||
|
|
1a3d0a82a6 | ||
|
|
ea083c8c6c | ||
|
|
dd4ba80a2b | ||
|
|
aea5bc614b | ||
|
|
e006d9e5a0 | ||
|
|
2daf624538 | ||
|
|
7d6d8f3606 | ||
|
|
0bac3ab38f | ||
|
|
7486af58b8 | ||
|
|
475321a86e | ||
|
|
690ae25c88 | ||
|
|
e1e714a818 | ||
|
|
27cd673038 | ||
|
|
1da9fe3405 | ||
|
|
401fdd26cd | ||
|
|
ad142c6f65 | ||
|
|
96d6d64f77 | ||
|
|
5e80ef41d6 | ||
|
|
58553a4de1 | ||
|
|
dc237d6e8f | ||
|
|
42fa4831f0 | ||
|
|
cdab19e920 | ||
|
|
05de5fd007 | ||
|
|
f1429b9560 | ||
|
|
d9452bd763 | ||
|
|
8f24ef1fa7 | ||
|
|
e9a9475deb | ||
|
|
21b56b8098 | ||
|
|
de04afc47f | ||
|
|
1573fc4a82 |
@@ -31,12 +31,26 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build-auth:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
outputs:
|
||||
image_tag: ${{ steps.push-auth.outputs.image_tag }}
|
||||
steps:
|
||||
- name: Prepare non-LFS checkout
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig-no-lfs
|
||||
GIT_CONFIG_NOSYSTEM: "1"
|
||||
run: |
|
||||
git config --global --unset-all filter.lfs.process || true
|
||||
git config --global filter.lfs.smudge "cat"
|
||||
git config --global filter.lfs.clean "cat"
|
||||
git config --global filter.lfs.required false
|
||||
rm -f .git/hooks/post-checkout .git/hooks/post-merge .git/hooks/pre-push
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig-no-lfs
|
||||
GIT_CONFIG_NOSYSTEM: "1"
|
||||
with:
|
||||
persist-credentials: false
|
||||
lfs: false
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
@@ -11,7 +11,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
# This uses 1 runner slot instead of 4, and Bazel parallelizes internally
|
||||
# NOTE: Must run on a runner with the bazel label to ensure consistent Bazel cache
|
||||
build-all:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
outputs:
|
||||
eagle_image_tag: ${{ steps.push-images.outputs.eagle_image_tag }}
|
||||
admin_image_tag: ${{ steps.push-images.outputs.admin_image_tag }}
|
||||
@@ -227,7 +227,7 @@ jobs:
|
||||
echo "=== All images pushed successfully ==="
|
||||
|
||||
deploy:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
needs: [build-all]
|
||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.push_images == 'true')
|
||||
environment: production
|
||||
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
build-unity:
|
||||
needs: check-changes
|
||||
if: needs.check-changes.outputs.should_build == 'true'
|
||||
runs-on: [self-hosted, macOS, testflight, halfdan]
|
||||
runs-on: [self-hosted, macOS, testflight]
|
||||
|
||||
steps:
|
||||
- name: Prune stale PR refs
|
||||
@@ -209,7 +209,7 @@ jobs:
|
||||
|
||||
archive-and-upload:
|
||||
needs: build-unity
|
||||
runs-on: [self-hosted, macOS, testflight, halfdan]
|
||||
runs-on: [self-hosted, macOS, testflight]
|
||||
|
||||
steps:
|
||||
- name: Ensure Git LFS available for checkout
|
||||
|
||||
@@ -66,7 +66,7 @@ env:
|
||||
|
||||
jobs:
|
||||
build-and-sign:
|
||||
runs-on: [self-hosted, macOS, unity-mac, halfdan]
|
||||
runs-on: [self-hosted, macOS, unity-mac]
|
||||
outputs:
|
||||
submission_id: ${{ steps.notarize-submit.outputs.submission_id }}
|
||||
should_deploy: ${{ steps.check-deploy.outputs.should_deploy }}
|
||||
@@ -274,7 +274,7 @@ jobs:
|
||||
wait-notarization:
|
||||
needs: build-and-sign
|
||||
if: needs.build-and-sign.outputs.should_deploy == 'true'
|
||||
runs-on: [self-hosted, macOS, notarize, halfdan]
|
||||
runs-on: [self-hosted, macOS, notarize]
|
||||
|
||||
steps:
|
||||
- name: Ensure Git LFS available for checkout
|
||||
@@ -342,7 +342,7 @@ jobs:
|
||||
deploy:
|
||||
needs: [build-and-sign, wait-notarization]
|
||||
if: needs.build-and-sign.outputs.should_deploy == 'true'
|
||||
runs-on: [self-hosted, macOS, notarize, halfdan]
|
||||
runs-on: [self-hosted, macOS, notarize]
|
||||
outputs:
|
||||
deployed_version: ${{ steps.deploy-mac.outputs.deployed_version }}
|
||||
|
||||
@@ -401,8 +401,13 @@ jobs:
|
||||
echo "$SPARKLE_EDDSA_PRIVATE_KEY" > "$SPARKLE_PRIVATE_KEY_PATH"
|
||||
chmod 600 "$SPARKLE_PRIVATE_KEY_PATH"
|
||||
|
||||
# Install dmgbuild (creates .DS_Store programmatically, no AppleScript needed)
|
||||
pip3 install dmgbuild
|
||||
# Install dmgbuild in an isolated venv. Homebrew Python rejects system
|
||||
# installs under PEP 668, and mac_build_handler shells out to dmgbuild.
|
||||
DMGBUILD_VENV="${{ env.EAGLE0_BUILD_DIR }}/dmgbuild-venv"
|
||||
python3 -m venv "$DMGBUILD_VENV"
|
||||
"$DMGBUILD_VENV/bin/python" -m pip install --upgrade pip
|
||||
"$DMGBUILD_VENV/bin/python" -m pip install dmgbuild
|
||||
export PATH="$DMGBUILD_VENV/bin:$PATH"
|
||||
|
||||
# Background image for styled DMG
|
||||
BACKGROUND_PATH="$(pwd)/ci/mac/dmg/background.png"
|
||||
|
||||
@@ -11,7 +11,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
|
||||
steps:
|
||||
- name: Ensure AWS CLI is available
|
||||
|
||||
@@ -30,12 +30,26 @@ permissions:
|
||||
|
||||
jobs:
|
||||
build-shardok-arm64:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
outputs:
|
||||
image_tag: ${{ steps.push-shardok.outputs.image_tag }}
|
||||
steps:
|
||||
- name: Prepare non-LFS checkout
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig-no-lfs
|
||||
GIT_CONFIG_NOSYSTEM: "1"
|
||||
run: |
|
||||
git config --global --unset-all filter.lfs.process || true
|
||||
git config --global filter.lfs.smudge "cat"
|
||||
git config --global filter.lfs.clean "cat"
|
||||
git config --global filter.lfs.required false
|
||||
rm -f .git/hooks/post-checkout .git/hooks/post-merge .git/hooks/pre-push
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig-no-lfs
|
||||
GIT_CONFIG_NOSYSTEM: "1"
|
||||
with:
|
||||
persist-credentials: false
|
||||
lfs: false
|
||||
@@ -170,7 +184,7 @@ jobs:
|
||||
echo "Also tagged as: registry.digitalocean.com/eagle0/shardok-server:arm64-latest"
|
||||
|
||||
deploy-hetzner:
|
||||
runs-on: [self-hosted, bazel, halfdan]
|
||||
runs-on: [self-hosted, bazel]
|
||||
needs: [build-shardok-arm64]
|
||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.push_images == 'true')
|
||||
environment: production
|
||||
|
||||
@@ -57,7 +57,7 @@ env:
|
||||
|
||||
jobs:
|
||||
windows-unity:
|
||||
runs-on: [self-hosted, macOS, unity-windows, halfdan]
|
||||
runs-on: [self-hosted, macOS, unity-windows]
|
||||
outputs:
|
||||
deployed_version: ${{ steps.get-version.outputs.deployed_version }}
|
||||
|
||||
|
||||
@@ -49,6 +49,17 @@ When code changes appear correct locally, create the PR promptly even if long-ru
|
||||
Opening the PR starts CI on the build machines, uploads results to the Bazel remote cache, and can speed up subsequent
|
||||
local validation. Continue monitoring any already-started local and CI validation after opening the PR.
|
||||
|
||||
## GitHub CLI PR Bodies
|
||||
|
||||
When creating or editing PR descriptions with multiline bodies, write the body to a temporary markdown file and pass it
|
||||
with `gh pr create --body-file <path>` or `gh pr edit <number> --body-file <path>`. Do not use multiline `$'...'`
|
||||
shell quoting for PR bodies; Codex's permission matching may treat that as a complex shell command instead of a clean
|
||||
`gh pr` invocation, causing unnecessary approval prompts.
|
||||
|
||||
Write these temporary body files, and any other scratch files needed for commands, under a known writable location such
|
||||
as `/private/tmp`, `$TMPDIR`, or the current repository workspace. Do not use protected paths that require additional
|
||||
user permission just to create or edit temporary files.
|
||||
|
||||
---
|
||||
|
||||
This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
|
||||
@@ -253,7 +264,7 @@ to be used for different players or game situations within the same server proce
|
||||
**C# (Unity Client):**
|
||||
|
||||
- Located in `/src/main/csharp/net/eagle0/clients/unity/eagle0/`
|
||||
- Uses Unity 6 (6000.4.9f1) with comprehensive protobuf integration (100+ .proto files)
|
||||
- Uses Unity 6 (6000.4.10f1) with comprehensive protobuf integration (100+ .proto files)
|
||||
- Key components: `EagleConnection.cs` (gRPC client), `EagleGameController.cs` (main game logic)
|
||||
- Real-time bidirectional streaming with server via `PersistentClientConnection.cs`
|
||||
- Strategic map UI in `Assets/Eagle/`, tactical battle UI in `Assets/Shardok/`
|
||||
|
||||
@@ -228,7 +228,7 @@ to be used for different players or game situations within the same server proce
|
||||
**C# (Unity Client):**
|
||||
|
||||
- Located in `/src/main/csharp/net/eagle0/clients/unity/eagle0/`
|
||||
- Uses Unity 6 (6000.4.9f1) with comprehensive protobuf integration (100+ .proto files)
|
||||
- Uses Unity 6 (6000.4.10f1) with comprehensive protobuf integration (100+ .proto files)
|
||||
- Key components: `EagleConnection.cs` (gRPC client), `EagleGameController.cs` (main game logic)
|
||||
- Real-time bidirectional streaming with server via `PersistentClientConnection.cs`
|
||||
- Strategic map UI in `Assets/Eagle/`, tactical battle UI in `Assets/Shardok/`
|
||||
|
||||
+47
-44
@@ -3,25 +3,29 @@ module(name = "net_eagle0")
|
||||
# Version constants
|
||||
SCALA_VERSION = "3.7.4"
|
||||
|
||||
NETTY_VERSION = "4.1.127.Final"
|
||||
NETTY_VERSION = "4.1.135.Final"
|
||||
|
||||
SCALAPB_VERSION = "1.0.0-alpha.1"
|
||||
SCALAPB_VERSION = "1.0.0-alpha.5"
|
||||
|
||||
AWS_SDK_VERSION = "2.41.18"
|
||||
SCALAPB_JSON4S_VERSION = "1.0.0-alpha.1"
|
||||
|
||||
AWS_SDK_VERSION = "2.46.7"
|
||||
|
||||
SLF4J_VERSION = "2.0.18"
|
||||
|
||||
#
|
||||
# Core Build Tools
|
||||
#
|
||||
|
||||
bazel_dep(name = "bazel_skylib", version = "1.9.0")
|
||||
bazel_dep(name = "platforms", version = "1.0.0")
|
||||
bazel_dep(name = "platforms", version = "1.1.0")
|
||||
bazel_dep(name = "rules_pkg", version = "1.2.0")
|
||||
|
||||
#
|
||||
# Language Support - Scala
|
||||
#
|
||||
|
||||
bazel_dep(name = "rules_scala", version = "7.2.1")
|
||||
bazel_dep(name = "rules_scala", version = "7.2.5")
|
||||
|
||||
scala_config = use_extension(
|
||||
"@rules_scala//scala/extensions:config.bzl",
|
||||
@@ -41,21 +45,21 @@ scala_deps.scala_proto()
|
||||
# Language Support - C++
|
||||
#
|
||||
|
||||
bazel_dep(name = "toolchains_llvm", version = "1.6.0")
|
||||
bazel_dep(name = "toolchains_llvm", version = "1.7.0")
|
||||
|
||||
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
|
||||
|
||||
# Native toolchain (macOS -> macOS, Linux -> Linux)
|
||||
llvm.toolchain(
|
||||
name = "llvm_toolchain",
|
||||
llvm_version = "20.1.4",
|
||||
llvm_version = "20.1.8",
|
||||
)
|
||||
|
||||
# Cross-compilation toolchain (macOS -> Linux x86_64)
|
||||
# Uses the same LLVM distribution but with a Linux sysroot
|
||||
llvm.toolchain(
|
||||
name = "llvm_toolchain_linux",
|
||||
llvm_version = "20.1.4",
|
||||
llvm_version = "20.1.8",
|
||||
)
|
||||
|
||||
# Linux x86_64 sysroot for cross-compilation
|
||||
@@ -68,7 +72,7 @@ llvm.sysroot(
|
||||
# Cross-compilation toolchain (macOS -> Linux ARM64)
|
||||
llvm.toolchain(
|
||||
name = "llvm_toolchain_linux_arm64",
|
||||
llvm_version = "20.1.4",
|
||||
llvm_version = "20.1.8",
|
||||
)
|
||||
|
||||
# Linux ARM64 sysroot for cross-compilation
|
||||
@@ -77,7 +81,6 @@ llvm.sysroot(
|
||||
label = "@linux_sysroot_arm64//sysroot",
|
||||
targets = ["linux-aarch64"],
|
||||
)
|
||||
|
||||
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_linux", "llvm_toolchain_linux_arm64")
|
||||
|
||||
# Download the Linux sysroots (Ubuntu 24.04 Noble for C++23 support)
|
||||
@@ -103,11 +106,11 @@ sysroot(
|
||||
# Language Support - Go
|
||||
#
|
||||
|
||||
bazel_dep(name = "rules_go", version = "0.59.0", repo_name = "io_bazel_rules_go")
|
||||
bazel_dep(name = "gazelle", version = "0.47.0", repo_name = "bazel_gazelle")
|
||||
bazel_dep(name = "rules_go", version = "0.61.1", repo_name = "io_bazel_rules_go")
|
||||
bazel_dep(name = "gazelle", version = "0.51.3", repo_name = "bazel_gazelle")
|
||||
|
||||
go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.23.3")
|
||||
go_sdk.download(version = "1.25.11")
|
||||
use_repo(go_sdk, "go_default_sdk")
|
||||
|
||||
go_deps = use_extension("@bazel_gazelle//:extensions.bzl", "go_deps")
|
||||
@@ -130,7 +133,7 @@ use_repo(
|
||||
# Language Support - Rust
|
||||
#
|
||||
|
||||
bazel_dep(name = "rules_rust", version = "0.68.1")
|
||||
bazel_dep(name = "rules_rust", version = "0.70.0")
|
||||
|
||||
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
|
||||
rust.toolchain(edition = "2021")
|
||||
@@ -150,7 +153,7 @@ use_repo(crate, "map_generator_crates")
|
||||
# Platform Support - Apple/iOS
|
||||
#
|
||||
|
||||
bazel_dep(name = "apple_support", version = "1.24.1", repo_name = "build_bazel_apple_support")
|
||||
bazel_dep(name = "apple_support", version = "1.24.5", 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
|
||||
@@ -164,7 +167,7 @@ use_repo(apple_cc_configure, "local_config_apple_cc", "local_config_apple_cc_too
|
||||
# Protocol Buffers & RPC
|
||||
#
|
||||
|
||||
bazel_dep(name = "protobuf", version = "33.5", repo_name = "com_google_protobuf")
|
||||
bazel_dep(name = "protobuf", version = "33.6", repo_name = "com_google_protobuf")
|
||||
|
||||
# Use pre-built protoc binaries instead of compiling from source.
|
||||
# See: https://protobuf.dev/reference/cpp/cpp-generated/#invocation
|
||||
@@ -183,7 +186,7 @@ use_repo(
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_proto", version = "7.1.0")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.14")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.19")
|
||||
bazel_dep(name = "grpc", version = "1.78.0")
|
||||
|
||||
# Patch grpc 1.78.0 to fix rules_python incompatibility: grpc requests Python
|
||||
@@ -197,7 +200,7 @@ single_version_override(
|
||||
version = "1.78.0",
|
||||
)
|
||||
|
||||
bazel_dep(name = "grpc-java", version = "1.78.0")
|
||||
bazel_dep(name = "grpc-java", version = "1.78.0.bcr.1")
|
||||
bazel_dep(name = "rules_proto_grpc_csharp", version = "5.8.0")
|
||||
bazel_dep(name = "flatbuffers", version = "25.12.19")
|
||||
|
||||
@@ -205,13 +208,13 @@ bazel_dep(name = "flatbuffers", version = "25.12.19")
|
||||
# Testing
|
||||
#
|
||||
|
||||
bazel_dep(name = "googletest", version = "1.17.0")
|
||||
bazel_dep(name = "googletest", version = "1.17.0.bcr.2")
|
||||
|
||||
#
|
||||
# Container Images (OCI)
|
||||
#
|
||||
|
||||
bazel_dep(name = "rules_oci", version = "2.2.7")
|
||||
bazel_dep(name = "rules_oci", version = "2.3.0")
|
||||
bazel_dep(name = "aspect_bazel_lib", version = "2.22.5")
|
||||
|
||||
oci = use_extension("@rules_oci//oci:extensions.bzl", "oci")
|
||||
@@ -261,7 +264,7 @@ use_repo(oci, "alpine_linux", "alpine_linux_linux_amd64", "eclipse_temurin_25_jd
|
||||
# Java/Scala Dependencies
|
||||
#
|
||||
|
||||
bazel_dep(name = "rules_java", version = "9.3.0")
|
||||
bazel_dep(name = "rules_java", version = "9.6.1")
|
||||
bazel_dep(name = "rules_jvm_external", version = "6.10")
|
||||
|
||||
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
|
||||
@@ -281,7 +284,7 @@ maven.install(
|
||||
|
||||
# ScalaPB
|
||||
"com.thesamet.scalapb:lenses_3:%s" % SCALAPB_VERSION,
|
||||
"com.thesamet.scalapb:scalapb-json4s_3:%s" % SCALAPB_VERSION,
|
||||
"com.thesamet.scalapb:scalapb-json4s_3:%s" % SCALAPB_JSON4S_VERSION,
|
||||
"com.thesamet.scalapb:scalapb-runtime_3:%s" % SCALAPB_VERSION,
|
||||
"com.thesamet.scalapb:scalapb-runtime-grpc_3:%s" % SCALAPB_VERSION,
|
||||
"com.thesamet.scalapb:compilerplugin_3:%s" % SCALAPB_VERSION,
|
||||
@@ -293,10 +296,10 @@ maven.install(
|
||||
"org.json4s:json4s-native_3:4.1.0-M8",
|
||||
|
||||
# Testing
|
||||
"org.scalamock:scalamock_3:7.4.1",
|
||||
"org.scalamock:scalamock_3:7.5.5",
|
||||
|
||||
# Developer tools
|
||||
"org.scalameta:scalafmt-cli_2.13:3.9.9",
|
||||
"org.scalameta:scalafmt-cli_2.13:3.11.1",
|
||||
|
||||
# AWS SDK
|
||||
"software.amazon.awssdk:s3-transfer-manager:%s" % AWS_SDK_VERSION,
|
||||
@@ -308,38 +311,38 @@ maven.install(
|
||||
"software.amazon.awssdk:http-client-spi:%s" % AWS_SDK_VERSION,
|
||||
|
||||
# AWS Lambda
|
||||
"com.amazonaws:aws-lambda-java-core:1.2.3",
|
||||
"com.amazonaws:aws-lambda-java-events:3.13.0",
|
||||
"com.amazonaws:aws-lambda-java-core:1.4.0",
|
||||
"com.amazonaws:aws-lambda-java-events:3.16.1",
|
||||
|
||||
# Logging
|
||||
"org.slf4j:slf4j-api:2.0.16",
|
||||
"org.slf4j:slf4j-simple:2.0.16",
|
||||
"org.slf4j:slf4j-api:%s" % SLF4J_VERSION,
|
||||
"org.slf4j:slf4j-simple:%s" % SLF4J_VERSION,
|
||||
|
||||
# Other
|
||||
"org.reactivestreams:reactive-streams:1.0.4",
|
||||
"javax.xml.bind:jaxb-api:2.3.1",
|
||||
|
||||
# OkHttp (for SSE with read timeout support, OAuth HTTP calls)
|
||||
"com.squareup.okhttp3:okhttp:4.12.0",
|
||||
"com.squareup.okhttp3:okhttp-sse:4.12.0",
|
||||
"com.squareup.okhttp3:okhttp-jvm:5.4.0",
|
||||
"com.squareup.okhttp3:okhttp-sse:5.4.0",
|
||||
|
||||
# JWT (for OAuth token handling)
|
||||
"com.nimbusds:nimbus-jose-jwt:9.37.3",
|
||||
"com.nimbusds:nimbus-jose-jwt:10.9.1",
|
||||
|
||||
# Error tracking
|
||||
"io.sentry:sentry:8.31.0",
|
||||
"io.sentry:sentry:8.43.2",
|
||||
|
||||
# SQLite for client text storage
|
||||
"org.xerial:sqlite-jdbc:3.46.1.0",
|
||||
"org.xerial:sqlite-jdbc:3.53.2.0",
|
||||
|
||||
# Postgres for production history benchmarking and migration work
|
||||
"org.postgresql:postgresql:42.7.4",
|
||||
"org.postgresql:postgresql:42.7.11",
|
||||
],
|
||||
duplicate_version_warning = "error",
|
||||
fail_if_repin_required = True,
|
||||
lock_file = "//:maven_install.json",
|
||||
repositories = [
|
||||
"https://repo1.maven.org/maven2",
|
||||
"https://repo.maven.apache.org/maven2",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -349,7 +352,7 @@ maven.artifact(
|
||||
artifact = "scala3-staging_3",
|
||||
exclusions = ["org.scala-lang:scala3-compiler_3"],
|
||||
group = "org.scala-lang",
|
||||
version = "3.3.6",
|
||||
version = SCALA_VERSION,
|
||||
)
|
||||
|
||||
# Force specific versions for dependencies with conflicts between grpc-java and protobuf
|
||||
@@ -357,21 +360,20 @@ maven.artifact(
|
||||
artifact = "gson",
|
||||
force_version = True,
|
||||
group = "com.google.code.gson",
|
||||
version = "2.11.0",
|
||||
version = "2.14.0",
|
||||
)
|
||||
maven.artifact(
|
||||
artifact = "error_prone_annotations",
|
||||
force_version = True,
|
||||
group = "com.google.errorprone",
|
||||
version = "2.30.0",
|
||||
version = "2.50.0",
|
||||
)
|
||||
maven.artifact(
|
||||
artifact = "guava",
|
||||
force_version = True,
|
||||
group = "com.google.guava",
|
||||
version = "33.3.1-android",
|
||||
version = "33.6.0-android",
|
||||
)
|
||||
|
||||
use_repo(maven, "maven", "unpinned_maven")
|
||||
|
||||
#
|
||||
@@ -379,6 +381,7 @@ use_repo(maven, "maven", "unpinned_maven")
|
||||
#
|
||||
|
||||
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
|
||||
|
||||
# GTL (for parallel_hashmap)
|
||||
@@ -431,24 +434,24 @@ http_archive(
|
||||
# Fallback: busybox.net (can be unreliable/slow)
|
||||
http_file(
|
||||
name = "busybox_x86_64",
|
||||
downloaded_file_path = "busybox",
|
||||
executable = True,
|
||||
sha256 = "6e123e7f3202a8c1e9b1f94d8941580a25135382b99e8d3e34fb858bba311348",
|
||||
urls = [
|
||||
"https://eagle0-sysroot.sfo3.digitaloceanspaces.com/busybox/busybox-1.35.0-x86_64-linux-musl",
|
||||
"https://busybox.net/downloads/binaries/1.35.0-x86_64-linux-musl/busybox",
|
||||
],
|
||||
downloaded_file_path = "busybox",
|
||||
executable = True,
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "busybox_aarch64",
|
||||
downloaded_file_path = "busybox",
|
||||
executable = True,
|
||||
sha256 = "141adb1b625a6f44c4b114f76b4387b4ea4f7ab802b88eb40e0d2f6adcccb1c3",
|
||||
urls = [
|
||||
# TODO: Upload aarch64 binary to GitHub release when needed
|
||||
"https://busybox.net/downloads/binaries/1.35.0-aarch64-linux-musl/busybox",
|
||||
],
|
||||
downloaded_file_path = "busybox",
|
||||
executable = True,
|
||||
)
|
||||
|
||||
# LLVM MinGW toolchain for Windows cross-compilation from macOS
|
||||
|
||||
Generated
+226
-201
File diff suppressed because one or more lines are too long
@@ -34,6 +34,7 @@ echo "Platform: ${PLATFORM}"
|
||||
# Check if Unity is installed and has required modules
|
||||
check_modules_installed() {
|
||||
local unity_path="${UNITY_INSTALL_PATH}/${UNITY_VERSION}"
|
||||
local unity_app_contents_path="${unity_path}/Unity.app/Contents"
|
||||
|
||||
if [ ! -d "$unity_path" ]; then
|
||||
return 1
|
||||
@@ -49,7 +50,8 @@ check_modules_installed() {
|
||||
;;
|
||||
mac)
|
||||
# Mac IL2CPP module
|
||||
if [ ! -d "${unity_path}/PlaybackEngines/MacStandaloneSupport/Variations/macos_development_il2cpp" ] && \
|
||||
if [ ! -d "${unity_app_contents_path}/PlaybackEngines/MacStandaloneSupport/Source/Player/MacPlayer/GameAssembly.xcodeproj" ] && \
|
||||
[ ! -d "${unity_path}/PlaybackEngines/MacStandaloneSupport/Variations/macos_development_il2cpp" ] && \
|
||||
[ ! -d "${unity_path}/PlaybackEngines/MacStandaloneSupport" ]; then
|
||||
echo "✗ Mac IL2CPP module not installed for Unity ${UNITY_VERSION}"
|
||||
return 1
|
||||
@@ -69,7 +71,8 @@ check_modules_installed() {
|
||||
echo "✗ iOS module missing"
|
||||
missing=1
|
||||
fi
|
||||
if [ ! -d "${unity_path}/PlaybackEngines/MacStandaloneSupport" ]; then
|
||||
if [ ! -d "${unity_app_contents_path}/PlaybackEngines/MacStandaloneSupport/Source/Player/MacPlayer/GameAssembly.xcodeproj" ] && \
|
||||
[ ! -d "${unity_path}/PlaybackEngines/MacStandaloneSupport" ]; then
|
||||
echo "✗ Mac module missing"
|
||||
missing=1
|
||||
fi
|
||||
@@ -191,8 +194,10 @@ echo "Running: ${INSTALL_CMD[*]}"
|
||||
echo ""
|
||||
|
||||
# Capture output to check for "already installed" messages
|
||||
OUTPUT=$("${INSTALL_CMD[@]}" 2>&1) || true
|
||||
set +e
|
||||
OUTPUT=$("${INSTALL_CMD[@]}" 2>&1)
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
echo "$OUTPUT"
|
||||
|
||||
# Check if modules are already installed (Unity Hub returns error but modules are present)
|
||||
@@ -219,13 +224,13 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify installation
|
||||
# Verify installation and requested modules
|
||||
echo ""
|
||||
if [ -d "${UNITY_INSTALL_PATH}/${UNITY_VERSION}" ]; then
|
||||
echo "✓ Verified: Unity ${UNITY_VERSION} is now installed"
|
||||
if check_modules_installed; then
|
||||
echo "✓ Verified: Unity ${UNITY_VERSION} is now installed with ${PLATFORM} support"
|
||||
exit 0
|
||||
else
|
||||
echo "✗ Unity ${UNITY_VERSION} installation could not be verified"
|
||||
echo "✗ Unity ${UNITY_VERSION} installation with ${PLATFORM} support could not be verified"
|
||||
echo " Expected path: ${UNITY_INSTALL_PATH}/${UNITY_VERSION}"
|
||||
echo ""
|
||||
echo "The installation may still be in progress, or may require manual intervention."
|
||||
|
||||
@@ -38,7 +38,7 @@ fi
|
||||
echo "Using git-lfs at $(command -v git-lfs)"
|
||||
git lfs version
|
||||
|
||||
git lfs install
|
||||
git lfs install --force
|
||||
|
||||
echo "LFS objects before pull:"
|
||||
git lfs ls-files | wc -l
|
||||
|
||||
@@ -19,6 +19,18 @@ SERVER_DATA="$UNITY_PROJECT/ServerData/$BUILD_TARGET"
|
||||
DO_ENDPOINT="https://sfo3.digitaloceanspaces.com"
|
||||
DO_BUCKET="eagle0-assets"
|
||||
|
||||
COMMON_PATHS="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||
export PATH="${COMMON_PATHS}:${PATH}"
|
||||
|
||||
if ! command -v aws >/dev/null 2>&1; then
|
||||
if command -v brew >/dev/null 2>&1; then
|
||||
brew install awscli
|
||||
else
|
||||
echo "ERROR: aws CLI is unavailable, and Homebrew is not on PATH"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$SERVER_DATA" ]; then
|
||||
echo "No Addressables bundles found at $SERVER_DATA"
|
||||
echo "Skipping upload (this is expected if Addressables are bundled locally)"
|
||||
|
||||
@@ -2,7 +2,7 @@ module github.com/nolen777/eagle0
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.3
|
||||
toolchain go1.25.11
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.8
|
||||
@@ -12,9 +12,9 @@ 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
|
||||
google.golang.org/grpc v1.68.0
|
||||
google.golang.org/protobuf v1.36.3
|
||||
golang.org/x/sys v0.33.0
|
||||
google.golang.org/grpc v1.71.0
|
||||
google.golang.org/protobuf v1.36.10
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -32,5 +32,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.6 // indirect
|
||||
github.com/aws/smithy-go v1.22.1 // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
|
||||
)
|
||||
|
||||
@@ -43,14 +43,24 @@ 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/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
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.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
||||
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||
google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
|
||||
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
|
||||
+1256
-684
File diff suppressed because it is too large
Load Diff
+269
-263
File diff suppressed because it is too large
Load Diff
+16
-13
@@ -24,34 +24,35 @@ public class MoveCamera : MonoBehaviour {
|
||||
|
||||
void Update() {
|
||||
// Get the left mouse button
|
||||
if (Input.GetMouseButtonDown(0)) {
|
||||
if (GameInput.PrimaryPointerPressedThisFrame()) {
|
||||
// Get mouse origin
|
||||
mouseOrigin = Input.mousePosition;
|
||||
mouseOrigin = GameInput.PointerPosition();
|
||||
isRotating = true;
|
||||
}
|
||||
|
||||
// Get the right mouse button
|
||||
if (Input.GetMouseButtonDown(1)) {
|
||||
if (GameInput.SecondaryPointerPressedThisFrame()) {
|
||||
// Get mouse origin
|
||||
mouseOrigin = Input.mousePosition;
|
||||
mouseOrigin = GameInput.PointerPosition();
|
||||
isPanning = true;
|
||||
}
|
||||
|
||||
// Get the middle mouse button
|
||||
if (Input.GetMouseButtonDown(2)) {
|
||||
if (GameInput.MiddlePointerPressedThisFrame()) {
|
||||
// Get mouse origin
|
||||
mouseOrigin = Input.mousePosition;
|
||||
mouseOrigin = GameInput.PointerPosition();
|
||||
isZooming = true;
|
||||
}
|
||||
|
||||
// Disable movements on button release
|
||||
if (!Input.GetMouseButton(0)) isRotating = false;
|
||||
if (!Input.GetMouseButton(1)) isPanning = false;
|
||||
if (!Input.GetMouseButton(2)) isZooming = false;
|
||||
if (!GameInput.PrimaryPointerPressed()) isRotating = false;
|
||||
if (!GameInput.SecondaryPointerPressed()) isPanning = false;
|
||||
if (!GameInput.MiddlePointerPressed()) isZooming = false;
|
||||
|
||||
// Rotate camera along X and Y axis
|
||||
if (isRotating) {
|
||||
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
|
||||
Vector3 pos = Camera.main.ScreenToViewportPoint(
|
||||
(Vector3)GameInput.PointerPosition() - mouseOrigin);
|
||||
|
||||
transform.RotateAround(transform.position, transform.right, -pos.y * turnSpeed);
|
||||
transform.RotateAround(transform.position, Vector3.up, pos.x * turnSpeed);
|
||||
@@ -59,7 +60,8 @@ public class MoveCamera : MonoBehaviour {
|
||||
|
||||
// Move the camera on it's XY plane
|
||||
if (isPanning) {
|
||||
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
|
||||
Vector3 pos = Camera.main.ScreenToViewportPoint(
|
||||
(Vector3)GameInput.PointerPosition() - mouseOrigin);
|
||||
|
||||
Vector3 move = new Vector3(pos.x * panSpeed, pos.y * panSpeed, 0);
|
||||
transform.Translate(move, Space.Self);
|
||||
@@ -67,10 +69,11 @@ public class MoveCamera : MonoBehaviour {
|
||||
|
||||
// Move the camera linearly along Z axis
|
||||
if (isZooming) {
|
||||
Vector3 pos = Camera.main.ScreenToViewportPoint(Input.mousePosition - mouseOrigin);
|
||||
Vector3 pos = Camera.main.ScreenToViewportPoint(
|
||||
(Vector3)GameInput.PointerPosition() - mouseOrigin);
|
||||
|
||||
Vector3 move = pos.y * zoomSpeed * transform.forward;
|
||||
transform.Translate(move, Space.World);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -145,10 +145,7 @@ namespace eagle {
|
||||
|
||||
public void Update() {
|
||||
// '?' key (Shift + /) toggles help panel when a command is selected
|
||||
if (Selector != null && Input.GetKeyDown(KeyCode.Slash) &&
|
||||
(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) {
|
||||
InfoButtonClicked();
|
||||
}
|
||||
if (Selector != null && GameInput.QuestionMarkPressed()) { InfoButtonClicked(); }
|
||||
}
|
||||
|
||||
public void PointerEnteredCommitButton() {
|
||||
|
||||
+4
-13
@@ -1,19 +1,10 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace eagle {
|
||||
public class KeyModifiedAmount {
|
||||
private static bool Shift() {
|
||||
return Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
|
||||
}
|
||||
private static bool Control() {
|
||||
return Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
|
||||
}
|
||||
|
||||
public static int Amount() {
|
||||
if (Shift() && Control()) { return 1000; }
|
||||
if (Shift()) { return 100; }
|
||||
if (Control()) { return 10; }
|
||||
if (GameInput.ShiftPressed() && GameInput.ControlPressed()) { return 1000; }
|
||||
if (GameInput.ShiftPressed()) { return 100; }
|
||||
if (GameInput.ControlPressed()) { return 10; }
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -115,7 +115,7 @@ namespace eagle {
|
||||
|
||||
// Update is called once per frame
|
||||
void Update() {
|
||||
if (Input.GetButtonUp("Toggle Dominion Table") && disclosureToggle != null) {
|
||||
if (GameInput.ToggleDominionTableReleased() && disclosureToggle != null) {
|
||||
disclosureToggle.isOn = !disclosureToggle.isOn;
|
||||
}
|
||||
}
|
||||
@@ -140,4 +140,4 @@ namespace eagle {
|
||||
mapController.OverrideTargetedProvinces = new List<ProvinceId>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace eagle {
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetButtonUp("Windowed Mode")) {
|
||||
if (GameInput.WindowedModeReleased()) {
|
||||
#if UNITY_EDITOR
|
||||
// do nothing
|
||||
#else
|
||||
|
||||
@@ -276,7 +276,13 @@ namespace eagle {
|
||||
|
||||
private void RestoreCachedStateIfAvailable(FactionId? factionId) {
|
||||
var cachedState = EagleGameStateDiskCache.Load(GameId, factionId);
|
||||
if (cachedState == null) { return; }
|
||||
if (cachedState == null) {
|
||||
_connectionLogger.LogLine(
|
||||
$"[STATE_CACHE] Cache miss game={GameId} " +
|
||||
$"player={factionId?.ToString() ?? "spectator"} " +
|
||||
$"reason={EagleGameStateDiskCache.LastLoadDiagnostic}");
|
||||
return;
|
||||
}
|
||||
|
||||
_currentModel.GsView = cachedState.GameStateView;
|
||||
_currentModel.BattalionTypes = cachedState.GameStateView.BattalionTypes.ToDictionary(
|
||||
@@ -289,29 +295,9 @@ namespace eagle {
|
||||
}
|
||||
_lastAppliedUnfilteredCount = cachedState.UnfilteredResultCount;
|
||||
|
||||
RestoreCachedShardokStates(cachedState.ShardokGames);
|
||||
|
||||
_connectionLogger.LogLine(
|
||||
$"[STATE_CACHE] Restored game {GameId} at count " +
|
||||
$"{cachedState.UnfilteredResultCount} with " +
|
||||
$"{cachedState.ShardokGames.Count} cached Shardok game(s)");
|
||||
}
|
||||
|
||||
private void RestoreCachedShardokStates(
|
||||
List<EagleGameStateDiskCache.CachedShardokGameState> cachedShardokStates) {
|
||||
foreach (var cachedShardokState in cachedShardokStates) {
|
||||
var model = MakeGameModel(cachedShardokState.ShardokGameId);
|
||||
if (model == null) { continue; }
|
||||
|
||||
var updatesOk = model.HandleUpdates(
|
||||
cachedShardokState.ActionResultViews,
|
||||
cachedShardokState.ResultCount);
|
||||
if (!updatesOk) { continue; }
|
||||
|
||||
_currentModel.ShardokGameModels[cachedShardokState.ShardokGameId] = model;
|
||||
_shardokResultCounts[cachedShardokState.ShardokGameId] =
|
||||
cachedShardokState.ResultCount;
|
||||
}
|
||||
$"{cachedState.UnfilteredResultCount}; Shardok state will refresh from server");
|
||||
}
|
||||
|
||||
private ShardokGameModel MakeGameModel(ShardokGameId shardokGameId) {
|
||||
@@ -423,8 +409,13 @@ namespace eagle {
|
||||
_connectionLogger.LogLine(
|
||||
"[UPDATE] Processed update and invoked UpdateAction");
|
||||
} else {
|
||||
RecordAppliedUnfilteredCount(
|
||||
updateItem.ActionResultResponse.UnfilteredResultCountAfter);
|
||||
SaveCurrentStateToCache(
|
||||
updateItem.ActionResultResponse.UnfilteredResultCountAfter);
|
||||
_connectionLogger.LogLine(
|
||||
"[UPDATE] SKIPPED - no results, has commands, token matches");
|
||||
"[UPDATE] SKIPPED - no results, has commands, token matches; " +
|
||||
"persisted accepted count");
|
||||
}
|
||||
|
||||
// Check for turn state mismatch after processing update
|
||||
@@ -736,11 +727,19 @@ namespace eagle {
|
||||
}
|
||||
|
||||
if (countAfter > _lastAppliedUnfilteredCount) {
|
||||
_lastAppliedUnfilteredCount = countAfter;
|
||||
RecordAppliedUnfilteredCount(countAfter);
|
||||
}
|
||||
SaveCurrentStateToCache(countAfter);
|
||||
}
|
||||
|
||||
private void RecordAppliedUnfilteredCount(int countAfter) {
|
||||
if (countAfter <= _lastAppliedUnfilteredCount) { return; }
|
||||
|
||||
_connectionLogger.LogLine(
|
||||
$"[STATE_CACHE] Accepted Eagle count {_lastAppliedUnfilteredCount} -> {countAfter}");
|
||||
_lastAppliedUnfilteredCount = countAfter;
|
||||
}
|
||||
|
||||
private void SaveCurrentStateToCache(int unfilteredResultCount) {
|
||||
if (unfilteredResultCount <= 0 || _currentModel.GsView == null) { return; }
|
||||
|
||||
@@ -748,8 +747,9 @@ namespace eagle {
|
||||
GameId,
|
||||
_currentModel.PlayerId,
|
||||
unfilteredResultCount,
|
||||
_currentModel.GsView,
|
||||
CachedShardokGameStates());
|
||||
_currentModel.GsView);
|
||||
_connectionLogger.LogLine(
|
||||
$"[STATE_CACHE] Saved game={GameId} count={unfilteredResultCount}");
|
||||
}
|
||||
|
||||
private void SaveCurrentStateToCache() {
|
||||
@@ -758,17 +758,6 @@ namespace eagle {
|
||||
SaveCurrentStateToCache(count);
|
||||
}
|
||||
|
||||
private List<EagleGameStateDiskCache.CachedShardokGameState> CachedShardokGameStates() {
|
||||
return _currentModel.ShardokGameModels
|
||||
.Where(kv => !_shardokNeedsResync.GetValueOrDefault(kv.Key, false))
|
||||
.Select(kv => new EagleGameStateDiskCache.CachedShardokGameState {
|
||||
ShardokGameId = kv.Key,
|
||||
ResultCount = kv.Value.History.Count,
|
||||
ActionResultViews = kv.Value.History.ToList()
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static HashSet<FactionId> InvitationAcceptedFactionIds(
|
||||
IEnumerable<ActionResultView> results) {
|
||||
var invitedFactionIds = new HashSet<FactionId>();
|
||||
|
||||
+53
-83
@@ -1,22 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Google.Protobuf;
|
||||
using Net.Eagle0.Eagle.Views;
|
||||
using ShardokActionResultView = Net.Eagle0.Shardok.Api.ActionResultView;
|
||||
using UnityEngine;
|
||||
|
||||
namespace eagle {
|
||||
public static class EagleGameStateDiskCache {
|
||||
private const int CurrentSchemaVersion = 2;
|
||||
|
||||
[Serializable]
|
||||
private class ShardokCacheEntry {
|
||||
public string shardokGameId;
|
||||
public int resultCount;
|
||||
public List<string> actionResultViewsBase64 = new();
|
||||
}
|
||||
private const int CurrentSchemaVersion = 3;
|
||||
|
||||
[Serializable]
|
||||
private class CacheFile {
|
||||
@@ -26,61 +16,89 @@ namespace eagle {
|
||||
public int playerId;
|
||||
public int unfilteredResultCount;
|
||||
public string gameStateViewBase64;
|
||||
public List<ShardokCacheEntry> shardokGames = new();
|
||||
public string savedAtUtc;
|
||||
}
|
||||
|
||||
public class CachedShardokGameState {
|
||||
public string ShardokGameId { get; set; }
|
||||
public List<ShardokActionResultView> ActionResultViews { get; set; }
|
||||
public int ResultCount { get; set; }
|
||||
}
|
||||
|
||||
public class CachedGameState {
|
||||
public GameStateView GameStateView { get; set; }
|
||||
public int UnfilteredResultCount { get; set; }
|
||||
public List<CachedShardokGameState> ShardokGames { get; set; } = new();
|
||||
}
|
||||
|
||||
private static string _cacheDirectory;
|
||||
public static string LastLoadDiagnostic { get; private set; }
|
||||
|
||||
public static CachedGameState Load(long gameId, int? playerId) {
|
||||
EnsureCacheDirectoryInitialized();
|
||||
|
||||
var path = CachePath(gameId, playerId);
|
||||
if (!File.Exists(path)) { return null; }
|
||||
LastLoadDiagnostic = $"path={path}";
|
||||
if (!File.Exists(path)) {
|
||||
LastLoadDiagnostic = $"file not found at {path}";
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var cache = JsonUtility.FromJson<CacheFile>(File.ReadAllText(path));
|
||||
if (cache == null || cache.schemaVersion != CurrentSchemaVersion) { return null; }
|
||||
if (cache.gameId != gameId) { return null; }
|
||||
if (cache.hasPlayerId != playerId.HasValue) { return null; }
|
||||
if (cache.hasPlayerId && cache.playerId != playerId.Value) { return null; }
|
||||
if (cache.unfilteredResultCount <= 0) { return null; }
|
||||
if (String.IsNullOrEmpty(cache.gameStateViewBase64)) { return null; }
|
||||
if (cache == null) {
|
||||
LastLoadDiagnostic = $"cache JSON parsed to null at {path}";
|
||||
return null;
|
||||
}
|
||||
if (cache.schemaVersion != CurrentSchemaVersion) {
|
||||
LastLoadDiagnostic =
|
||||
$"schema mismatch at {path}: cache={cache.schemaVersion} current={CurrentSchemaVersion}";
|
||||
return null;
|
||||
}
|
||||
if (cache.gameId != gameId) {
|
||||
LastLoadDiagnostic =
|
||||
$"game id mismatch at {path}: cache={cache.gameId} requested={gameId}";
|
||||
return null;
|
||||
}
|
||||
if (cache.hasPlayerId != playerId.HasValue) {
|
||||
LastLoadDiagnostic =
|
||||
$"player presence mismatch at {path}: cacheHas={cache.hasPlayerId} requestedHas={playerId.HasValue}";
|
||||
return null;
|
||||
}
|
||||
if (cache.hasPlayerId && cache.playerId != playerId.Value) {
|
||||
LastLoadDiagnostic =
|
||||
$"player id mismatch at {path}: cache={cache.playerId} requested={playerId.Value}";
|
||||
return null;
|
||||
}
|
||||
if (cache.unfilteredResultCount <= 0) {
|
||||
LastLoadDiagnostic =
|
||||
$"invalid unfiltered count at {path}: {cache.unfilteredResultCount}";
|
||||
return null;
|
||||
}
|
||||
if (String.IsNullOrEmpty(cache.gameStateViewBase64)) {
|
||||
LastLoadDiagnostic = $"missing GameStateView payload at {path}";
|
||||
return null;
|
||||
}
|
||||
|
||||
var bytes = Convert.FromBase64String(cache.gameStateViewBase64);
|
||||
var gameStateView = GameStateView.Parser.ParseFrom(bytes);
|
||||
if (gameStateView.GameId != gameId) { return null; }
|
||||
if (gameStateView.GameId == 0) {
|
||||
gameStateView.GameId = gameId;
|
||||
} else if (gameStateView.GameId != gameId) {
|
||||
LastLoadDiagnostic =
|
||||
$"GameStateView game id mismatch at {path}: view={gameStateView.GameId} requested={gameId}";
|
||||
return null;
|
||||
}
|
||||
|
||||
LastLoadDiagnostic = $"loaded {path} count={cache.unfilteredResultCount}";
|
||||
|
||||
return new CachedGameState {
|
||||
GameStateView = gameStateView,
|
||||
UnfilteredResultCount = cache.unfilteredResultCount,
|
||||
ShardokGames = LoadShardokGames(cache.shardokGames)
|
||||
UnfilteredResultCount = cache.unfilteredResultCount
|
||||
};
|
||||
} catch (Exception e) {
|
||||
LastLoadDiagnostic = $"exception loading {path}: {e}";
|
||||
Debug.LogWarning($"Failed to load Eagle game state cache for game {gameId}: {e}");
|
||||
TryDelete(path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save(
|
||||
long gameId,
|
||||
int? playerId,
|
||||
int unfilteredResultCount,
|
||||
GameStateView gameStateView,
|
||||
IEnumerable<CachedShardokGameState> shardokGames) {
|
||||
public static void
|
||||
Save(long gameId, int? playerId, int unfilteredResultCount, GameStateView gameStateView) {
|
||||
if (unfilteredResultCount <= 0 || gameStateView == null) { return; }
|
||||
|
||||
EnsureCacheDirectoryInitialized();
|
||||
@@ -94,7 +112,6 @@ namespace eagle {
|
||||
playerId = playerId ?? 0,
|
||||
unfilteredResultCount = unfilteredResultCount,
|
||||
gameStateViewBase64 = Convert.ToBase64String(gameStateView.ToByteArray()),
|
||||
shardokGames = SaveShardokGames(shardokGames),
|
||||
savedAtUtc = DateTime.UtcNow.ToString("O")
|
||||
};
|
||||
|
||||
@@ -104,53 +121,6 @@ namespace eagle {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<CachedShardokGameState> LoadShardokGames(
|
||||
List<ShardokCacheEntry> cacheEntries) {
|
||||
var result = new List<CachedShardokGameState>();
|
||||
if (cacheEntries == null) { return result; }
|
||||
|
||||
foreach (var cacheEntry in cacheEntries) {
|
||||
if (String.IsNullOrEmpty(cacheEntry.shardokGameId) || cacheEntry.resultCount < 0 ||
|
||||
cacheEntry.actionResultViewsBase64 == null ||
|
||||
cacheEntry.resultCount != cacheEntry.actionResultViewsBase64.Count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var actionResultViews =
|
||||
cacheEntry.actionResultViewsBase64
|
||||
.Select(encoded => ShardokActionResultView.Parser.ParseFrom(
|
||||
Convert.FromBase64String(encoded)))
|
||||
.ToList();
|
||||
|
||||
result.Add(new CachedShardokGameState {
|
||||
ShardokGameId = cacheEntry.shardokGameId,
|
||||
ResultCount = cacheEntry.resultCount,
|
||||
ActionResultViews = actionResultViews
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<ShardokCacheEntry> SaveShardokGames(
|
||||
IEnumerable<CachedShardokGameState> shardokGames) {
|
||||
if (shardokGames == null) { return new List<ShardokCacheEntry>(); }
|
||||
|
||||
return shardokGames
|
||||
.Where(game => !String.IsNullOrEmpty(game.ShardokGameId) &&
|
||||
game.ActionResultViews != null &&
|
||||
game.ResultCount == game.ActionResultViews.Count)
|
||||
.Select(game => new ShardokCacheEntry {
|
||||
shardokGameId = game.ShardokGameId,
|
||||
resultCount = game.ResultCount,
|
||||
actionResultViewsBase64 =
|
||||
game.ActionResultViews
|
||||
.Select(view => Convert.ToBase64String(view.ToByteArray()))
|
||||
.ToList()
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static void EnsureCacheDirectoryInitialized() {
|
||||
if (_cacheDirectory != null) { return; }
|
||||
|
||||
|
||||
@@ -220,6 +220,16 @@ namespace eagle {
|
||||
void Start() {
|
||||
Enabled = true;
|
||||
_previouslyHoveredProvinceId = null;
|
||||
PlaceClickedProvincePanelAboveMap();
|
||||
}
|
||||
|
||||
private void PlaceClickedProvincePanelAboveMap() {
|
||||
var clickedProvincePanel = provinceNameText.transform.parent;
|
||||
clickedProvincePanel.SetAsLastSibling();
|
||||
|
||||
foreach (var graphic in clickedProvincePanel.GetComponentsInChildren<Graphic>()) {
|
||||
graphic.raycastTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
int? ProvinceFromPoint(Vector2 point) {
|
||||
@@ -260,7 +270,7 @@ namespace eagle {
|
||||
}
|
||||
_activeHighlights.Clear();
|
||||
|
||||
var maybeHoveredProvinceId = ProvinceFromPoint(Input.mousePosition);
|
||||
var maybeHoveredProvinceId = ProvinceFromPoint(GameInput.PointerPosition());
|
||||
if (Model != null && maybeHoveredProvinceId != _previouslyHoveredProvinceId) {
|
||||
_previouslyHoveredProvinceId = maybeHoveredProvinceId;
|
||||
hoveredProvinceChangedCallback.Invoke(maybeHoveredProvinceId);
|
||||
|
||||
@@ -68,12 +68,12 @@ namespace eagle {
|
||||
}
|
||||
|
||||
private void HandleTouchInput() {
|
||||
if (Input.touchCount == 2) {
|
||||
Touch touch0 = Input.GetTouch(0);
|
||||
Touch touch1 = Input.GetTouch(1);
|
||||
if (GameInput.TouchCount() == 2) {
|
||||
var touch0 = GameInput.GetTouch(0);
|
||||
var touch1 = GameInput.GetTouch(1);
|
||||
|
||||
float currentDistance = Vector2.Distance(touch0.position, touch1.position);
|
||||
Vector2 currentCenter = (touch0.position + touch1.position) / 2f;
|
||||
float currentDistance = Vector2.Distance(touch0.Position, touch1.Position);
|
||||
Vector2 currentCenter = (touch0.Position + touch1.Position) / 2f;
|
||||
|
||||
if (!_isPinching) {
|
||||
_isPinching = true;
|
||||
|
||||
+6
-1
@@ -285,10 +285,15 @@ namespace eagle {
|
||||
lock (_pendingSubscriptionAcks) { _pendingSubscriptionAcks[gameId] = ackTcs; }
|
||||
|
||||
var shardokCount = shardokStatuses.Count();
|
||||
var streamingTextStatuses = streamGameRequest.StreamingTextStatuses;
|
||||
var completeTextCount = streamingTextStatuses.Count(status => status.KnownComplete);
|
||||
var incompleteTextCount = streamingTextStatuses.Count - completeTextCount;
|
||||
LogFlow($"SUBSCRIBE game={gameId} unfilteredCount={subscriber.LastUnfilteredResultCount} shardokGames={shardokCount}");
|
||||
_remoteEagleClientLogger.LogLine(
|
||||
$"[SUBSCRIBE] Sending StreamGameRequest for game {gameId}, " +
|
||||
$"unfilteredCount={subscriber.LastUnfilteredResultCount}");
|
||||
$"unfilteredCount={subscriber.LastUnfilteredResultCount}, " +
|
||||
$"shardokGames={shardokCount}, completeTexts={completeTextCount}, " +
|
||||
$"incompleteTexts={incompleteTextCount}");
|
||||
|
||||
var sendSuccess = await DoWithStreamingCall(async (sc) => {
|
||||
await sc.RequestStream.WriteAsync(request);
|
||||
|
||||
+2
-2
@@ -380,11 +380,11 @@ namespace eagle {
|
||||
panel.SetActive(true);
|
||||
}
|
||||
|
||||
if (!WideScreen && Input.GetButtonUp("Toggle Dominion Table")) {
|
||||
if (!WideScreen && GameInput.ToggleDominionTableReleased()) {
|
||||
dominionViewToggle.isOn = !dominionViewToggle.isOn;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy() { factionTextUpdater?.Dispose(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -22,9 +22,9 @@ public class CtrPanel : MonoBehaviour {
|
||||
void Update() {
|
||||
if (panels.Count <= 0 || !isReady) return;
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
|
||||
if (GameInput.LeftArrowPressed()) {
|
||||
Click_Prev();
|
||||
} else if (Input.GetKeyDown(KeyCode.RightArrow)) {
|
||||
} else if (GameInput.RightArrowPressed()) {
|
||||
Click_Next();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class HoveringTooltip : MonoBehaviour {
|
||||
// ItemRect is in screen pixels. Position the tooltip to the right of the item.
|
||||
Vector2 screenPos;
|
||||
if (HugsCursor) {
|
||||
screenPos = (Vector2)Input.mousePosition + new Vector2(15, -10);
|
||||
screenPos = GameInput.PointerPosition() + new Vector2(15, -10);
|
||||
} else {
|
||||
screenPos = new Vector2(ItemRect.xMax + 10, ItemRect.center.y);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public class HoveringTooltip : MonoBehaviour {
|
||||
float screenWidth = rectTransform.rect.width * canvas.scaleFactor;
|
||||
if (screenPos.x + screenWidth > Screen.width) {
|
||||
if (HugsCursor) {
|
||||
screenPos.x = Input.mousePosition.x - screenWidth - 15;
|
||||
screenPos.x = GameInput.PointerPosition().x - screenWidth - 15;
|
||||
} else {
|
||||
screenPos.x = ItemRect.xMin - screenWidth - 10;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using UnityEngine.EventSystems;
|
||||
|
||||
public interface IClickReceiver {
|
||||
HexGrid HexGrid { get; }
|
||||
bool CanReceiveGridInput { get; }
|
||||
void HandleLongHover(int? gridIndex, Vector3 mousePosition);
|
||||
void HandleLongUIHover(IEnumerable<GameObject> hoveredObjects);
|
||||
void HandlePrimaryClick(int clickedIndex);
|
||||
@@ -49,26 +50,26 @@ public class MouseHandler : MonoBehaviour {
|
||||
}
|
||||
|
||||
void HandleTouchLongPress() {
|
||||
if (clickReceiver?.HexGrid?.IsSetUp != true) { return; }
|
||||
if (clickReceiver?.CanReceiveGridInput != true) { return; }
|
||||
|
||||
// Handle touch input for long-press detection
|
||||
if (Input.touchCount > 0) {
|
||||
Touch touch = Input.GetTouch(0);
|
||||
if (GameInput.TouchCount() > 0) {
|
||||
var touch = GameInput.GetTouch(0);
|
||||
|
||||
if (touch.phase == TouchPhase.Began) {
|
||||
if (touch.Phase == TouchPhase.Began) {
|
||||
// Touch started - begin tracking
|
||||
var touchDownGridIndex = currentGridIndex(touch.position);
|
||||
var touchDownGridIndex = currentGridIndex(touch.Position);
|
||||
if (touchDownGridIndex.HasValue ||
|
||||
!IsPointerOverBlockingUI(touch.fingerId, touch.position)) {
|
||||
!IsPointerOverBlockingUI(touch.FingerId, touch.Position)) {
|
||||
_touchDownTime = Time.time;
|
||||
_touchDownPosition = touch.position;
|
||||
_touchDownPosition = touch.Position;
|
||||
_touchDownGridIndex = touchDownGridIndex;
|
||||
_longPressTriggered = false;
|
||||
}
|
||||
} else if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary) {
|
||||
} else if (touch.Phase == TouchPhase.Moved || touch.Phase == TouchPhase.Stationary) {
|
||||
// Touch ongoing - check for long-press
|
||||
if (_touchDownTime.HasValue && !_longPressTriggered) {
|
||||
var moved = Vector2.Distance(touch.position, _touchDownPosition);
|
||||
var moved = Vector2.Distance(touch.Position, _touchDownPosition);
|
||||
if (moved > MovementTolerancePixels) {
|
||||
// Finger moved too much, cancel long-press
|
||||
_touchDownTime = null;
|
||||
@@ -80,11 +81,14 @@ public class MouseHandler : MonoBehaviour {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled) {
|
||||
} else if (touch.Phase == TouchPhase.Ended || touch.Phase == TouchPhase.Canceled) {
|
||||
// Touch ended
|
||||
_touchDownTime = null;
|
||||
_touchDownGridIndex = null;
|
||||
}
|
||||
} else {
|
||||
_touchDownTime = null;
|
||||
_touchDownGridIndex = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +102,9 @@ public class MouseHandler : MonoBehaviour {
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<RaycastResult> RaycastMouse() { return RaycastPointer(Input.mousePosition, -1); }
|
||||
private List<RaycastResult> RaycastMouse() {
|
||||
return RaycastPointer(GameInput.PointerPosition(), -1);
|
||||
}
|
||||
|
||||
private bool IsPointerOverBlockingUI(int pointerId, Vector2 position) {
|
||||
if (EventSystem.current == null || clickReceiver?.HexGrid == null) { return false; }
|
||||
@@ -110,12 +116,12 @@ public class MouseHandler : MonoBehaviour {
|
||||
}
|
||||
|
||||
void HandleMouse() {
|
||||
if (clickReceiver?.HexGrid?.IsSetUp != true) { return; }
|
||||
if (clickReceiver?.CanReceiveGridInput != true) { return; }
|
||||
|
||||
int? possibleGridIndex = currentGridIndex();
|
||||
bool pointerOverBlockingUI = IsPointerOverBlockingUI(-1, Input.mousePosition);
|
||||
bool pointerOverBlockingUI = IsPointerOverBlockingUI(-1, GameInput.PointerPosition());
|
||||
|
||||
Vector3 currentPosition = Input.mousePosition;
|
||||
Vector3 currentPosition = GameInput.PointerPosition();
|
||||
if (currentPosition == hoverPosition) {
|
||||
if (Time.time - hoverStartSeconds > HOVER_THRESHOLD_SECONDS) {
|
||||
isInLongHover = true;
|
||||
@@ -157,9 +163,9 @@ public class MouseHandler : MonoBehaviour {
|
||||
clickReceiver.HandleStopHover(lhIndex);
|
||||
lastHoveredIndex = null;
|
||||
}
|
||||
if (Input.GetMouseButton(0)) {
|
||||
if (GameInput.PrimaryPointerPressed()) {
|
||||
handleLeftMouseDown(currentMouseGridIndex);
|
||||
} else if (Input.GetMouseButton(1)) {
|
||||
} else if (GameInput.SecondaryPointerPressed()) {
|
||||
handleRightMouseDown(currentMouseGridIndex);
|
||||
} else {
|
||||
if (leftButtonDownIndex.HasValue) {
|
||||
@@ -203,7 +209,7 @@ public class MouseHandler : MonoBehaviour {
|
||||
}
|
||||
}
|
||||
|
||||
int? currentGridIndex() { return currentGridIndex(Input.mousePosition); }
|
||||
int? currentGridIndex() { return currentGridIndex(GameInput.PointerPosition()); }
|
||||
|
||||
int? currentGridIndex(Vector2 screenPosition) {
|
||||
return clickReceiver.HexGrid.GridIndexForScreenPoint(screenPosition);
|
||||
|
||||
@@ -56483,7 +56483,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.392}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.5686275}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
|
||||
@@ -12110,17 +12110,39 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 1004000001}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_SendPointerHoverToParent: 1
|
||||
m_HorizontalAxis: Horizontal
|
||||
m_VerticalAxis: Vertical
|
||||
m_SubmitButton: Submit
|
||||
m_CancelButton: Cancel
|
||||
m_InputActionsPerSecond: 10
|
||||
m_RepeatDelay: 0.5
|
||||
m_ForceModuleActive: 0
|
||||
m_MoveRepeatDelay: 0.5
|
||||
m_MoveRepeatRate: 0.1
|
||||
m_XRTrackingOrigin: {fileID: 0}
|
||||
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_PointAction: {fileID: 1054132383583890850, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_MoveAction: {fileID: 3710738434707379630, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_SubmitAction: {fileID: 2064916234097673511, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_CancelAction: {fileID: -1967631576421560919, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_LeftClickAction: {fileID: 8056856818456041789, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_MiddleClickAction: {fileID: 3279352641294131588, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_RightClickAction: {fileID: 3837173908680883260, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_ScrollWheelAction: {fileID: 4502412055082496612, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_TrackedDevicePositionAction: {fileID: 4754684134866288074, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_TrackedDeviceOrientationAction: {fileID: 1025543830046995696, guid: ca9f5fa95ffab41fb9a615ab714db018,
|
||||
type: 3}
|
||||
m_DeselectOnBackgroundClick: 1
|
||||
m_PointerBehavior: 0
|
||||
m_CursorLockBehavior: 0
|
||||
m_ScrollDeltaPerTick: 6
|
||||
--- !u!81 &1004000005
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ public class SettingsKeyListener : MonoBehaviour {
|
||||
void Start() { settingsPanelController.ApplyPersistedSettings(); }
|
||||
|
||||
void Update() {
|
||||
if (Input.GetButtonUp("Cancel")) { settingsPanelController.HandleEscape(); }
|
||||
if (GameInput.CancelReleased()) { settingsPanelController.HandleEscape(); }
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.F11)) { settingsPanelController.HandleF11(); }
|
||||
if (GameInput.F11Pressed()) { settingsPanelController.HandleF11(); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,9 +100,13 @@ public class HexGrid : MonoBehaviour {
|
||||
private const int HexOverlaySortingOrder = 101;
|
||||
private const int TerrainModifierEffectSortingOrder = 101;
|
||||
private const int ForegroundCanvasSortingOrder = 102;
|
||||
private const string ForegroundGraphicShaderName = "Shardok/Foreground UI Overlay";
|
||||
private const string ForegroundTextShaderName = "TextMeshPro/Distance Field Overlay";
|
||||
|
||||
HexMetrics metrics;
|
||||
Cell[] cells;
|
||||
private Material _foregroundGraphicMaterial;
|
||||
private Material _foregroundTextMaterial;
|
||||
|
||||
// Track mapArea size for resolution change detection
|
||||
private Vector2 _lastMapAreaSize;
|
||||
@@ -157,6 +161,47 @@ public class HexGrid : MonoBehaviour {
|
||||
|
||||
private static void IgnoreRaycasts(Graphic graphic) { graphic.raycastTarget = false; }
|
||||
|
||||
private Material ForegroundGraphicMaterial() {
|
||||
if (_foregroundGraphicMaterial != null) { return _foregroundGraphicMaterial; }
|
||||
|
||||
Shader shader = Shader.Find(ForegroundGraphicShaderName);
|
||||
if (shader == null) {
|
||||
throw new InvalidOperationException(
|
||||
message: $"Could not find required shader {ForegroundGraphicShaderName}");
|
||||
}
|
||||
|
||||
_foregroundGraphicMaterial = new Material(shader) {
|
||||
name = "Shardok Foreground UI Overlay",
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
};
|
||||
return _foregroundGraphicMaterial;
|
||||
}
|
||||
|
||||
private Material ForegroundTextMaterial() {
|
||||
if (_foregroundTextMaterial != null) { return _foregroundTextMaterial; }
|
||||
|
||||
Shader shader = Shader.Find(ForegroundTextShaderName);
|
||||
if (shader == null) {
|
||||
throw new InvalidOperationException(
|
||||
message: $"Could not find required shader {ForegroundTextShaderName}");
|
||||
}
|
||||
|
||||
_foregroundTextMaterial = new Material(mainFont.material) {
|
||||
shader = shader,
|
||||
name = "Shardok Foreground TMP Overlay",
|
||||
hideFlags = HideFlags.HideAndDontSave,
|
||||
};
|
||||
return _foregroundTextMaterial;
|
||||
}
|
||||
|
||||
private void UseForegroundMaterial(Graphic graphic) {
|
||||
graphic.material = ForegroundGraphicMaterial();
|
||||
}
|
||||
|
||||
private void UseForegroundTextMaterial(TMP_Text label) {
|
||||
label.fontSharedMaterial = ForegroundTextMaterial();
|
||||
}
|
||||
|
||||
private static void SetMeshRendererSorting(HexMesh mesh, int sortingOrder) {
|
||||
var meshRenderer = mesh.GetComponent<MeshRenderer>();
|
||||
meshRenderer.sortingLayerName = HexMeshSortingLayer;
|
||||
@@ -551,6 +596,7 @@ public class HexGrid : MonoBehaviour {
|
||||
worldPositionStays: false);
|
||||
newImage.gameObject.name = $"SecondaryImage{coordSuffix}_{imageIndex}";
|
||||
IgnoreRaycasts(newImage);
|
||||
UseForegroundMaterial(newImage);
|
||||
newImage.rectTransform.anchoredPosition = new Vector2(
|
||||
x: position.x + column * singleWidth * 0.5f,
|
||||
y: position.z + 1 - row * singleHeight);
|
||||
@@ -597,6 +643,7 @@ public class HexGrid : MonoBehaviour {
|
||||
worldPositionStays: false);
|
||||
backing.gameObject.name = $"UnitTypeBacking{coordSuffix}";
|
||||
IgnoreRaycasts(backing);
|
||||
UseForegroundMaterial(backing);
|
||||
backing.texture = GetOrCreateSoftCircleTexture();
|
||||
backing.color = imageBackingColor;
|
||||
backing.rectTransform.anchoredPosition = anchoredPos;
|
||||
@@ -610,6 +657,7 @@ public class HexGrid : MonoBehaviour {
|
||||
worldPositionStays: false);
|
||||
newImage.gameObject.name = $"UnitType{coordSuffix}";
|
||||
IgnoreRaycasts(newImage);
|
||||
UseForegroundMaterial(newImage);
|
||||
newImage.rectTransform.anchoredPosition = anchoredPos;
|
||||
newImage.rectTransform.sizeDelta = new Vector2(x: size, y: size);
|
||||
newImage.gameObject.SetActive(value: false);
|
||||
@@ -631,6 +679,7 @@ public class HexGrid : MonoBehaviour {
|
||||
worldPositionStays: false);
|
||||
backing.gameObject.name = $"ProfessionBacking{coordSuffix}";
|
||||
IgnoreRaycasts(backing);
|
||||
UseForegroundMaterial(backing);
|
||||
backing.texture = GetOrCreateSoftCircleTexture();
|
||||
backing.color = imageBackingColor;
|
||||
backing.rectTransform.anchoredPosition = anchoredPos;
|
||||
@@ -644,6 +693,7 @@ public class HexGrid : MonoBehaviour {
|
||||
worldPositionStays: false);
|
||||
newImage.gameObject.name = $"Profession{coordSuffix}";
|
||||
IgnoreRaycasts(newImage);
|
||||
UseForegroundMaterial(newImage);
|
||||
newImage.rectTransform.anchoredPosition = anchoredPos;
|
||||
newImage.rectTransform.sizeDelta = new Vector2(x: size, y: size);
|
||||
newImage.gameObject.SetActive(value: false);
|
||||
@@ -664,6 +714,7 @@ public class HexGrid : MonoBehaviour {
|
||||
worldPositionStays: false);
|
||||
backing.gameObject.name = backingName;
|
||||
IgnoreRaycasts(backing);
|
||||
UseForegroundMaterial(backing);
|
||||
backing.texture = GetOrCreateSoftCircleTexture();
|
||||
backing.color = labelBackingColor;
|
||||
backing.rectTransform.anchoredPosition = anchoredPos;
|
||||
@@ -688,6 +739,7 @@ public class HexGrid : MonoBehaviour {
|
||||
label.rectTransform.anchoredPosition = anchoredPos;
|
||||
label.rectTransform.sizeDelta = labelSize;
|
||||
label.font = mainFont;
|
||||
UseForegroundTextMaterial(label);
|
||||
label.fontSizeMin = 10;
|
||||
label.fontSize = 300;
|
||||
label.fontSizeMax = 300;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3527cb6d31f54c3faf9b729605a92664
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
Shader "Shardok/Foreground UI Overlay" {
|
||||
Properties {
|
||||
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||||
_Color ("Tint", Color) = (1,1,1,1)
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||
_ColorMask ("Color Mask", Float) = 15
|
||||
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags {
|
||||
"Queue" = "Overlay"
|
||||
"IgnoreProjector" = "True"
|
||||
"RenderType" = "Transparent"
|
||||
"PreviewType" = "Plane"
|
||||
"CanUseSpriteAtlas" = "True"
|
||||
}
|
||||
|
||||
Stencil {
|
||||
Ref [_Stencil]
|
||||
Comp [_StencilComp]
|
||||
Pass [_StencilOp]
|
||||
ReadMask [_StencilReadMask]
|
||||
WriteMask [_StencilWriteMask]
|
||||
}
|
||||
|
||||
Cull Off
|
||||
Lighting Off
|
||||
ZWrite Off
|
||||
ZTest Always
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
ColorMask [_ColorMask]
|
||||
|
||||
Pass {
|
||||
Name "Default"
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma target 2.0
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityUI.cginc"
|
||||
|
||||
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
|
||||
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
|
||||
|
||||
struct appdata_t {
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f {
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
fixed4 _Color;
|
||||
fixed4 _TextureSampleAdd;
|
||||
float4 _ClipRect;
|
||||
float4 _MainTex_ST;
|
||||
|
||||
v2f vert(appdata_t v) {
|
||||
v2f OUT;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
|
||||
OUT.worldPosition = v.vertex;
|
||||
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
||||
OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
OUT.color = v.color * _Color;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
fixed4 frag(v2f IN) : SV_Target {
|
||||
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
|
||||
|
||||
#ifdef UNITY_UI_CLIP_RECT
|
||||
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_UI_ALPHACLIP
|
||||
clip(color.a - 0.001);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccd58ed8b9624c54a8bbd9554a4a8777
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+15
-43
@@ -90,6 +90,7 @@ namespace Shardok {
|
||||
public class ShardokGameController : MonoBehaviour, IClickReceiver {
|
||||
public HexGrid hexGrid;
|
||||
public HexGrid HexGrid => hexGrid;
|
||||
public bool CanReceiveGridInput => hexGrid.IsSetUp && Model?.Map != null;
|
||||
public Camera mainCamera;
|
||||
public UnitInfoPanelController unitInfoPanel;
|
||||
public EventBasedTable armiesTable;
|
||||
@@ -1061,12 +1062,15 @@ namespace Shardok {
|
||||
}
|
||||
|
||||
private bool IsPrimaryOrSecondaryPressActive() {
|
||||
if (Input.GetMouseButton(0) || Input.GetMouseButton(1)) { return true; }
|
||||
if (GameInput.PrimaryPointerPressed() || GameInput.SecondaryPointerPressed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Input.touchCount == 0) { return false; }
|
||||
int touchCount = GameInput.TouchCount();
|
||||
if (touchCount == 0) { return false; }
|
||||
|
||||
for (int i = 0; i < Input.touchCount; i++) {
|
||||
var phase = Input.GetTouch(i).phase;
|
||||
for (int i = 0; i < touchCount; i++) {
|
||||
var phase = GameInput.GetTouch(i).Phase;
|
||||
if (phase != TouchPhase.Ended && phase != TouchPhase.Canceled) { return true; }
|
||||
}
|
||||
|
||||
@@ -1472,54 +1476,22 @@ namespace Shardok {
|
||||
}
|
||||
|
||||
void HandleButton() {
|
||||
/* else if (Input.GetButtonUp("Lightning")) {
|
||||
LightningButtonClicked();
|
||||
}
|
||||
else if (Input.GetButtonUp("Meteor")) {
|
||||
StartMeteorButtonClicked();
|
||||
}
|
||||
else if (Input.GetButtonUp("Move")) {
|
||||
SetDisplayActionsUIState(DisplayActionsUIState.standardState);
|
||||
|
||||
handleOverlaysForSelection();
|
||||
}
|
||||
else if (Input.GetButtonUp("Extinguish")) {
|
||||
ExtinguishButtonClicked();
|
||||
}
|
||||
else if (Input.GetButtonUp("StartFire")) {
|
||||
StartFireButtonClicked();
|
||||
}*/
|
||||
|
||||
// if (Input.GetButton("Horizontal"))
|
||||
//{
|
||||
// float horizontalValue = Input.GetAxis("Horizontal");
|
||||
// Vector3 v = mainCamera.transform.position;
|
||||
// v.x -= horizontalValue;
|
||||
// mainCamera.transform.position = v;
|
||||
// }
|
||||
// if (Input.GetButton("Vertical"))
|
||||
//{
|
||||
// float verticalValue = Input.GetAxis("Vertical");
|
||||
// Vector3 v = mainCamera.transform.position;
|
||||
// v.z -= verticalValue;
|
||||
// mainCamera.transform.position = v;
|
||||
// }
|
||||
if (Input.GetButton("Zoom")) {
|
||||
float zoomValue = Input.GetAxis("Zoom");
|
||||
float zoomValue = GameInput.ShardokZoomAxis();
|
||||
if (!Mathf.Approximately(a: zoomValue, b: 0f)) {
|
||||
var transform1 = mainCamera.transform;
|
||||
Vector3 v = transform1.position;
|
||||
v.y += zoomValue;
|
||||
transform1.position = v;
|
||||
}
|
||||
if (Input.GetButtonDown("Hex Coords")) { SetCoordsLabels(); }
|
||||
if (Input.GetButtonUp("Hex Coords")) { SetHeroLabels(); }
|
||||
if (GameInput.HexCoordsPressed()) { SetCoordsLabels(); }
|
||||
if (GameInput.HexCoordsReleased()) { SetHeroLabels(); }
|
||||
|
||||
if (Input.GetButtonDown("Profession Attack")) {
|
||||
if (GameInput.ProfessionAttackPressed()) {
|
||||
var prev = _displayedCommandGroup;
|
||||
SetDisplayedCommandGroup(CommandTypeUIManager.ProfessionAttackGroup);
|
||||
_previouslyDisplayedCommandGroup = prev;
|
||||
}
|
||||
if (Input.GetButtonUp("Profession Attack")) {
|
||||
if (GameInput.ProfessionAttackReleased()) {
|
||||
SetDisplayedCommandGroup(_previouslyDisplayedCommandGroup ?? 0);
|
||||
}
|
||||
}
|
||||
@@ -1835,7 +1807,7 @@ namespace Shardok {
|
||||
|
||||
// Position tooltip to the right of the cursor (pivot is centered,
|
||||
// tooltip is 130 units wide, so offset by ~half-width + padding)
|
||||
var cursorScreenPos = (Vector2)Input.mousePosition + new Vector2(160, -15);
|
||||
var cursorScreenPos = GameInput.PointerPosition() + new Vector2(160, -15);
|
||||
RectTransformUtility.ScreenPointToWorldPointInRectangle(
|
||||
_canvasRect,
|
||||
cursorScreenPos,
|
||||
|
||||
@@ -11,20 +11,20 @@ public class TouchHandler : MonoBehaviour {
|
||||
const float LONG_TOUCH_SECONDS = 2.0f;
|
||||
|
||||
// Use this for initialization
|
||||
void Start() { Input.simulateMouseWithTouches = false; }
|
||||
void Start() { GameInput.DisableMouseSimulationWithTouches(); }
|
||||
|
||||
// Update is called once per frame
|
||||
void Update() {
|
||||
if (gameController.hexGrid == null) { return; }
|
||||
|
||||
int numFingersDown = Input.touchCount;
|
||||
int numFingersDown = GameInput.TouchCount();
|
||||
|
||||
if (numFingersDown > 0) {
|
||||
Touch firstFingerTouch = Input.GetTouch(0);
|
||||
var firstFingerTouch = GameInput.GetTouch(0);
|
||||
|
||||
if (EventSystem.current.IsPointerOverGameObject(firstFingerTouch.fingerId)) { return; }
|
||||
if (EventSystem.current.IsPointerOverGameObject(firstFingerTouch.FingerId)) { return; }
|
||||
|
||||
Ray firstFingerInputRay = Camera.main.ScreenPointToRay(firstFingerTouch.position);
|
||||
Ray firstFingerInputRay = Camera.main.ScreenPointToRay(firstFingerTouch.Position);
|
||||
RaycastHit firstFingerHit;
|
||||
if (Physics.Raycast(firstFingerInputRay, out firstFingerHit)) {
|
||||
int? firstFingerGridIndex =
|
||||
|
||||
+1
-2
@@ -204,8 +204,7 @@ namespace common {
|
||||
}
|
||||
|
||||
// Hold Shift to pause scrolling (lets user read at their own pace)
|
||||
bool isPausedByUser =
|
||||
Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
|
||||
bool isPausedByUser = GameInput.ShiftPressed();
|
||||
if (isPausedByUser) return;
|
||||
|
||||
// Handle pause at bottom
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ namespace common.GUIUtils {
|
||||
|
||||
void Update() {
|
||||
// Escape key closes the panel
|
||||
if (panel.activeSelf && Input.GetButtonUp("Cancel")) { Hide(); }
|
||||
if (panel.activeSelf && GameInput.CancelReleased()) { Hide(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public class GeneralClickDetector : MonoBehaviour,
|
||||
public void Update() {
|
||||
if (_pointerDownTime is {} downTime && !_longPressTriggered) {
|
||||
var elapsed = Time.time - downTime;
|
||||
var moved = Vector2.Distance(Input.mousePosition, _pointerDownPosition);
|
||||
var moved = Vector2.Distance(GameInput.PointerPosition(), _pointerDownPosition);
|
||||
|
||||
if (moved > MovementTolerancePixels) {
|
||||
// Finger moved too much, cancel long-press detection
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public class TableRowClickDetector : MonoBehaviour,
|
||||
public void Update() {
|
||||
if (_pointerDownTime is {} downTime && !_longPressTriggered) {
|
||||
var elapsed = Time.time - downTime;
|
||||
var moved = Vector2.Distance(Input.mousePosition, _pointerDownPosition);
|
||||
var moved = Vector2.Distance(GameInput.PointerPosition(), _pointerDownPosition);
|
||||
|
||||
if (moved > MovementTolerancePixels) {
|
||||
// Finger moved too much, cancel long-press detection
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
public static class GameInput {
|
||||
public struct GameTouch {
|
||||
public int FingerId;
|
||||
public Vector2 Position;
|
||||
public UnityEngine.TouchPhase Phase;
|
||||
|
||||
public GameTouch(int fingerId, Vector2 position, UnityEngine.TouchPhase phase) {
|
||||
FingerId = fingerId;
|
||||
Position = position;
|
||||
Phase = phase;
|
||||
}
|
||||
}
|
||||
|
||||
private const float MouseScrollUnit = 120f;
|
||||
|
||||
public static Vector2 PointerPosition() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.mousePosition;
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null) { return Mouse.current.position.ReadValue(); }
|
||||
if (Touchscreen.current != null && Touchscreen.current.primaryTouch.press.isPressed) {
|
||||
return Touchscreen.current.primaryTouch.position.ReadValue();
|
||||
}
|
||||
#endif
|
||||
|
||||
return Vector2.zero;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool PrimaryPointerPressed() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButton(0);
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.leftButton.isPressed) { return true; }
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool PrimaryPointerPressedThisFrame() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButtonDown(0);
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame) { return true; }
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool SecondaryPointerPressed() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButton(1);
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.rightButton.isPressed) { return true; }
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool SecondaryPointerPressedThisFrame() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButtonDown(1);
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.rightButton.wasPressedThisFrame) { return true; }
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool MiddlePointerPressed() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButton(2);
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.middleButton.isPressed) { return true; }
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool MiddlePointerPressedThisFrame() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetMouseButtonDown(2);
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.middleButton.wasPressedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool CancelReleased() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.escapeKey.wasReleasedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
if (Gamepad.current != null && Gamepad.current.buttonEast.wasReleasedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetButtonUp("Cancel");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool F11Pressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.f11Key.wasPressedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKeyDown(KeyCode.F11);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool LeftArrowPressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.leftArrowKey.wasPressedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKeyDown(KeyCode.LeftArrow);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool RightArrowPressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.rightArrowKey.wasPressedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKeyDown(KeyCode.RightArrow);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool ToggleDominionTableReleased() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.tKey.wasReleasedThisFrame) { return true; }
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetButtonUp("Toggle Dominion Table");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool WindowedModeReleased() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.wKey.wasReleasedThisFrame) { return true; }
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetButtonUp("Windowed Mode");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool ShiftPressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null &&
|
||||
(Keyboard.current.leftShiftKey.isPressed || Keyboard.current.rightShiftKey.isPressed)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool ControlPressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null &&
|
||||
(Keyboard.current.leftCtrlKey.isPressed || Keyboard.current.rightCtrlKey.isPressed)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool QuestionMarkPressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.slashKey.wasPressedThisFrame &&
|
||||
ShiftPressed()) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetKeyDown(KeyCode.Slash) && ShiftPressed();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static float ShardokZoomAxis() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
float zoom = 0f;
|
||||
if (Keyboard.current != null) {
|
||||
if (Keyboard.current.sKey.isPressed) { zoom += 1f; }
|
||||
if (Keyboard.current.wKey.isPressed) { zoom -= 1f; }
|
||||
}
|
||||
if (Mouse.current != null) {
|
||||
float scrollY = Mouse.current.scroll.ReadValue().y;
|
||||
if (!Mathf.Approximately(a: scrollY, b: 0f)) {
|
||||
zoom += Mathf.Clamp(value: scrollY / MouseScrollUnit, min: -1f, max: 1f);
|
||||
}
|
||||
}
|
||||
if (!Mathf.Approximately(a: zoom, b: 0f)) { return zoom; }
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetAxis("Zoom");
|
||||
#else
|
||||
return 0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool HexCoordsPressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.cKey.wasPressedThisFrame) { return true; }
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetButtonDown("Hex Coords");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool HexCoordsReleased() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && Keyboard.current.cKey.wasReleasedThisFrame) { return true; }
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetButtonUp("Hex Coords");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool ProfessionAttackPressed() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && (Keyboard.current.leftCtrlKey.wasPressedThisFrame ||
|
||||
Keyboard.current.rightCtrlKey.wasPressedThisFrame)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetButtonDown("Profession Attack");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool ProfessionAttackReleased() {
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null && (Keyboard.current.leftCtrlKey.wasReleasedThisFrame ||
|
||||
Keyboard.current.rightCtrlKey.wasReleasedThisFrame)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.GetButtonUp("Profession Attack");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void DisableMouseSimulationWithTouches() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
Input.simulateMouseWithTouches = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static int TouchCount() {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.touchCount;
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Touchscreen.current == null) { return 0; }
|
||||
|
||||
int count = 0;
|
||||
foreach (var touch in Touchscreen.current.touches) {
|
||||
if (IsTrackedTouchPhase(touch.phase.ReadValue())) { count++; }
|
||||
}
|
||||
return count;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
public static GameTouch GetTouch(int index) {
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
UnityEngine.Touch touch = Input.GetTouch(index);
|
||||
return new GameTouch(
|
||||
fingerId: touch.fingerId,
|
||||
position: touch.position,
|
||||
phase: touch.phase);
|
||||
#else
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Touchscreen.current != null) {
|
||||
int currentIndex = 0;
|
||||
foreach (var touch in Touchscreen.current.touches) {
|
||||
var phase = touch.phase.ReadValue();
|
||||
if (!IsTrackedTouchPhase(phase)) { continue; }
|
||||
|
||||
if (currentIndex == index) {
|
||||
return new GameTouch(
|
||||
fingerId: touch.touchId.ReadValue(),
|
||||
position: touch.position.ReadValue(),
|
||||
phase: ToUnityTouchPhase(phase));
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
throw new ArgumentOutOfRangeException(
|
||||
paramName: nameof(index),
|
||||
message: $"No touch exists at index {index}");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
private static bool IsTrackedTouchPhase(UnityEngine.InputSystem.TouchPhase phase) {
|
||||
return phase != UnityEngine.InputSystem.TouchPhase.None;
|
||||
}
|
||||
|
||||
private static UnityEngine.TouchPhase ToUnityTouchPhase(
|
||||
UnityEngine.InputSystem.TouchPhase phase) {
|
||||
switch (phase) {
|
||||
case UnityEngine.InputSystem.TouchPhase.Began: return UnityEngine.TouchPhase.Began;
|
||||
case UnityEngine.InputSystem.TouchPhase.Moved: return UnityEngine.TouchPhase.Moved;
|
||||
case UnityEngine.InputSystem.TouchPhase.Ended: return UnityEngine.TouchPhase.Ended;
|
||||
case UnityEngine.InputSystem.TouchPhase.Canceled:
|
||||
return UnityEngine.TouchPhase.Canceled;
|
||||
case UnityEngine.InputSystem.TouchPhase.Stationary:
|
||||
return UnityEngine.TouchPhase.Stationary;
|
||||
case UnityEngine.InputSystem.TouchPhase.None:
|
||||
default: return UnityEngine.TouchPhase.Canceled;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e81647e810048ac940fe0c95a1f3321
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public static class UIInputSystemModuleDefaultActions {
|
||||
private static int configurationLogCount;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
||||
private static void Initialize() {
|
||||
ConfigureEditorInputBehavior();
|
||||
InputSystem.onDeviceChange -= LogDeviceChange;
|
||||
InputSystem.onDeviceChange += LogDeviceChange;
|
||||
SceneManager.sceneLoaded -= AssignDefaultActionsToLoadedModules;
|
||||
SceneManager.sceneLoaded += AssignDefaultActionsToLoadedModules;
|
||||
AssignDefaultActionsToLoadedModules();
|
||||
EnsureDiagnosticsRunner();
|
||||
}
|
||||
|
||||
private static void ConfigureEditorInputBehavior() {
|
||||
#if UNITY_EDITOR
|
||||
InputSystem.settings.editorInputBehaviorInPlayMode =
|
||||
InputSettings.EditorInputBehaviorInPlayMode.AllDeviceInputAlwaysGoesToGameView;
|
||||
InputSystem.settings.backgroundBehavior = InputSettings.BackgroundBehavior.IgnoreFocus;
|
||||
if (InputSystem.devices.Count == 0) {
|
||||
InputSystem.AddDevice<Mouse>();
|
||||
InputSystem.AddDevice<Keyboard>();
|
||||
Debug.Log("[UIInputSystem] Added editor fallback Mouse and Keyboard devices.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void LogDeviceChange(InputDevice device, InputDeviceChange change) {
|
||||
Debug.Log(
|
||||
"[UIInputSystem] Device change. " + $"change={change}, " +
|
||||
$"device={device.displayName}, " + $"devices={DescribeDevices()}");
|
||||
}
|
||||
|
||||
private static void AssignDefaultActionsToLoadedModules(Scene scene, LoadSceneMode mode) {
|
||||
AssignDefaultActionsToLoadedModules();
|
||||
}
|
||||
|
||||
private static void AssignDefaultActionsToLoadedModules() {
|
||||
var modules = Object.FindObjectsByType<InputSystemUIInputModule>(FindObjectsSortMode.None);
|
||||
foreach (InputSystemUIInputModule module in modules) {
|
||||
if (!HasRequiredActions(module)) {
|
||||
module.AssignDefaultActions();
|
||||
module.enabled = false;
|
||||
module.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (EventSystem.current != null && EventSystem.current.currentInputModule == null) {
|
||||
EventSystem.current.UpdateModules();
|
||||
}
|
||||
|
||||
if (configurationLogCount < 8) {
|
||||
configurationLogCount++;
|
||||
Debug.Log(
|
||||
"[UIInputSystem] Configured UI input modules. " +
|
||||
$"moduleCount={modules.Length}, " +
|
||||
$"eventSystem={(EventSystem.current == null ? "<none>" : EventSystem.current.name)}, " +
|
||||
$"currentModule={DescribeCurrentModule()}, " +
|
||||
$"devices={DescribeDevices()}, " +
|
||||
$"moduleActions={string.Join(" | ", modules.Select(DescribeModuleActions))}");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasRequiredActions(InputSystemUIInputModule module) {
|
||||
return module.point?.action != null && module.leftClick?.action != null &&
|
||||
module.submit?.action != null && module.cancel?.action != null;
|
||||
}
|
||||
|
||||
private static void EnsureDiagnosticsRunner() {
|
||||
if (Object.FindFirstObjectByType<UIInputSystemDiagnostics>() != null) { return; }
|
||||
|
||||
var gameObject = new GameObject("UI Input System Diagnostics");
|
||||
Object.DontDestroyOnLoad(gameObject);
|
||||
gameObject.AddComponent<UIInputSystemDiagnostics>();
|
||||
}
|
||||
|
||||
private static string DescribeCurrentModule() {
|
||||
if (EventSystem.current?.currentInputModule == null) { return "<none>"; }
|
||||
|
||||
var module = EventSystem.current.currentInputModule;
|
||||
return $"{module.GetType().Name}({module.name}, active={module.isActiveAndEnabled})";
|
||||
}
|
||||
|
||||
private static string DescribeDevices() {
|
||||
return $"mouse={(Mouse.current == null ? "<none>" : Mouse.current.displayName)}, " +
|
||||
$"touchscreen={(Touchscreen.current == null ? "<none>" : Touchscreen.current.displayName)}, " +
|
||||
$"keyboard={(Keyboard.current == null ? "<none>" : Keyboard.current.displayName)}, " +
|
||||
$"deviceCount={InputSystem.devices.Count}, " +
|
||||
$"allDevices={string.Join(", ", InputSystem.devices.Select(device => device.displayName))}";
|
||||
}
|
||||
|
||||
private static string DescribeModuleActions(InputSystemUIInputModule module) {
|
||||
return $"{module.name}: " + $"active={module.isActiveAndEnabled}, " +
|
||||
$"point={DescribeAction(module.point)}, " +
|
||||
$"leftClick={DescribeAction(module.leftClick)}, " +
|
||||
$"submit={DescribeAction(module.submit)}, " +
|
||||
$"cancel={DescribeAction(module.cancel)}";
|
||||
}
|
||||
|
||||
private static string DescribeAction(UnityEngine.InputSystem.InputActionReference reference) {
|
||||
if (reference?.action == null) { return "<null>"; }
|
||||
|
||||
return $"{reference.action.name}(enabled={reference.action.enabled}, " +
|
||||
$"phase={reference.action.phase})";
|
||||
}
|
||||
|
||||
private class UIInputSystemDiagnostics : MonoBehaviour {
|
||||
private void Update() {
|
||||
if (!PointerPressedThisFrame()) { return; }
|
||||
|
||||
Vector2 pointerPosition = PointerPosition();
|
||||
var raycastResults = RaycastPointer(pointerPosition);
|
||||
var modules =
|
||||
Object.FindObjectsByType<InputSystemUIInputModule>(FindObjectsSortMode.None);
|
||||
string topHit =
|
||||
raycastResults.Count == 0
|
||||
? "<none>"
|
||||
: $"{raycastResults[0].gameObject.name} " +
|
||||
$"(module={raycastResults[0].module?.GetType().Name})";
|
||||
|
||||
Debug.Log(
|
||||
"[UIInputSystem] Pointer click diagnostic. " + $"position={pointerPosition}, " +
|
||||
$"eventSystem={(EventSystem.current == null ? "<none>" : EventSystem.current.name)}, " +
|
||||
$"currentModule={DescribeCurrentModule()}, " +
|
||||
$"moduleCount={modules.Length}, " + $"topRaycastHit={topHit}, " +
|
||||
$"allRaycastHits={string.Join(", ", raycastResults.Select(r => r.gameObject.name).Take(8))}, " +
|
||||
$"moduleActions={string.Join(" | ", modules.Select(DescribeModuleActions))}");
|
||||
}
|
||||
|
||||
private static bool PointerPressedThisFrame() {
|
||||
if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
if (Touchscreen.current != null &&
|
||||
Touchscreen.current.primaryTouch.press.wasPressedThisFrame) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return GameInput.PrimaryPointerPressedThisFrame();
|
||||
}
|
||||
|
||||
private static Vector2 PointerPosition() {
|
||||
if (Mouse.current != null) { return Mouse.current.position.ReadValue(); }
|
||||
if (Touchscreen.current != null) {
|
||||
return Touchscreen.current.primaryTouch.position.ReadValue();
|
||||
}
|
||||
|
||||
return GameInput.PointerPosition();
|
||||
}
|
||||
|
||||
private static List<RaycastResult> RaycastPointer(Vector2 position) {
|
||||
if (EventSystem.current == null) { return new List<RaycastResult>(); }
|
||||
|
||||
var pointerData = new PointerEventData(EventSystem.current) {
|
||||
pointerId = -1,
|
||||
position = position,
|
||||
};
|
||||
var results = new List<RaycastResult>();
|
||||
EventSystem.current.RaycastAll(pointerData, results);
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a7d6c2c7e3b4cc29875996ad7ba5952
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+1
-1
@@ -56,7 +56,7 @@ namespace common.WhatsNew {
|
||||
|
||||
void Update() {
|
||||
// Escape key closes the panel
|
||||
if (panel != null && panel.activeSelf && Input.GetButtonUp("Cancel")) { Hide(); }
|
||||
if (panel != null && panel.activeSelf && GameInput.CancelReleased()) { Hide(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"com.unity.ext.nunit": "2.0.5",
|
||||
"com.unity.ide.rider": "3.0.40",
|
||||
"com.unity.ide.visualstudio": "2.0.27",
|
||||
"com.unity.inputsystem": "1.19.0",
|
||||
"com.unity.multiplayer.center": "1.0.1",
|
||||
"com.unity.nuget.newtonsoft-json": "3.2.2",
|
||||
"com.unity.postprocessing": "3.5.4",
|
||||
|
||||
@@ -149,6 +149,15 @@
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.inputsystem": {
|
||||
"version": "1.19.0",
|
||||
"depth": 0,
|
||||
"source": "registry",
|
||||
"dependencies": {
|
||||
"com.unity.modules.uielements": "1.0.0"
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.mathematics": {
|
||||
"version": "1.3.3",
|
||||
"depth": 2,
|
||||
@@ -217,12 +226,12 @@
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.services.core": {
|
||||
"version": "1.16.0",
|
||||
"version": "1.17.0",
|
||||
"depth": 2,
|
||||
"source": "registry",
|
||||
"dependencies": {
|
||||
"com.unity.modules.androidjni": "1.0.0",
|
||||
"com.unity.nuget.newtonsoft-json": "3.2.1",
|
||||
"com.unity.nuget.newtonsoft-json": "3.2.2",
|
||||
"com.unity.modules.unitywebrequest": "1.0.0"
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
|
||||
+1
-1
@@ -883,7 +883,7 @@ PlayerSettings:
|
||||
qnxGraphicConfPath:
|
||||
apiCompatibilityLevel: 6
|
||||
captureStartupLogs: {}
|
||||
activeInputHandler: 0
|
||||
activeInputHandler: 2
|
||||
windowsGamepadBackendHint: 0
|
||||
cloudProjectId: 34326edd-6b91-4774-9c79-e04218c750da
|
||||
framebufferDepthMemorylessMode: 0
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
m_EditorVersion: 6000.4.9f1
|
||||
m_EditorVersionWithRevision: 6000.4.9f1 (f7258d6eebbe)
|
||||
m_EditorVersion: 6000.4.10f1
|
||||
m_EditorVersionWithRevision: 6000.4.10f1 (feeafc12a938)
|
||||
|
||||
@@ -114,7 +114,7 @@ hide_extensions = ['app']
|
||||
|
||||
// Run dmgbuild
|
||||
cmd := exec.Command("dmgbuild", "-s", settingsFile.Name(), volumeName, dmgPath)
|
||||
cmd.Env = append(os.Environ(), "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:"+os.Getenv("HOME")+"/.local/bin")
|
||||
cmd.Env = append(os.Environ(), "PATH="+pathWithPythonUserBins())
|
||||
|
||||
log.Printf("Running: dmgbuild -s %s %s %s", settingsFile.Name(), volumeName, dmgPath)
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
@@ -124,6 +124,29 @@ hide_extensions = ['app']
|
||||
return nil
|
||||
}
|
||||
|
||||
func pathWithPythonUserBins() string {
|
||||
pathEntries := []string{os.Getenv("PATH")}
|
||||
|
||||
if home, err := os.UserHomeDir(); err == nil {
|
||||
pathEntries = append(pathEntries, filepath.Join(home, ".local", "bin"))
|
||||
|
||||
if pythonUserBins, err := filepath.Glob(filepath.Join(home, "Library", "Python", "*", "bin")); err == nil {
|
||||
pathEntries = append(pathEntries, pythonUserBins...)
|
||||
}
|
||||
}
|
||||
|
||||
pathEntries = append(
|
||||
pathEntries,
|
||||
"/opt/homebrew/bin",
|
||||
"/usr/local/bin",
|
||||
"/usr/bin",
|
||||
"/bin",
|
||||
"/usr/sbin",
|
||||
"/sbin")
|
||||
|
||||
return strings.Join(pathEntries, ":")
|
||||
}
|
||||
|
||||
func signWithSparkle(filePath string, privateKeyPath string) (string, error) {
|
||||
// Use Sparkle's sign_update tool
|
||||
// First, try to find it in the Sparkle cache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
# GameAdmin service for game management (admin console)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_grpc_compile", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
|
||||
# Admin service for user management (admin console)
|
||||
proto_library(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
package(default_visibility = [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
|
||||
cc_proto_library(
|
||||
name = "ai_battle_config_cc_proto",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||
load("@rules_proto_grpc_csharp//:defs.bzl", "csharp_proto_compile")
|
||||
load("@rules_scala//scala_proto:scala_proto.bzl", "scala_proto_library")
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ scala_library(
|
||||
":rate_limits",
|
||||
":streaming_text_results",
|
||||
"//src/main/scala/net/eagle0/common/sse:okhttp_sse_listener",
|
||||
"@maven//:com_squareup_okhttp3_okhttp",
|
||||
"@maven//:com_squareup_okhttp3_okhttp_jvm",
|
||||
"@maven//:com_squareup_okhttp3_okhttp_sse",
|
||||
"@maven//:com_squareup_okio_okio_jvm",
|
||||
],
|
||||
|
||||
@@ -25,7 +25,7 @@ scala_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//src/main/scala/net/eagle0/common/llm_integration:external_text_generation_error",
|
||||
"@maven//:com_squareup_okhttp3_okhttp",
|
||||
"@maven//:com_squareup_okhttp3_okhttp_jvm",
|
||||
"@maven//:com_squareup_okhttp3_okhttp_sse",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1104,10 +1104,19 @@ final case class GameController(
|
||||
0
|
||||
} else knownResultCount
|
||||
|
||||
val knownCompleteTextIds = streamingTextStatuses
|
||||
val knownCompleteTextIds = streamingTextStatuses
|
||||
.filter(_.knownComplete)
|
||||
.map(_.llmIdentifier)
|
||||
.toSet
|
||||
val knownIncompleteTextCount = streamingTextStatuses.count(!_.knownComplete)
|
||||
SimpleTimedLogger.printLogger.logLine(
|
||||
s"[CLIENT-CACHE] game=$gameId user=$userId clientId=$clientId " +
|
||||
s"reportedCount=$knownResultCount acceptedCount=$safeKnownResultCount " +
|
||||
s"serverCount=${fullHistory.count} delta=${fullHistory.count - safeKnownResultCount} " +
|
||||
s"shardokStatuses=${knownShardokResultCounts.size} " +
|
||||
s"knownCompleteTexts=${knownCompleteTextIds.size} " +
|
||||
s"knownIncompleteTexts=$knownIncompleteTextCount"
|
||||
)
|
||||
|
||||
this.withHumanClient(
|
||||
clientTextStore
|
||||
|
||||
@@ -5,7 +5,7 @@ scala_library(
|
||||
srcs = glob(["*.scala"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@maven//:com_squareup_okhttp3_okhttp",
|
||||
"@maven//:com_squareup_okhttp3_okhttp_jvm",
|
||||
"@maven//:com_squareup_okio_okio_jvm",
|
||||
"@maven//:org_json4s_json4s_ast_3",
|
||||
"@maven//:org_json4s_json4s_core_3",
|
||||
|
||||
@@ -17,7 +17,7 @@ scala_test(
|
||||
|
||||
scala_test(
|
||||
name = "sqlite_history_test",
|
||||
timeout = "short",
|
||||
timeout = "moderate",
|
||||
srcs = ["SqliteHistoryTest.scala"],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:battalion_type_scala_proto",
|
||||
|
||||
Reference in New Issue
Block a user