Compare commits

..

59 Commits

Author SHA1 Message Date
Kain344 dd2f98c809 feat: optimaze
Build / build (push) Successful in 5m41s
2026-06-07 13:20:59 +07:00
Kain344 08ee73b2eb feat: update data
Build / build (push) Successful in 5m32s
2026-06-04 08:39:19 +07:00
Kain344 3b1f235e81 feat: update data
Build / build (push) Has been cancelled
2026-06-04 08:35:14 +07:00
Kain344 87f9c17352 UPDATE: 4.2.0
Build / build (push) Successful in 5m10s
2026-04-22 08:32:05 +07:00
Kain344 79776ddb45 UPDATE: new data
Build / build (push) Successful in 5m15s
2026-04-16 11:29:55 +07:00
Kain344 e398ead7ba UPDATE: Support custom lineup
Build / build (push) Successful in 5m32s
2026-04-12 17:16:00 +07:00
Kain344 f6938e8b8a FIX: fix stuck when replace lineup
Build / build (push) Successful in 5m22s
2026-04-07 20:46:46 +07:00
Kain344 a2eb9d37f6 UPDATE: v4
Build / build (push) Successful in 10m49s
2026-04-07 16:23:40 +07:00
Kain344 a99eb85fdd UPDATE: Real map fix
Build / build (push) Successful in 5m24s
2026-04-04 00:11:40 +07:00
Kain344 bd647edd48 UPDATE: Fix bug
Build / build (push) Successful in 5m18s
2026-04-03 18:01:15 +07:00
Kain344 77374d8b50 UPDATE: Fix bug 2026-04-03 18:00:54 +07:00
Kain344 a6be76cc3a UPDATE: Fix load map
Build / build (push) Successful in 5m18s
2026-04-02 01:09:45 +07:00
Kain344 8c56999da0 UPDATE: New data
Build / build (push) Successful in 5m40s
2026-03-31 12:38:21 +07:00
Kain344 898b0b9235 UPDATE: Fix something
Build / build (push) Successful in 5m49s
2026-03-29 12:38:39 +07:00
Kain344 2d74e99b32 UPDATE: 4.1.5X
Build / build (push) Successful in 5m56s
2026-03-20 02:51:29 +07:00
Kain344 988eeb2dd9 UPDATE: 4.0.5X
Build / build (push) Successful in 10m25s
2026-03-16 16:51:31 +07:00
Kain344 f64f690a0a UPDATE: 3.7.52
Build / build (push) Successful in 13m0s
2025-11-11 21:04:25 +07:00
Kain344 b0c4a7e05a UPDATE: Support TCP, Apply Singleton pattern, Replace reflection with Type Factory + sync.Pool for optimization, Optimize file release process
Build / build (push) Successful in 8m47s
2025-10-19 13:20:56 +07:00
Kain344 0a44f56c2f Re-optima apk
Build / build (push) Successful in 6m3s
2025-10-18 09:13:43 +07:00
Kain344 527c8176e4 FIX: Update new resource
Build / build (push) Successful in 7m18s
2025-10-17 12:31:30 +07:00
Kain344 a54219b781 FIX: Update new resource
Build / build (push) Failing after 3m37s
2025-10-17 12:24:53 +07:00
Kain344 84cf16c3bf UPDATE: Update to 3.6.54
Build / build (push) Failing after 6m2s
2025-10-17 10:47:09 +07:00
Kain344 becf6779f7 Add CI/CD
Build / build (push) Successful in 8m55s
2025-10-08 21:51:08 +07:00
Kain344 d61b2aa907 Add CI/CD
Build / build (push) Failing after 5m40s
2025-10-08 20:51:48 +07:00
Kain344 534c08c70a Add CI/CD
Build / build (push) Has been cancelled
2025-10-08 19:51:05 +07:00
Kain344 bc3e6f514a Add CI/CD
Build / build (push) Failing after 8m14s
2025-10-08 19:29:42 +07:00
Kain344 2469b9ff83 Add CI/CD
Build / build (push) Failing after 9m7s
2025-10-08 19:15:26 +07:00
Kain344 f3abdff971 Add CI/CD
Build / build (push) Has been cancelled
2025-10-08 19:11:38 +07:00
Kain344 af1b71f929 Add CI/CD
Build / build (push) Failing after 7m20s
2025-10-08 19:00:23 +07:00
Kain344 4146f260ac Add CI/CD
Build / build (push) Failing after 6m29s
2025-10-08 18:00:20 +07:00
Kain344 7c5200f838 Add CI/CD
Build / build (push) Failing after 2m56s
2025-10-08 17:42:30 +07:00
Kain344 17d6856f58 Add CI/CD
Build / build (push) Failing after 4m3s
2025-10-08 17:32:49 +07:00
Kain344 2ba164a05c Add CI/CD
Build / build (push) Failing after 6m11s
2025-10-08 17:23:30 +07:00
Kain344 ecd02b8885 Add CI/CD
Build / build (push) Failing after 9m16s
2025-10-08 17:11:26 +07:00
Kain344 08caef28ab Add CI/CD
Build / build (push) Has been cancelled
2025-10-08 17:09:26 +07:00
Kain344 b587da0b9a Add CI/CD
Build / build (push) Has been cancelled
2025-10-08 16:52:32 +07:00
Kain344 0f7748a1df Add CI/CD
Build / build (push) Failing after 5m7s
2025-10-08 16:47:19 +07:00
Kain344 2a2159eb8a Add CI/CD
Build / build (push) Has been cancelled
2025-10-08 16:27:52 +07:00
Kain344 866de7a49e Add CI/CD
Build / build (push) Failing after 27s
2025-10-08 16:27:05 +07:00
Kain344 c49be0b2e7 Add CI/CD
Build / build (push) Failing after 29s
2025-10-08 16:19:25 +07:00
Kain344 00155e3619 Add CI/CD
Build / build (push) Failing after 27s
2025-10-08 16:14:26 +07:00
Kain344 6a9b6bc3a8 Add CI/CD
Build / build (push) Failing after 28s
2025-10-08 16:11:22 +07:00
Kain344 e7b7751fbb Add CI/CD
Build / build (push) Failing after 13m27s
2025-10-08 14:04:47 +07:00
Kain344 66f6ef6cec Add CI/CD
Build / build (push) Failing after 3m31s
2025-10-08 13:36:07 +07:00
Kain344 1d149bfa19 Add CI/CD
Build / build (push) Has been cancelled
2025-10-08 13:31:03 +07:00
Kain344 707f7adbeb Add CI/CD
Build / build (push) Failing after 4m26s
2025-10-08 13:21:11 +07:00
Kain344 b9f73f0d0f Add CI/CD
Build / build (push) Failing after 3m59s
2025-10-08 13:01:38 +07:00
Kain344 2f191a2c41 Add CI/CD
Build / build (push) Failing after 5m8s
2025-10-08 12:44:45 +07:00
Kain344 47f3f1f55d Add CI/CD
Build / build (push) Failing after 9m53s
2025-10-08 12:28:39 +07:00
Kain344 9399dbe051 Add CI/CD
Build / build (push) Failing after 6m43s
2025-10-08 12:02:22 +07:00
Kain344 a044ca8189 Add CI/CD
Build / build (push) Failing after 5m20s
2025-10-08 11:48:31 +07:00
Kain344 67e06fd017 Add CI/CD
Build / build (push) Failing after 3m30s
2025-10-08 11:26:43 +07:00
Kain344 629e0cb456 Add CI/CD
Build / build (push) Failing after 4m55s
2025-10-08 11:17:28 +07:00
Kain344 4135f02885 Add CI/CD
Build / build (push) Failing after 3m18s
2025-10-08 11:01:09 +07:00
Kain344 6149ff55ab FIX: Fix sync data 2025-10-04 22:14:57 +07:00
Kain344 7722e5fa70 UPDATE: Re-optimize performance 2025-10-04 21:16:44 +07:00
Kain344 dafb6aba1b UPDATE: New res 2025-10-03 22:03:27 +07:00
Kain344 3e967d7bed UPDATE: New res 2025-10-03 22:02:57 +07:00
Kain344 c75207f8e1 UPDATE: Extra setting 2025-10-02 23:37:14 +07:00
34 changed files with 12485 additions and 5011 deletions
+61
View File
@@ -0,0 +1,61 @@
name: Build
run-name: ${{ gitea.actor }} build 🚀
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Set Up JDK
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: Setup Android SDK
uses: amyu/setup-android@v5
with:
cache-disabled: true
- name: Grant execute permissions
run: |
chmod +x ./gradlew
chmod +x ./script/release-uploader
- name: Download AAR manually
run: |
FILE="app/libs/firefly-go.aar"
URL="https://git.kain.io.vn/Firefly-Shelter/FireflyGo_Android/media/branch/master/app/libs/firefly-go.aar"
echo "📥 Downloading $FILE from $URL"
curl -L -o "$FILE" "$URL"
- name: Build signed release APK
env:
KEYSTORE_PATH: ${{ github.workspace }}/KeyStore.jks
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: |
./gradlew assembleRelease \
-Pandroid.injected.signing.store.file=$KEYSTORE_PATH \
-Pandroid.injected.signing.store.password=$KEYSTORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$KEY_ALIAS \
-Pandroid.injected.signing.key.password=$KEY_PASSWORD
- name: Find and rename release APK
run: |
APK_FILE=$(ls app/build/outputs/apk/release/*.apk | head -n 1)
echo "Found APK: $APK_FILE"
mv "$APK_FILE" app/build/outputs/apk/release/firefly_go_android.apk
- name: Upload release
env:
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
run: script/release-uploader -token=$REPO_TOKEN -release-url="https://git.kain.io.vn/api/v1/repos/Firefly-Shelter/FireflyGo_Android/releases" -files="app/build/outputs/apk/release/firefly_go_android.apk"
+1
View File
@@ -15,3 +15,4 @@
.externalNativeBuild
.cxx
local.properties
.history/
Generated
+1 -1
View File
@@ -1 +1 @@
FireflyPsAndorid
FireflyGoAndroid
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
<bytecodeTargetLevel target="17" />
</component>
</project>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceTable">
<option name="columnSorters">
<list>
<ColumnSorterState>
<option name="column" value="Name" />
<option name="order" value="ASCENDING" />
</ColumnSorterState>
</list>
</option>
</component>
</project>
+1 -1
View File
@@ -6,7 +6,6 @@
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
@@ -15,5 +14,6 @@
</option>
</GradleProjectSettings>
</option>
<option name="parallelModelFetch" value="true" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettings">
<option name="previewPanelProviderInfo">
<ProviderInfo name="Compose (experimental)" className="com.intellij.markdown.compose.preview.ComposePanelProvider" />
</option>
</component>
</project>
+2 -1
View File
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
+24 -13
View File
@@ -5,43 +5,48 @@ plugins {
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}
kotlin {
jvmToolchain(17)
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
android {
namespace = "com.example.firefly_go_android"
compileSdk = 36
defaultConfig {
applicationId = "com.example.firefly_go_android"
applicationId = "com.kain344.firefly_go_android"
minSdk = 24
//noinspection OldTargetApi
targetSdk = 35
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
ndk {
abiFilters.addAll(listOf("arm64-v8a"))
}
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
viewBinding = true
}
composeOptions {
@@ -49,6 +54,10 @@ android {
}
buildToolsVersion = "36.0.0"
ndkVersion = "27.2.12479018"
dependenciesInfo {
includeInApk = false
includeInBundle = false
}
}
dependencies {
@@ -87,6 +96,8 @@ dependencies {
debugImplementation(libs.ui.test.manifest)
// Local AAR library
implementation(files("../library/firefly-go.aar"))
implementation(files("libs/firefly-go.aar"))
implementation(libs.slf4j.android)
}
Binary file not shown.
BIN
View File
Binary file not shown.
+22 -8
View File
@@ -2,12 +2,22 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"
tools:ignore="ForegroundServicesPolicy" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
tools:ignore="RequestInstallPackagesPolicy" />
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application
android:allowBackup="true"
@@ -18,12 +28,13 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:requestLegacyExternalStorage="true"
android:theme="@style/Theme.FireflyPsAndorid"
android:theme="@style/Theme.FireflyGoAndroid"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.FireflyPsAndorid">
android:theme="@style/Theme.FireflyGoAndroid">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -32,9 +43,12 @@
<service
android:name=".GolangServerService"
android:foregroundServiceType="dataSync"
android:exported="false" />
android:foregroundServiceType="specialUse"
android:exported="false">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Running local Golang TCP/UDP Server" />
</service>
<provider
android:name="androidx.core.content.FileProvider"
+588
View File
@@ -0,0 +1,588 @@
{
"leader": 2,
"lineups": {
"0": 1409,
"1": 1407,
"2": 1406,
"3": 1403
},
"position": {
"x": -4030,
"z": -13006,
"y": 0,
"rot_y": 270000
},
"scene": {
"plane_id": 10000,
"floor_id": 10000000,
"entry_id": 100000104
},
"player_outfit": [
1003
],
"char_path": {
"main": 8008,
"march_7": 1224
},
"char_enhanced": {
"1004": 1,
"1005": 0,
"1006": 1,
"1102": 1,
"1205": 1,
"1212": 1,
"1217": 1,
"1306": 1,
"1307": 1,
"1310": 1
},
"challenge": {
"challenge_id": 0,
"skip_half": 0,
"random_seed": 0,
"blessings": [],
"is_in_challenge": false,
"current_stage_id": 0,
"path_resonance_id": 0,
"maze_buff": 0,
"first_lineup": [],
"second_lineup": []
},
"challenge_tierce": {
"challenge_id": 0,
"current_stage_id": 0,
"maze_buff": 0,
"path_resonance_id": 0,
"is_in_challenge": false,
"is_single_stage": false,
"challenge_tierce_data": {
"20245": {
"stage_1": {
"blessing": 3031361,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 40000,
"lineup": [
1407,
1413,
1415,
1409
]
},
"stage_2": {
"blessing": 3031361,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 40000,
"lineup": [
1310,
1225,
1321,
1222
]
},
"stage_3": {
"blessing": 3031362,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 40000,
"lineup": [
1506,
1502,
1501,
1217
]
}
},
"30185": {
"stage_1": {
"blessing": 3111090,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 3932,
"lineup": [
1501,
1502,
1414,
1506
]
},
"stage_2": {
"blessing": 3111085,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 3913,
"lineup": [
1310,
1225,
1303,
1321
]
},
"stage_3": {
"blessing": 3111071,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 4000,
"lineup": [
1415,
1413,
1407,
1409
]
}
},
"5213": {
"stage_1": {
"blessing": 0,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 0,
"lineup": [
1407,
1413,
1415,
1409
]
},
"stage_2": {
"blessing": 0,
"cycle_count": 1,
"battle_status": 1,
"DeadCount": 0,
"score": 0,
"lineup": [
1310,
1321,
1225,
1222
]
},
"stage_3": {
"blessing": 0,
"cycle_count": 0,
"battle_status": 1,
"DeadCount": 0,
"score": 0,
"lineup": [
1506,
1502,
1501,
1414
]
}
},
"5313": {
"stage_1": {
"blessing": 0,
"cycle_count": 0,
"battle_status": 3,
"DeadCount": 0,
"score": 0,
"lineup": [
1510,
8001,
1004,
1414
]
},
"stage_2": {
"blessing": 0,
"cycle_count": 0,
"battle_status": 0,
"DeadCount": 0,
"score": 0,
"lineup": [
1302
]
},
"stage_3": {
"blessing": 0,
"cycle_count": 0,
"battle_status": 0,
"DeadCount": 0,
"score": 0,
"lineup": [
1321
]
}
}
}
},
"challenge_peak": {
"current_mode": "Knight",
"group_id": 8,
"is_in_challenge_peak": false,
"challenge_peak_data": {
"1": {
"checkmate_data": {
"challenge_id": 104,
"blessing": 3033006,
"lineup": [
1413,
1409,
1407,
1403
],
"stage_id": 30501022,
"is_hard_mode": true
},
"knight_data": {
"current_challenge_id": 103,
"details_data": [
{
"lineup": [
1222,
1225,
1310,
1303
],
"stage_id": 30501011,
"challenge_id": 101
},
{
"lineup": [
1412,
1414,
1408,
1313
],
"stage_id": 30501012,
"challenge_id": 102
},
{
"lineup": [
1407,
1403,
1409,
1413
],
"stage_id": 30501013,
"challenge_id": 103
}
]
}
},
"2": {
"checkmate_data": {
"challenge_id": 204,
"blessing": 3033021,
"lineup": [
1415,
1413,
1409,
1407
],
"stage_id": 30502022,
"is_hard_mode": true
},
"knight_data": {
"current_challenge_id": 203,
"details_data": [
{
"lineup": [
1302,
1309,
1410
],
"stage_id": 30502011,
"challenge_id": 201
},
{
"lineup": [
1221,
1222
],
"stage_id": 30502012,
"challenge_id": 202
},
{
"lineup": [
1415,
8001,
1414,
1313
],
"stage_id": 30502013,
"challenge_id": 203
}
]
}
},
"3": {
"checkmate_data": {
"challenge_id": 304,
"blessing": 3033032,
"lineup": [
1222,
1225,
1310,
1321
],
"stage_id": 30503021,
"is_hard_mode": false
},
"knight_data": {
"current_challenge_id": 302,
"details_data": [
{
"lineup": [
1003
],
"stage_id": 30503011,
"challenge_id": 301
},
{
"lineup": [
1315
],
"stage_id": 30503012,
"challenge_id": 302
},
{
"lineup": [
8001
],
"stage_id": 30503013,
"challenge_id": 303
}
]
}
},
"4": {
"checkmate_data": {
"challenge_id": 404,
"blessing": 3033045,
"lineup": [
1310
],
"stage_id": 30504021,
"is_hard_mode": false
},
"knight_data": {
"current_challenge_id": 401,
"details_data": [
{
"lineup": [
1302
],
"stage_id": 30504011,
"challenge_id": 401
},
{
"lineup": [
1321
],
"stage_id": 30504012,
"challenge_id": 402
},
{
"lineup": [
1218
],
"stage_id": 30504013,
"challenge_id": 403
}
]
}
},
"5": {
"checkmate_data": {
"challenge_id": 504,
"blessing": 3033050,
"lineup": [
1415,
1413,
1407,
1409
],
"stage_id": 30505021,
"is_hard_mode": false
},
"knight_data": {
"current_challenge_id": 501,
"details_data": [
{
"lineup": [
1310
],
"stage_id": 30505011,
"challenge_id": 501
},
{
"lineup": [
1407
],
"stage_id": 30505012,
"challenge_id": 502
},
{
"lineup": [
1502
],
"stage_id": 30505013,
"challenge_id": 503
}
]
}
},
"6": {
"checkmate_data": {
"challenge_id": 604,
"blessing": 3033053,
"lineup": [
1505,
1217,
1502,
8001
],
"stage_id": 30506021,
"is_hard_mode": false
},
"knight_data": {
"current_challenge_id": 602,
"details_data": [
{
"lineup": [
1309
],
"stage_id": 30506011,
"challenge_id": 601
},
{
"lineup": [
1321,
1310,
1225,
1303
],
"stage_id": 30506012,
"challenge_id": 602
},
{
"lineup": [
1415,
1413,
1409,
1407
],
"stage_id": 30506013,
"challenge_id": 603
}
]
}
},
"7": {
"checkmate_data": {
"challenge_id": 704,
"blessing": 3033061,
"lineup": [
1505,
1502,
1414,
1410
],
"stage_id": 30507021,
"is_hard_mode": false
},
"knight_data": {
"current_challenge_id": 703,
"details_data": [
{
"lineup": [
1414
],
"stage_id": 30507011,
"challenge_id": 701
},
{
"lineup": [
1501
],
"stage_id": 30507012,
"challenge_id": 702
},
{
"lineup": [
1507,
1222
],
"stage_id": 30507013,
"challenge_id": 703
}
]
}
},
"8": {
"checkmate_data": {
"challenge_id": 0,
"blessing": 0,
"lineup": null,
"stage_id": 0,
"is_hard_mode": false
},
"knight_data": {
"current_challenge_id": 0,
"details_data": null
}
}
}
},
"theory_craft": {
"hp": {
"1": [
200000,
1000000,
200000
],
"2": [
2000000000,
2000000000,
2000000000
],
"3": []
},
"cycle_count": 1,
"stage_id": 30118121,
"mode": false,
"custom_lineup": []
},
"profile_data": {
"cur_chat_bubble_id": 220009,
"cur_phone_theme_id": 221012,
"cur_phone_case_id": 254001,
"cur_pam_skin_id": 252000,
"cur_pet_id": 0,
"cur_avatar_player_icon": 202034,
"cur_player_personal_card": 253001,
"cur_signature": "Firefly GO By Kain",
"cur_nickname": "Firefly GO",
"cur_display_avatar": [
1310,
1309,
1407,
1413,
1412
],
"cur_is_display_avatar": true
},
"skin_data": {
"1001": 1100101,
"1310": 1131001,
"1407": 1140701,
"1415": 1141501
},
"extra_setting": {
"censorship": false,
"cm": false,
"first_person": false,
"hide_ui": false
}
}
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
{
"CNBETAAndroid4.3.51": {
"asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_15261247_f6e6db2125cf_369da465b36faf",
"asset_bundle_url_b": "https://autopatchos.starrails.com/asb/BetaLive/output_15235885_6091fd15561a_83828f542dc1f3",
"ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_15265964_c2fbb1eb05fc_f2238199ee2b6e",
"lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_15242148_d40f856defc0_599b68a0adf7bd",
"ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_15265964_799df4f0ecef_5a94550ba64cff"
},
"CNBETAWin4.3.51": {
"asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_15261247_f6e6db2125cf_369da465b36faf",
"asset_bundle_url_b": "https://autopatchos.starrails.com/asb/BetaLive/output_15235885_6091fd15561a_83828f542dc1f3",
"ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_15265964_c2fbb1eb05fc_f2238199ee2b6e",
"lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_15242148_d40f856defc0_599b68a0adf7bd",
"ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_15265964_799df4f0ecef_5a94550ba64cff"
},
"CNBETAiOS4.3.51": {
"asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_15261247_f6e6db2125cf_369da465b36faf",
"asset_bundle_url_b": "https://autopatchos.starrails.com/asb/BetaLive/output_15235885_6091fd15561a_83828f542dc1f3",
"ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_15265964_c2fbb1eb05fc_f2238199ee2b6e",
"lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_15242148_d40f856defc0_599b68a0adf7bd",
"ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_15265964_799df4f0ecef_5a94550ba64cff"
},
"OSBETAAndroid4.3.51": {
"asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_15261247_f6e6db2125cf_369da465b36faf",
"asset_bundle_url_b": "https://autopatchos.starrails.com/asb/BetaLive/output_15235885_6091fd15561a_83828f542dc1f3",
"ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_15265964_c2fbb1eb05fc_f2238199ee2b6e",
"lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_15242148_d40f856defc0_599b68a0adf7bd",
"ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_15265964_799df4f0ecef_5a94550ba64cff"
},
"OSBETAWin4.3.51": {
"asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_15261247_f6e6db2125cf_369da465b36faf",
"asset_bundle_url_b": "https://autopatchos.starrails.com/asb/BetaLive/output_15235885_6091fd15561a_83828f542dc1f3",
"ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_15265964_c2fbb1eb05fc_f2238199ee2b6e",
"lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_15242148_d40f856defc0_599b68a0adf7bd",
"ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_15265964_799df4f0ecef_5a94550ba64cff"
},
"OSBETAiOS4.3.51": {
"asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_15261247_f6e6db2125cf_369da465b36faf",
"asset_bundle_url_b": "https://autopatchos.starrails.com/asb/BetaLive/output_15235885_6091fd15561a_83828f542dc1f3",
"ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_15265964_c2fbb1eb05fc_f2238199ee2b6e",
"lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_15242148_d40f856defc0_599b68a0adf7bd",
"ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_15265964_799df4f0ecef_5a94550ba64cff"
}
}
@@ -1,11 +1,13 @@
package com.example.firefly_go_android
import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.graphics.BitmapFactory
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
@@ -14,7 +16,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import libandroid.Libandroid
import androidx.core.content.edit
class GolangServerService : Service() {
@@ -32,9 +36,10 @@ class GolangServerService : Service() {
createNotificationChannel()
}
@SuppressLint("WakelockTimeout")
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (isRunning) {
Log.d(TAG, "Server is already running")
Log.d(TAG, "Server is already running")
return START_STICKY
}
isRunning = true
@@ -47,49 +52,79 @@ class GolangServerService : Service() {
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val largeIcon = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setLargeIcon(largeIcon)
.setContentTitle("FireflyGO Server")
.setContentText("FireflyGO is running...")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentText("Server is running...")
.setColor(ContextCompat.getColor(this, R.color.teal_700))
.setOngoing(true)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setShowWhen(false)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.build()
startForeground(NOTIFICATION_ID, notification)
if (Build.VERSION.SDK_INT >= 34) {
startForeground(
NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
)
} else if (Build.VERSION.SDK_INT >= 29) {
startForeground(
NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST
)
} else {
startForeground(NOTIFICATION_ID, notification)
}
// Khởi tạo WakeLock và WifiLock
try {
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "GolangServer::WakeLock")
wakeLock?.acquire()
Log.d(TAG, "WakeLock acquired")
Log.d(TAG, "WakeLock acquired")
} catch (e: Exception) {
Log.e(TAG, "❌ WakeLock failed", e)
Log.e(TAG, "Lock failed", e)
}
Thread {
try {
val appDataPath = intent?.getStringExtra("appDataPath")
val sharedPrefs = getSharedPreferences("AppPrefs", MODE_PRIVATE)
var appDataPath = intent?.getStringExtra("appDataPath")
if (appDataPath != null) {
sharedPrefs.edit { putString("saved_app_data_path", appDataPath) }
} else {
appDataPath = sharedPrefs.getString("saved_app_data_path", null)
}
if (appDataPath != null) {
Libandroid.setPathDataLocal(appDataPath)
Log.d(TAG, "Set path data: $appDataPath")
Log.d(TAG, "Set path data: $appDataPath")
} else {
isRunning = false
Log.e(TAG, "appDataPath not received in intent")
Log.e(TAG, "appDataPath not received and not found in SharedPreferences")
stopSelf()
return@Thread
}
Libandroid.setServerRunning(true)
isRunning = true
Log.d(TAG, "Server started")
Log.d(TAG, "Server started")
} catch (e: Exception) {
isRunning = false
Log.e(TAG, "Error starting server", e)
Log.e(TAG, "Error starting server", e)
stopSelf()
}
}.start()
return START_STICKY
}
@@ -97,7 +132,6 @@ class GolangServerService : Service() {
super.onDestroy()
Log.d(TAG, "onDestroy called")
// 1. Tắt server
try {
val result = Libandroid.setServerRunning(false)
isRunning = false
@@ -106,16 +140,16 @@ class GolangServerService : Service() {
Log.e(TAG, "Error shutting down server", e)
}
// 2. Giải phóng WakeLock nếu còn giữ
// Nhả các khóa tài nguyên
try {
wakeLock?.let {
if (it.isHeld) {
it.release()
Log.d(TAG, "WakeLock released")
Log.d(TAG, "WakeLock released")
}
}
} catch (e: Exception) {
Log.e(TAG, "Failed to release WakeLock", e)
Log.e(TAG, "Failed to release Locks", e)
}
isRunning = false
}
@@ -132,9 +166,9 @@ class GolangServerService : Service() {
description = "Channel for running Golang backend in foreground"
}
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
Log.d(TAG, "Notification channel created")
Log.d(TAG, "Notification channel created")
}
}
}
@@ -4,8 +4,9 @@ import AutoUpdaterManager
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
@@ -16,7 +17,6 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
@@ -56,12 +56,23 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import kotlinx.coroutines.delay
import org.json.JSONObject
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily
import android.os.PowerManager
import android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import android.provider.Settings
data class AppVersion(
val latestVersion: String,
@@ -72,14 +83,33 @@ data class AppVersion(
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestBatteryExemption(this)
requestInstallPermission(this)
requestStoragePermission(this)
val appDataPath = filesDir.absolutePath
val appDataPath = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "FireflyGo").absolutePath
val dataDir = File("$appDataPath/data")
dataDir.mkdirs()
if (!dataDir.exists()) dataDir.mkdirs()
copyRawToFile(this, dataDir, "data-in-game.json", R.raw.data_in_game_json)
copyRawToFile(this, dataDir, "freesr-data.json", R.raw.freesr_data_json)
copyRawToFile(this, dataDir, "version.json", R.raw.version_json)
val sharedPrefs = getSharedPreferences("AppPrefs", MODE_PRIVATE)
val currentVersion = try {
if (Build.VERSION.SDK_INT >= 33) {
packageManager.getPackageInfo(packageName, android.content.pm.PackageManager.PackageInfoFlags.of(0)).longVersionCode
} else {
@Suppress("DEPRECATION")
packageManager.getPackageInfo(packageName, 0).versionCode.toLong()
}
} catch (e: Exception) {
1L
}
val lastVersion = sharedPrefs.getLong("last_version_code", 0L)
val shouldOverride = currentVersion > lastVersion
copyRawToFile(dataDir, shouldOverride)
if (shouldOverride) {
sharedPrefs.edit().putLong("last_version_code", currentVersion).apply()
}
val jsonString = resources.openRawResource(R.raw.app_version_json).use { input ->
input.bufferedReader().use { it.readText() }
@@ -98,7 +128,7 @@ class MainActivity : ComponentActivity() {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Box(modifier = Modifier.fillMaxSize()) {
ServerControlScreen(appDataPath, dataDir, appVersion, Modifier.padding(innerPadding))
AutoUpdateDialog(onDismiss = {}, appVersion, true)
AutoUpdateDialog(onDismiss = {}, appVersion, dataDir, true)
}
}
}
@@ -107,25 +137,107 @@ class MainActivity : ComponentActivity() {
}
}
@SuppressLint("BatteryLife")
fun copyRawToFile(context: Context, targetDir: File, fileName: String, resId: Int, override: Boolean = false) {
val outFile = File(targetDir, fileName)
if (!outFile.exists() || override) {
try {
context.resources.openRawResource(resId).use { input ->
FileOutputStream(outFile).use { output ->
input.copyTo(output)
}
}
Log.i("FileCopy", "${if (override) "✅ Overridden" else "✅ Copied"} $fileName to ${outFile.absolutePath}")
} catch (e: Exception) {
Log.e("FileCopy", "❌ Failed to copy $fileName: ${e.message}")
fun requestBatteryExemption(context: Context) {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
if (!powerManager.isIgnoringBatteryOptimizations(context.packageName)) {
val intent = Intent().apply {
action = ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
data = "package:${context.packageName}".toUri()
}
} else {
Log.i("FileCopy", "$fileName already exists at ${outFile.absolutePath}")
context.startActivity(intent)
}
}
fun requestInstallPermission(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!context.packageManager.canRequestPackageInstalls()) {
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
data = "package:${context.packageName}".toUri()
}
context.startActivity(intent)
Toast.makeText(context, "Please allow installing unknown apps to update", Toast.LENGTH_LONG).show()
}
}
}
fun requestStoragePermission(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) {
try {
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
data = "package:${context.packageName}".toUri()
}
context.startActivity(intent)
Toast.makeText(context, "Please allow All Files Access to load game data", Toast.LENGTH_LONG).show()
} catch (e: Exception) {
try {
val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
context.startActivity(intent)
} catch (ex: Exception) {
Log.e("StoragePermission", "Failed to open settings", ex)
}
}
}
}
}
fun copyRawToFile(targetDir: File, override: Boolean = false): Boolean {
val files = listOf(
"assets/data-in-game.json" to "data-in-game.json",
"assets/freesr-data.json" to "freesr-data.json",
"assets/version.json" to "version.json"
)
return try {
if (!targetDir.exists()) targetDir.mkdirs()
for ((assetPath, name) in files) {
val outFile = File(targetDir, name)
if (outFile.exists() && !override) continue
val inputStream =
MainActivity::class.java.classLoader
?.getResourceAsStream(assetPath)
?: return false
inputStream.use { input ->
FileOutputStream(outFile).use { output ->
input.copyTo(output)
output.fd.sync()
}
}
}
true
} catch (e: Exception) {
false
}
}
fun removeFile(targetDir: File, fileName: String): Boolean {
val file = File(targetDir, fileName)
return if (file.exists()) {
try {
if (file.delete()) {
Log.i("FileRemove", "Removed $fileName from ${file.absolutePath}")
true
} else {
Log.e("FileRemove", "Failed to remove $fileName from ${file.absolutePath}")
false
}
} catch (e: Exception) {
Log.e("FileRemove", "Error removing $fileName: ${e.message}")
false
}
} else {
Log.i("FileRemove", "$fileName does not exist in ${targetDir.absolutePath}")
false
}
}
@SuppressLint("ImplicitSamInstance")
@Composable
fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersion, modifier: Modifier = Modifier) {
@@ -161,7 +273,7 @@ fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersi
) {
// Title
Text(
text = "Firefly Ps for Android",
text = "Firefly GO for Android",
fontSize = 26.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(top = 24.dp),
@@ -212,7 +324,7 @@ fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersi
if (!isRunning) {
val intent = Intent(context, GolangServerService::class.java)
intent.putExtra("appDataPath", appDataPath)
context.startService(intent)
ContextCompat.startForegroundService(context, intent)
} else {
context.stopService(Intent(context, GolangServerService::class.java))
}
@@ -245,15 +357,16 @@ fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersi
// Widget icons row
Row(
horizontalArrangement = Arrangement.spacedBy(32.dp),
modifier = Modifier.fillMaxWidth(0.85f),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
val context = LocalContext.current
// Check Update widget
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.width(80.dp)
.clickable { showUpdateDialog = true }
.background(
Color.White.copy(alpha = 0.8f),
@@ -281,6 +394,7 @@ fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersi
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.width(80.dp)
.clickable { showResetDialog = true }
.background(
Color.White.copy(alpha = 0.8f),
@@ -308,6 +422,7 @@ fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersi
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.width(80.dp)
.clickable {
showLogs = true // mở popup log
}
@@ -356,9 +471,7 @@ fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersi
onClick = {
showResetDialog = false
try {
copyRawToFile(context, dataDir, "data-in-game.json", R.raw.data_in_game_json, true)
copyRawToFile(context, dataDir, "freesr-data.json", R.raw.freesr_data_json, true)
copyRawToFile(context, dataDir, "version.json", R.raw.version_json, true)
copyRawToFile(dataDir, true)
Toast.makeText(context, "Data has been reset successfully", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
Toast.makeText(context, "Reset failed: ${e.message}", Toast.LENGTH_SHORT).show()
@@ -381,7 +494,9 @@ fun ServerControlScreen(appDataPath: String, dataDir: File, appVersion: AppVersi
// Auto Update Dialog
if (showUpdateDialog) {
AutoUpdateDialog(
onDismiss = { showUpdateDialog = false }, appVersion
onDismiss = { showUpdateDialog = false },
appVersion,
dataDir
)
}
}
@@ -395,6 +510,59 @@ fun parseGoLogLine(line: String): String? {
}
fun parseAnsi(text: String, defaultColor: Color): AnnotatedString {
val regex = Regex("\u001B\\[(\\d+)(;\\d+)*m")
val builder = buildAnnotatedString {
var lastIndex = 0
var currentColor = defaultColor
for (match in regex.findAll(text)) {
val start = match.range.first
// 1. Thêm phần text TRƯỚC mã ANSI với màu HIỆN TẠI
val before = text.substring(lastIndex, start)
if (before.isNotEmpty()) {
withStyle(SpanStyle(color = currentColor)) {
append(before)
}
}
// 2. Lấy mã code (ví dụ 31, 36, hoặc 0)
val code = try {
match.groupValues[1].toInt()
} catch (e: NumberFormatException) {
0
}
currentColor = when (code) {
0 -> defaultColor
30 -> Color.Black
31 -> Color.Red
32 -> Color(0xFF00C853) // Green
33 -> Color(0xFFFFD600) // Yellow
34 -> Color(0xFF2962FF) // Blue
35 -> Color(0xFFD500F9) // Magenta
36 -> Color(0xFF00B8D4) // Cyan
37 -> Color.White
else -> currentColor
}
lastIndex = match.range.last + 1
}
if (lastIndex < text.length) {
val remain = text.substring(lastIndex)
if (remain.isNotEmpty()) {
withStyle(SpanStyle(color = currentColor)) {
append(remain)
}
}
}
}
return builder
}
@Composable
fun LogPopup(
onDismiss: () -> Unit
@@ -428,6 +596,8 @@ fun LogPopup(
}
}
val defaultTextColor = LocalContentColor.current
Dialog(onDismissRequest = { onDismiss() }) {
Surface(
shape = RoundedCornerShape(12.dp),
@@ -444,19 +614,23 @@ fun LogPopup(
)
Spacer(modifier = Modifier.height(8.dp))
LazyColumn(
state = listState,
modifier = Modifier.weight(1f)
) {
LazyColumn(state = listState, modifier = Modifier.weight(1f)) {
items(logs.size) { index ->
Text(
text = logs[index],
text = parseAnsi(logs[index], defaultTextColor),
fontSize = 12.sp,
color = Color.Black,
// 2. DÙNG FONT MONOSPACE
fontFamily = FontFamily.Monospace,
// 3. (Tuỳ chọn) Giảm chiều cao dòng để logo liền mạch
lineHeight = 14.sp,
modifier = Modifier.padding(vertical = 2.dp)
)
}
}
Spacer(modifier = Modifier.height(8.dp))
Button(
onClick = { onDismiss() },
@@ -475,6 +649,7 @@ fun LogPopup(
fun AutoUpdateDialog(
onDismiss: () -> Unit,
appVersion: AppVersion,
dataDir: File,
isFirstOpen: Boolean = false
) {
val context = LocalContext.current
@@ -522,6 +697,10 @@ fun AutoUpdateDialog(
LaunchedEffect(progress) {
if (progress >= 100 && isDownloading) {
downloadComplete = true
removeFile(dataDir, "data-in-game.json" )
removeFile(dataDir, "freesr-data.json")
removeFile(dataDir, "version.json")
delay(500)
}
}
@@ -601,7 +780,7 @@ fun AutoUpdateDialog(
autoUpdaterManager.downloadapk(
context,
update!!.apk_url,
"MyApp_${update!!.latestversion}.apk"
"FireflyGO_${update!!.latestversion}.apk"
) { prog -> progress = prog }
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
{
"latest_version": "3.6.2-02",
"changelog": "UPDATE: Fix env",
"apk_url": "https://git.kain.io.vn/Firefly-Shelter/FireflyGo_Android/releases/download/3.6.2-02/firefly_go_android.apk"
"latest_version": "4.3.1-02",
"changelog": "UPDATE: 4.3.5X",
"apk_url": "https://git.kain.io.vn/Firefly-Shelter/FireflyGo_Android/releases/download/4.3.1-02/firefly_go_android.apk"
}
-177
View File
@@ -1,177 +0,0 @@
{
"leader": 0,
"lineups": {
"0": 1413,
"1": 1403,
"2": 1409,
"3": 1407
},
"position": {
"x": -30,
"z": -22750,
"y": -15000,
"rot_y": 234288
},
"scene": {
"plane_id": 10000,
"floor_id": 10000003,
"entry_id": 100000352
},
"player_outfit": [
1001
],
"char_path": {
"main": 8008,
"march_7": 1224
},
"char_enhanced": {
"1005": 1,
"1006": 1,
"1205": 1,
"1212": 1
},
"challenge": {
"challenge_id": 0,
"skip_half": 0,
"blessings": [],
"is_in_challenge": false,
"current_stage_id": 30118121,
"path_resonance_id": 0,
"maze_buff": 0,
"first_lineup": [],
"second_lineup": []
},
"challenge_peak": {
"current_mode": "Knight",
"group_id": 2,
"is_in_challenge_peak": false,
"challenge_peak_data": {
"1": {
"checkmate_data": {
"challenge_id": 104,
"blessing": 3033006,
"lineup": [
1413,
1409,
1407,
1403
],
"stage_id": 30501022,
"is_hard_mode": true
},
"knight_data": {
"current_challenge_id": 103,
"details_data": [
{
"lineup": [
1222,
1225,
1310,
1303
],
"stage_id": 30501011,
"challenge_id": 101
},
{
"lineup": [
1412,
1414,
1408,
1313
],
"stage_id": 30501012,
"challenge_id": 102
},
{
"lineup": [
1407,
1403,
1409,
1413
],
"stage_id": 30501013,
"challenge_id": 103
}
]
}
},
"2": {
"checkmate_data": {
"challenge_id": 204,
"blessing": 3033021,
"lineup": [
1415,
1413,
1409,
1407
],
"stage_id": 30502022,
"is_hard_mode": true
},
"knight_data": {
"current_challenge_id": 203,
"details_data": [
{
"lineup": [
1302,
1309,
1410
],
"stage_id": 30502011,
"challenge_id": 201
},
{
"lineup": [
1221,
1222
],
"stage_id": 30502012,
"challenge_id": 202
},
{
"lineup": [
1415,
8001,
1414,
1313
],
"stage_id": 30502013,
"challenge_id": 203
}
]
}
}
}
},
"theory_craft": {
"hp": {
"1": 600000,
"2": 10000000
},
"cycle_count": 1,
"log": false,
"mode": false
},
"profile_data": {
"cur_chat_bubble_id": 220008,
"cur_phone_theme_id": 221012,
"cur_phone_case_id": 254001,
"cur_pam_skin_id": 252000,
"cur_pet_id": 1003,
"cur_avatar_player_icon": 202034,
"cur_player_personal_card": 253001,
"cur_signature": "Firefly GO By Kain",
"cur_display_avatar": [
1310,
1309,
1407,
1413,
1412
],
"cur_is_display_avatar": true
},
"skin_data": {
"1001": 1100101,
"1310": 1131001
}
}
-44
View File
@@ -1,44 +0,0 @@
{
"CNBETAAndroid3.6.51": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12066992_f083970b907e_999074cab6dce6",
"asset_bundle_url_b": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12056690_16bfd67c199f_f3c0367d7b051e",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_12114942_e99cbde25134_e63a6b835f17f9",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_12103115_ee78155e9867_3626f0948d93e2",
"ifix_url": "https://autopatchcn.bhsr.com/ifix/BetaLive/output_12118783_55113408814f_c874267d04c04a"
},
"CNBETAWin3.6.51": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12066992_f083970b907e_999074cab6dce6",
"asset_bundle_url_b": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12056690_16bfd67c199f_f3c0367d7b051e",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_12114942_e99cbde25134_e63a6b835f17f9",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_12103115_ee78155e9867_3626f0948d93e2",
"ifix_url": "https://autopatchcn.bhsr.com/ifix/BetaLive/output_12118783_55113408814f_c874267d04c04a"
},
"CNBETAiOS3.6.51": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12066992_f083970b907e_999074cab6dce6",
"asset_bundle_url_b": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12056690_16bfd67c199f_f3c0367d7b051e",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_12114942_e99cbde25134_e63a6b835f17f9",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_12103115_ee78155e9867_3626f0948d93e2",
"ifix_url": "https://autopatchcn.bhsr.com/ifix/BetaLive/output_12118783_55113408814f_c874267d04c04a"
},
"OSBETAAndroid3.6.51": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12066992_f083970b907e_999074cab6dce6",
"asset_bundle_url_b": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12056690_16bfd67c199f_f3c0367d7b051e",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_12114942_e99cbde25134_e63a6b835f17f9",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_12103115_ee78155e9867_3626f0948d93e2",
"ifix_url": "https://autopatchcn.bhsr.com/ifix/BetaLive/output_12118783_55113408814f_c874267d04c04a"
},
"OSBETAWin3.6.51": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12066992_f083970b907e_999074cab6dce6",
"asset_bundle_url_b": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12056690_16bfd67c199f_f3c0367d7b051e",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_12114942_e99cbde25134_e63a6b835f17f9",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_12103115_ee78155e9867_3626f0948d93e2",
"ifix_url": "https://autopatchcn.bhsr.com/ifix/BetaLive/output_12118783_55113408814f_c874267d04c04a"
},
"OSBETAiOS3.6.51": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12066992_f083970b907e_999074cab6dce6",
"asset_bundle_url_b": "https://autopatchcn.bhsr.com/asb/BetaLive/output_12056690_16bfd67c199f_f3c0367d7b051e",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_12114942_e99cbde25134_e63a6b835f17f9",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_12103115_ee78155e9867_3626f0948d93e2",
"ifix_url": "https://autopatchcn.bhsr.com/ifix/BetaLive/output_12118783_55113408814f_c874267d04c04a"
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.FireflyPsAndorid" parent="android:Theme.Material.Light.NoActionBar" />
<style name="Theme.FireflyGoAndroid" parent="android:Theme.Material.Light.NoActionBar" />
</resources>
+4 -2
View File
@@ -14,12 +14,14 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
org.gradle.parallel=true
android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
org.gradle.configuration-cache=true
#org.gradle.configuration-cache=false
android.r8.optimizedResourceShrinking=true
org.gradle.java.installations.auto-download=true
+13
View File
@@ -0,0 +1,13 @@
#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/536afcd1dff540251f85e5d2c80458cf/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/398ffe3949748bfb1d5636f023d228fd/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/536afcd1dff540251f85e5d2c80458cf/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/398ffe3949748bfb1d5636f023d228fd/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e99bae143b75f9a10ead10248f02055e/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/658299a896470fbb3103ba3a430ee227/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/536afcd1dff540251f85e5d2c80458cf/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/398ffe3949748bfb1d5636f023d228fd/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/248ffb1098f61659502d0c09aa348294/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/932015f6361ccaead0c6d9b8717ed96e/redirect
toolchainVendor=JETBRAINS
toolchainVersion=21
+16 -14
View File
@@ -1,24 +1,25 @@
[versions]
activityComposeVersion = "1.10.1"
agp = "8.9.3"
activityComposeVersion = "1.11.0"
agp = "8.13.0"
androidxJunit = "1.3.0"
animationCore = "1.9.0"
animationCore = "1.9.3"
autoupdater = "1.0.1"
espressoCoreVersion = "3.7.0"
foundation = "1.9.0"
kotlin = "2.0.21"
foundation = "1.9.3"
kotlin = "2.2.20"
coreKtx = "1.17.0"
junit = "4.13.2"
lifecycleRuntimeKtxVersion = "2.9.3"
material = "1.9.0"
material3WindowSizeClass = "1.3.2"
lifecycleRuntimeKtxVersion = "2.9.4"
material = "1.9.3"
material3WindowSizeClass = "1.4.0"
materialIconsExtended = "1.7.8"
ui = "1.9.0"
uiGraphics = "1.9.0"
uiTestJunit4 = "1.9.0"
uiTestManifest = "1.9.0"
uiTooling = "1.9.0"
uiToolingPreview = "1.9.0"
slf4jAndroidVersion = "1.7.36"
ui = "1.9.3"
uiGraphics = "1.9.3"
uiTestJunit4 = "1.9.3"
uiTestManifest = "1.9.3"
uiTooling = "1.9.3"
uiToolingPreview = "1.9.3"
[libraries]
androidx-activity-compose-v1101 = { module = "androidx.activity:activity-compose", version.ref = "activityComposeVersion" }
@@ -35,6 +36,7 @@ androidx-material3-window-size-class1 = { module = "androidx.compose.material3:m
autoupdater = { module = "com.github.CSAbhiOnline:AutoUpdater", version.ref = "autoupdater" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
material3 = { module = "androidx.compose.material3:material3", version.ref = "material3WindowSizeClass" }
slf4j-android = { module = "org.slf4j:slf4j-android", version.ref = "slf4jAndroidVersion" }
ui = { module = "androidx.compose.ui:ui", version.ref = "ui" }
ui-graphics = { module = "androidx.compose.ui:ui-graphics", version.ref = "uiGraphics" }
ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "uiTestJunit4" }
+2 -2
View File
@@ -1,6 +1,6 @@
#Mon Apr 28 17:05:34 ICT 2025
#Wed Oct 08 15:20:16 ICT 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-3
View File
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2e71e934cd45ec0cea8c45d9ca8fb64c375f7059691dc51b9c05f3834d2ae2e9
size 89535013
-2
View File
@@ -1,2 +0,0 @@
.env
*.exe
+2 -1
View File
@@ -1,2 +1,3 @@
# Changelog
UPDATE: Fix env
## - UPDATE: Support 4.3.5X
-5
View File
@@ -1,5 +0,0 @@
module release
go 1.25.0
require github.com/joho/godotenv v1.5.1
-2
View File
@@ -1,2 +0,0 @@
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
-154
View File
@@ -1,154 +0,0 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"github.com/joho/godotenv"
)
const (
repoOwner = "Firefly-Shelter"
repoName = "FireflyGo_Android"
giteaURL = "https://git.kain.io.vn"
)
type ReleaseInput struct {
TagName string `json:"tag_name"`
Name string `json:"name"`
Body string `json:"body"`
Draft bool `json:"draft"`
Prerelease bool `json:"prerelease"`
}
type ReleaseResponse struct {
ID int `json:"id"`
HTMLURL string `json:"html_url"`
URL string `json:"url"`
}
func readFile(path string) string {
data, err := os.ReadFile(path)
if err != nil {
panic(fmt.Sprintf("Failed to read %s: %v", path, err))
}
return string(data)
}
func main() {
err := godotenv.Load("script/.env")
if err != nil {
fmt.Println("Error loading .env file")
}
token := os.Getenv("TOKEN")
if token == "" {
fmt.Println("TOKEN not found in .env")
}
releaseJSON := readFile("script/release.json")
var meta map[string]string
if err := json.Unmarshal([]byte(releaseJSON), &meta); err != nil {
panic("Invalid release.json")
}
tag := meta["tag"]
title := meta["title"]
body := readFile("script/README_Note.md")
// Step 1: Create release
releaseInput := ReleaseInput{
TagName: tag,
Name: title,
Body: body,
Draft: false,
Prerelease: false,
}
payload, _ := json.Marshal(releaseInput)
req, _ := http.NewRequest("POST",
fmt.Sprintf("%s/api/v1/repos/%s/%s/releases", giteaURL, repoOwner, repoName),
bytes.NewReader(payload),
)
req.Header.Set("Authorization", "token "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
bodyBytes, _ := io.ReadAll(resp.Body)
panic(fmt.Sprintf("Failed to create release: %s", bodyBytes))
}
var releaseResp ReleaseResponse
if err := json.NewDecoder(resp.Body).Decode(&releaseResp); err != nil {
panic("Failed to decode release response")
}
fmt.Printf("Release created:\n- ID: %d\n- HTML: %s\n", releaseResp.ID, releaseResp.HTMLURL)
uploadURL := releaseResp.URL
if uploadURL == "" {
panic("url missing in release response")
}
files, err := os.ReadDir("app/release")
if err != nil {
panic("Cannot read prebuild folder")
}
for _, file := range files {
if filepath.Ext(file.Name()) != ".apk" {
continue
}
uploadPath := filepath.Join("app/release", file.Name())
fmt.Println("Uploading:", uploadPath)
buf := new(bytes.Buffer)
writer := multipart.NewWriter(buf)
part, err := writer.CreateFormFile("attachment", filepath.Base(uploadPath))
if err != nil {
fmt.Printf("Failed to create form: %v\n", err)
continue
}
src, err := os.Open(uploadPath)
if err != nil {
fmt.Printf("Cannot open file %s: %v\n", file.Name(), err)
continue
}
io.Copy(part, src)
src.Close()
writer.Close()
req, err := http.NewRequest("POST", uploadURL+"/assets", buf)
if err != nil {
fmt.Printf("NewRequest error: %v\n", err)
continue
}
req.Header.Set("Authorization", "token "+token)
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Printf("Upload failed: %v\n", err)
continue
}
if resp.StatusCode != http.StatusCreated {
bodyBytes, _ := io.ReadAll(resp.Body)
fmt.Printf("Upload failed: %s\n", bodyBytes)
} else {
fmt.Println("Uploaded:", file.Name())
}
resp.Body.Close()
}
}
Binary file not shown.
+2 -2
View File
@@ -1,5 +1,5 @@
{
"tag": "3.6.2-02",
"title": "PreBuild Version 3.6.52 - 02"
"tag": "4.3.1-02",
"title": "PreBuild Version 4.3.51 - 02"
}
+12 -4
View File
@@ -1,5 +1,8 @@
pluginManagement {
repositories {
maven {
setUrl("https://jitpack.io")
}
google {
content {
includeGroupByRegex("com\\.android.*")
@@ -9,18 +12,23 @@ pluginManagement {
}
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0"
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
maven {
setUrl("https://jitpack.io")
}
google()
mavenCentral()
maven{
url=uri("https://jitpack.io")
}
}
}
rootProject.name = "FireflyPsAndorid"
rootProject.name = "FireflyGoAndroid"
include(":app")