Skip to content

Commit

Permalink
Merge pull request #1842 from gettakaro/map-api
Browse files Browse the repository at this point in the history
Add map API support
  • Loading branch information
niekcandaele authored Dec 15, 2024
2 parents b4af5fe + 31cbc2b commit fc99f56
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 2 deletions.
47 changes: 46 additions & 1 deletion packages/app-api/src/controllers/GameServerController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,19 @@ import {
ModuleInstallDTO,
} from '../service/GameServerService.js';
import { AuthenticatedRequest, AuthService, checkPermissions } from '../service/AuthService.js';
import { Body, Get, Post, Delete, JsonController, UseBefore, Req, Put, Params, Res } from 'routing-controllers';
import {
Body,
Get,
Post,
Delete,
JsonController,
UseBefore,
Req,
Put,
Params,
Res,
ContentType,
} from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { Type } from 'class-transformer';
import { ParamId, PogParam } from '../lib/validators.js';
Expand Down Expand Up @@ -233,6 +245,17 @@ class ImportOutputDTO extends TakaroDTO<ImportOutputDTO> {
id!: string;
}

class MapTileInputDTO extends TakaroDTO<MapTileInputDTO> {
@IsUUID('4')
id: string;
@IsNumber()
z: number;
@IsNumber()
x: number;
@IsNumber()
y: number;
}

class ImportOutputDTOAPI extends APIOutput<ImportOutputDTO> {
@Type(() => ImportOutputDTO)
@ValidateNested()
Expand Down Expand Up @@ -588,4 +611,26 @@ export class GameServerController {
const result = await service.import(parsedImportData, validatedOptions);
return apiResponse(result);
}

@Get('/gameserver/:id/map/info')
@UseBefore(AuthService.getAuthMiddleware([]))
@OpenAPI({
description: 'Get map metadata for Leaflet',
})
async getMapInfo(@Req() req: AuthenticatedRequest, @Params() params: ParamId) {
const service = new GameServerService(req.domainId);
return apiResponse(await service.getMapInfo(params.id));
}

@Get('/gameserver/:id/map/tile/:x/:y/:z')
@UseBefore(AuthService.getAuthMiddleware([]))
@ContentType('image/png')
@OpenAPI({
description: 'Get a map tile for Leaflet',
})
async getMapTile(@Req() req: AuthenticatedRequest, @Params() params: MapTileInputDTO) {
const service = new GameServerService(req.domainId);
const result = await service.getMapTile(params.id, params.x, params.y, params.z);
return result;
}
}
10 changes: 10 additions & 0 deletions packages/app-api/src/service/GameServerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,4 +589,14 @@ export class GameServerService extends TakaroService<
id: job.id,
};
}

async getMapInfo(gameServerId: string) {
const gameInstance = await this.getGame(gameServerId);
return gameInstance.getMapInfo();
}

async getMapTile(gameServerId: string, x: number, y: number, z: number) {
const gameInstance = await this.getGame(gameServerId);
return gameInstance.getMapTile(x, y, z);
}
}
25 changes: 24 additions & 1 deletion packages/app-mock-gameserver/src/lib/gameserver/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ import { errors, logger } from '@takaro/util';
import { Redis } from '@takaro/db';

import { getSocketServer } from '../socket/index.js';
import { IPlayerReferenceDTO, IGameServer, IMessageOptsDTO, CommandOutput, BanDTO, IItemDTO } from '@takaro/gameserver';
import {
IPlayerReferenceDTO,
IGameServer,
IMessageOptsDTO,
CommandOutput,
BanDTO,
IItemDTO,
MapInfoDTO,
} from '@takaro/gameserver';
import {
EventLogLine,
GameEvents,
Expand Down Expand Up @@ -394,6 +402,21 @@ export class MockGameserver implements IMockGameServer {
async shutdown() {
await this.sendLog('Shutting down');
}

async getMapInfo() {
return new MapInfoDTO({
enabled: false,
mapBlockSize: 100,
maxZoom: 5,
mapSizeX: 1000,
mapSizeY: 1000,
mapSizeZ: 1000,
});
}

async getMapTile(_x: number, _y: number, _z: number) {
return Buffer.from('mock-tile');
}
}

const cachedMockServer: Map<string, MockGameserver> = new Map();
Expand Down
8 changes: 8 additions & 0 deletions packages/lib-gameserver/src/gameservers/7d2d/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,12 @@ export class SevenDaysToDie implements IGameServer {
await this.executeConsoleCommand('shutdown');
}
}

