feat: 新增Android平台支持及构建流程

集成Android平台相关目录与配置文件,包含Gradle构建脚本、资源文件、启动图标、Java入口、Proguard规则等,完善.gitignore以排除Android构建产物。更新CI流程,支持自动构建并发布Android APK。移除README中项目结构说明,简化文档。
This commit is contained in:
谦君
2025-12-20 00:48:36 +08:00
parent 20fb2bb6a4
commit 1368bb4445
97 changed files with 7859 additions and 335 deletions

View File

@@ -6,6 +6,7 @@ import * as researchLogic from './researchLogic'
import * as pointsLogic from './pointsLogic'
import * as planetLogic from './planetLogic'
import * as resourceLogic from './resourceLogic'
import * as achievementLogic from './achievementLogic'
/**
* 初始化玩家数据
@@ -105,6 +106,14 @@ export const processGameUpdate = (
): {
updatedResearchQueue: BuildQueueItem[]
} => {
// 确保成就统计数据存在
if (!player.achievementStats) {
player.achievementStats = achievementLogic.initializeAchievementStats()
}
if (!player.achievements) {
player.achievements = achievementLogic.initializeAchievements()
}
// 获取军官加成
const bonuses = officerLogic.calculateActiveBonuses(player.officers, now)
@@ -113,16 +122,48 @@ export const processGameUpdate = (
pointsLogic.addPoints(player, points)
}
// 通知回调
const onCompleted = (type: string, itemType: string, level?: number, _quantity?: number) => {
// 通知回调 + 成就统计更新
const onCompleted = (type: string, itemType: string, level?: number, quantity?: number) => {
if (onNotification) {
onNotification(type, itemType, level)
}
// 更新成就统计
if (player.achievementStats) {
if (type === 'building' && level !== undefined) {
achievementLogic.updateBuildingStats(player.achievementStats, itemType as any, level)
} else if (type === 'technology' && level !== undefined) {
achievementLogic.updateResearchStats(player.achievementStats, itemType as any, level)
} else if (type === 'ship' && quantity !== undefined) {
achievementLogic.updateShipProductionStats(player.achievementStats, itemType as any, quantity)
} else if (type === 'defense' && quantity !== undefined) {
achievementLogic.updateDefenseProductionStats(player.achievementStats, itemType as any, quantity)
}
}
}
// 更新所有星球资源(直接同步计算,避免 Worker 通信开销)
player.planets.forEach(planet => {
// 计算更新前的资源(用于计算生产量)
const resourcesBefore = { ...planet.resources }
resourceLogic.updatePlanetResources(planet, now, bonuses, gameSpeed)
// 追踪资源生产统计
if (player.achievementStats) {
const metalProduced = Math.max(0, planet.resources.metal - resourcesBefore.metal)
const crystalProduced = Math.max(0, planet.resources.crystal - resourcesBefore.crystal)
const deuteriumProduced = Math.max(0, planet.resources.deuterium - resourcesBefore.deuterium)
const darkMatterProduced = Math.max(0, planet.resources.darkMatter - resourcesBefore.darkMatter)
if (metalProduced > 0 || crystalProduced > 0 || deuteriumProduced > 0 || darkMatterProduced > 0) {
achievementLogic.updateResourceProductionStats(player.achievementStats, {
metal: metalProduced,
crystal: crystalProduced,
deuterium: deuteriumProduced,
darkMatter: darkMatterProduced
})
}
}
})
// 更新所有星球其他状态
@@ -159,3 +200,161 @@ export const processGameUpdate = (
export const checkOfficersExpiration = (officers: Record<OfficerType, Officer>, now: number): void => {
officerLogic.checkAndDeactivateExpiredOfficers(officers, now)
}
/**
* 检查成就进度并解锁新成就
*/
export const checkAndUnlockAchievements = (player: Player): achievementLogic.AchievementUnlock[] => {
if (!player.achievementStats || !player.achievements) {
return []
}
const unlocks = achievementLogic.checkAchievements(player)
// 应用奖励
unlocks.forEach(unlock => {
achievementLogic.applyAchievementReward(player, unlock.reward)
})
return unlocks
}
/**
* 更新资源消耗统计
*/
export const trackResourceConsumption = (
player: Player,
consumed: { metal?: number; crystal?: number; deuterium?: number; darkMatter?: number }
): void => {
if (!player.achievementStats) {
player.achievementStats = achievementLogic.initializeAchievementStats()
}
achievementLogic.updateResourceConsumptionStats(player.achievementStats, consumed)
}
/**
* 更新攻击统计(玩家作为攻击者)
*/
export const trackAttackStats = (player: Player, battleResult: any, won: boolean, debrisValue: number): void => {
if (!player.achievementStats) {
player.achievementStats = achievementLogic.initializeAchievementStats()
}
achievementLogic.updateAttackStats(player.achievementStats, battleResult, won, debrisValue)
}
/**
* 更新防御统计(玩家作为防御者)
*/
export const trackDefenseStats = (player: Player, battleResult: any, won: boolean, debrisValue: number): void => {
if (!player.achievementStats) {
player.achievementStats = achievementLogic.initializeAchievementStats()
}
achievementLogic.updateDefenseStats(player.achievementStats, battleResult, won, debrisValue)
}
/**
* 更新任务统计
*/
export const trackMissionStats = (
player: Player,
missionType: string,
details?: {
resourcesAmount?: number
successful?: boolean
fuelAmount?: number
}
): void => {
if (!player.achievementStats) {
player.achievementStats = achievementLogic.initializeAchievementStats()
}
const stats = player.achievementStats
achievementLogic.updateFlightMissionStats(stats)
switch (missionType) {
case 'transport':
if (details?.resourcesAmount) {
achievementLogic.updateTransportStats(stats, details.resourcesAmount)
}
break
case 'colonize':
achievementLogic.updateColonizationStats(stats)
break
case 'spy':
achievementLogic.updateSpyStats(stats)
break
case 'deploy':
achievementLogic.updateDeploymentStats(stats)
break
case 'expedition':
achievementLogic.updateExpeditionStats(stats, details?.successful ?? false)
break
case 'recycle':
// 回收任务总是计入任务次数,但只有有资源时才增加回收资源量
achievementLogic.updateRecyclingStats(stats, details?.resourcesAmount ?? 0)
break
case 'destroy':
achievementLogic.updatePlanetDestructionStats(stats)
break
}
if (details?.fuelAmount) {
achievementLogic.updateFuelConsumptionStats(stats, details.fuelAmount)
}
}
/**
* 更新外交统计
*/
export const trackDiplomacyStats = (
player: Player,
eventType: string,
details?: {
resourcesAmount?: number
friendlyCount?: number
hostileCount?: number
}
): void => {
if (!player.achievementStats) {
player.achievementStats = achievementLogic.initializeAchievementStats()
}
const stats = player.achievementStats
switch (eventType) {
case 'gift':
if (details?.resourcesAmount) {
achievementLogic.updateGiftStats(stats, details.resourcesAmount)
}
break
case 'attackedByNPC':
achievementLogic.updateAttackedByNPCStats(stats)
break
case 'spiedByNPC':
achievementLogic.updateSpiedByNPCStats(stats)
break
case 'debrisRecycledByNPC':
if (details?.resourcesAmount) {
achievementLogic.updateDebrisRecycledByNPCStats(stats, details.resourcesAmount)
}
break
case 'updateRelations':
if (details?.friendlyCount !== undefined) {
achievementLogic.updateFriendlyNPCStats(stats, details.friendlyCount)
}
if (details?.hostileCount !== undefined) {
achievementLogic.updateHostileNPCStats(stats, details.hostileCount)
}
break
}
}
/**
* 追踪燃料消耗(在舰队出发时调用)
*/
export const trackFuelConsumption = (player: Player, fuelAmount: number): void => {
if (!player.achievementStats) {
player.achievementStats = achievementLogic.initializeAchievementStats()
}
achievementLogic.updateFuelConsumptionStats(player.achievementStats, fuelAmount)
}