Skip to content

Commit

Permalink
Merge pull request #12 from lovezhangchuangxin/feat/combat
Browse files Browse the repository at this point in the history
feat: 增加科技、防御设施类型建筑
  • Loading branch information
lovezhangchuangxin authored Dec 5, 2024
2 parents bd20f22 + 224ab96 commit aaf6cbc
Show file tree
Hide file tree
Showing 32 changed files with 1,789 additions and 593 deletions.
53 changes: 51 additions & 2 deletions packages/backend/scripts/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ResourceType,
StorageConfig,
StructureConfigs,
UniverseMap,
} from '@star-angry/core'

/**
Expand Down Expand Up @@ -55,7 +56,6 @@ const migrate = async () => {
;(structureMap[newStructureId] as ProducerData).produceSpeed =
StructureConfigs[newStructureId].getProduceSpeed?.(
oldStructureData.level,
data.userDataMap,
) || {}
;(structureMap[newStructureId] as ProducerData).consumeSpeed =
StructureConfigs[newStructureId].getConsumeSpeed?.(
Expand Down Expand Up @@ -111,12 +111,61 @@ const migrate = async () => {
structures,
},
},
}
} as any
})

data.version = '0.0.1'
}

if (data.version === '0.0.1') {
if (!data.config) {
data.config = {
seed: 0.63,
}
}

const userDatas = Object.values(data.userDataMap)
const userPlanetCount = userDatas.reduce(
(count, userData) => count + Object.keys(userData.planets).length,
0,
)
// 一个区块放四个玩家的星球
const chunkNumber = Math.ceil(userPlanetCount / 4)
// 获取星球
const universeMap = new UniverseMap(data.config.seed)
// 取地图中心的区块范围半径
const radius = Math.floor(
(Math.ceil(Math.sqrt(chunkNumber)) * universeMap.chunkSize) / 2,
)
const chunks = universeMap.getChunks(-radius, -radius, radius, radius)
const planets = chunks
.map((chunkId) => universeMap.getPlanets(chunkId))
.flat()
const gap = Math.floor(planets.length / userPlanetCount)
let index = 0

userDatas.forEach((userData) => {
Object.keys(userData.planets).forEach((planetId) => {
const planet = userData.planets[planetId]
planet.id = planetId
// 重新分配一个
const newPlanet = planets[index]
planet.id = universeMap.getBlockId(...newPlanet).toString()
planet.position = newPlanet
userData.planets[planet.id] = planet
delete userData.planets[planetId]
index += gap

if (!(planet.targetPosition instanceof Array)) {
const { x: tx = 0, y: ty = 0 } = planet.targetPosition as any
planet.targetPosition = [tx, ty]
}
})
})

data.version = '0.0.2'
}

await GameDB.getDB().setData(data)
console.log('迁移完成')
process.exit(0)
Expand Down
3 changes: 3 additions & 0 deletions packages/backend/src/error/ErrorCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ export class ErrorCode {

static ROOM_NOT_EXIST = new ErrorCode(2001, '房间不存在')
static MESSAGE_TOO_LONG = new ErrorCode(2002, '消息太长')

static PLANET_NOT_EXIST = new ErrorCode(2021, '星球不存在')
static PLANET_OCCUPIED = new ErrorCode(2022, '星球已被占领')
}
2 changes: 2 additions & 0 deletions packages/backend/src/service/game/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { init, loop } from '@star-angry/core'
import { GameDB } from '@star-angry/db'
import MapService from '../map'

export default class GameService {
/**
Expand Down Expand Up @@ -32,6 +33,7 @@ export default class GameService {
*/
static async initData() {
const data = await GameDB.getDB().getData()
MapService.init(data)
init(data.userDataMap)
console.log('initGameData')
}
Expand Down
121 changes: 121 additions & 0 deletions packages/backend/src/service/map/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { ErrorCode } from '../../error/ErrorCode'
import { GameError } from '../../error/GameError'
import {
getPlanetBaseData,
initPlanetData,
PlanetData,
UniverseMap,
} from '@star-angry/core'
import { GameDB, GameModel } from '@star-angry/db'

/**
* 地图缓存对象数据
*/
export interface ObjectCacheData {
userId?: string
userName?: string
planet: PlanetData
}

