Compare commits
140 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80071ef0f6 | ||
|
|
d8dd4e7317 | ||
|
|
15eccd8f0d | ||
|
|
d4f55f6916 | ||
|
|
2cfa275c7a | ||
|
|
b1cf0acaae | ||
|
|
8f29a63756 | ||
|
|
a8ab2b0f1a | ||
|
|
28c3da2582 | ||
|
|
b0a7b5ce90 | ||
|
|
bd46c24824 | ||
|
|
8e49998205 | ||
|
|
703563c9b2 | ||
|
|
d44ea60ae9 | ||
|
|
1fc807915f | ||
|
|
bd6c474913 | ||
|
|
66c0ed8d0e | ||
|
|
9634dcb023 | ||
|
|
e4c4cdd63c | ||
|
|
7279bcbc89 | ||
|
|
d9c708e0ca | ||
|
|
21cf5762d2 | ||
|
|
8db70ea674 | ||
|
|
136591a3dd | ||
|
|
72f37aa435 | ||
|
|
4c54e1b773 | ||
|
|
9e8ceb0414 | ||
|
|
ec96d2541e | ||
|
|
9e7560cc4b | ||
|
|
1ad051cd6d | ||
|
|
fda15646eb | ||
|
|
6a9846c6df | ||
|
|
49753566c3 | ||
|
|
66783f896c | ||
|
|
7cc885c62a | ||
|
|
5c6404d86a | ||
|
|
010ea137ac | ||
|
|
6dbca76252 | ||
|
|
c047ffb88e | ||
|
|
6f8adfa586 | ||
|
|
94fa2ad57a | ||
|
|
7ed508945a | ||
|
|
fe2e5bfad9 | ||
|
|
7f36b6693f | ||
|
|
27d60ae71a | ||
|
|
ca1aed1e9b | ||
|
|
04ee72a33d | ||
|
|
d95dffcfcd | ||
|
|
b6bcae3294 | ||
|
|
ebed10b82f | ||
|
|
f4f5a719f5 | ||
|
|
1686622013 | ||
|
|
b9b2b0966c | ||
|
|
724a70bebb | ||
|
|
b24a262ca7 | ||
|
|
06b878a731 | ||
|
|
8c799dc3bf | ||
|
|
4a0734bb04 | ||
|
|
c11699706b | ||
|
|
11dbdcc82a | ||
|
|
9ea6fabbd1 | ||
|
|
5a06022798 | ||
|
|
b85b84399a | ||
|
|
b6be379702 | ||
|
|
5e3557e2da | ||
|
|
a475b1b554 | ||
|
|
dc5f1c1370 | ||
|
|
8e34d08545 | ||
|
|
65a143bec2 | ||
|
|
9a52bac7f1 | ||
|
|
c16d264209 | ||
|
|
9469486174 | ||
|
|
ba3330c0f3 | ||
|
|
859418e50c | ||
|
|
3fe1e4a347 | ||
|
|
d7dfe3c824 | ||
|
|
18843e271f | ||
|
|
1185dad4da | ||
|
|
5c4ca2b07c | ||
|
|
1368bb4445 | ||
|
|
20fb2bb6a4 | ||
|
|
752cade67c | ||
|
|
a689ce21b7 | ||
|
|
37045b432b | ||
|
|
a0ab4beaf4 | ||
|
|
53d5216e88 | ||
|
|
2ed15c4782 | ||
|
|
0da82802b8 | ||
|
|
d2465b5d4b | ||
|
|
e8590d54c7 | ||
|
|
2e3ac1231f | ||
|
|
99e4dbbb0d | ||
|
|
07ece4412f | ||
|
|
bde0532dbd | ||
|
|
d69b842c80 | ||
|
|
57fdc1b637 | ||
|
|
d700216cfc | ||
|
|
6813456d12 | ||
|
|
97db1324b6 | ||
|
|
ebd7eb1405 | ||
|
|
310372b8e2 | ||
|
|
d5a6dd49a1 | ||
|
|
f30676df07 | ||
|
|
690e6cbbf5 | ||
|
|
bd24ca02ae | ||
|
|
d9a8accad7 | ||
|
|
b166babf12 | ||
|
|
4aa4d9d350 | ||
|
|
60fd4135ec | ||
|
|
0bb9244214 | ||
|
|
cfcde0b024 | ||
|
|
053bd24855 | ||
|
|
7d1f36046d | ||
|
|
22ae07de90 | ||
|
|
a76909a2c7 | ||
|
|
8144f305e2 | ||
|
|
04721e2450 | ||
|
|
85ab19fb4a | ||
|
|
03f76b6497 | ||
|
|
9a571da4b1 | ||
|
|
797cc815f6 | ||
|
|
30aceb2a76 | ||
|
|
4340450d78 | ||
|
|
2bac87cd39 | ||
|
|
1aac97dfee | ||
|
|
84b090d51d | ||
|
|
a592713623 | ||
|
|
ec6b9cee07 | ||
|
|
b6fcad0a65 | ||
|
|
5273520305 | ||
|
|
751cb1e341 | ||
|
|
add90c5603 | ||
|
|
3410eeda19 | ||
|
|
c690323803 | ||
|
|
59dd7bfd05 | ||
|
|
3fa716e515 | ||
|
|
9aa240e335 | ||
|
|
88fa8aa2ee | ||
|
|
2601f1b776 | ||
|
|
763dfdde04 |
31
.dockerignore
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# 排除不需要的文件和目录,减少 Docker 构建上下文大小
|
||||||
|
|
||||||
|
# 开发工具
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# 构建产物(本地构建时会重新生成)
|
||||||
|
docs/
|
||||||
|
pkg/
|
||||||
|
|
||||||
|
# 临时文件
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# CI 相关文件
|
||||||
|
.github/
|
||||||
|
Dockerfile.ci
|
||||||
|
|
||||||
|
# 其他不需要的目录
|
||||||
|
android/app/build/
|
||||||
|
android/.gradle/
|
||||||
|
resources/
|
||||||
|
electron/dist/
|
||||||
38
.dockerignore.ci
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# CI 构建专用的 dockerignore
|
||||||
|
# 只保留构建产物和必要的配置文件
|
||||||
|
|
||||||
|
# 排除所有源代码和开发文件
|
||||||
|
src/
|
||||||
|
public/
|
||||||
|
electron/
|
||||||
|
node_modules/
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
.git/
|
||||||
|
.github/
|
||||||
|
|
||||||
|
# 排除构建工具配置
|
||||||
|
vite.config.ts
|
||||||
|
tsconfig*.json
|
||||||
|
*.config.js
|
||||||
|
*.config.ts
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
||||||
|
pnpm-lock.yaml
|
||||||
|
|
||||||
|
# 排除其他构建产物
|
||||||
|
pkg/
|
||||||
|
android/
|
||||||
|
resources/
|
||||||
|
|
||||||
|
# 排除临时文件
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# 只保留以下文件:
|
||||||
|
# - docs/ (构建产物)
|
||||||
|
# - nginx.conf (nginx配置)
|
||||||
|
# - Dockerfile.ci
|
||||||
15
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||||
|
polar: # Replace with a single Polar username
|
||||||
|
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||||
|
thanks_dev: # Replace with a single thanks.dev username
|
||||||
|
custom: ['https://afdian.com/a/setube'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
31
.github/ISSUE_TEMPLATE/BUG反馈.md
vendored
@@ -1,31 +0,0 @@
|
|||||||
---
|
|
||||||
name: BUG反馈
|
|
||||||
about: 报告项目中发现的缺陷或问题
|
|
||||||
title: '[BUG] 简要描述问题'
|
|
||||||
labels: 'bug'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
**问题描述**
|
|
||||||
清晰准确地描述遇到的问题
|
|
||||||
|
|
||||||
**重现步骤**
|
|
||||||
|
|
||||||
1. 第一步操作
|
|
||||||
2. 第二步操作
|
|
||||||
3. 出现问题的操作
|
|
||||||
|
|
||||||
**期望行为**
|
|
||||||
描述您认为正确的行为应该是怎样的
|
|
||||||
|
|
||||||
**实际行为**
|
|
||||||
描述实际发生的错误行为
|
|
||||||
|
|
||||||
**环境信息**
|
|
||||||
|
|
||||||
- 操作系统:
|
|
||||||
- 浏览器(如适用):
|
|
||||||
- 项目版本:
|
|
||||||
|
|
||||||
**截图或日志(可选)**
|
|
||||||
如果有错误截图或日志,请提供
|
|
||||||
19
.github/ISSUE_TEMPLATE/功能请求.md
vendored
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
name: 功能请求
|
|
||||||
about: 请求添加新功能或改进现有功能
|
|
||||||
title: '[功能] 简要描述功能'
|
|
||||||
labels: 'enhancement'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
**功能描述**
|
|
||||||
清晰描述您希望添加的功能
|
|
||||||
|
|
||||||
**功能背景**
|
|
||||||
说明为什么需要这个功能,它能解决什么问题
|
|
||||||
|
|
||||||
**建议实现方案(可选)**
|
|
||||||
如果有具体的实现想法,可以在这里描述
|
|
||||||
|
|
||||||
**附加信息**
|
|
||||||
任何其他有助于理解这个功能的信息
|
|
||||||
19
.github/ISSUE_TEMPLATE/反馈建议.md
vendored
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
name: 反馈建议
|
|
||||||
about: 为这个项目提出功能建议或改进意见
|
|
||||||
title: '[建议] 简要描述您的建议'
|
|
||||||
labels: 'enhancement'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
**您的建议是什么?**
|
|
||||||
请清晰描述您希望添加的功能或改进点
|
|
||||||
|
|
||||||
**为什么需要这个功能/改进?**
|
|
||||||
说明这个建议会解决什么问题或带来什么价值
|
|
||||||
|
|
||||||
**您期望的实现方式(可选)**
|
|
||||||
如果有具体的实现想法,可以在这里描述
|
|
||||||
|
|
||||||
**附加信息(可选)**
|
|
||||||
任何其他有助于理解这个建议的信息
|
|
||||||
19
.github/ISSUE_TEMPLATE/文档改进.md
vendored
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
name: 文档改进
|
|
||||||
about: 报告文档问题或建议改进
|
|
||||||
title: '[文档] 简要描述问题'
|
|
||||||
labels: 'documentation'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
**文档位置**
|
|
||||||
指出需要改进的文档路径或 URL
|
|
||||||
|
|
||||||
**当前问题**
|
|
||||||
描述当前文档存在的问题或不清晰的地方
|
|
||||||
|
|
||||||
**改进建议**
|
|
||||||
提出具体的改进建议
|
|
||||||
|
|
||||||
**附加信息(可选)**
|
|
||||||
任何其他有助于改进文档的信息
|
|
||||||
140
.github/workflows/build.yml
vendored
@@ -15,26 +15,27 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- goos: windows
|
- goos: windows
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
executable: ogame-server-win.exe
|
executable: OGame-Vue-Ts-server-win.exe
|
||||||
- goos: linux
|
- goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
executable: ogame-server-linux
|
executable: OGame-Vue-Ts-server-linux
|
||||||
- goos: linux
|
- goos: linux
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
executable: ogame-server-linux-arm64
|
executable: OGame-Vue-Ts-server-linux-arm64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v3
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 8
|
version: latest
|
||||||
- name: Setup Node & Go
|
- name: Setup Node & Go
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25'
|
go-version: '1.23'
|
||||||
|
cache: true
|
||||||
|
|
||||||
- name: Build Frontend & Server
|
- name: Build Frontend & Server
|
||||||
run: |
|
run: |
|
||||||
@@ -49,7 +50,78 @@ jobs:
|
|||||||
name: server-${{ matrix.goos }}-${{ matrix.goarch }}
|
name: server-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
path: ${{ matrix.executable }}
|
path: ${{ matrix.executable }}
|
||||||
|
|
||||||
# 2. 构建 Electron 客户端
|
# 2. 构建 Android APK (ARM64, ARMv7, x86_64)
|
||||||
|
build-android:
|
||||||
|
name: Build Android APK
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: 'pnpm'
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v5
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '21'
|
||||||
|
- name: Setup Android SDK
|
||||||
|
uses: android-actions/setup-android@v3
|
||||||
|
|
||||||
|
# 使用官方 Gradle Action(内置智能缓存)
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
with:
|
||||||
|
cache-read-only: false
|
||||||
|
|
||||||
|
- name: Build Frontend
|
||||||
|
run: |
|
||||||
|
pnpm install
|
||||||
|
pnpm run build
|
||||||
|
|
||||||
|
- name: Install ImageMagick
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y imagemagick
|
||||||
|
|
||||||
|
- name: Generate Android Icons
|
||||||
|
run: |
|
||||||
|
# 使用 ImageMagick 生成各尺寸图标
|
||||||
|
convert logo.png -resize 48x48 android/app/src/main/res/mipmap-mdpi/ic_launcher.png
|
||||||
|
convert logo.png -resize 48x48 android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
|
||||||
|
convert logo.png -resize 72x72 android/app/src/main/res/mipmap-hdpi/ic_launcher.png
|
||||||
|
convert logo.png -resize 72x72 android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
|
||||||
|
convert logo.png -resize 96x96 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
|
||||||
|
convert logo.png -resize 96x96 android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
|
||||||
|
convert logo.png -resize 144x144 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
|
||||||
|
convert logo.png -resize 144x144 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
|
||||||
|
convert logo.png -resize 192x192 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
|
||||||
|
convert logo.png -resize 192x192 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
|
||||||
|
# foreground 图标需要更大(108dp with 72dp safe zone)
|
||||||
|
convert logo.png -resize 108x108 android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
|
||||||
|
convert logo.png -resize 162x162 android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
|
||||||
|
convert logo.png -resize 216x216 android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
|
||||||
|
convert logo.png -resize 324x324 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
|
||||||
|
convert logo.png -resize 432x432 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
|
||||||
|
|
||||||
|
- name: Sync Capacitor
|
||||||
|
run: npx cap sync android
|
||||||
|
|
||||||
|
- name: Build APK (Release)
|
||||||
|
working-directory: android
|
||||||
|
run: |
|
||||||
|
chmod +x ./gradlew
|
||||||
|
./gradlew assembleRelease --build-cache
|
||||||
|
|
||||||
|
- name: Upload APK Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: android-apk
|
||||||
|
path: android/app/build/outputs/apk/release/*.apk
|
||||||
|
|
||||||
|
# 3. 构建 Electron 客户端
|
||||||
build-electron:
|
build-electron:
|
||||||
name: Build Electron (${{ matrix.os }})
|
name: Build Electron (${{ matrix.os }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
@@ -64,16 +136,26 @@ jobs:
|
|||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
platform: linux
|
platform: linux
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v3
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 8
|
version: latest
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Cache Electron Builder
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/electron
|
||||||
|
~/.cache/electron-builder
|
||||||
|
key: electron-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
electron-${{ runner.os }}-
|
||||||
|
|
||||||
- name: Build Electron
|
- name: Build Electron
|
||||||
run: |
|
run: |
|
||||||
pnpm install
|
pnpm install
|
||||||
@@ -91,14 +173,14 @@ jobs:
|
|||||||
pkg/*.dmg
|
pkg/*.dmg
|
||||||
pkg/*.AppImage
|
pkg/*.AppImage
|
||||||
|
|
||||||
# 3. 发布 Release
|
# 4. 发布 Release
|
||||||
release:
|
release:
|
||||||
needs: [ build-server, build-electron ]
|
needs: [build-server, build-android, build-electron]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Get Version
|
- name: Get Version
|
||||||
id: get_version
|
id: get_version
|
||||||
@@ -116,21 +198,35 @@ jobs:
|
|||||||
mkdir -p ./final-release
|
mkdir -p ./final-release
|
||||||
|
|
||||||
# 移动 Server 文件并确保名字唯一
|
# 移动 Server 文件并确保名字唯一
|
||||||
# 注意:根据你之前的附件,Artifact 名字是 server-windows-amd64
|
cp ./raw-assets/server-windows-amd64/OGame-Vue-Ts-server-win.exe ./final-release/OGame-Vue-Ts-server-win.exe || cp ./raw-assets/server-windows-amd64/server-windows-amd64.exe ./final-release/OGame-Vue-Ts-server-win.exe || true
|
||||||
cp ./raw-assets/server-windows-amd64/ogame-server-win.exe ./final-release/ogame-server-win.exe || cp ./raw-assets/server-windows-amd64/server-windows-amd64.exe ./final-release/ogame-server-win.exe || true
|
cp ./raw-assets/server-linux-amd64/OGame-Vue-Ts-server-linux ./final-release/OGame-Vue-Ts-server-linux || true
|
||||||
cp ./raw-assets/server-linux-amd64/ogame-server-linux ./final-release/ogame-server-linux || true
|
cp ./raw-assets/server-linux-arm64/OGame-Vue-Ts-server-linux-arm64 ./final-release/OGame-Vue-Ts-server-linux-arm64 || true
|
||||||
cp ./raw-assets/server-linux-arm64/ogame-server-linux-arm64 ./final-release/ogame-server-linux-arm64 || true
|
|
||||||
|
|
||||||
# 移动 Electron 安装包 (排除 unpacked 目录)
|
# 移动 Electron 安装包 (排除 unpacked 目录)
|
||||||
find ./raw-assets/electron-* -type f \( -name "*.exe" -o -name "*.dmg" -o -name "*.AppImage" -o -name "*.zip" \) -exec cp {} ./final-release/ \;
|
find ./raw-assets/electron-* -type f \( -name "*.exe" -o -name "*.dmg" -o -name "*.AppImage" -o -name "*.zip" \) -exec cp {} ./final-release/ \;
|
||||||
|
|
||||||
|
# 移动 Android APK
|
||||||
|
find ./raw-assets/android-apk -type f -name "*.apk" -exec cp {} ./final-release/ \; || true
|
||||||
|
|
||||||
# 检查结果
|
# 检查结果
|
||||||
echo "Final assets to upload:"
|
echo "Final assets to upload:"
|
||||||
ls -R ./final-release
|
ls -R ./final-release
|
||||||
|
|
||||||
# 3. 一次性上传,禁止重复匹配
|
# 3. 删除已存在的同名 APK 资源(避免 422 错误)
|
||||||
|
- name: Delete existing APK assets
|
||||||
|
run: |
|
||||||
|
VERSION=${{ steps.get_version.outputs.VERSION }}
|
||||||
|
# 获取 release 中的现有 assets 并删除 APK 文件
|
||||||
|
gh release view "$VERSION" --json assets -q '.assets[].name' 2>/dev/null | grep -i '\.apk$' | while read asset; do
|
||||||
|
echo "Deleting existing asset: $asset"
|
||||||
|
gh release delete-asset "$VERSION" "$asset" -y || true
|
||||||
|
done
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# 4. 一次性上传,禁止重复匹配
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ steps.get_version.outputs.VERSION }}
|
tag_name: ${{ steps.get_version.outputs.VERSION }}
|
||||||
name: Release ${{ steps.get_version.outputs.VERSION }}
|
name: Release ${{ steps.get_version.outputs.VERSION }}
|
||||||
|
|||||||
72
.github/workflows/github-pages.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
name: 构建 Github Pages
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main] # 如果你的主分支叫 master,请改为 master
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: 设置 pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
- name: 设置 Node.js
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: 缓存 pnpm 依赖
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
node_modules
|
||||||
|
key: ${{ runner.os }}-pnpm-pages-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-pages-
|
||||||
|
|
||||||
|
- name: 安装依赖
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: 构建前端项目
|
||||||
|
run: pnpm run build
|
||||||
|
|
||||||
|
- name: 验证构建产物
|
||||||
|
run: |
|
||||||
|
if [ ! -d "docs" ]; then
|
||||||
|
echo "❌ 构建失败:docs 目录不存在"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "docs/index.html" ]; then
|
||||||
|
echo "❌ 构建失败:docs/index.html 不存在"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✅ 构建产物验证通过"
|
||||||
|
ls -la docs/
|
||||||
|
|
||||||
|
# 关键步骤:告诉 GitHub Actions 跳过 Jekyll 检查
|
||||||
|
- name: 配置 Github Pages
|
||||||
|
uses: actions/configure-pages@v5
|
||||||
|
|
||||||
|
- name: 上传构建版
|
||||||
|
uses: actions/upload-pages-artifact@v4
|
||||||
|
with:
|
||||||
|
path: './docs'
|
||||||
|
|
||||||
|
- name: 部署到 GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
136
.github/workflows/ogame-vue-ts.yml
vendored
@@ -1,9 +1,9 @@
|
|||||||
name: Docker 多架构构建并发布
|
name: 构建并发布 Docker 镜像
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [main]
|
||||||
tags: [ 'v*.*.*' ] # 打 tag 时也触发
|
tags: ['v*.*.*'] # 打 tag 时也触发
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -15,10 +15,113 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 检出代码
|
- name: 检出代码
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# 设置 Node.js 环境
|
||||||
|
- name: 设置 Node.js
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
# 设置 pnpm
|
||||||
|
- name: 设置 pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
# 缓存 pnpm 依赖
|
||||||
|
- name: 缓存 pnpm 依赖
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
node_modules
|
||||||
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pnpm-
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
- name: 安装依赖
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# 构建项目
|
||||||
|
- name: 构建项目
|
||||||
|
run: pnpm run build
|
||||||
|
|
||||||
|
# 验证构建产物
|
||||||
|
- name: 验证构建产物
|
||||||
|
run: |
|
||||||
|
if [ ! -d "docs" ]; then
|
||||||
|
echo "❌ 构建失败:docs 目录不存在"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "docs/index.html" ]; then
|
||||||
|
echo "❌ 构建失败:docs/index.html 不存在"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查构建产物的时间戳,确保是最新的
|
||||||
|
BUILD_TIME=$(stat -c %Y docs/index.html 2>/dev/null || stat -f %m docs/index.html 2>/dev/null || echo "0")
|
||||||
|
CURRENT_TIME=$(date +%s)
|
||||||
|
TIME_DIFF=$((CURRENT_TIME - BUILD_TIME))
|
||||||
|
|
||||||
|
echo "📊 构建产物信息:"
|
||||||
|
echo " 构建时间: $(date -d @$BUILD_TIME 2>/dev/null || date -r $BUILD_TIME 2>/dev/null || echo '未知')"
|
||||||
|
echo " 当前时间: $(date)"
|
||||||
|
echo " 时间差: ${TIME_DIFF}秒"
|
||||||
|
|
||||||
|
if [ $TIME_DIFF -gt 300 ]; then
|
||||||
|
echo "⚠️ 警告: 构建产物可能不是最新的(超过5分钟)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ 构建产物验证通过"
|
||||||
|
ls -la docs/
|
||||||
|
|
||||||
|
# 获取当前日期
|
||||||
|
- name: 获取当前日期
|
||||||
|
id: date
|
||||||
|
run: echo "date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# 获取版本号
|
||||||
|
- name: 获取版本号
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
VERSION=$(node -p "require('./package.json').version")
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "📦 当前版本: $VERSION"
|
||||||
|
|
||||||
|
# 准备 CI 构建环境
|
||||||
|
- name: 准备 CI 构建环境
|
||||||
|
run: |
|
||||||
|
# 使用 CI 专用的 dockerignore
|
||||||
|
cp .dockerignore.ci .dockerignore
|
||||||
|
echo "✅ 已切换到 CI 构建模式"
|
||||||
|
echo "📁 当前构建上下文文件:"
|
||||||
|
ls -la | grep -E "(docs|nginx.conf|Dockerfile.ci|\.dockerignore)$"
|
||||||
|
|
||||||
|
# 清理可能冲突的镜像标签
|
||||||
|
- name: 清理可能冲突的镜像标签
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
|
echo "🧹 尝试清理可能冲突的镜像标签..."
|
||||||
|
|
||||||
|
# 尝试删除 GHCR 中的现有标签(如果存在)
|
||||||
|
echo "清理 GHCR 标签..."
|
||||||
|
docker buildx imagetools inspect ghcr.io/${{ github.repository_owner }}/ogame-vue-ts:$VERSION 2>/dev/null && \
|
||||||
|
echo "发现现有版本标签,将被覆盖" || echo "版本标签不存在,可以安全推送"
|
||||||
|
|
||||||
|
# 如果配置了 Docker Hub,也尝试检查
|
||||||
|
if [ -n "${{ vars.DOCKERHUB_USERNAME }}" ]; then
|
||||||
|
echo "检查 Docker Hub 标签..."
|
||||||
|
docker buildx imagetools inspect ${{ vars.DOCKERHUB_USERNAME }}/ogame-vue-ts:$VERSION 2>/dev/null && \
|
||||||
|
echo "发现现有 Docker Hub 版本标签,将被覆盖" || echo "Docker Hub 版本标签不存在,可以安全推送"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ 标签冲突检查完成,构建将覆盖任何现有标签"
|
||||||
|
|
||||||
# QEMU 用于支持多架构构建(必须)
|
# QEMU 用于支持多架构构建(必须)
|
||||||
- name: 设置 QEMU
|
- name: 设置 QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
@@ -37,23 +140,40 @@ jobs:
|
|||||||
|
|
||||||
# 登录 Docker Hub(只在用户名存在时执行)
|
# 登录 Docker Hub(只在用户名存在时执行)
|
||||||
- name: 登录 Docker Hub
|
- name: 登录 Docker Hub
|
||||||
if: vars.DOCKERHUB_USERNAME != '' # 只检查 vars,忽略 secrets
|
if: vars.DOCKERHUB_USERNAME != '' # 只检查 vars,忽略 secrets
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
# 真正一键构建 + 推送多架构镜像(amd64 + arm64)
|
# 构建并推送多架构镜像(使用构建产物)
|
||||||
- name: 构建并推送多架构镜像
|
- name: 构建并推送多架构镜像
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: ./Dockerfile.ci
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
|
no-cache: false
|
||||||
|
pull: true
|
||||||
tags: |
|
tags: |
|
||||||
ghcr.io/${{ github.repository_owner }}/ogame-vue-ts:latest
|
ghcr.io/${{ github.repository_owner }}/ogame-vue-ts:latest
|
||||||
|
ghcr.io/${{ github.repository_owner }}/ogame-vue-ts:${{ steps.version.outputs.version }}
|
||||||
ghcr.io/${{ github.repository_owner }}/ogame-vue-ts:${{ github.sha }}
|
ghcr.io/${{ github.repository_owner }}/ogame-vue-ts:${{ github.sha }}
|
||||||
${{ vars.DOCKERHUB_USERNAME != '' && format('docker.io/{0}/ogame-vue-ts:latest', vars.DOCKERHUB_USERNAME) || '' }}
|
${{ vars.DOCKERHUB_USERNAME && format('{0}/ogame-vue-ts:latest', vars.DOCKERHUB_USERNAME) || '' }}
|
||||||
${{ vars.DOCKERHUB_USERNAME != '' && format('docker.io/{0}/ogame-vue-ts:{1}', vars.DOCKERHUB_USERNAME, github.sha) || '' }}
|
${{ vars.DOCKERHUB_USERNAME && format('{0}/ogame-vue-ts:{1}', vars.DOCKERHUB_USERNAME, steps.version.outputs.version) || '' }}
|
||||||
|
${{ vars.DOCKERHUB_USERNAME && format('{0}/ogame-vue-ts:{1}', vars.DOCKERHUB_USERNAME, github.sha) || '' }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
build-args: |
|
||||||
|
BUILDKIT_INLINE_CACHE=1
|
||||||
|
BUILD_DATE=${{ steps.date.outputs.date }}
|
||||||
|
VERSION=${{ steps.version.outputs.version }}
|
||||||
|
COMMIT_SHA=${{ github.sha }}
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.title=OGame Vue Ts
|
||||||
|
org.opencontainers.image.description=OGame Vue TypeScript Implementation
|
||||||
|
org.opencontainers.image.version=${{ steps.version.outputs.version }}
|
||||||
|
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.created=${{ steps.date.outputs.date }}
|
||||||
|
|||||||
13
.gitignore
vendored
@@ -11,6 +11,8 @@ CLAUDE.md
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
|
dist-electron
|
||||||
|
docs
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
@@ -24,3 +26,14 @@ dist-ssr
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
/docs
|
||||||
|
/docs/assets
|
||||||
|
|
||||||
|
# Android build outputs
|
||||||
|
android/.gradle
|
||||||
|
android/app/build
|
||||||
|
android/build
|
||||||
|
android/local.properties
|
||||||
|
android/.idea
|
||||||
|
android/*.iml
|
||||||
|
android/app/*.iml
|
||||||
|
|||||||
89
DOCKER.md
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# Docker 构建说明
|
||||||
|
|
||||||
|
本项目支持两种 Docker 构建方式:
|
||||||
|
|
||||||
|
## 🏠 本地构建
|
||||||
|
|
||||||
|
### 方式一:使用构建脚本(推荐)
|
||||||
|
|
||||||
|
**Linux/macOS:**
|
||||||
|
```bash
|
||||||
|
chmod +x build-docker.sh
|
||||||
|
./build-docker.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows:**
|
||||||
|
```cmd
|
||||||
|
build-docker.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式二:直接使用 Docker 命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建镜像
|
||||||
|
docker build -t ogame-vue-ts:local .
|
||||||
|
|
||||||
|
# 运行容器
|
||||||
|
docker run -p 8080:80 ogame-vue-ts:local
|
||||||
|
```
|
||||||
|
|
||||||
|
## ☁️ GitHub Actions 自动构建
|
||||||
|
|
||||||
|
当代码推送到 `main` 分支或创建 tag 时,GitHub Actions 会自动:
|
||||||
|
|
||||||
|
1. 在 Actions 环境中构建项目
|
||||||
|
2. 使用构建产物创建 Docker 镜像
|
||||||
|
3. 推送到 GitHub Container Registry 和 Docker Hub
|
||||||
|
|
||||||
|
### 使用预构建镜像
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 从 GitHub Container Registry 拉取
|
||||||
|
docker pull ghcr.io/your-username/ogame-vue-ts:latest
|
||||||
|
|
||||||
|
# 从 Docker Hub 拉取(如果配置了)
|
||||||
|
docker pull your-dockerhub-username/ogame-vue-ts:latest
|
||||||
|
|
||||||
|
# 运行
|
||||||
|
docker run -p 8080:80 ghcr.io/your-username/ogame-vue-ts:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 文件说明
|
||||||
|
|
||||||
|
- `Dockerfile` - 本地构建用,包含完整的源代码构建流程
|
||||||
|
- `Dockerfile.ci` - GitHub Actions 构建用,使用预构建产物
|
||||||
|
- `.dockerignore` - 本地构建时排除的文件
|
||||||
|
- `.dockerignore.ci` - CI 构建时排除的文件
|
||||||
|
- `build-docker.sh` / `build-docker.bat` - 本地构建便捷脚本
|
||||||
|
|
||||||
|
## 🔧 配置说明
|
||||||
|
|
||||||
|
### GitHub Actions 环境变量
|
||||||
|
|
||||||
|
需要在 GitHub 仓库设置中配置:
|
||||||
|
|
||||||
|
**Variables (公开):**
|
||||||
|
- `DOCKERHUB_USERNAME` - Docker Hub 用户名(可选)
|
||||||
|
|
||||||
|
**Secrets (私密):**
|
||||||
|
- `DOCKERHUB_TOKEN` - Docker Hub 访问令牌(可选)
|
||||||
|
- `GITHUB_TOKEN` - 自动提供,用于 GHCR
|
||||||
|
|
||||||
|
### 本地构建要求
|
||||||
|
|
||||||
|
- Docker
|
||||||
|
- 足够的磁盘空间(构建过程中会下载 Node.js 依赖)
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
1. **本地开发测试:**
|
||||||
|
```bash
|
||||||
|
./build-docker.sh
|
||||||
|
docker run -p 8080:80 ogame-vue-ts:local
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **访问应用:**
|
||||||
|
打开浏览器访问 `http://localhost:8080`
|
||||||
|
|
||||||
|
3. **生产部署:**
|
||||||
|
使用 GitHub Actions 自动构建的镜像进行部署
|
||||||
39
Dockerfile
@@ -1,21 +1,40 @@
|
|||||||
FROM node:latest AS builder
|
# 本地构建用的 Dockerfile
|
||||||
|
# 支持完整的源代码构建流程
|
||||||
|
|
||||||
RUN mkdir -p /workspace
|
FROM node:20-alpine AS builder
|
||||||
WORKDIR /workspace
|
|
||||||
RUN npm config set registry https://registry.npmmirror.com
|
|
||||||
RUN git clone https://github.com/setube/ogame-vue-ts.git
|
|
||||||
RUN mv ./ogame-vue-ts/* . ; rm -rf ./ogame-vue-ts/
|
|
||||||
|
|
||||||
RUN npm install -g pnpm ; pnpm install;
|
# 设置工作目录
|
||||||
RUN pnpm build
|
WORKDIR /app
|
||||||
|
|
||||||
# --- 第二阶段:Nginx ---
|
# 复制 package 文件
|
||||||
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
|
||||||
|
# 安装 pnpm
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# 复制源代码
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 构建项目
|
||||||
|
RUN pnpm run build
|
||||||
|
|
||||||
|
# 生产阶段
|
||||||
FROM nginx:alpine
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# 复制 nginx 配置文件
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# 清理默认的 nginx 静态文件
|
||||||
RUN rm -rf /usr/share/nginx/html/*
|
RUN rm -rf /usr/share/nginx/html/*
|
||||||
COPY --from=builder /workspace/docs /usr/share/nginx/html
|
|
||||||
|
|
||||||
|
# 复制构建产物到 nginx 静态文件目录
|
||||||
|
COPY --from=builder /app/docs /usr/share/nginx/html
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
|
# 启动 nginx
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
35
Dockerfile.ci
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# GitHub Actions 构建用的 Dockerfile
|
||||||
|
# 使用预构建的产物,不包含源代码构建过程
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# 添加构建参数用于缓存破坏
|
||||||
|
ARG BUILD_DATE
|
||||||
|
ARG VERSION
|
||||||
|
ARG COMMIT_SHA
|
||||||
|
|
||||||
|
# 添加标签信息
|
||||||
|
LABEL build.date="${BUILD_DATE}" \
|
||||||
|
build.version="${VERSION}" \
|
||||||
|
build.commit="${COMMIT_SHA}"
|
||||||
|
|
||||||
|
# 复制 nginx 配置文件
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# 清理默认的 nginx 静态文件
|
||||||
|
RUN rm -rf /usr/share/nginx/html/*
|
||||||
|
|
||||||
|
# 复制构建产物到 nginx 静态文件目录
|
||||||
|
# 这里的 docs 目录是在 GitHub Actions 中构建生成的
|
||||||
|
# 使用 --chown 确保正确的文件权限
|
||||||
|
COPY --chown=nginx:nginx docs /usr/share/nginx/html
|
||||||
|
|
||||||
|
# 验证构建产物
|
||||||
|
RUN ls -la /usr/share/nginx/html/ && \
|
||||||
|
test -f /usr/share/nginx/html/index.html || (echo "构建产物验证失败" && exit 1)
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# 启动 nginx
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
125
README-DE.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img src="public/logo.svg" alt="OGame Vue TS Logo" width="128" height="128">
|
||||||
|
|
||||||
|
# OGame Vue TS
|
||||||
|
|
||||||
|
Ein modernes Weltraum-Strategiespiel basierend auf dem klassischen OGame, entwickelt mit Vue 3 und TypeScript.
|
||||||
|
|
||||||
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
|
[](https://www.taptap.cn/app/801190)
|
||||||
|
|
||||||
|
[简体中文](README.md)| [繁體中文](README-zh-TW.md) | [English](README-EN.md) | Deutsch | [Русский](README-RU.md) | [Español](README-ES.md) | [한국어](README-KO.md) | [日本語](README-JA.md)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Über das Projekt
|
||||||
|
|
||||||
|
OGame Vue TS ist ein Einzelspieler-Weltraum-Strategiespiel im Browser, inspiriert vom klassischen OGame. Baue dein Imperium in der Galaxie auf, erforsche Technologien, konstruiere Raumschiffe und nimm an epischen Weltraumschlachten teil. Dieses Projekt wurde mit modernen Webtechnologien entwickelt und läuft vollständig im Browser mit lokaler Datenspeicherung.
|
||||||
|
|
||||||
|
## Hauptfunktionen
|
||||||
|
|
||||||
|
- **Gebäudeverwaltung** - Baue und verbessere verschiedene Gebäude auf Planeten und Monden
|
||||||
|
- **Technologieforschung** - Schalte fortschrittliche Technologien frei, um dein Imperium zu stärken
|
||||||
|
- **Flottenverwaltung** - Baue Schiffe, sende Missionen und nimm an taktischen Weltraumkämpfen teil
|
||||||
|
- **Verteidigungssysteme** - Errichte Verteidigungsanlagen zum Schutz deiner Kolonien
|
||||||
|
- **Offiziersystem** - Rekrutiere Offiziere für strategische Vorteile
|
||||||
|
- **Kampfsimulator** - Teste Kampfszenarien, bevor du Ressourcen einsetzt
|
||||||
|
- **Galaxieansicht** - Erkunde das Universum und interagiere mit anderen Planeten
|
||||||
|
- **Lokale Datenspeicherung** - Alle Spieldaten werden verschlüsselt im Browser gespeichert
|
||||||
|
- **Dunkler/Heller Modus** - Wähle dein bevorzugtes visuelles Thema
|
||||||
|
- **Warteschlangenverwaltung** - Verwalte mehrere Bau- und Forschungswarteschlangen
|
||||||
|
- **Mondgenerierung** - Wahrscheinlichkeitsbasierte Monderzeugung aus Trümmerfeldern
|
||||||
|
|
||||||
|
## Technologie-Stack
|
||||||
|
|
||||||
|
- **Frontend-Framework:** [Vue 3](https://vuejs.org) + Composition API (`<script setup>` Syntax)
|
||||||
|
- **Programmiersprache:** [TypeScript](https://www.typescriptlang.org) (mit strikter Typprüfung)
|
||||||
|
- **Build-Tool:** [Vite](https://vitejs.dev) (Custom Rolldown-Vite 7.2.5), [Golang](https://golang.org) (für plattformübergreifenden Webserver), [Electron](https://www.electronjs.org) (für plattformübergreifende Desktop-Anwendung)
|
||||||
|
- **Zustandsverwaltung:** [Pinia](https://pinia.vuejs.org) + Persistenz-Plugin
|
||||||
|
- **Routing:** [Vue Router 4](https://router.vuejs.org)
|
||||||
|
- **UI-Komponenten:** [shadcn-vue](https://www.shadcn-vue.com) (New York Stil)
|
||||||
|
- **Styling:** [Tailwind CSS v4](https://tailwindcss.com) + CSS-Variablen
|
||||||
|
- **Icons:** [Lucide Vue Next](https://lucide.dev)
|
||||||
|
- **Animationen:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
|
- **Internationalisierung:** Eigene i18n-Implementierung
|
||||||
|
|
||||||
|
## Schnellstart
|
||||||
|
|
||||||
|
### Voraussetzungen
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org) (Version 18 oder höher empfohlen)
|
||||||
|
- [pnpm](https://pnpm.io) (Version 10.13.1 oder höher)
|
||||||
|
- [Go](https://golang.org) (Version 1.21 oder höher) (optional)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Repository klonen
|
||||||
|
git clone https://github.com/setube/ogame-vue-ts.git
|
||||||
|
|
||||||
|
# In das Projektverzeichnis wechseln
|
||||||
|
cd ogame-vue-ts
|
||||||
|
|
||||||
|
# Abhängigkeiten installieren
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Entwicklung
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Entwicklungsserver starten (läuft auf Port 25121)
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Öffne deinen Browser und besuche `http://localhost:25121`
|
||||||
|
|
||||||
|
### Produktions-Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Anwendung bauen
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# Produktions-Build vorschauen
|
||||||
|
pnpm preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## Datensicherheit
|
||||||
|
|
||||||
|
Alle Spieldaten werden automatisch mit AES-Verschlüsselung verschlüsselt, bevor sie im lokalen Speicher des Browsers gespeichert werden. Dein Spielfortschritt ist sicher und privat.
|
||||||
|
|
||||||
|
## Anpassung
|
||||||
|
|
||||||
|
Die Anwendung unterstützt vollständige Theme-Anpassung durch Tailwind CSS-Variablen, die in `src/style.css` definiert sind. Du kannst einfach zwischen hellem und dunklem Modus wechseln.
|
||||||
|
|
||||||
|
## Mitwirken
|
||||||
|
|
||||||
|
Beiträge sind willkommen! Bitte zögere nicht, Issues oder Pull Requests einzureichen.
|
||||||
|
|
||||||
|
## Lizenz
|
||||||
|
|
||||||
|
Dieses Werk ist lizenziert unter der [Creative Commons Namensnennung-Nicht kommerziell 4.0 International Lizenz](https://creativecommons.org/licenses/by-nc/4.0).
|
||||||
|
|
||||||
|
### Du darfst:
|
||||||
|
- **Teilen** — das Material in jedwedem Format oder Medium vervielfältigen und weiterverbreiten
|
||||||
|
- **Bearbeiten** — das Material remixen, verändern und darauf aufbauen
|
||||||
|
|
||||||
|
### Unter folgenden Bedingungen:
|
||||||
|
- **Namensnennung** — Du musst angemessene Urheber- und Rechteangaben machen, einen Link zur Lizenz beifügen und angeben, ob Änderungen vorgenommen wurden
|
||||||
|
- **Nicht kommerziell** — Du darfst das Material nicht für kommerzielle Zwecke nutzen
|
||||||
|
|
||||||
|
## Danksagung
|
||||||
|
|
||||||
|
Dieses Projekt wurde vom originalen [OGame](https://ogame.org) Browserspiel inspiriert. Alle Spielmechaniken und Designelemente wurden zu Bildungs- und Unterhaltungszwecken neu implementiert.
|
||||||
|
|
||||||
|
## Haftungsausschluss
|
||||||
|
|
||||||
|
Dieses Projekt ist nicht mit Gameforge AG oder dem offiziellen OGame-Spiel verbunden, wird nicht von diesen unterstützt oder ist mit diesen verbunden. Es ist ein unabhängiges Fan-Projekt, das zu Bildungszwecken und zur persönlichen Unterhaltung erstellt wurde.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
Mit ❤️ erstellt von <a href="https://github.com/setube">setube</a>
|
||||||
|
<br>
|
||||||
|
© 2025 - Alle Rechte vorbehalten (außer den durch die CC BY-NC 4.0 Lizenz gewährten Rechten)
|
||||||
|
</div>
|
||||||
160
README-EN.md
@@ -5,13 +5,11 @@
|
|||||||
|
|
||||||
A modern of the classic OGame space strategy game, built with Vue 3 and TypeScript.
|
A modern of the classic OGame space strategy game, built with Vue 3 and TypeScript.
|
||||||
|
|
||||||
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
[](https://vuejs.org/)
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
[](https://www.typescriptlang.org/)
|
[](https://www.taptap.cn/app/801190)
|
||||||
[](https://vitejs.dev/)
|
|
||||||
[](https://golang.org/)
|
|
||||||
|
|
||||||
[简体中文](README.md) | English
|
[简体中文](README.md)| [繁體中文](README-zh-TW.md) | English | [Deutsch](README-DE.md) | [Русский](README-RU.md) | [Español](README-ES.md) | [한국어](README-KO.md) | [日本語](README-JA.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -21,7 +19,6 @@ OGame Vue TS is a single-player, browser-based space strategy game inspired by t
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Multi-language Support** - Available in 6 languages: English, Chinese (Simplified & Traditional), German, Russian, and Korean
|
|
||||||
- **Building Management** - Construct and upgrade various buildings on planets and moons
|
- **Building Management** - Construct and upgrade various buildings on planets and moons
|
||||||
- **Research Technologies** - Unlock advanced technologies to enhance your empire
|
- **Research Technologies** - Unlock advanced technologies to enhance your empire
|
||||||
- **Fleet Management** - Build ships, send missions, and engage in tactical space battles
|
- **Fleet Management** - Build ships, send missions, and engage in tactical space battles
|
||||||
@@ -36,46 +33,24 @@ OGame Vue TS is a single-player, browser-based space strategy game inspired by t
|
|||||||
|
|
||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
- **Frontend Framework:** [Vue 3](https://vuejs.org/) with Composition API (`<script setup>`)
|
- **Frontend Framework:** [Vue 3](https://vuejs.org) with Composition API (`<script setup>`)
|
||||||
- **Language:** [TypeScript](https://www.typescriptlang.org/) with strict type checking
|
- **Language:** [TypeScript](https://www.typescriptlang.org) with strict type checking
|
||||||
- **Build Tool:** [Vite](https://vitejs.dev/) (Custom Rolldown-Vite 7.2.5)、[Golang](https://golang.org/)(Building cross-platform Web server.)、[Electron](https://www.electronjs.org/)(Building cross-platform visual interfaces)
|
- **Build Tool:** [Vite](https://vitejs.dev) (Custom Rolldown-Vite 7.2.5)、[Golang](https://golang.org)(Building cross-platform Web server.)、[Electron](https://www.electronjs.org)(Building cross-platform visual interfaces)
|
||||||
- **State Management:** [Pinia](https://pinia.vuejs.org/) with persisted state plugin
|
- **State Management:** [Pinia](https://pinia.vuejs.org) with persisted state plugin
|
||||||
- **Routing:** [Vue Router 4](https://router.vuejs.org/)
|
- **Routing:** [Vue Router 4](https://router.vuejs.org)
|
||||||
- **UI Components:** [shadcn-vue](https://www.shadcn-vue.com/) (New York style)
|
- **UI Components:** [shadcn-vue](https://www.shadcn-vue.com) (New York style)
|
||||||
- **Styling:** [Tailwind CSS v4](https://tailwindcss.com/) with CSS variables
|
- **Styling:** [Tailwind CSS v4](https://tailwindcss.com) with CSS variables
|
||||||
- **Icons:** [Lucide Vue Next](https://lucide.dev/)
|
- **Icons:** [Lucide Vue Next](https://lucide.dev)
|
||||||
- **Animations:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
- **Animations:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
- **Internationalization:** Custom i18n implementation
|
- **Internationalization:** Custom i18n implementation
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Download Build Product
|
|
||||||
|
|
||||||
#### Server version
|
|
||||||
|
|
||||||
[Windows](/releases/latest/download/ogame-windows-amd64.exe)
|
|
||||||
|
|
||||||
[Linux amd64](/releases/latest/download/ogame-linux-amd64)
|
|
||||||
|
|
||||||
[Linux arm64](/releases/latest/download/ogame-linux-arm64)
|
|
||||||
|
|
||||||
[MacOS Intel](/releases/latest/download/ogame-macos-amd64)
|
|
||||||
|
|
||||||
[MacOS](/releases/latest/download/ogame-macos-arm64)
|
|
||||||
|
|
||||||
#### Desktop version
|
|
||||||
|
|
||||||
[Windows](/releases/latest/download/OGame.Setup.exe)
|
|
||||||
|
|
||||||
[Ubuntu](/releases/latest/download/OGame.AppImage)
|
|
||||||
|
|
||||||
[MacOS](/releases/latest/download/OGame-mac.dmg)
|
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org/) (version 18 or higher recommended)
|
- [Node.js](https://nodejs.org) (version 18 or higher recommended)
|
||||||
- [pnpm](https://pnpm.io/) (version 10.13.1 or higher)
|
- [pnpm](https://pnpm.io) (version 10.13.1 or higher)
|
||||||
- [Go](https://golang.org/) (version 1.21 or higher recommended) (optional for binary builds)
|
- [Go](https://golang.org) (version 1.21 or higher recommended) (optional for binary builds)
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
@@ -109,98 +84,6 @@ pnpm build
|
|||||||
pnpm preview
|
pnpm preview
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
ogame-vue-ts/
|
|
||||||
├── public/ # Static assets
|
|
||||||
│ └── logo.svg # Application logo
|
|
||||||
├── src/
|
|
||||||
│ ├── assets/ # Dynamic assets
|
|
||||||
│ ├── components/ # Vue components
|
|
||||||
│ │ └── ui/ # shadcn-vue UI components
|
|
||||||
│ ├── composables/ # Vue composables
|
|
||||||
│ ├── config/ # Game configuration
|
|
||||||
│ ├── lib/ # Utility libraries
|
|
||||||
│ ├── locales/ # i18n translation files
|
|
||||||
│ ├── logic/ # Game logic modules
|
|
||||||
│ │ ├── buildingLogic.ts
|
|
||||||
│ │ ├── buildingValidation.ts
|
|
||||||
│ │ ├── fleetLogic.ts
|
|
||||||
│ │ ├── moonLogic.ts
|
|
||||||
│ │ ├── moonValidation.ts
|
|
||||||
│ │ ├── researchLogic.ts
|
|
||||||
│ │ ├── researchValidation.ts
|
|
||||||
│ │ ├── shipLogic.ts
|
|
||||||
│ │ └── shipValidation.ts
|
|
||||||
│ ├── router/ # Vue Router configuration
|
|
||||||
│ ├── stores/ # Pinia state stores
|
|
||||||
│ ├── types/ # TypeScript type definitions
|
|
||||||
│ ├── utils/ # Utility functions
|
|
||||||
│ ├── views/ # Page components
|
|
||||||
│ │ ├── OverviewView.vue
|
|
||||||
│ │ ├── BuildingsView.vue
|
|
||||||
│ │ ├── ResearchView.vue
|
|
||||||
│ │ ├── ShipyardView.vue
|
|
||||||
│ │ ├── DefenseView.vue
|
|
||||||
│ │ ├── FleetView.vue
|
|
||||||
│ │ ├── GalaxyView.vue
|
|
||||||
│ │ ├── OfficersView.vue
|
|
||||||
│ │ ├── BattleSimulatorView.vue
|
|
||||||
│ │ ├── MessagesView.vue
|
|
||||||
│ │ └── SettingsView.vue
|
|
||||||
│ ├── App.vue # Root component
|
|
||||||
│ ├── main.ts # Application entry point
|
|
||||||
│ └── style.css # Global styles
|
|
||||||
├── .github/
|
|
||||||
│ └── ISSUE_TEMPLATE/ # GitHub issue templates
|
|
||||||
├── LICENSE # CC BY-NC 4.0 License
|
|
||||||
├── package.json # Project dependencies
|
|
||||||
├── tsconfig.json # TypeScript configuration
|
|
||||||
└── vite.config.ts # Vite configuration
|
|
||||||
```
|
|
||||||
|
|
||||||
## Available Languages
|
|
||||||
|
|
||||||
- 🇺🇸 English
|
|
||||||
- 🇨🇳 简体中文 (Simplified Chinese)
|
|
||||||
- 🇹🇼 繁體中文 (Traditional Chinese)
|
|
||||||
- 🇩🇪 Deutsch (German)
|
|
||||||
- 🇷🇺 Русский (Russian)
|
|
||||||
- 🇰🇷 한국어 (Korean)
|
|
||||||
|
|
||||||
## Game Features
|
|
||||||
|
|
||||||
### Resource Management
|
|
||||||
- **Metal** - Primary construction material
|
|
||||||
- **Crystal** - Advanced technology component
|
|
||||||
- **Deuterium** - Fuel and research resource
|
|
||||||
- **Dark Matter** - Premium resource
|
|
||||||
- **Energy** - Powers your facilities
|
|
||||||
|
|
||||||
### Building Types
|
|
||||||
- **Resource Buildings** - Metal Mine, Crystal Mine, Deuterium Synthesizer, Solar Plant
|
|
||||||
- **Facilities** - Robotics Factory, Shipyard, Research Lab, Storage facilities
|
|
||||||
- **Special Buildings** - Nanite Factory, Terraformer, and more
|
|
||||||
|
|
||||||
### Technologies
|
|
||||||
- **Energy Technology** - Improves energy efficiency
|
|
||||||
- **Laser Technology** - Enhances weapon systems
|
|
||||||
- **Ion Technology** - Advanced propulsion and weapons
|
|
||||||
- **Hyperspace Technology** - Enables faster travel
|
|
||||||
- **Plasma Technology** - Ultimate weapon systems
|
|
||||||
- And many more...
|
|
||||||
|
|
||||||
### Ship Classes
|
|
||||||
- **Civil Ships** - Small/Large Cargo, Colony Ship, Recycler
|
|
||||||
- **Combat Ships** - Light/Heavy Fighter, Cruiser, Battleship, Bomber
|
|
||||||
- **Special Ships** - Deathstar, Battlecruiser, Destroyer
|
|
||||||
|
|
||||||
### Defense Systems
|
|
||||||
- Rocket Launcher, Light/Heavy Laser, Gauss Cannon
|
|
||||||
- Ion Cannon, Plasma Turret
|
|
||||||
- Small/Large Shield Dome
|
|
||||||
|
|
||||||
## Data Security
|
## Data Security
|
||||||
|
|
||||||
All game data is automatically encrypted using AES encryption before being stored in your browser's local storage. Your game progress is secure and private.
|
All game data is automatically encrypted using AES encryption before being stored in your browser's local storage. Your game progress is secure and private.
|
||||||
@@ -213,16 +96,9 @@ The application supports full theme customization through Tailwind CSS variables
|
|||||||
|
|
||||||
Contributions are welcome! Please feel free to submit issues or pull requests.
|
Contributions are welcome! Please feel free to submit issues or pull requests.
|
||||||
|
|
||||||
### Issue Templates
|
|
||||||
We provide the following issue templates in both Chinese and English:
|
|
||||||
- Bug Report
|
|
||||||
- Feature Request
|
|
||||||
- Documentation Improvement
|
|
||||||
- eedback & Suggestion
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This work is licensed under the [Creative Commons Attribution-NonCommercial 4.0 International License](https://creativecommons.org/licenses/by-nc/4.0/).
|
This work is licensed under the [Creative Commons Attribution-NonCommercial 4.0 International License](https://creativecommons.org/licenses/by-nc/4.0).
|
||||||
|
|
||||||
### You are free to:
|
### You are free to:
|
||||||
- **Share** — copy and redistribute the material in any medium or format
|
- **Share** — copy and redistribute the material in any medium or format
|
||||||
@@ -236,7 +112,7 @@ This work is licensed under the [Creative Commons Attribution-NonCommercial 4.0
|
|||||||
|
|
||||||
## Acknowledgments
|
## Acknowledgments
|
||||||
|
|
||||||
This project is inspired by the original [OGame](https://ogame.org/) browser game. All game mechanics and design elements are reimplemented for educational and entertainment purposes.
|
This project is inspired by the original [OGame](https://ogame.org) browser game. All game mechanics and design elements are reimplemented for educational and entertainment purposes.
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
||||||
@@ -245,7 +121,7 @@ This project is not affiliated with, endorsed by, or connected to Gameforge AG o
|
|||||||
---
|
---
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
Made with ❤️ by Jun Qian
|
Made with ❤️ by <a href="https://github.com/setube">setube</a>
|
||||||
<br>
|
<br>
|
||||||
© 2025 - All rights reserved (except those granted by CC BY-NC 4.0 License)
|
© 2025 - All rights reserved (except those granted by CC BY-NC 4.0 License)
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
125
README-ES.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img src="public/logo.svg" alt="OGame Vue TS Logo" width="128" height="128">
|
||||||
|
|
||||||
|
# OGame Vue TS
|
||||||
|
|
||||||
|
Un juego de estrategia espacial moderno basado en Vue 3 y TypeScript.
|
||||||
|
|
||||||
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
|
[](https://www.taptap.cn/app/801190)
|
||||||
|
|
||||||
|
[简体中文](README.md) | [繁體中文](README-zh-TW.md) | [English](README-EN.md) | [Deutsch](README-DE.md) | [Русский](README-RU.md) | Español | [한국어](README-KO.md) | [日本語](README-JA.md)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Acerca del Proyecto
|
||||||
|
|
||||||
|
OGame Vue TS es un juego de estrategia espacial basado en navegador, versión offline, inspirado en el clásico OGame. Construye tu imperio en la galaxia, investiga tecnologías, construye naves y participa en épicas batallas espaciales. Este proyecto está construido con tecnologías web modernas, se ejecuta completamente en el navegador, ofrece una experiencia de juego fluida y responsiva, y todos los datos se almacenan localmente.
|
||||||
|
|
||||||
|
## Características Principales
|
||||||
|
|
||||||
|
- **Gestión de Edificios** - Construye y mejora varios edificios en planetas y lunas
|
||||||
|
- **Investigación Tecnológica** - Desbloquea tecnologías avanzadas para fortalecer tu imperio
|
||||||
|
- **Gestión de Flotas** - Construye naves, envía misiones, participa en batallas espaciales tácticas
|
||||||
|
- **Sistema de Defensa** - Despliega instalaciones defensivas para proteger tus colonias
|
||||||
|
- **Sistema de Oficiales** - Recluta oficiales para obtener ventajas estratégicas
|
||||||
|
- **Simulador de Batallas** - Prueba escenarios de combate antes de invertir recursos
|
||||||
|
- **Vista Galáctica** - Explora el universo e interactúa con otros planetas
|
||||||
|
- **Persistencia de Datos Local** - Todos los datos del juego están encriptados y almacenados localmente en el navegador
|
||||||
|
- **Tema Oscuro/Claro** - Elige tu tema visual preferido
|
||||||
|
- **Gestión de Colas** - Administra múltiples colas de construcción e investigación
|
||||||
|
- **Generación de Lunas** - Mecanismo de generación de lunas basado en probabilidad desde campos de escombros
|
||||||
|
|
||||||
|
## Stack Tecnológico
|
||||||
|
|
||||||
|
- **Framework Frontend:** [Vue 3](https://vuejs.org) + Composition API (sintaxis `<script setup>`)
|
||||||
|
- **Lenguaje de Desarrollo:** [TypeScript](https://www.typescriptlang.org) (verificación de tipos estricta habilitada)
|
||||||
|
- **Herramientas de Construcción:** [Vite](https://vitejs.dev) (Rolldown-Vite 7.2.5 personalizado), [Golang](https://golang.org) (servidor web multiplataforma), [Electron](https://www.electronjs.org) (interfaz visual multiplataforma)
|
||||||
|
- **Gestión de Estado:** [Pinia](https://pinia.vuejs.org) + plugin de persistencia
|
||||||
|
- **Enrutamiento:** [Vue Router 4](https://router.vuejs.org)
|
||||||
|
- **Componentes UI:** [shadcn-vue](https://www.shadcn-vue.com) (estilo New York)
|
||||||
|
- **Estilos:** [Tailwind CSS v4](https://tailwindcss.com) + Variables CSS
|
||||||
|
- **Iconos:** [Lucide Vue Next](https://lucide.dev)
|
||||||
|
- **Animaciones:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
|
- **Internacionalización:** Implementación i18n personalizada
|
||||||
|
|
||||||
|
## Inicio Rápido
|
||||||
|
|
||||||
|
### Requisitos
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org) (versión 18 o superior recomendada)
|
||||||
|
- [pnpm](https://pnpm.io) (versión 10.13.1 o superior)
|
||||||
|
- [Go](https://golang.org) (versión 1.21 o superior) (opcional)
|
||||||
|
|
||||||
|
### Instalación
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clonar el repositorio
|
||||||
|
git clone https://github.com/setube/ogame-vue-ts.git
|
||||||
|
|
||||||
|
# Entrar al directorio del proyecto
|
||||||
|
cd ogame-vue-ts
|
||||||
|
|
||||||
|
# Instalar dependencias
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desarrollo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Iniciar servidor de desarrollo (puerto 25121)
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Visita `http://localhost:25121` en tu navegador
|
||||||
|
|
||||||
|
### Construcción para Producción
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Construir la aplicación
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# Vista previa de la construcción
|
||||||
|
pnpm preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## Seguridad de Datos
|
||||||
|
|
||||||
|
Todos los datos del juego se encriptan automáticamente usando AES antes de almacenarse en el almacenamiento local del navegador. Tu progreso de juego es seguro y privado.
|
||||||
|
|
||||||
|
## Personalización
|
||||||
|
|
||||||
|
La aplicación soporta personalización completa de temas a través de variables CSS de Tailwind definidas en `src/style.css`. Puedes cambiar fácilmente entre modo claro y oscuro.
|
||||||
|
|
||||||
|
## Contribuciones
|
||||||
|
|
||||||
|
¡Las contribuciones son bienvenidas! No dudes en enviar issues o pull requests.
|
||||||
|
|
||||||
|
## Licencia
|
||||||
|
|
||||||
|
Este trabajo está licenciado bajo la [Licencia Creative Commons Atribución-NoComercial 4.0 Internacional](https://creativecommons.org/licenses/by-nc/4.0).
|
||||||
|
|
||||||
|
### Eres libre de:
|
||||||
|
- **Compartir** — Copiar y redistribuir el material en cualquier medio o formato
|
||||||
|
- **Adaptar** — Remezclar, transformar y construir a partir del material
|
||||||
|
|
||||||
|
### Bajo los siguientes términos:
|
||||||
|
- **Atribución** — Debes dar crédito apropiado, proporcionar un enlace a la licencia e indicar si se realizaron cambios
|
||||||
|
- **NoComercial** — No puedes usar el material para fines comerciales
|
||||||
|
|
||||||
|
## Agradecimientos
|
||||||
|
|
||||||
|
Este proyecto está inspirado en el juego de navegador original [OGame](https://ogame.org). Todas las mecánicas de juego y elementos de diseño han sido reimplementados con fines educativos y de entretenimiento.
|
||||||
|
|
||||||
|
## Aviso Legal
|
||||||
|
|
||||||
|
Este proyecto no está afiliado, respaldado ni conectado con Gameforge AG o el juego oficial OGame. Este es un proyecto independiente de fans creado únicamente con fines educativos y de entretenimiento personal.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
Hecho con ❤️ por <a href="https://github.com/setube">setube</a>
|
||||||
|
<br>
|
||||||
|
© 2025 - Todos los derechos reservados (excepto los otorgados por la licencia CC BY-NC 4.0)
|
||||||
|
</div>
|
||||||
125
README-JA.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img src="public/logo.svg" alt="OGame Vue TS Logo" width="128" height="128">
|
||||||
|
|
||||||
|
# OGame Vue TS
|
||||||
|
|
||||||
|
Vue 3とTypeScriptで構築されたモダンな宇宙戦略ゲーム。
|
||||||
|
|
||||||
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
|
[](https://www.taptap.cn/app/801190)
|
||||||
|
|
||||||
|
[简体中文](README.md) | [繁體中文](README-zh-TW.md) | [English](README-EN.md) | [Deutsch](README-DE.md) | [Русский](README-RU.md) | [Español](README-ES.md) | [한국어](README-KO.md) | 日本語
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## プロジェクトについて
|
||||||
|
|
||||||
|
OGame Vue TSは、クラシックなOGameにインスパイアされたシングルプレイヤー向けブラウザベースの宇宙戦略ゲームです。銀河に帝国を築き、テクノロジーを研究し、宇宙船を建造し、壮大な宇宙戦闘に参加しましょう。このプロジェクトはモダンなWeb技術で構築されており、ブラウザ内で完全に動作し、すべてのデータはローカルに保存されます。
|
||||||
|
|
||||||
|
## 主な機能
|
||||||
|
|
||||||
|
- **建物管理** - 惑星と月で様々な建物を建設・アップグレード
|
||||||
|
- **技術研究** - 先進技術をアンロックして帝国を強化
|
||||||
|
- **艦隊管理** - 宇宙船を建造し、ミッションを派遣し、戦術的な宇宙戦闘に参加
|
||||||
|
- **防衛システム** - 防衛施設を配置してコロニーを守る
|
||||||
|
- **士官システム** - 士官を雇用して戦略的優位性を獲得
|
||||||
|
- **戦闘シミュレーター** - 資源を投入する前に戦闘シナリオをテスト
|
||||||
|
- **銀河ビュー** - 宇宙を探索し、他の惑星と交流
|
||||||
|
- **ローカルデータ永続化** - すべてのゲームデータは暗号化されブラウザにローカル保存
|
||||||
|
- **ダーク/ライトテーマ** - お好みのビジュアルテーマを選択
|
||||||
|
- **キュー管理** - 複数の建設・研究キューを管理
|
||||||
|
- **月の生成** - デブリフィールドからの確率ベースの月生成メカニズム
|
||||||
|
|
||||||
|
## 技術スタック
|
||||||
|
|
||||||
|
- **フロントエンドフレームワーク:** [Vue 3](https://vuejs.org) + Composition API (`<script setup>` 構文)
|
||||||
|
- **開発言語:** [TypeScript](https://www.typescriptlang.org) (厳密な型チェック有効)
|
||||||
|
- **ビルドツール:** [Vite](https://vitejs.dev) (カスタムRolldown-Vite 7.2.5)、[Golang](https://golang.org) (クロスプラットフォームWebサーバー)、[Electron](https://www.electronjs.org) (クロスプラットフォームビジュアルインターフェース)
|
||||||
|
- **状態管理:** [Pinia](https://pinia.vuejs.org) + 永続化プラグイン
|
||||||
|
- **ルーティング:** [Vue Router 4](https://router.vuejs.org)
|
||||||
|
- **UIコンポーネント:** [shadcn-vue](https://www.shadcn-vue.com) (New Yorkスタイル)
|
||||||
|
- **スタイリング:** [Tailwind CSS v4](https://tailwindcss.com) + CSS変数
|
||||||
|
- **アイコン:** [Lucide Vue Next](https://lucide.dev)
|
||||||
|
- **アニメーション:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
|
- **国際化:** カスタムi18n実装
|
||||||
|
|
||||||
|
## クイックスタート
|
||||||
|
|
||||||
|
### 必要条件
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org) (バージョン18以上推奨)
|
||||||
|
- [pnpm](https://pnpm.io) (バージョン10.13.1以上)
|
||||||
|
- [Go](https://golang.org) (バージョン1.21以上) (オプション)
|
||||||
|
|
||||||
|
### インストール
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# リポジトリをクローン
|
||||||
|
git clone https://github.com/setube/ogame-vue-ts.git
|
||||||
|
|
||||||
|
# プロジェクトディレクトリに移動
|
||||||
|
cd ogame-vue-ts
|
||||||
|
|
||||||
|
# 依存関係をインストール
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 開発
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 開発サーバーを起動 (ポート25121)
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
ブラウザで `http://localhost:25121` にアクセス
|
||||||
|
|
||||||
|
### 本番ビルド
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# アプリケーションをビルド
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# 本番ビルドをプレビュー
|
||||||
|
pnpm preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## データセキュリティ
|
||||||
|
|
||||||
|
すべてのゲームデータは、ブラウザのローカルストレージに保存される前にAESで自動的に暗号化されます。ゲームの進行状況は安全でプライベートです。
|
||||||
|
|
||||||
|
## カスタマイズ
|
||||||
|
|
||||||
|
アプリケーションは`src/style.css`で定義されたTailwind CSS変数による完全なテーマカスタマイズをサポートしています。ライトモードとダークモードを簡単に切り替えることができます。
|
||||||
|
|
||||||
|
## 貢献
|
||||||
|
|
||||||
|
貢献は大歓迎です!お気軽にissueやpull requestを提出してください。
|
||||||
|
|
||||||
|
## ライセンス
|
||||||
|
|
||||||
|
この作品は[クリエイティブ・コモンズ 表示-非営利 4.0 国際ライセンス](https://creativecommons.org/licenses/by-nc/4.0)の下でライセンスされています。
|
||||||
|
|
||||||
|
### あなたは自由に:
|
||||||
|
- **共有** — どのようなメディアやフォーマットでも資料をコピー・再配布できます
|
||||||
|
- **翻案** — 資料をリミックス、変形、加工できます
|
||||||
|
|
||||||
|
### 以下の条件に従う必要があります:
|
||||||
|
- **表示** — 適切なクレジットを表示し、ライセンスへのリンクを提供し、変更があったかどうかを示す必要があります
|
||||||
|
- **非営利** — 資料を営利目的で使用することはできません
|
||||||
|
|
||||||
|
## 謝辞
|
||||||
|
|
||||||
|
このプロジェクトはオリジナルの[OGame](https://ogame.org)ブラウザゲームにインスパイアされています。すべてのゲームメカニクスとデザイン要素は、教育およびエンターテイメント目的で再実装されています。
|
||||||
|
|
||||||
|
## 免責事項
|
||||||
|
|
||||||
|
このプロジェクトはGameforge AGや公式OGameゲームとは一切関係がなく、承認や接続もありません。これは教育と個人的なエンターテイメントのみを目的として作成された独立したファンプロジェクトです。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
❤️を込めて作成 by <a href="https://github.com/setube">setube</a>
|
||||||
|
<br>
|
||||||
|
© 2025 - All rights reserved (CC BY-NC 4.0ライセンスで付与された権利を除く)
|
||||||
|
</div>
|
||||||
125
README-KO.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img src="public/logo.svg" alt="OGame Vue TS Logo" width="128" height="128">
|
||||||
|
|
||||||
|
# OGame Vue TS
|
||||||
|
|
||||||
|
Vue 3와 TypeScript로 제작된 클래식 OGame을 기반으로 한 현대적인 우주 전략 게임입니다.
|
||||||
|
|
||||||
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
|
[](https://www.taptap.cn/app/801190)
|
||||||
|
|
||||||
|
[简体中文](README.md) | [繁體中文](README-zh-TW.md) | [English](README-EN.md) | [Deutsch](README-DE.md) | [Русский](README-RU.md) | [Español](README-ES.md) | 한국어 | [日本語](README-JA.md)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## 프로젝트 소개
|
||||||
|
|
||||||
|
OGame Vue TS는 클래식 OGame에서 영감을 받은 싱글플레이어 브라우저 기반 우주 전략 게임입니다. 은하계에서 제국을 건설하고, 기술을 연구하고, 우주선을 제작하고, 장대한 우주 전투에 참여하세요. 이 프로젝트는 현대 웹 기술로 제작되었으며, 로컬 데이터 저장과 함께 브라우저에서 완전히 실행됩니다.
|
||||||
|
|
||||||
|
## 주요 기능
|
||||||
|
|
||||||
|
- **건물 관리** - 행성과 달에서 다양한 건물을 건설하고 업그레이드
|
||||||
|
- **기술 연구** - 제국을 강화하기 위한 첨단 기술 해금
|
||||||
|
- **함대 관리** - 우주선 건조, 미션 파견, 전술적 우주 전투 참여
|
||||||
|
- **방어 시스템** - 식민지 보호를 위한 방어 시설 배치
|
||||||
|
- **장교 시스템** - 전략적 이점을 위한 장교 고용
|
||||||
|
- **전투 시뮬레이터** - 자원 투입 전 전투 시나리오 테스트
|
||||||
|
- **은하 뷰** - 우주 탐험 및 다른 행성과의 상호작용
|
||||||
|
- **로컬 데이터 저장** - 모든 게임 데이터는 암호화되어 브라우저에 로컬 저장
|
||||||
|
- **다크/라이트 모드** - 선호하는 비주얼 테마 선택
|
||||||
|
- **대기열 관리** - 여러 건설 및 연구 대기열 관리
|
||||||
|
- **달 생성** - 잔해 필드에서 확률 기반 달 생성
|
||||||
|
|
||||||
|
## 기술 스택
|
||||||
|
|
||||||
|
- **프론트엔드 프레임워크:** [Vue 3](https://vuejs.org) + Composition API (`<script setup>` 문법)
|
||||||
|
- **프로그래밍 언어:** [TypeScript](https://www.typescriptlang.org) (엄격한 타입 검사 활성화)
|
||||||
|
- **빌드 도구:** [Vite](https://vitejs.dev) (Custom Rolldown-Vite 7.2.5), [Golang](https://golang.org) (크로스 플랫폼 웹 서버 구축), [Electron](https://www.electronjs.org) (크로스 플랫폼 데스크톱 애플리케이션 구축)
|
||||||
|
- **상태 관리:** [Pinia](https://pinia.vuejs.org) + 지속성 플러그인
|
||||||
|
- **라우팅:** [Vue Router 4](https://router.vuejs.org)
|
||||||
|
- **UI 컴포넌트:** [shadcn-vue](https://www.shadcn-vue.com) (New York 스타일)
|
||||||
|
- **스타일링:** [Tailwind CSS v4](https://tailwindcss.com) + CSS 변수
|
||||||
|
- **아이콘:** [Lucide Vue Next](https://lucide.dev)
|
||||||
|
- **애니메이션:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
|
- **국제화:** 커스텀 i18n 구현
|
||||||
|
|
||||||
|
## 빠른 시작
|
||||||
|
|
||||||
|
### 요구 사항
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org) (버전 18 이상 권장)
|
||||||
|
- [pnpm](https://pnpm.io) (버전 10.13.1 이상)
|
||||||
|
- [Go](https://golang.org) (버전 1.21 이상) (선택 사항)
|
||||||
|
|
||||||
|
### 설치
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 저장소 클론
|
||||||
|
git clone https://github.com/setube/ogame-vue-ts.git
|
||||||
|
|
||||||
|
# 프로젝트 디렉토리로 이동
|
||||||
|
cd ogame-vue-ts
|
||||||
|
|
||||||
|
# 의존성 설치
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 개발
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 개발 서버 시작 (포트 25121에서 실행)
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
브라우저를 열고 `http://localhost:25121`로 이동하세요
|
||||||
|
|
||||||
|
### 프로덕션 빌드
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 애플리케이션 빌드
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# 프로덕션 빌드 미리보기
|
||||||
|
pnpm preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## 데이터 보안
|
||||||
|
|
||||||
|
모든 게임 데이터는 브라우저의 로컬 스토리지에 저장되기 전에 AES 암호화로 자동 암호화됩니다. 게임 진행 상황은 안전하고 비공개로 유지됩니다.
|
||||||
|
|
||||||
|
## 커스터마이징
|
||||||
|
|
||||||
|
애플리케이션은 `src/style.css`에 정의된 Tailwind CSS 변수를 통해 완전한 테마 커스터마이징을 지원합니다. 라이트 모드와 다크 모드 간에 쉽게 전환할 수 있습니다.
|
||||||
|
|
||||||
|
## 기여
|
||||||
|
|
||||||
|
기여를 환영합니다! 이슈나 풀 리퀘스트를 자유롭게 제출해 주세요.
|
||||||
|
|
||||||
|
## 라이선스
|
||||||
|
|
||||||
|
이 작품은 [크리에이티브 커먼즈 저작자표시-비영리 4.0 국제 라이선스](https://creativecommons.org/licenses/by-nc/4.0)에 따라 라이선스가 부여됩니다.
|
||||||
|
|
||||||
|
### 자유롭게:
|
||||||
|
- **공유** — 어떤 매체나 포맷으로든 자료를 복사하고 재배포할 수 있습니다
|
||||||
|
- **변경** — 자료를 리믹스, 변형하고 자료를 기반으로 2차 저작물을 만들 수 있습니다
|
||||||
|
|
||||||
|
### 다음 조건을 따라야 합니다:
|
||||||
|
- **저작자표시** — 적절한 출처를 표시하고, 라이선스 링크를 제공하며, 변경이 있었는지 표시해야 합니다
|
||||||
|
- **비영리** — 이 자료를 상업적 목적으로 사용할 수 없습니다
|
||||||
|
|
||||||
|
## 감사의 말
|
||||||
|
|
||||||
|
이 프로젝트는 원작 [OGame](https://ogame.org) 브라우저 게임에서 영감을 받았습니다. 모든 게임 메커니즘과 디자인 요소는 교육 및 오락 목적으로 재구현되었습니다.
|
||||||
|
|
||||||
|
## 면책 조항
|
||||||
|
|
||||||
|
이 프로젝트는 Gameforge AG 또는 공식 OGame 게임과 제휴, 보증 또는 연결되어 있지 않습니다. 이것은 교육 목적과 개인적인 즐거움을 위해 만들어진 독립적인 팬 프로젝트입니다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
❤️를 담아 제작, 작성자: <a href="https://github.com/setube">setube</a>
|
||||||
|
<br>
|
||||||
|
© 2025 - 모든 권리 보유 (CC BY-NC 4.0 라이선스에 의해 부여된 권리 제외)
|
||||||
|
</div>
|
||||||
125
README-RU.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img src="public/logo.svg" alt="OGame Vue TS Logo" width="128" height="128">
|
||||||
|
|
||||||
|
# OGame Vue TS
|
||||||
|
|
||||||
|
Современная космическая стратегическая игра, вдохновлённая классической OGame, созданная на Vue 3 и TypeScript.
|
||||||
|
|
||||||
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
|
[](https://www.taptap.cn/app/801190)
|
||||||
|
|
||||||
|
[简体中文](README.md) | [繁體中文](README-zh-TW.md) | [English](README-EN.md) | [Deutsch](README-DE.md) | Русский | [Español](README-ES.md) | [한국어](README-KO.md) | [日本語](README-JA.md)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## О проекте
|
||||||
|
|
||||||
|
OGame Vue TS — это однопользовательская браузерная космическая стратегическая игра, вдохновлённая классической OGame. Постройте свою империю в галактике, исследуйте технологии, создавайте космические корабли и участвуйте в эпических космических сражениях. Этот проект создан с использованием современных веб-технологий и полностью работает в браузере с локальным хранением данных.
|
||||||
|
|
||||||
|
## Основные возможности
|
||||||
|
|
||||||
|
- **Управление зданиями** - Стройте и улучшайте различные здания на планетах и лунах
|
||||||
|
- **Исследование технологий** - Открывайте передовые технологии для усиления вашей империи
|
||||||
|
- **Управление флотом** - Стройте корабли, отправляйте миссии, участвуйте в тактических космических боях
|
||||||
|
- **Системы обороны** - Размещайте оборонительные сооружения для защиты ваших колоний
|
||||||
|
- **Система офицеров** - Нанимайте офицеров для получения стратегических преимуществ
|
||||||
|
- **Боевой симулятор** - Тестируйте боевые сценарии перед вложением ресурсов
|
||||||
|
- **Вид галактики** - Исследуйте вселенную и взаимодействуйте с другими планетами
|
||||||
|
- **Локальное хранение данных** - Все игровые данные зашифрованы и хранятся локально в браузере
|
||||||
|
- **Тёмный/светлый режим** - Выберите предпочитаемую визуальную тему
|
||||||
|
- **Управление очередями** - Управляйте несколькими очередями строительства и исследований
|
||||||
|
- **Генерация луны** - Вероятностное создание луны из поля обломков
|
||||||
|
|
||||||
|
## Технологический стек
|
||||||
|
|
||||||
|
- **Frontend-фреймворк:** [Vue 3](https://vuejs.org) + Composition API (синтаксис `<script setup>`)
|
||||||
|
- **Язык программирования:** [TypeScript](https://www.typescriptlang.org) (со строгой проверкой типов)
|
||||||
|
- **Инструмент сборки:** [Vite](https://vitejs.dev) (Custom Rolldown-Vite 7.2.5), [Golang](https://golang.org) (для кроссплатформенного веб-сервера), [Electron](https://www.electronjs.org) (для кроссплатформенного десктоп-приложения)
|
||||||
|
- **Управление состоянием:** [Pinia](https://pinia.vuejs.org) + плагин персистентности
|
||||||
|
- **Маршрутизация:** [Vue Router 4](https://router.vuejs.org)
|
||||||
|
- **UI-компоненты:** [shadcn-vue](https://www.shadcn-vue.com) (стиль New York)
|
||||||
|
- **Стилизация:** [Tailwind CSS v4](https://tailwindcss.com) + CSS-переменные
|
||||||
|
- **Иконки:** [Lucide Vue Next](https://lucide.dev)
|
||||||
|
- **Анимации:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
|
- **Интернационализация:** Собственная реализация i18n
|
||||||
|
|
||||||
|
## Быстрый старт
|
||||||
|
|
||||||
|
### Требования
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org) (рекомендуется версия 18 или выше)
|
||||||
|
- [pnpm](https://pnpm.io) (версия 10.13.1 или выше)
|
||||||
|
- [Go](https://golang.org) (версия 1.21 или выше) (опционально)
|
||||||
|
|
||||||
|
### Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Клонировать репозиторий
|
||||||
|
git clone https://github.com/setube/ogame-vue-ts.git
|
||||||
|
|
||||||
|
# Перейти в директорию проекта
|
||||||
|
cd ogame-vue-ts
|
||||||
|
|
||||||
|
# Установить зависимости
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Разработка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запустить сервер разработки (работает на порту 25121)
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Откройте браузер и перейдите по адресу `http://localhost:25121`
|
||||||
|
|
||||||
|
### Сборка для продакшена
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Собрать приложение
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# Предпросмотр продакшен-сборки
|
||||||
|
pnpm preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## Безопасность данных
|
||||||
|
|
||||||
|
Все игровые данные автоматически шифруются с помощью AES перед сохранением в локальном хранилище браузера. Ваш игровой прогресс защищён и приватен.
|
||||||
|
|
||||||
|
## Кастомизация
|
||||||
|
|
||||||
|
Приложение поддерживает полную настройку темы через CSS-переменные Tailwind, определённые в `src/style.css`. Вы можете легко переключаться между светлым и тёмным режимами.
|
||||||
|
|
||||||
|
## Участие в разработке
|
||||||
|
|
||||||
|
Приветствуем вклад в проект! Пожалуйста, не стесняйтесь создавать issues или pull requests.
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
Эта работа лицензирована под [Creative Commons Attribution-NonCommercial 4.0 International License](https://creativecommons.org/licenses/by-nc/4.0).
|
||||||
|
|
||||||
|
### Вы можете:
|
||||||
|
- **Делиться** — копировать и распространять материал в любом формате или на любом носителе
|
||||||
|
- **Адаптировать** — ремиксовать, преобразовывать и создавать на основе материала
|
||||||
|
|
||||||
|
### При соблюдении следующих условий:
|
||||||
|
- **Атрибуция** — Вы должны указать соответствующую атрибуцию, предоставить ссылку на лицензию и указать, были ли внесены изменения
|
||||||
|
- **Некоммерческое использование** — Вы не можете использовать материал в коммерческих целях
|
||||||
|
|
||||||
|
## Благодарности
|
||||||
|
|
||||||
|
Этот проект вдохновлён оригинальной браузерной игрой [OGame](https://ogame.org). Все игровые механики и элементы дизайна были переосмыслены в образовательных и развлекательных целях.
|
||||||
|
|
||||||
|
## Отказ от ответственности
|
||||||
|
|
||||||
|
Этот проект не связан с Gameforge AG или официальной игрой OGame, не одобрен и не поддерживается ими. Это независимый фан-проект, созданный в образовательных целях и для личного развлечения.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
Сделано с ❤️ автором <a href="https://github.com/setube">setube</a>
|
||||||
|
<br>
|
||||||
|
© 2025 - Все права защищены (кроме прав, предоставленных лицензией CC BY-NC 4.0)
|
||||||
|
</div>
|
||||||
125
README-zh-TW.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img src="public/logo.svg" alt="OGame Vue TS Logo" width="128" height="128">
|
||||||
|
|
||||||
|
# OGame Vue TS
|
||||||
|
|
||||||
|
一個基於 Vue 3 和 TypeScript 構建的現代化 OGame 太空策略遊戲。
|
||||||
|
|
||||||
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
|
[](https://www.taptap.cn/app/801190)
|
||||||
|
|
||||||
|
[简体中文](README.md) | 繁體中文 | [English](README-EN.md) | [Deutsch](README-DE.md) | [Русский](README-RU.md) | [Español](README-ES.md) | [한국어](README-KO.md) | [日本語](README-JA.md)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## 關於專案
|
||||||
|
|
||||||
|
OGame Vue TS 是一款受經典 OGame 遊戲啟發的單機版、基於瀏覽器的太空策略遊戲。在銀河系中建立你的帝國,研究科技,建造艦船,參與史詩般的太空戰鬥。本專案採用現代 Web 技術構建,完全在瀏覽器中運行,提供流暢且響應迅速的遊戲體驗,所有數據都儲存在本地。
|
||||||
|
|
||||||
|
## 核心特性
|
||||||
|
|
||||||
|
- **建築管理** - 在行星和月球上建造和升級各種建築
|
||||||
|
- **科技研究** - 解鎖先進科技來增強你的帝國
|
||||||
|
- **艦隊管理** - 建造艦船、派遣任務、參與戰術太空戰鬥
|
||||||
|
- **防禦系統** - 部署防禦設施來保護你的殖民地
|
||||||
|
- **軍官系統** - 招募軍官以獲得戰略優勢
|
||||||
|
- **戰鬥模擬器** - 在投入資源前測試戰鬥場景
|
||||||
|
- **銀河視圖** - 探索宇宙並與其他星球互動
|
||||||
|
- **本地數據持久化** - 所有遊戲數據都經過加密並儲存在瀏覽器本地
|
||||||
|
- **深色/淺色主題** - 選擇你喜歡的視覺主題
|
||||||
|
- **隊列管理** - 管理多個建造和研究隊列
|
||||||
|
- **月球生成** - 基於概率的月球從殘骸場生成機制
|
||||||
|
|
||||||
|
## 技術棧
|
||||||
|
|
||||||
|
- **前端框架:** [Vue 3](https://vuejs.org) + Composition API (`<script setup>` 語法)
|
||||||
|
- **開發語言:** [TypeScript](https://www.typescriptlang.org) (啟用嚴格類型檢查)
|
||||||
|
- **構建工具:** [Vite](https://vitejs.dev) (自定義 Rolldown-Vite 7.2.5)、[Golang](https://golang.org)(構建跨平台的Web服務端)、[Electron](https://www.electronjs.org)(構建跨平台可視化介面)
|
||||||
|
- **狀態管理:** [Pinia](https://pinia.vuejs.org) + 持久化插件
|
||||||
|
- **路由管理:** [Vue Router 4](https://router.vuejs.org)
|
||||||
|
- **UI 組件:** [shadcn-vue](https://www.shadcn-vue.com) (New York 風格)
|
||||||
|
- **樣式方案:** [Tailwind CSS v4](https://tailwindcss.com) + CSS 變數
|
||||||
|
- **圖標庫:** [Lucide Vue Next](https://lucide.dev)
|
||||||
|
- **動畫效果:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
|
- **國際化:** 自定義 i18n 實現
|
||||||
|
|
||||||
|
## 快速開始
|
||||||
|
|
||||||
|
### 環境要求
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org) (推薦 18 或更高版本)
|
||||||
|
- [pnpm](https://pnpm.io) (版本 10.13.1 或更高)
|
||||||
|
- [Go](https://golang.org) (版本 1.21 或更高版本)(可選)
|
||||||
|
|
||||||
|
### 安裝
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 克隆倉庫
|
||||||
|
git clone https://github.com/setube/ogame-vue-ts.git
|
||||||
|
|
||||||
|
# 進入專案目錄
|
||||||
|
cd ogame-vue-ts
|
||||||
|
|
||||||
|
# 安裝依賴
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 開發
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 啟動開發服務器 (運行在端口 25121)
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
在瀏覽器中訪問 `http://localhost:25121`
|
||||||
|
|
||||||
|
### 生產構建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 構建應用
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# 預覽生產構建
|
||||||
|
pnpm preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## 數據安全
|
||||||
|
|
||||||
|
所有遊戲數據在儲存到瀏覽器的本地存儲之前都會使用 AES 加密自動加密。您的遊戲進度是安全且私密的。
|
||||||
|
|
||||||
|
## 自定義
|
||||||
|
|
||||||
|
應用支援通過 `src/style.css` 中定義的 Tailwind CSS 變數進行完整的主題自定義。您可以輕鬆地在淺色和深色模式之間切換。
|
||||||
|
|
||||||
|
## 貢獻
|
||||||
|
|
||||||
|
歡迎貢獻!請隨時提交 issue 或 pull request。
|
||||||
|
|
||||||
|
## 許可證
|
||||||
|
|
||||||
|
本作品採用 [創用CC 姓名標示-非商業性 4.0 國際 授權條款](https://creativecommons.org/licenses/by-nc/4.0) 授權。
|
||||||
|
|
||||||
|
### 您可以自由地:
|
||||||
|
- **分享** — 以任何媒介或格式重製及散布本素材
|
||||||
|
- **修改** — 重混、轉換本素材、及依本素材建立新素材
|
||||||
|
|
||||||
|
### 惟需遵照下列條件:
|
||||||
|
- **姓名標示** — 您必須給予適當表彰、提供指向本授權條款的連結,以及指出是否已對本素材進行變更
|
||||||
|
- **非商業性** — 您不得將本素材用於商業目的
|
||||||
|
|
||||||
|
## 致謝
|
||||||
|
|
||||||
|
本專案受原版 [OGame](https://ogame.org) 瀏覽器遊戲啟發。所有遊戲機制和設計元素都是為了教育和娛樂目的而重新實現的。
|
||||||
|
|
||||||
|
## 免責聲明
|
||||||
|
|
||||||
|
本專案與 Gameforge AG 或官方 OGame 遊戲沒有任何關聯、認可或聯繫。這是一個獨立的粉絲專案,創建目的僅用於教育和個人娛樂。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
用 ❤️ 製作,作者:<a href="https://github.com/setube">setube</a>
|
||||||
|
<br>
|
||||||
|
© 2025 - 保留所有權利(除 CC BY-NC 4.0 許可證授予的權利外)
|
||||||
|
</div>
|
||||||
160
README.md
@@ -5,13 +5,11 @@
|
|||||||
|
|
||||||
一个基于 Vue 3 和 TypeScript 构建的现代化 OGame 太空策略游戏。
|
一个基于 Vue 3 和 TypeScript 构建的现代化 OGame 太空策略游戏。
|
||||||
|
|
||||||
[](https://creativecommons.org/licenses/by-nc/4.0/)
|
[](https://github.com/setube/ogame-vue-ts/releases/latest)
|
||||||
[](https://vuejs.org/)
|
[](https://creativecommons.org/licenses/by-nc/4.0)
|
||||||
[](https://www.typescriptlang.org/)
|
[](https://www.taptap.cn/app/801190)
|
||||||
[](https://vitejs.dev/)
|
|
||||||
[](https://golang.org/)
|
|
||||||
|
|
||||||
[English](README-EN.md) | 简体中文
|
简体中文 | [繁體中文](README-zh-TW.md) | [English](README-EN.md) | [Deutsch](README-DE.md) | [Русский](README-RU.md) | [Español](README-ES.md) | [한국어](README-KO.md) | [日本語](README-JA.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -21,7 +19,6 @@ OGame Vue TS 是一款受经典 OGame 游戏启发的单机版、基于浏览器
|
|||||||
|
|
||||||
## 核心特性
|
## 核心特性
|
||||||
|
|
||||||
- **多语言支持** - 支持 6 种语言:英语、简体中文、繁体中文、德语、俄语和韩语
|
|
||||||
- **建筑管理** - 在行星和月球上建造和升级各种建筑
|
- **建筑管理** - 在行星和月球上建造和升级各种建筑
|
||||||
- **科技研究** - 解锁先进科技来增强你的帝国
|
- **科技研究** - 解锁先进科技来增强你的帝国
|
||||||
- **舰队管理** - 建造舰船、派遣任务、参与战术太空战斗
|
- **舰队管理** - 建造舰船、派遣任务、参与战术太空战斗
|
||||||
@@ -36,46 +33,24 @@ OGame Vue TS 是一款受经典 OGame 游戏启发的单机版、基于浏览器
|
|||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
- **前端框架:** [Vue 3](https://vuejs.org/) + Composition API (`<script setup>` 语法)
|
- **前端框架:** [Vue 3](https://vuejs.org) + Composition API (`<script setup>` 语法)
|
||||||
- **开发语言:** [TypeScript](https://www.typescriptlang.org/) (启用严格类型检查)
|
- **开发语言:** [TypeScript](https://www.typescriptlang.org) (启用严格类型检查)
|
||||||
- **构建工具:** [Vite](https://vitejs.dev/) (自定义 Rolldown-Vite 7.2.5)、[Golang](https://golang.org/)(构建跨平台的Web服务端)、[Electron](https://www.electronjs.org/)(构建跨平台可视化界面)
|
- **构建工具:** [Vite](https://vitejs.dev) (自定义 Rolldown-Vite 7.2.5)、[Golang](https://golang.org)(构建跨平台的Web服务端)、[Electron](https://www.electronjs.org)(构建跨平台可视化界面)
|
||||||
- **状态管理:** [Pinia](https://pinia.vuejs.org/) + 持久化插件
|
- **状态管理:** [Pinia](https://pinia.vuejs.org) + 持久化插件
|
||||||
- **路由管理:** [Vue Router 4](https://router.vuejs.org/)
|
- **路由管理:** [Vue Router 4](https://router.vuejs.org)
|
||||||
- **UI 组件:** [shadcn-vue](https://www.shadcn-vue.com/) (New York 风格)
|
- **UI 组件:** [shadcn-vue](https://www.shadcn-vue.com) (New York 风格)
|
||||||
- **样式方案:** [Tailwind CSS v4](https://tailwindcss.com/) + CSS 变量
|
- **样式方案:** [Tailwind CSS v4](https://tailwindcss.com) + CSS 变量
|
||||||
- **图标库:** [Lucide Vue Next](https://lucide.dev/)
|
- **图标库:** [Lucide Vue Next](https://lucide.dev)
|
||||||
- **动画效果:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
- **动画效果:** [tw-animate-css](https://www.npmjs.com/package/tw-animate-css)
|
||||||
- **国际化:** 自定义 i18n 实现
|
- **国际化:** 自定义 i18n 实现
|
||||||
|
|
||||||
## 快速开始
|
## 快速开始
|
||||||
|
|
||||||
### 下载构建版本
|
|
||||||
|
|
||||||
#### 服务端
|
|
||||||
|
|
||||||
[Windows](/releases/latest/download/ogame-windows-amd64.exe)
|
|
||||||
|
|
||||||
[Linux amd64](/releases/latest/download/ogame-linux-amd64)
|
|
||||||
|
|
||||||
[Linux arm64](/releases/latest/download/ogame-linux-arm64)
|
|
||||||
|
|
||||||
[MacOS Intel](/releases/latest/download/ogame-macos-amd64)
|
|
||||||
|
|
||||||
[MacOS](/releases/latest/download/ogame-macos-arm64)
|
|
||||||
|
|
||||||
#### 桌面版
|
|
||||||
|
|
||||||
[Windows](/releases/latest/download/OGame.Setup.exe)
|
|
||||||
|
|
||||||
[Ubuntu](/releases/latest/download/OGame.AppImage)
|
|
||||||
|
|
||||||
[MacOS](/releases/latest/download/OGame-mac.dmg)
|
|
||||||
|
|
||||||
### 环境要求
|
### 环境要求
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org/) (推荐 18 或更高版本)
|
- [Node.js](https://nodejs.org) (推荐 18 或更高版本)
|
||||||
- [pnpm](https://pnpm.io/) (版本 10.13.1 或更高)
|
- [pnpm](https://pnpm.io) (版本 10.13.1 或更高)
|
||||||
- [Go](https://golang.org/) (版本 1.21 或更高版本)(可选)
|
- [Go](https://golang.org) (版本 1.21 或更高版本)(可选)
|
||||||
|
|
||||||
### 安装
|
### 安装
|
||||||
|
|
||||||
@@ -109,98 +84,6 @@ pnpm build
|
|||||||
pnpm preview
|
pnpm preview
|
||||||
```
|
```
|
||||||
|
|
||||||
## 项目结构
|
|
||||||
|
|
||||||
```
|
|
||||||
ogame-vue-ts/
|
|
||||||
├── public/ # 静态资源
|
|
||||||
│ └── logo.svg # 应用图标
|
|
||||||
├── src/
|
|
||||||
│ ├── assets/ # 动态资源
|
|
||||||
│ ├── components/ # Vue 组件
|
|
||||||
│ │ └── ui/ # shadcn-vue UI 组件
|
|
||||||
│ ├── composables/ # Vue 组合式函数
|
|
||||||
│ ├── config/ # 游戏配置
|
|
||||||
│ ├── lib/ # 工具库
|
|
||||||
│ ├── locales/ # 国际化翻译文件
|
|
||||||
│ ├── logic/ # 游戏逻辑模块
|
|
||||||
│ │ ├── buildingLogic.ts # 建筑逻辑
|
|
||||||
│ │ ├── buildingValidation.ts # 建筑验证
|
|
||||||
│ │ ├── fleetLogic.ts # 舰队逻辑
|
|
||||||
│ │ ├── moonLogic.ts # 月球逻辑
|
|
||||||
│ │ ├── moonValidation.ts # 月球验证
|
|
||||||
│ │ ├── researchLogic.ts # 研究逻辑
|
|
||||||
│ │ ├── researchValidation.ts # 研究验证
|
|
||||||
│ │ ├── shipLogic.ts # 舰船逻辑
|
|
||||||
│ │ └── shipValidation.ts # 舰船验证
|
|
||||||
│ ├── router/ # Vue Router 路由配置
|
|
||||||
│ ├── stores/ # Pinia 状态存储
|
|
||||||
│ ├── types/ # TypeScript 类型定义
|
|
||||||
│ ├── utils/ # 工具函数
|
|
||||||
│ ├── views/ # 页面组件
|
|
||||||
│ │ ├── OverviewView.vue # 概览页面
|
|
||||||
│ │ ├── BuildingsView.vue # 建筑页面
|
|
||||||
│ │ ├── ResearchView.vue # 研究页面
|
|
||||||
│ │ ├── ShipyardView.vue # 船坞页面
|
|
||||||
│ │ ├── DefenseView.vue # 防御页面
|
|
||||||
│ │ ├── FleetView.vue # 舰队页面
|
|
||||||
│ │ ├── GalaxyView.vue # 银河页面
|
|
||||||
│ │ ├── OfficersView.vue # 军官页面
|
|
||||||
│ │ ├── BattleSimulatorView.vue # 战斗模拟器
|
|
||||||
│ │ ├── MessagesView.vue # 消息页面
|
|
||||||
│ │ └── SettingsView.vue # 设置页面
|
|
||||||
│ ├── App.vue # 根组件
|
|
||||||
│ ├── main.ts # 应用入口
|
|
||||||
│ └── style.css # 全局样式
|
|
||||||
├── .github/
|
|
||||||
│ └── ISSUE_TEMPLATE/ # GitHub issue 模板
|
|
||||||
├── LICENSE # CC BY-NC 4.0 许可证
|
|
||||||
├── package.json # 项目依赖
|
|
||||||
├── tsconfig.json # TypeScript 配置
|
|
||||||
└── vite.config.ts # Vite 配置
|
|
||||||
```
|
|
||||||
|
|
||||||
## 支持的语言
|
|
||||||
|
|
||||||
- 🇺🇸 English (英语)
|
|
||||||
- 🇨🇳 简体中文
|
|
||||||
- 🇹🇼 繁體中文
|
|
||||||
- 🇩🇪 Deutsch (德语)
|
|
||||||
- 🇷🇺 Русский (俄语)
|
|
||||||
- 🇰🇷 한국어 (韩语)
|
|
||||||
|
|
||||||
## 游戏特性
|
|
||||||
|
|
||||||
### 资源管理
|
|
||||||
- **金属** - 主要建筑材料
|
|
||||||
- **晶体** - 高级科技组件
|
|
||||||
- **重氢** - 燃料和研究资源
|
|
||||||
- **暗物质** - 高级资源
|
|
||||||
- **能量** - 为设施供电
|
|
||||||
|
|
||||||
### 建筑类型
|
|
||||||
- **资源建筑** - 金属矿、晶体矿、重氢合成器、太阳能发电厂
|
|
||||||
- **设施建筑** - 机器人工厂、船坞、研究实验室、仓储设施
|
|
||||||
- **特殊建筑** - 纳米机器人工厂、行星改造器等
|
|
||||||
|
|
||||||
### 科技系统
|
|
||||||
- **能量技术** - 提高能量效率
|
|
||||||
- **激光技术** - 增强武器系统
|
|
||||||
- **离子技术** - 高级推进和武器
|
|
||||||
- **超空间技术** - 实现更快的旅行
|
|
||||||
- **等离子技术** - 终极武器系统
|
|
||||||
- 还有更多...
|
|
||||||
|
|
||||||
### 舰船类别
|
|
||||||
- **民用舰船** - 小型/大型货船、殖民船、回收船
|
|
||||||
- **战斗舰船** - 轻型/重型战斗机、巡洋舰、战列舰、轰炸机
|
|
||||||
- **特殊舰船** - 死星、战列巡洋舰、毁灭者
|
|
||||||
|
|
||||||
### 防御系统
|
|
||||||
- 火箭发射器、轻型/重型激光炮、高斯炮
|
|
||||||
- 离子炮、等离子炮塔
|
|
||||||
- 小型/大型防护罩
|
|
||||||
|
|
||||||
## 数据安全
|
## 数据安全
|
||||||
|
|
||||||
所有游戏数据在存储到浏览器的本地存储之前都会使用 AES 加密自动加密。您的游戏进度是安全且私密的。
|
所有游戏数据在存储到浏览器的本地存储之前都会使用 AES 加密自动加密。您的游戏进度是安全且私密的。
|
||||||
@@ -213,16 +96,9 @@ ogame-vue-ts/
|
|||||||
|
|
||||||
欢迎贡献!请随时提交 issue 或 pull request。
|
欢迎贡献!请随时提交 issue 或 pull request。
|
||||||
|
|
||||||
### Issue 模板
|
|
||||||
我们提供以下中英文 issue 模板:
|
|
||||||
- BUG反馈 / Bug Report
|
|
||||||
- 功能请求 / Feature Request
|
|
||||||
- 文档改进 / Documentation Improvement
|
|
||||||
- 反馈建议 / Feedback & Suggestion
|
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|
||||||
本作品采用 [知识共享署名-非商业性使用 4.0 国际许可协议](https://creativecommons.org/licenses/by-nc/4.0/) 进行许可。
|
本作品采用 [知识共享署名-非商业性使用 4.0 国际许可协议](https://creativecommons.org/licenses/by-nc/4.0) 进行许可。
|
||||||
|
|
||||||
### 您可以自由地:
|
### 您可以自由地:
|
||||||
- **共享** — 在任何媒介以任何形式复制、发行本作品
|
- **共享** — 在任何媒介以任何形式复制、发行本作品
|
||||||
@@ -234,7 +110,7 @@ ogame-vue-ts/
|
|||||||
|
|
||||||
## 致谢
|
## 致谢
|
||||||
|
|
||||||
本项目受原版 [OGame](https://ogame.org/) 浏览器游戏启发。所有游戏机制和设计元素都是为了教育和娱乐目的而重新实现的。
|
本项目受原版 [OGame](https://ogame.org) 浏览器游戏启发。所有游戏机制和设计元素都是为了教育和娱乐目的而重新实现的。
|
||||||
|
|
||||||
## 免责声明
|
## 免责声明
|
||||||
|
|
||||||
@@ -243,7 +119,7 @@ ogame-vue-ts/
|
|||||||
---
|
---
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
用 ❤️ 制作,作者:谦君
|
用 ❤️ 制作,作者:<a href="https://github.com/setube">setube</a>
|
||||||
<br>
|
<br>
|
||||||
© 2025 - 保留所有权利(除 CC BY-NC 4.0 许可证授予的权利外)
|
© 2025 - 保留所有权利(除 CC BY-NC 4.0 许可证授予的权利外)
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
101
android/.gitignore
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore
|
||||||
|
|
||||||
|
# Built application files
|
||||||
|
*.apk
|
||||||
|
*.aar
|
||||||
|
*.ap_
|
||||||
|
*.aab
|
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
out/
|
||||||
|
# Uncomment the following line in case you need and you don't have the release build type files in your app
|
||||||
|
# release/
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
proguard/
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio Navigation editor temp files
|
||||||
|
.navigation/
|
||||||
|
|
||||||
|
# Android Studio captures folder
|
||||||
|
captures/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/workspace.xml
|
||||||
|
.idea/tasks.xml
|
||||||
|
.idea/gradle.xml
|
||||||
|
.idea/assetWizardSettings.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
.idea/libraries
|
||||||
|
# Android Studio 3 in .gitignore file.
|
||||||
|
.idea/caches
|
||||||
|
.idea/modules.xml
|
||||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||||
|
.idea/navEditor.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
|
#*.jks
|
||||||
|
#*.keystore
|
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx/
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
# google-services.json
|
||||||
|
|
||||||
|
# Freeline
|
||||||
|
freeline.py
|
||||||
|
freeline/
|
||||||
|
freeline_project_description.json
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots
|
||||||
|
fastlane/test_output
|
||||||
|
fastlane/readme.md
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
vcs.xml
|
||||||
|
|
||||||
|
# lint
|
||||||
|
lint/intermediates/
|
||||||
|
lint/generated/
|
||||||
|
lint/outputs/
|
||||||
|
lint/tmp/
|
||||||
|
# lint/reports/
|
||||||
|
|
||||||
|
# Android Profiling
|
||||||
|
*.hprof
|
||||||
|
|
||||||
|
# Cordova plugins for Capacitor
|
||||||
|
capacitor-cordova-android-plugins
|
||||||
|
|
||||||
|
# Copied web assets
|
||||||
|
app/src/main/assets/public
|
||||||
|
|
||||||
|
# Generated Config files
|
||||||
|
app/src/main/assets/capacitor.config.json
|
||||||
|
app/src/main/assets/capacitor.plugins.json
|
||||||
|
app/src/main/res/xml/config.xml
|
||||||
2
android/app/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/build/*
|
||||||
|
!/build/.npmkeep
|
||||||
102
android/app/build.gradle
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
// 从 package.json 读取版本号
|
||||||
|
def packageJsonFile = file('../../package.json')
|
||||||
|
def packageJsonText = packageJsonFile.text
|
||||||
|
// 使用正则提取版本号
|
||||||
|
def versionMatcher = packageJsonText =~ /"version"\s*:\s*"([^"]+)"/
|
||||||
|
def appVersionName = versionMatcher ? versionMatcher[0][1] : "1.0.0"
|
||||||
|
// 将版本号转换为 versionCode,例如 "1.5.5" -> 1*10000 + 5*100 + 5 = 10505
|
||||||
|
def versionParts = appVersionName.split('\\.')
|
||||||
|
def appVersionCode = versionParts[0].toInteger() * 10000 + versionParts[1].toInteger() * 100 + versionParts[2].toInteger()
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "games.wenzi.ogame"
|
||||||
|
compileSdk = rootProject.ext.compileSdkVersion
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "games.wenzi.ogame"
|
||||||
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
|
versionCode appVersionCode
|
||||||
|
versionName appVersionName
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
aaptOptions {
|
||||||
|
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||||
|
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
|
||||||
|
ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按 ABI 拆分 APK (arm64-v8a, armeabi-v7a, x86_64)
|
||||||
|
splits {
|
||||||
|
abi {
|
||||||
|
enable true
|
||||||
|
reset()
|
||||||
|
include "arm64-v8a", "armeabi-v7a", "x86_64"
|
||||||
|
universalApk false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
release {
|
||||||
|
storeFile file('release.keystore')
|
||||||
|
storePassword 'ogame123'
|
||||||
|
keyAlias 'ogame'
|
||||||
|
keyPassword 'ogame123'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled true
|
||||||
|
shrinkResources true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
signingConfig signingConfigs.release
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为每个 ABI 设置不同的 versionCode
|
||||||
|
applicationVariants.configureEach { variant ->
|
||||||
|
variant.outputs.configureEach { output ->
|
||||||
|
def abiVersionCode = [
|
||||||
|
"armeabi-v7a": 1,
|
||||||
|
"arm64-v8a": 2,
|
||||||
|
"x86_64": 3
|
||||||
|
]
|
||||||
|
def abi = output.getFilter(com.android.build.OutputFile.ABI)
|
||||||
|
if (abi != null) {
|
||||||
|
output.versionCodeOverride = abiVersionCode[abi] * 1000 + defaultConfig.versionCode
|
||||||
|
output.outputFileName = "OGame-Vue-Ts-${abi}.apk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
flatDir{
|
||||||
|
dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
||||||
|
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
||||||
|
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
||||||
|
implementation project(':capacitor-android')
|
||||||
|
testImplementation "junit:junit:$junitVersion"
|
||||||
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||||
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||||
|
implementation project(':capacitor-cordova-android-plugins')
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: 'capacitor.build.gradle'
|
||||||
|
|
||||||
|
try {
|
||||||
|
def servicesJSON = file('google-services.json')
|
||||||
|
if (servicesJSON.text) {
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
|
||||||
|
}
|
||||||
20
android/app/capacitor.build.gradle
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_21
|
||||||
|
targetCompatibility JavaVersion.VERSION_21
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||||
|
dependencies {
|
||||||
|
implementation project(':capacitor-app')
|
||||||
|
implementation project(':capacitor-filesystem')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hasProperty('postBuildExtras')) {
|
||||||
|
postBuildExtras()
|
||||||
|
}
|
||||||
21
android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
BIN
android/app/release.keystore
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package com.getcapacitor.myapp;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void useAppContext() throws Exception {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||||
|
|
||||||
|
assertEquals("com.getcapacitor.app", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
||||||
59
android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:label="@string/title_activity_main"
|
||||||
|
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:exported="true">
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths"></meta-data>
|
||||||
|
</provider>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<!-- Permissions -->
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<!-- 旧版本存储权限 (Android 10 及以下) -->
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="30" />
|
||||||
|
|
||||||
|
<!-- Android 11+ (API 30+) 完整外部存储访问权限 -->
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
<!-- Android 13+ (API 33+) 细粒度媒体权限 -->
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
|
</manifest>
|
||||||
148
android/app/src/main/java/games/wenzi/ogame/MainActivity.java
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package games.wenzi.ogame;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
|
import android.webkit.ValueCallback;
|
||||||
|
import android.webkit.WebChromeClient;
|
||||||
|
import android.webkit.WebSettings;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.content.Intent;
|
||||||
|
import androidx.core.splashscreen.SplashScreen;
|
||||||
|
import androidx.core.view.WindowCompat;
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat;
|
||||||
|
import com.getcapacitor.BridgeActivity;
|
||||||
|
|
||||||
|
public class MainActivity extends BridgeActivity {
|
||||||
|
private boolean isWebViewReady = false;
|
||||||
|
private static final int FILE_CHOOSER_REQUEST_CODE = 1001;
|
||||||
|
private ValueCallback<Uri[]> filePathCallback;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
// 安装 SplashScreen,必须在 super.onCreate 之前调用
|
||||||
|
SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
|
||||||
|
|
||||||
|
// 保持 SplashScreen 直到 WebView 加载完成
|
||||||
|
splashScreen.setKeepOnScreenCondition(() -> !isWebViewReady);
|
||||||
|
|
||||||
|
// 设置淡出退出动画
|
||||||
|
splashScreen.setOnExitAnimationListener(splashScreenView -> {
|
||||||
|
// 创建淡出动画
|
||||||
|
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(
|
||||||
|
splashScreenView.getView(),
|
||||||
|
View.ALPHA,
|
||||||
|
1f,
|
||||||
|
0f
|
||||||
|
);
|
||||||
|
fadeOut.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||||
|
fadeOut.setDuration(300);
|
||||||
|
|
||||||
|
// 动画结束后移除 SplashScreen
|
||||||
|
fadeOut.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
splashScreenView.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fadeOut.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
Window window = getWindow();
|
||||||
|
|
||||||
|
// 启用边到边显示(Edge-to-Edge)
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false);
|
||||||
|
|
||||||
|
// 设置透明状态栏和导航栏
|
||||||
|
window.setStatusBarColor(Color.TRANSPARENT);
|
||||||
|
window.setNavigationBarColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
|
// 设置状态栏图标为浅色(因为背景是深色)
|
||||||
|
WindowInsetsControllerCompat controller = WindowCompat.getInsetsController(window, window.getDecorView());
|
||||||
|
if (controller != null) {
|
||||||
|
controller.setAppearanceLightStatusBars(false);
|
||||||
|
controller.setAppearanceLightNavigationBars(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
WebView webView = getBridge().getWebView();
|
||||||
|
if (webView != null) {
|
||||||
|
WebSettings settings = webView.getSettings();
|
||||||
|
// 禁用 WebView 文本缩放,防止系统字体大小设置影响布局
|
||||||
|
settings.setTextZoom(100);
|
||||||
|
// 优化 WebView 性能
|
||||||
|
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||||
|
settings.setDomStorageEnabled(true);
|
||||||
|
settings.setDatabaseEnabled(true);
|
||||||
|
// 启用硬件加速渲染
|
||||||
|
webView.setLayerType(android.view.View.LAYER_TYPE_HARDWARE, null);
|
||||||
|
|
||||||
|
// 监听页面加载进度,加载完成后隐藏 SplashScreen
|
||||||
|
webView.setWebChromeClient(new WebChromeClient() {
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(WebView view, int newProgress) {
|
||||||
|
super.onProgressChanged(view, newProgress);
|
||||||
|
// 当页面加载达到 80% 时认为可以显示
|
||||||
|
if (newProgress >= 80) {
|
||||||
|
isWebViewReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
|
||||||
|
FileChooserParams fileChooserParams) {
|
||||||
|
// 清理之前的回调
|
||||||
|
if (MainActivity.this.filePathCallback != null) {
|
||||||
|
MainActivity.this.filePathCallback.onReceiveValue(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainActivity.this.filePathCallback = filePathCallback;
|
||||||
|
|
||||||
|
// 创建文件选择器 Intent
|
||||||
|
Intent intent = fileChooserParams.createIntent();
|
||||||
|
try {
|
||||||
|
startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE);
|
||||||
|
} catch (android.content.ActivityNotFoundException e) {
|
||||||
|
MainActivity.this.filePathCallback = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
|
if (requestCode == FILE_CHOOSER_REQUEST_CODE) {
|
||||||
|
if (filePathCallback == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri[] results = null;
|
||||||
|
if (resultCode == RESULT_OK && data != null) {
|
||||||
|
String dataString = data.getDataString();
|
||||||
|
if (dataString != null) {
|
||||||
|
results = new Uri[]{Uri.parse(dataString)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filePathCallback.onReceiveValue(results);
|
||||||
|
filePathCallback = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
android/app/src/main/res/drawable-land-hdpi/splash.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
android/app/src/main/res/drawable-land-mdpi/splash.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
android/app/src/main/res/drawable-land-xhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
android/app/src/main/res/drawable-land-xxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
android/app/src/main/res/drawable-land-xxxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
android/app/src/main/res/drawable-port-hdpi/splash.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
android/app/src/main/res/drawable-port-mdpi/splash.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
android/app/src/main/res/drawable-port-xhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
android/app/src/main/res/drawable-port-xxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
android/app/src/main/res/drawable-port-xxxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,34 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
|
android:viewportWidth="108">
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:strokeWidth="1">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="78.5885"
|
||||||
|
android:endY="90.9159"
|
||||||
|
android:startX="48.7653"
|
||||||
|
android:startY="61.0927"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:strokeWidth="1" />
|
||||||
|
</vector>
|
||||||
170
android/app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
|
android:viewportWidth="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#26A69A"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
</vector>
|
||||||
BIN
android/app/src/main/res/drawable/splash.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
9
android/app/src/main/res/drawable/splash_icon.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 启动画面专用图标,使用较小的尺寸避免模糊 -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:width="96dp"
|
||||||
|
android:height="96dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:drawable="@mipmap/ic_launcher_foreground" />
|
||||||
|
</layer-list>
|
||||||
12
android/app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<WebView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 15 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
5
android/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="status_bar_color">#1a1a2e</color>
|
||||||
|
<color name="splash_background">#0f0f1a</color>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#FFFFFF</color>
|
||||||
|
</resources>
|
||||||
7
android/app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">OGame Vue Ts</string>
|
||||||
|
<string name="title_activity_main">OGame Vue Ts</string>
|
||||||
|
<string name="package_name">games.wenzi.ogame</string>
|
||||||
|
<string name="custom_url_scheme">games.wenzi.ogame</string>
|
||||||
|
</resources>
|
||||||
33
android/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="colorPrimary">#1a1a2e</item>
|
||||||
|
<item name="colorPrimaryDark">#0f0f1a</item>
|
||||||
|
<item name="colorAccent">#6366f1</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
|
<item name="windowActionBar">false</item>
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="android:background">@null</item>
|
||||||
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
|
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||||
|
<item name="android:windowTranslucentStatus">false</item>
|
||||||
|
<item name="android:windowTranslucentNavigation">false</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- 启动画面主题 - 延长显示直到 WebView 加载完成 -->
|
||||||
|
<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
|
||||||
|
<item name="windowSplashScreenBackground">@color/splash_background</item>
|
||||||
|
<!-- 使用较小的自定义图标避免模糊 -->
|
||||||
|
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
|
||||||
|
<!-- 图标大小限制 -->
|
||||||
|
<item name="windowSplashScreenIconBackgroundColor">@color/splash_background</item>
|
||||||
|
<!-- 退出动画时长 -->
|
||||||
|
<item name="android:windowSplashScreenAnimationDuration">500</item>
|
||||||
|
<item name="postSplashScreenTheme">@style/AppTheme.NoActionBar</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
5
android/app/src/main/res/xml/file_paths.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<external-path name="my_images" path="." />
|
||||||
|
<cache-path name="my_cache_images" path="." />
|
||||||
|
</paths>
|
||||||
8
android/app/src/main/res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<network-security-config>
|
||||||
|
<base-config cleartextTrafficPermitted="true">
|
||||||
|
<trust-anchors>
|
||||||
|
<certificates src="system" />
|
||||||
|
</trust-anchors>
|
||||||
|
</base-config>
|
||||||
|
</network-security-config>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.getcapacitor.myapp;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() throws Exception {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
android/build.gradle
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:8.13.0'
|
||||||
|
classpath 'com.google.gms:google-services:4.4.4'
|
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "variables.gradle"
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
||||||
9
android/capacitor.settings.gradle
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||||
|
include ':capacitor-android'
|
||||||
|
project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@8.0.0_@capacitor+core@8.0.0/node_modules/@capacitor/android/capacitor')
|
||||||
|
|
||||||
|
include ':capacitor-app'
|
||||||
|
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@8.0.0_@capacitor+core@8.0.0/node_modules/@capacitor/app/android')
|
||||||
|
|
||||||
|
include ':capacitor-filesystem'
|
||||||
|
project(':capacitor-filesystem').projectDir = new File('../node_modules/.pnpm/@capacitor+filesystem@8.0.0_@capacitor+core@8.0.0/node_modules/@capacitor/filesystem/android')
|
||||||
22
android/gradle.properties
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
|
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
|
||||||
|
# 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
|
||||||
|
android.useAndroidX=true
|
||||||
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
7
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
251
android/gradlew
vendored
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH="\\\"\\\""
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
94
android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
5
android/settings.gradle
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
include ':app'
|
||||||
|
include ':capacitor-cordova-android-plugins'
|
||||||
|
project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')
|
||||||
|
|
||||||
|
apply from: 'capacitor.settings.gradle'
|
||||||
16
android/variables.gradle
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
ext {
|
||||||
|
minSdkVersion = 24
|
||||||
|
compileSdkVersion = 36
|
||||||
|
targetSdkVersion = 36
|
||||||
|
androidxActivityVersion = '1.11.0'
|
||||||
|
androidxAppCompatVersion = '1.7.1'
|
||||||
|
androidxCoordinatorLayoutVersion = '1.3.0'
|
||||||
|
androidxCoreVersion = '1.17.0'
|
||||||
|
androidxFragmentVersion = '1.8.9'
|
||||||
|
coreSplashScreenVersion = '1.2.0'
|
||||||
|
androidxWebkitVersion = '1.14.0'
|
||||||
|
junitVersion = '4.13.2'
|
||||||
|
androidxJunitVersion = '1.3.0'
|
||||||
|
androidxEspressoCoreVersion = '3.7.0'
|
||||||
|
cordovaAndroidVersion = '14.0.1'
|
||||||
|
}
|
||||||
17
build-docker.bat
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@echo off
|
||||||
|
REM 本地 Docker 构建脚本 (Windows)
|
||||||
|
REM 使用完整的源代码构建流程
|
||||||
|
|
||||||
|
echo 🚀 开始本地 Docker 构建...
|
||||||
|
|
||||||
|
REM 构建镜像
|
||||||
|
docker build -t ogame-vue-ts:local .
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 0 (
|
||||||
|
echo ✅ Docker 镜像构建成功!
|
||||||
|
echo 📦 镜像标签: ogame-vue-ts:local
|
||||||
|
echo 🏃 运行命令: docker run -p 8080:80 ogame-vue-ts:local
|
||||||
|
) else (
|
||||||
|
echo ❌ Docker 镜像构建失败!
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
18
build-docker.sh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 本地 Docker 构建脚本
|
||||||
|
# 使用完整的源代码构建流程
|
||||||
|
|
||||||
|
echo "🚀 开始本地 Docker 构建..."
|
||||||
|
|
||||||
|
# 构建镜像
|
||||||
|
docker build -t ogame-vue-ts:local .
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ Docker 镜像构建成功!"
|
||||||
|
echo "📦 镜像标签: ogame-vue-ts:local"
|
||||||
|
echo "🏃 运行命令: docker run -p 8080:80 ogame-vue-ts:local"
|
||||||
|
else
|
||||||
|
echo "❌ Docker 镜像构建失败!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
18
capacitor.config.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import type { CapacitorConfig } from '@capacitor/cli'
|
||||||
|
|
||||||
|
const config: CapacitorConfig = {
|
||||||
|
appId: 'games.wenzi.ogame',
|
||||||
|
appName: 'OGame Vue Ts',
|
||||||
|
webDir: 'docs',
|
||||||
|
server: { androidScheme: 'https', cacheControl: 'max-age=31536000' },
|
||||||
|
android: {
|
||||||
|
buildOptions: { keystorePath: undefined, keystoreAlias: undefined },
|
||||||
|
webContentsDebuggingEnabled: false,
|
||||||
|
allowMixedContent: false,
|
||||||
|
hardwareAcceleration: true
|
||||||
|
},
|
||||||
|
// 禁用键盘自动调整视口
|
||||||
|
plugins: { Keyboard: { resize: 'none' } }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default config
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { BrowserWindow, app } from "electron";
|
|
||||||
import path, { dirname } from "node:path";
|
|
||||||
import { fileURLToPath } from "node:url";
|
|
||||||
app.whenReady().then(() => {
|
|
||||||
let i = dirname(fileURLToPath(import.meta.url)), a = new BrowserWindow({
|
|
||||||
title: "OGame",
|
|
||||||
icon: path.join(i, "../public/favicon.ico"),
|
|
||||||
width: 1200,
|
|
||||||
height: 800
|
|
||||||
});
|
|
||||||
a.setMenu(null), process.env.VITE_DEV_SERVER_URL ? a.loadURL(process.env.VITE_DEV_SERVER_URL) : a.loadFile("docs/index.html");
|
|
||||||
});
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ogame-vue-ts.wenzi.games
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import{$t as e,At as t,Ct as n,Dn as r,En as i,Gn as a,Gt as o,Jt as s,Ln as c,Ot as ee,Qt as l,Vt as te,Xn as u,Xt as d,Yn as ne,Yt as f,Zt as p,_ as m,b as h,en as g,g as re,gn as _,jt as ie,kt as ae,m as oe,mn as v,p as se,qn as y,tn as ce,v as le,y as b}from"./game-logic-Bi1l7y4K.js";import"./vendor-pinia-DqhKuBjp.js";import"./vendor-crypto-CQM8pryk.js";import"./game-i18n-Dr0JspcV.js";import"./vendor-others-DTUzJ7S-.js";import"./vendor-reka-ui-BEHIKScj.js";import"./vendor-utils-BlvnUqQX.js";import"./vendor-vueuse-CJcfYqoW.js";import{B as ue,M as x}from"./vendor-icons-z9V6Jdbh.js";import{t as S}from"./CardDescription-BSLS07AU.js";import{d as C,v as de}from"./game-config-CG6z6nnH.js";import{D as fe,H as pe,K as w,N as T,W as E,_ as D,a as O,b as me,c as he,f as k,h as ge,i as A,l as j,o as M,p as N,q as P,r as F,s as I,u as L,v as _e,y as ve}from"./index-BT5w6et-.js";import{t as ye}from"./useGameConfig-b98LOtBY.js";import{t as be}from"./CardUnlockOverlay-DYfgGY6J.js";var xe={key:0,class:`container mx-auto p-4 sm:p-6`},Se={class:`text-2xl sm:text-3xl font-bold mb-4 sm:mb-6`},Ce={class:`mb-4 sm:mb-6 p-3 sm:p-4 bg-muted/50 rounded-lg border`},we={class:`flex items-center justify-between`},Te={class:`text-sm sm:text-base font-medium flex items-center gap-2`},Ee={class:`text-sm sm:text-base font-bold`},De={class:`mt-2`},Oe={class:`w-full bg-background rounded-full h-2.5 sm:h-3 overflow-hidden`},ke={class:`grid grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4`},Ae={class:`mb-2`},je={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-2`},Me={class:`space-y-3`},R={class:`text-xs sm:text-sm space-y-1.5 sm:space-y-2`},Ne={class:`text-muted-foreground mb-1 sm:mb-2`},Pe={class:`space-y-1 sm:space-y-1.5`},Fe={class:`text-xs`},Ie={class:`text-xs sm:text-sm space-y-0.5 sm:space-y-1`},Le={class:`flex items-center gap-1.5 text-muted-foreground`},Re={class:`flex items-center gap-1.5 text-muted-foreground`},ze={key:1,class:`text-xs text-muted-foreground`},Be={class:`flex gap-2 flex-wrap`},Ve={key:0},z=ce({__name:`BuildingsView`,setup(ce){let z=P(),He=fe(),{t:B}=w(),{BUILDINGS:V,TECHNOLOGIES:Ue}=ye(),H=s(()=>z.currentPlanet),U=c(!1),W=c(``),G=c(``),K=c(!1),q=c(``),J=c(null),We=[{key:`metal`},{key:`crystal`},{key:`deuterium`},{key:`darkMatter`}],Ge=s(()=>H.value?Object.values(C).filter(e=>{let t=V.value[e];return H.value.isMoon?t.moonOnly===!0:t.moonOnly!==!0}):[]),Ke=e=>{if(!z.currentPlanet||!m(z.currentPlanet,e,z.player.technologies,z.player.officers).valid)return!1;let t=oe(z.currentPlanet,e,z.player.officers);return z.currentPlanet.buildQueue.push(t),!0},Y=e=>ie(e),qe=e=>{if(!Z(e)){W.value=B(`common.requirementsNotMet`),G.value=Ye(e),U.value=!0;return}Ke(e)||(W.value=B(`buildingsView.upgradeFailed`),G.value=B(`buildingsView.upgradeFailedMessage`),U.value=!0)},X=e=>H.value?.buildings[e]||0,Z=e=>{if(!H.value)return!1;let t=V.value[e],n=b(t,X(e)+1);return!n||Object.keys(n).length===0?!0:le(H.value,z.player.technologies,n)},Je=e=>{if(!H.value)return B(`buildingsView.upgrade`);let t=V.value[e],n=X(e);return t.maxLevel!==void 0&&n>=t.maxLevel?B(`buildingsView.maxLevelReached`):H.value.buildQueue.length>0||Z(e)?B(`buildingsView.upgrade`):B(`buildingsView.requirementsNotMet`)},Ye=e=>{let t=V.value[e],n=b(t,X(e)+1);if(!n||!H.value)return``;let r=[];for(let[e,t]of Object.entries(n))if(Object.values(C).includes(e)){let n=e,i=H.value.buildings[n]||0,a=V.value[n]?.name||n,o=i>=t?`✓`:`✗`;r.push(`${o} ${a}: Lv ${t} (${B(`common.current`)}: Lv ${i})`)}else if(Object.values(de).includes(e)){let n=e,i=z.player.technologies[n]||0,a=Ue.value[n]?.name||n,o=i>=t?`✓`:`✗`;r.push(`${o} ${a}: Lv ${t} (${B(`common.current`)}: Lv ${i})`)}return r.join(`
|
|
||||||
`)},Xe=e=>{if(!H.value)return!1;let t=V.value[e],r=X(e);if(t.maxLevel!==void 0&&r>=t.maxLevel)return!1;let i=n(z.player.officers,Date.now()),a=h(H.value,i.additionalBuildQueue);if(H.value.buildQueue.filter(e=>e.type===`building`||e.type===`demolish`).length>=a||!m(H.value,e,z.player.technologies,z.player.officers).valid)return!1;let o=Q(e,r+1);return H.value.resources.metal>=o.metal&&H.value.resources.crystal>=o.crystal&&H.value.resources.deuterium>=o.deuterium&&H.value.resources.darkMatter>=o.darkMatter},Q=(e,t)=>ee(e,t),Ze=(e,t)=>{if(!H.value)return 0;let r=n(z.player.officers,Date.now()),i=H.value.buildings[C.RoboticsFactory]||0,a=H.value.buildings[C.NaniteFactory]||0;return ae(e,t,r.buildingSpeedBonus,i,a)},Qe=e=>{if(!z.currentPlanet||!re(z.currentPlanet,e,z.player.officers).valid)return!1;let t=se(z.currentPlanet,e,z.player.officers);return z.currentPlanet.buildQueue.push(t),!0},$e=e=>{let t=V.value[e].name,n=$(e);q.value=`${B(`buildingsView.confirmDemolishMessage`)}: ${t}
|
|
||||||
|
|
||||||
${B(`buildingsView.demolishRefund`)}:
|
|
||||||
${B(`resources.metal`)}: ${k(n.metal)}
|
|
||||||
${B(`resources.crystal`)}: ${k(n.crystal)}
|
|
||||||
${B(`resources.deuterium`)}: ${k(n.deuterium)}${n.darkMatter>0?`\n${B(`resources.darkMatter`)}: ${k(n.darkMatter)}`:``}`,J.value=e,K.value=!0},et=()=>{J.value&&(Qe(J.value)||(W.value=B(`buildingsView.demolishFailed`),G.value=B(`buildingsView.demolishFailedMessage`),U.value=!0)),K.value=!1,J.value=null},tt=e=>{if(!H.value||X(e)<=0)return!1;let t=n(z.player.officers,Date.now()),r=h(H.value,t.additionalBuildQueue);return!(H.value.buildQueue.filter(e=>e.type===`building`||e.type===`demolish`).length>=r)},$=e=>t(e,X(e));return(t,n)=>H.value?(v(),l(`div`,xe,[f(`h1`,Se,u(a(B)(`buildingsView.title`)),1),f(`div`,Ce,[f(`div`,we,[f(`div`,Te,[g(a(x),{size:16}),e(` `+u(a(B)(`buildingsView.spaceUsage`))+`: `,1)]),f(`div`,Ee,[f(`span`,{class:y(Y(H.value)>H.value.maxSpace?`text-destructive`:`text-primary`)},u(a(k)(Y(H.value))),3),n[2]||=f(`span`,{class:`text-muted-foreground mx-1`},`/`,-1),f(`span`,null,u(a(k)(H.value.maxSpace)),1)])]),f(`div`,De,[f(`div`,Oe,[f(`div`,{class:y([`h-full transition-all duration-300`,Y(H.value)>H.value.maxSpace?`bg-destructive`:`bg-primary`]),style:ne({width:`${Math.min(Y(H.value)/H.value.maxSpace*100,100)}%`})},null,6)])])]),f(`div`,ke,[(v(!0),l(o,null,_(Ge.value,t=>(v(),d(a(me),{key:t,class:`relative`},{default:i(()=>[g(be,{requirements:a(V)[t].requirements,currentLevel:X(t)},null,8,[`requirements`,`currentLevel`]),g(a(_e),null,{default:i(()=>[f(`div`,Ae,[f(`div`,je,[g(a(D),{class:`text-sm sm:text-base lg:text-lg cursor-pointer hover:text-primary transition-colors underline decoration-dotted underline-offset-4 order-2 sm:order-1`,onClick:e=>a(He).openBuilding(t,X(t))},{default:i(()=>[e(u(a(V)[t].name),1)]),_:2},1032,[`onClick`]),g(a(pe),{variant:`secondary`,class:`text-xs whitespace-nowrap self-start order-1 sm:order-2`},{default:i(()=>[e(` Lv `+u(X(t)),1)]),_:2},1024)])]),g(a(S),{class:`text-xs sm:text-sm`},{default:i(()=>[e(u(a(V)[t].description),1)]),_:2},1024)]),_:2},1024),g(a(ve),null,{default:i(()=>[f(`div`,Me,[f(`div`,R,[f(`p`,Ne,u(a(B)(`buildingsView.upgradeCost`))+`:`,1),f(`div`,Pe,[(v(),l(o,null,_(We,e=>r(f(`div`,{key:e.key,class:`flex items-center gap-1.5 sm:gap-2`},[g(T,{type:e.key,size:`sm`},null,8,[`type`]),f(`span`,Fe,u(a(B)(`resources.${e.key}`))+`:`,1),f(`span`,{class:y([`font-medium text-xs sm:text-sm`,a(ge)(H.value.resources[e.key],Q(t,X(t)+1)[e.key])])},u(a(k)(Q(t,X(t)+1)[e.key])),3)]),[[te,e.key!==`darkMatter`||Q(t,X(t)+1).darkMatter>0]])),64))])]),f(`div`,Ie,[f(`div`,Le,[g(a(ue),{size:14,class:`flex-shrink-0`}),f(`span`,null,u(a(N)(Ze(t,X(t)+1))),1)]),f(`div`,Re,[g(a(x),{size:14,class:`flex-shrink-0`}),f(`span`,null,u(a(V)[t].spaceUsage),1)])]),g(a(E),{onClick:e=>qe(t),disabled:!Xe(t),class:`w-full`},{default:i(()=>[e(u(Je(t)),1)]),_:2},1032,[`onClick`,`disabled`]),X(t)>0?(v(),d(a(E),{key:0,onClick:e=>$e(t),disabled:!tt(t),variant:`destructive`,class:`w-full`},{default:i(()=>[e(u(a(B)(`buildingsView.demolish`)),1)]),_:1},8,[`onClick`,`disabled`])):p(``,!0),X(t)>0?(v(),l(`div`,ze,[f(`p`,null,u(a(B)(`buildingsView.demolishRefund`))+`:`,1),f(`div`,Be,[f(`span`,null,u(a(k)($(t).metal))+` `+u(a(B)(`resources.metal`)),1),f(`span`,null,u(a(k)($(t).crystal))+` `+u(a(B)(`resources.crystal`)),1),f(`span`,null,u(a(k)($(t).deuterium))+` `+u(a(B)(`resources.deuterium`)),1),$(t).darkMatter>0?(v(),l(`span`,Ve,u(a(k)($(t).darkMatter))+` `+u(a(B)(`resources.darkMatter`)),1)):p(``,!0)])])):p(``,!0)])]),_:2},1024)]),_:2},1024))),128))]),g(a(L),{open:U.value,"onUpdate:open":n[0]||=e=>U.value=e},{default:i(()=>[g(a(I),null,{default:i(()=>[g(a(A),null,{default:i(()=>[g(a(F),null,{default:i(()=>[e(u(W.value),1)]),_:1}),g(a(M),{class:`whitespace-pre-line`},{default:i(()=>[e(u(G.value),1)]),_:1})]),_:1}),g(a(O),null,{default:i(()=>[g(a(j),null,{default:i(()=>[e(u(a(B)(`common.confirm`)),1)]),_:1})]),_:1})]),_:1})]),_:1},8,[`open`]),g(a(L),{open:K.value,"onUpdate:open":n[1]||=e=>K.value=e},{default:i(()=>[g(a(I),null,{default:i(()=>[g(a(A),null,{default:i(()=>[g(a(F),null,{default:i(()=>[e(u(a(B)(`buildingsView.confirmDemolish`)),1)]),_:1}),g(a(M),{class:`whitespace-pre-line`},{default:i(()=>[e(u(q.value),1)]),_:1})]),_:1}),g(a(O),null,{default:i(()=>[g(a(he),null,{default:i(()=>[e(u(a(B)(`common.cancel`)),1)]),_:1}),g(a(j),{onClick:et},{default:i(()=>[e(u(a(B)(`common.confirm`)),1)]),_:1})]),_:1})]),_:1})]),_:1},8,[`open`])])):p(``,!0)}});export{z as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{Gn as e,Qt as t,_n as n,mn as r,qn as i,tn as a}from"./game-logic-Bi1l7y4K.js";import{G as o}from"./index-BT5w6et-.js";var s=a({__name:`CardDescription`,props:{class:{}},setup(a){let s=a;return(a,c)=>(r(),t(`p`,{"data-slot":`card-description`,class:i(e(o)(`text-muted-foreground text-sm`,s.class))},[n(a.$slots,`default`)],2))}});export{s as t};
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import{$t as e,En as t,Gn as n,Jt as r,Ln as i,Qt as a,Xn as o,Yt as s,Zt as c,en as l,mn as u,tn as d,v as f}from"./game-logic-Bi1l7y4K.js";import{D as p}from"./vendor-icons-z9V6Jdbh.js";import{d as m,v as h}from"./game-config-CG6z6nnH.js";import{K as g,W as _,a as v,i as y,l as b,o as x,q as S,r as C,s as w,u as T}from"./index-BT5w6et-.js";import{t as E}from"./useGameConfig-b98LOtBY.js";var D={key:0,class:`absolute inset-0 z-10 bg-background/70 backdrop-blur-[2px] rounded-lg flex items-center justify-center`},O={class:`text-center p-4 space-y-2`},k={class:`flex justify-center`},A={class:`rounded-full bg-muted p-2`},j={class:`text-xs font-medium text-muted-foreground`},M=d({__name:`CardUnlockOverlay`,props:{requirements:{},currentLevel:{}},setup(d){let M=d,N=S(),{t:P}=g(),{BUILDINGS:F,TECHNOLOGIES:I}=E(),L=i(!1),R=i(``),z=i(``),B=r(()=>M.currentLevel!==void 0&&M.currentLevel>0||!M.requirements||!N.currentPlanet?!0:f(N.currentPlanet,N.player.technologies,M.requirements)),V=()=>{if(!M.requirements||!N.currentPlanet)return``;let e=[];for(let[t,n]of Object.entries(M.requirements))if(Object.values(m).includes(t)){let r=t,i=N.currentPlanet.buildings[r]||0,a=F.value[r]?.name||r,o=i>=n?`✓`:`✗`;e.push(`${o} ${a}: Lv ${n} (${P(`common.current`)}: Lv ${i})`)}else if(Object.values(h).includes(t)){let r=t,i=N.player.technologies[r]||0,a=I.value[r]?.name||r,o=i>=n?`✓`:`✗`;e.push(`${o} ${a}: Lv ${n} (${P(`common.current`)}: Lv ${i})`)}return e.join(`
|
|
||||||
`)},H=()=>{R.value=P(`common.requirementsNotMet`),z.value=V(),L.value=!0};return(r,i)=>B.value?c(``,!0):(u(),a(`div`,D,[s(`div`,O,[s(`div`,k,[s(`div`,A,[l(n(p),{size:20,class:`text-muted-foreground`})])]),s(`p`,j,o(n(P)(`common.locked`)),1),l(n(_),{variant:`outline`,size:`sm`,onClick:H,class:`text-xs`},{default:t(()=>[e(o(n(P)(`common.viewRequirements`)),1)]),_:1})]),l(n(T),{open:L.value,"onUpdate:open":i[0]||=e=>L.value=e},{default:t(()=>[l(n(w),null,{default:t(()=>[l(n(y),null,{default:t(()=>[l(n(C),null,{default:t(()=>[e(o(R.value),1)]),_:1}),l(n(x),{class:`whitespace-pre-line`},{default:t(()=>[e(o(z.value),1)]),_:1})]),_:1}),l(n(v),null,{default:t(()=>[l(n(b),null,{default:t(()=>[e(o(n(P)(`common.confirm`)),1)]),_:1})]),_:1})]),_:1})]),_:1},8,[`open`])]))}});export{M as t};
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import{$t as e,Dn as t,En as n,Gn as r,Gt as i,It as a,Jt as o,Ln as s,Qt as c,S as l,Vt as ee,Xn as u,Xt as te,Yt as d,Zt as ne,d as re,en as f,gn as p,mn as m,qn as ie,tn as ae,u as oe,v as h,y as g}from"./game-logic-Bi1l7y4K.js";import"./vendor-pinia-DqhKuBjp.js";import"./vendor-vue-router-1sDnnIWZ.js";import"./vendor-crypto-CQM8pryk.js";import"./game-i18n-Dr0JspcV.js";import"./vendor-others-DTUzJ7S-.js";import"./vendor-reka-ui-BEHIKScj.js";import"./vendor-utils-BlvnUqQX.js";import"./vendor-vueuse-CJcfYqoW.js";import"./vendor-icons-z9V6Jdbh.js";import{t as se}from"./CardDescription-BSLS07AU.js";import{d as _,v}from"./game-config-CG6z6nnH.js";import{D as ce,H as le,K as ue,N as de,W as y,_ as b,a as x,b as S,f as C,h as w,i as T,l as E,o as D,q as O,r as k,s as A,u as j,v as M,y as N}from"./index-BT5w6et-.js";import{t as P}from"./useGameConfig-b98LOtBY.js";import{t as F}from"./CardUnlockOverlay-DYfgGY6J.js";import{t as I}from"./UnlockRequirement-CoWPiUl8.js";var L={key:0,class:`container mx-auto p-4 sm:p-6`},R={class:`text-2xl sm:text-3xl font-bold mb-4 sm:mb-6`},fe={class:`grid grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4`},z={class:`mb-2`},B={class:`flex flex-col sm:flex-row sm:justify-between sm:items-start gap-2`},V={class:`space-y-2.5 sm:space-y-3`},pe={class:`text-xs sm:text-sm space-y-1.5 sm:space-y-2`},me={class:`text-muted-foreground mb-1 sm:mb-2`},he={class:`space-y-1 sm:space-y-1.5`},ge={class:`text-xs`},H=ae({__name:`ResearchView`,setup(ae){let H=O(),_e=ce(),{t:U}=ue(),{TECHNOLOGIES:W,BUILDINGS:ve}=P(),G=o(()=>H.currentPlanet),K=o(()=>H.player),q=s(!1),J=s(``),Y=s(``),ye=[{key:`metal`},{key:`crystal`},{key:`deuterium`},{key:`darkMatter`}],X=e=>{if(!H.currentPlanet||!re(H.currentPlanet,e,H.player.technologies,H.player.researchQueue).valid)return!1;let t=H.player.technologies[e]||0,{queueItem:n}=oe(H.currentPlanet,e,t,H.player.officers,H.player.technologies);return H.player.researchQueue.push(n),!0},Z=e=>{if(!G.value)return!1;let t=W.value[e],n=g(t,Q(e)+1);return!n||Object.keys(n).length===0?!0:h(G.value,H.player.technologies,n)},be=e=>{if(!G.value)return U(`researchView.research`);let t=W.value[e],n=Q(e);if(t.maxLevel!==void 0&&n>=t.maxLevel)return U(`researchView.maxLevelReached`);let r=l(H.player.technologies);return K.value.researchQueue.length>=r||Z(e)?U(`researchView.research`):U(`buildingsView.requirementsNotMet`)},xe=e=>{let t=W.value[e],n=g(t,Q(e)+1);if(!n||!G.value)return``;let r=[];for(let[e,t]of Object.entries(n))if(Object.values(_).includes(e)){let n=e,i=G.value.buildings[n]||0,a=ve.value[n]?.name||n,o=i>=t?`✓`:`✗`;r.push(`${o} ${a}: Lv ${t} (${U(`common.current`)}: Lv ${i})`)}else if(Object.values(v).includes(e)){let n=e,i=H.player.technologies[n]||0,a=W.value[n]?.name||n,o=i>=t?`✓`:`✗`;r.push(`${o} ${a}: Lv ${t} (${U(`common.current`)}: Lv ${i})`)}return r.join(`
|
|
||||||
`)},Se=e=>{if(!Z(e)){J.value=U(`common.requirementsNotMet`),Y.value=xe(e),q.value=!0;return}X(e)||(J.value=U(`researchView.researchFailed`),Y.value=U(`researchView.researchFailedMessage`),q.value=!0)},Q=e=>K.value.technologies[e]||0,Ce=e=>{if(!G.value)return!1;let t=W.value[e],n=Q(e);if(t.maxLevel!==void 0&&n>=t.maxLevel)return!1;let r=l(H.player.technologies);if(K.value.researchQueue.length>=r)return!1;let i=$(e,n+1);return h(G.value,H.player.technologies,t.requirements)&&G.value.resources.metal>=i.metal&&G.value.resources.crystal>=i.crystal&&G.value.resources.deuterium>=i.deuterium&&G.value.resources.darkMatter>=i.darkMatter},$=(e,t)=>a(e,t);return(a,o)=>G.value?(m(),c(`div`,L,[f(I,{"required-building":r(_).ResearchLab,"required-level":1},null,8,[`required-building`]),d(`h1`,R,u(r(U)(`researchView.title`)),1),d(`div`,fe,[(m(!0),c(i,null,p(Object.values(r(v)),a=>(m(),te(r(S),{key:a,class:`relative`},{default:n(()=>[f(F,{requirements:r(W)[a].requirements,currentLevel:Q(a)},null,8,[`requirements`,`currentLevel`]),f(r(M),null,{default:n(()=>[d(`div`,z,[d(`div`,B,[f(r(b),{class:`text-sm sm:text-base lg:text-lg cursor-pointer hover:text-primary transition-colors underline decoration-dotted underline-offset-4 order-2 sm:order-1`,onClick:e=>r(_e).openTechnology(a,Q(a))},{default:n(()=>[e(u(r(W)[a].name),1)]),_:2},1032,[`onClick`]),f(r(le),{variant:`secondary`,class:`text-xs whitespace-nowrap self-start order-1 sm:order-2`},{default:n(()=>[e(` Lv `+u(Q(a)),1)]),_:2},1024)])]),f(r(se),{class:`text-xs sm:text-sm`},{default:n(()=>[e(u(r(W)[a].description),1)]),_:2},1024)]),_:2},1024),f(r(N),null,{default:n(()=>[d(`div`,V,[d(`div`,pe,[d(`p`,me,u(r(U)(`researchView.researchCost`))+`:`,1),d(`div`,he,[(m(),c(i,null,p(ye,e=>t(d(`div`,{key:e.key,class:`flex items-center gap-1.5 sm:gap-2`},[f(de,{type:e.key,size:`sm`},null,8,[`type`]),d(`span`,ge,u(r(U)(`resources.${e.key}`))+`:`,1),d(`span`,{class:ie([`font-medium text-xs sm:text-sm`,r(w)(G.value.resources[e.key],$(a,Q(a)+1)[e.key])])},u(r(C)($(a,Q(a)+1)[e.key])),3)]),[[ee,e.key!==`darkMatter`||$(a,Q(a)+1).darkMatter>0]])),64))])]),f(r(y),{onClick:e=>Se(a),disabled:!Ce(a),class:`w-full`},{default:n(()=>[e(u(be(a)),1)]),_:2},1032,[`onClick`,`disabled`])])]),_:2},1024)]),_:2},1024))),128))]),f(r(j),{open:q.value,"onUpdate:open":o[0]||=e=>q.value=e},{default:n(()=>[f(r(A),null,{default:n(()=>[f(r(T),null,{default:n(()=>[f(r(k),null,{default:n(()=>[e(u(J.value),1)]),_:1}),f(r(D),{class:`whitespace-pre-line`},{default:n(()=>[e(u(Y.value),1)]),_:1})]),_:1}),f(r(x),null,{default:n(()=>[f(r(E),null,{default:n(()=>[e(u(r(U)(`common.confirm`)),1)]),_:1})]),_:1})]),_:1})]),_:1},8,[`open`])])):ne(``,!0)}});export{H as default};
|
|
||||||