async getMapInfo() {
return this.apiClient.getMapInfo();
}

async getMapTile(x: number, y: number, z: number) {
return this.apiClient.getMapTile(x, y, z);
}
}
19 changes: 19 additions & 0 deletions packages/lib-gameserver/src/gameservers/7d2d/sdtdAPIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
StatsResponse,
} from './apiResponses.js';
import { addCounterToAxios, errors } from '@takaro/util';
import { MapInfoDTO } from '../../main.js';

export class SdtdApiClient {
private client: Axios;
Expand Down Expand Up @@ -77,4 +78,22 @@ export class SdtdApiClient {
async getPlayerInventory(id: string): Promise<AxiosResponse<InventoryResponse>> {
return this.client.get(`/api/getplayerinventory?userid=${id}`);
}

async getMapInfo(): Promise<MapInfoDTO> {
const res = await this.client.get('/api/map/config');

return new MapInfoDTO({
enabled: res.data.data.enabled,
mapBlockSize: res.data.data.mapBlockSize,
maxZoom: res.data.data.maxZoom,
mapSizeX: res.data.data.mapSize.x,
mapSizeY: res.data.data.mapSize.y,
mapSizeZ: res.data.data.mapSize.z,
});
}

async getMapTile(x: number, y: number, z: number): Promise<Buffer> {
const res = await this.client.get(`/map/${z}/${x}/${y}.png?t=${Date.now() / 1000}`);
return res.data;
}
}
16 changes: 16 additions & 0 deletions packages/lib-gameserver/src/gameservers/mock/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
IItemDTO,
IMessageOptsDTO,
IPlayerReferenceDTO,
MapInfoDTO,
TestReachabilityOutputDTO,
} from '../../interfaces/GameServer.js';
import { MockEmitter } from './emitter.js';
Expand Down Expand Up @@ -163,4 +164,19 @@ export class Mock implements IGameServer {
async shutdown(): Promise<void> {
return this.requestFromServer('shutdown');
}

async getMapInfo(): Promise<MapInfoDTO> {
return new MapInfoDTO({
enabled: false,
mapBlockSize: 0,
maxZoom: 0,
mapSizeX: 0,
mapSizeY: 0,
mapSizeZ: 0,
});
}

async getMapTile(_x: number, _y: number, _z: number): Promise<Buffer> {
throw new Error('Not implemented');
}
}
16 changes: 16 additions & 0 deletions packages/lib-gameserver/src/gameservers/rust/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
IGameServer,
IItemDTO,
IPlayerReferenceDTO,
MapInfoDTO,
TestReachabilityOutputDTO,
} from '../../interfaces/GameServer.js';
import { RustConnectionInfo } from './connectionInfo.js';
Expand Down Expand Up @@ -237,4 +238,19 @@ export class Rust implements IGameServer {
async shutdown(): Promise<void> {
await this.executeConsoleCommand('quit');
}

async getMapInfo(): Promise<MapInfoDTO> {
return new MapInfoDTO({
enabled: false,
mapBlockSize: 0,
maxZoom: 0,
mapSizeX: 0,
mapSizeY: 0,
mapSizeZ: 0,
});
}

async getMapTile(_x: number, _y: number, _z: number): Promise<Buffer> {
throw new Error('Not implemented');
}
}
18 changes: 18 additions & 0 deletions packages/lib-gameserver/src/interfaces/GameServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ export class BanDTO extends TakaroDTO<BanDTO> {
expiresAt: string | null;
}

export class MapInfoDTO extends TakaroDTO<MapInfoDTO> {
@IsBoolean()
enabled: boolean;
@IsNumber()
mapBlockSize: number;
@IsNumber()
maxZoom: number;
@IsNumber()
mapSizeX: number;
@IsNumber()
mapSizeY: number;
@IsNumber()
mapSizeZ: number;
}

export interface IGameServer {
connectionInfo: unknown;
getEventEmitter(): TakaroEmitter;
Expand Down Expand Up @@ -100,4 +115,7 @@ export interface IGameServer {
unbanPlayer(player: IPlayerReferenceDTO): Promise<void>;
listBans(): Promise<BanDTO[]>;
shutdown(): Promise<void>;

getMapInfo(): Promise<MapInfoDTO>;
getMapTile(x: number, y: number, z: number): Promise<Buffer>;
}

0 comments on commit fc99f56

Please sign in to comment.