export default class MapService {
static map: UniverseMap

/**
* 缓存区块中的物体
*/
static objectCache: {
[chunkId: number]: ObjectCacheData[]
} = {}

/**
* 区块中原始星球(后来被玩家占领)的id
*/
static originalPlanetIds: Record<number, Set<number>> = {}

/**
* 新玩家注册星球
*/
static async registerPlanet(userId: string, planetId: string) {
const data = await GameDB.getDB().getData()
const userDataMap = data.userDataMap
const userData = userDataMap[userId]
if (!userData || Object.keys(userData.planets).length > 0) {
throw new GameError(ErrorCode.USER_NOT_EXIST)
}
const map = MapService.map
const [x, y] = map.getBlockCoord(+planetId)
// 不是一个星球
if (!map.isPlanet(x, y)) {
throw new GameError(ErrorCode.PLANET_NOT_EXIST)
}
// 已经被别人占了
const originChunkId = map.getChunkId(x, y)
if (MapService.originalPlanetIds[originChunkId]?.has(+planetId)) {
throw new GameError(ErrorCode.PLANET_OCCUPIED)
}

const planet = getPlanetBaseData(planetId)
planet.position = [x, y]
userData.planets[planetId] = planet
initPlanetData(planet, userDataMap)
}

/**
* 获取区块中的物体
*/
static getObjectsFromChunks(chunkIds: number[]) {
return chunkIds.reduce(
(prev, chunkId) => {
prev[chunkId] = MapService.objectCache[chunkId] || []
return prev
},
{} as { [chunkId: number]: ObjectCacheData[] },
)
}

/**
* 获取区块中已经被占领的星球
*/
static getOccupiedPlanetsFromChunks(chunkIds: number[]) {
return chunkIds.reduce(
(prev, chunkId) => {
prev[chunkId] = Array.from(MapService.originalPlanetIds[chunkId] || [])
return prev
},
{} as Record<number, number[]>,
)
}

/**
* 初始化地图相关数据
*/
static init(data: GameModel) {
MapService.map = new UniverseMap(data.config.seed)

Object.keys(data.userDataMap).forEach((userId) => {
const userData = data.userDataMap[userId]
Object.values(userData.planets).forEach((planet) => {
// 缓存现在的坐标
const [x, y] = planet.position
const chunkId = MapService.map.getChunkId(x, y)
if (!MapService.objectCache[chunkId]) {
MapService.objectCache[chunkId] = []
}
MapService.objectCache[chunkId].push({
userId,
userName:
data.user.find((user) => user.id === userId)?.username || '',
planet,
})
// 缓存原始的坐标
const originChunkId = MapService.map.getChunkId(
...MapService.map.getBlockCoord(+planet.id),
)
if (!MapService.originalPlanetIds[originChunkId]) {
MapService.originalPlanetIds[originChunkId] = new Set()
}
MapService.originalPlanetIds[originChunkId].add(+planet.id)
})
})
}
}
13 changes: 4 additions & 9 deletions packages/backend/src/service/structure/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import { processor } from '../../../../core/src'
import { processor, StructureOperationParams } from '@star-angry/core'
import { GameDB } from '@star-angry/db'
import { ErrorCode } from '../../error/ErrorCode'
import { GameError } from '../../error/GameError'
import { GameDB } from '@star-angry/db'

export default class StructureService {
/**
* 添加操作
*/
static async addOperation(params: {
userId: string
planetId: string
structureId: string
operation: string
}) {
const { userId, planetId, structureId, operation } = params
static async addOperation(params: StructureOperationParams) {
const { userId } = params
const data = await GameDB.getDB().getData()
const userDataMap = data.userDataMap
const userData = userDataMap[userId]
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/socket/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
userEventHandler,
structureEventHandler,
gameEventHandler,
mapEventHandler,
} from './event'

const users: Map<string, Partial<UserModel>> = new Map()
Expand All @@ -27,6 +28,7 @@ export const createConnection = (io: Server) => {

userEventHandler(socket, io)
gameEventHandler(socket, io)
mapEventHandler(socket, io)
structureEventHandler(socket, io)
messageEventHandler(socket, io)

Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/socket/event/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './message'
export * from './user'
export * from './game'
export * from './structure'
export * from './map'
49 changes: 49 additions & 0 deletions packages/backend/src/socket/event/map/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Server, Socket } from 'socket.io'
import { Result } from '../../../utils/result'
import { ErrorCode } from '../../../error/ErrorCode'
import { GameError } from '../../../error/GameError'
import MapService from '../../../service/map'

export const mapEventHandler = (socket: Socket, io: Server) => {
/**
* 新玩家注册星球
*/
socket.on('registerPlanet', async (planetId: string, callback) => {
const userId = socket.userId
if (!userId) {
return callback(Result.error(ErrorCode.PARAM_ERROR))
}

try {
await MapService.registerPlanet(userId, planetId)
return callback(Result.success({}))
} catch (error: unknown) {
console.error(error)
if (error instanceof GameError) {
return callback(Result.error(error.errorCode))
}
}
})

/**
* 获取区块中的物体
*/
socket.on('getObjectsFromChunks', async (chunkIds: number[], callback) => {
try {
const data = MapService.getObjectsFromChunks(chunkIds)
const occupiedPlanets = MapService.getOccupiedPlanetsFromChunks(chunkIds)
return callback(
Result.success({
seed: MapService.map.seed,
chunkObjects: data,
occupiedPlanets,
}),
)
} catch (error: unknown) {
console.error(error)
if (error instanceof GameError) {
return callback(Result.error(error.errorCode))
}
}
})
}
10 changes: 2 additions & 8 deletions packages/backend/src/socket/event/structure/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Server, Socket } from 'socket.io'
import { StructureOperationParams } from '@star-angry/core'
import { Result } from '../../../utils/result'
import { ErrorCode } from '../../../error/ErrorCode'
import StructureService from '../../../service/structure'
Expand All @@ -9,14 +10,7 @@ export const structureEventHandler = (socket: Socket, io: Server) => {
// 添加操作
socket.on(
'addOperation',
async (
params: {
planetId: string
structureId: string
operation: string
},
callback,
) => {
async (params: Omit<StructureOperationParams, 'userId'>, callback) => {
const userId = socket.userId
if (!userId) {
return callback(Result.error(ErrorCode.PARAM_ERROR))
Expand Down
38 changes: 38 additions & 0 deletions packages/core/src/config/combat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* 攻击种类
*/
export enum AttackType {
/**
* 炮弹攻击
*/
Ballistic,
/**
* 导弹攻击
*/
Missile,
/**
* 激光攻击
*/
Laser,
/**
* 离子攻击
*/
Ion,
/**
* 等离子攻击
*/
Plasma,
}

/**
* 攻击名称
*/
export const AttackTypeName: {
[key in AttackType]: string
} = {
[AttackType.Ballistic]: '炮弹攻击',
[AttackType.Missile]: '导弹攻击',
[AttackType.Laser]: '激光攻击',
[AttackType.Ion]: '离子攻击',
[AttackType.Plasma]: '等离子攻击',
}
Loading

0 comments on commit aaf6cbc

Please sign in to comment.