-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from lovezhangchuangxin/feat/combat
feat: 增加科技、防御设施类型建筑
- Loading branch information
Showing
32 changed files
with
1,789 additions
and
593 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]: '等离子攻击', | ||
} |
Oops, something went wrong.