diff --git a/.gitignore b/.gitignore index 40b878d..0634372 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -node_modules/ \ No newline at end of file +node_modules/ +packages/bridge-server/data/data.db +packages/bridge-server/upload \ No newline at end of file diff --git a/packages/bridge-server/data/data.db b/packages/bridge-server/data/data.db index e69de29..1cbd428 100644 Binary files a/packages/bridge-server/data/data.db and b/packages/bridge-server/data/data.db differ diff --git a/packages/bridge-server/src/app.module.ts b/packages/bridge-server/src/app.module.ts index 076cc60..3b13ca7 100644 --- a/packages/bridge-server/src/app.module.ts +++ b/packages/bridge-server/src/app.module.ts @@ -2,6 +2,8 @@ import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; +import { MulterModule } from '@nestjs/platform-express' + import { SequelizeModule } from '@nestjs/sequelize'; import { AuthModule } from './auth/auth.module'; import { UsersService } from './users/users.service'; @@ -10,6 +12,15 @@ import { UsersModule } from './users/users.module'; import { LoggerMiddleware } from './auth/logger.middleware'; import { SeasonsController } from './seasons/seasons.controller'; import { UploadController } from './upload/upload.controller'; +import { SeasonsModule } from './seasons/seasons.module'; +import { RacersService } from './racers/racers.service'; +import { RacesService } from './races/races.service'; +import { SeasonStandingsService } from './season-standings/season-standings.service'; +import { RaceResultsService } from './race-results/race-results.service'; +import { RaceResultsModule } from './race-results/race-results.module'; +import { RacesModule } from './races/races.module'; +import { RacersModule } from './racers/racers.module'; +import { SeasonStandingsModule } from './season-standings/season-standings.module'; @Module({ imports: [ @@ -21,9 +32,17 @@ import { UploadController } from './upload/upload.controller'; }), AuthModule, UsersModule, + MulterModule.register({ + dest: './upload', + }), + SeasonsModule, + RaceResultsModule, + RacesModule, + RacersModule, + SeasonStandingsModule, ], controllers: [AppController, SeasonsController, UploadController], - providers: [AppService, UsersService], + providers: [AppService, UsersService, RacersService, RacesService, SeasonStandingsService, RaceResultsService], }) export class AppModule { configure(consumer: MiddlewareConsumer) { diff --git a/packages/bridge-server/src/race-results/race-result.model.ts b/packages/bridge-server/src/race-results/race-result.model.ts new file mode 100644 index 0000000..11cdab8 --- /dev/null +++ b/packages/bridge-server/src/race-results/race-result.model.ts @@ -0,0 +1,26 @@ +import { Column, Model, Table, HasMany, ForeignKey, BelongsTo } from "sequelize-typescript"; +import { Racer } from "src/racers/racer.model"; +import { Race } from "src/races/race.model"; + +@Table +export class RaceResult extends Model { + @ForeignKey(() => Race) + @Column + raceId: number; + + @BelongsTo(() => Race) + race: Race + + @ForeignKey(() => Racer) + @Column + racerId: number; + + @BelongsTo(() => Racer) + racer: Racer + + @Column + replayPath: string; + + @Column + time: number; +} \ No newline at end of file diff --git a/packages/bridge-server/src/race-results/race-results.module.ts b/packages/bridge-server/src/race-results/race-results.module.ts new file mode 100644 index 0000000..cc7a511 --- /dev/null +++ b/packages/bridge-server/src/race-results/race-results.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { RaceResult } from './race-result.model'; +import { RaceResultsService } from './race-results.service'; + +@Module({ + imports: [SequelizeModule.forFeature([RaceResult])], + providers: [RaceResultsService], + exports: [SequelizeModule, RaceResultsService] +}) +export class RaceResultsModule {} diff --git a/packages/bridge-server/src/race-results/race-results.service.spec.ts b/packages/bridge-server/src/race-results/race-results.service.spec.ts new file mode 100644 index 0000000..f98d199 --- /dev/null +++ b/packages/bridge-server/src/race-results/race-results.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { RaceResultsService } from './race-results.service'; + +describe('RaceResultsService', () => { + let service: RaceResultsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [RaceResultsService], + }).compile(); + + service = module.get(RaceResultsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/packages/bridge-server/src/race-results/race-results.service.ts b/packages/bridge-server/src/race-results/race-results.service.ts new file mode 100644 index 0000000..c2fdcab --- /dev/null +++ b/packages/bridge-server/src/race-results/race-results.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class RaceResultsService {} diff --git a/packages/bridge-server/src/racers/racer.model.ts b/packages/bridge-server/src/racers/racer.model.ts new file mode 100644 index 0000000..fce6138 --- /dev/null +++ b/packages/bridge-server/src/racers/racer.model.ts @@ -0,0 +1,14 @@ +import { Column, Model, Table, HasMany } from "sequelize-typescript"; +import { RaceResult } from "src/race-results/race-result.model"; + +@Table +export class Racer extends Model { + @Column + name: string; + + @Column + gameHandle: string; + + @HasMany(() => RaceResult) + results: RaceResult[]; +} \ No newline at end of file diff --git a/packages/bridge-server/src/racers/racers.module.ts b/packages/bridge-server/src/racers/racers.module.ts new file mode 100644 index 0000000..89ba325 --- /dev/null +++ b/packages/bridge-server/src/racers/racers.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { Racer } from './racer.model'; +import { RacersService } from './racers.service'; + +@Module({ + imports: [SequelizeModule.forFeature([Racer])], + providers: [RacersService], + exports: [SequelizeModule, RacersService] +}) +export class RacersModule {} \ No newline at end of file diff --git a/packages/bridge-server/src/racers/racers.service.spec.ts b/packages/bridge-server/src/racers/racers.service.spec.ts new file mode 100644 index 0000000..f148654 --- /dev/null +++ b/packages/bridge-server/src/racers/racers.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { RacersService } from './racers.service'; + +describe('RacersService', () => { + let service: RacersService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [RacersService], + }).compile(); + + service = module.get(RacersService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/packages/bridge-server/src/racers/racers.service.ts b/packages/bridge-server/src/racers/racers.service.ts new file mode 100644 index 0000000..b96daed --- /dev/null +++ b/packages/bridge-server/src/racers/racers.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class RacersService {} diff --git a/packages/bridge-server/src/races/race.model.ts b/packages/bridge-server/src/races/race.model.ts new file mode 100644 index 0000000..48994c5 --- /dev/null +++ b/packages/bridge-server/src/races/race.model.ts @@ -0,0 +1,34 @@ +import { Column, Model, Table, HasMany, HasOne, ForeignKey, BelongsTo } from "sequelize-typescript"; +import { RaceResult } from "src/race-results/race-result.model"; +import { Season } from "src/seasons/season.model"; + +@Table +export class Race extends Model { + @Column + mapName: string; + + @Column + mapURL: string; + + @Column + mapUID: string; + + @Column + mapImgUrl: string; + + @Column + startDate: Date; + + @Column + endDate: Date; + + @HasMany(() => RaceResult) + results: RaceResult[]; + + @ForeignKey(() => Season) + @Column + seasonId: number; + + @BelongsTo(() => Season) + season: Season; +} \ No newline at end of file diff --git a/packages/bridge-server/src/races/races.module.ts b/packages/bridge-server/src/races/races.module.ts new file mode 100644 index 0000000..7b882c2 --- /dev/null +++ b/packages/bridge-server/src/races/races.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { Race } from './race.model'; +import { RacesService } from './races.service'; + +@Module({ + imports: [SequelizeModule.forFeature([Race])], + providers: [RacesService], + exports: [SequelizeModule, RacesService] +}) +export class RacesModule {} diff --git a/packages/bridge-server/src/races/races.service.spec.ts b/packages/bridge-server/src/races/races.service.spec.ts new file mode 100644 index 0000000..b6b4088 --- /dev/null +++ b/packages/bridge-server/src/races/races.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { RacesService } from './races.service'; + +describe('RacesService', () => { + let service: RacesService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [RacesService], + }).compile(); + + service = module.get(RacesService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/packages/bridge-server/src/races/races.service.ts b/packages/bridge-server/src/races/races.service.ts new file mode 100644 index 0000000..40579db --- /dev/null +++ b/packages/bridge-server/src/races/races.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class RacesService {} diff --git a/packages/bridge-server/src/season-standings/season-standing.model.ts b/packages/bridge-server/src/season-standings/season-standing.model.ts new file mode 100644 index 0000000..a5c82ef --- /dev/null +++ b/packages/bridge-server/src/season-standings/season-standing.model.ts @@ -0,0 +1,23 @@ +import { Column, Model, Table, HasMany, ForeignKey, BelongsTo } from "sequelize-typescript"; +import { Racer } from "src/racers/racer.model"; +import { Season } from "src/seasons/season.model"; + +@Table +export class SeasonStanding extends Model { + @ForeignKey(() => Season) + @Column + seasonId: number; + + @BelongsTo(() => Season) + season: Season + + @ForeignKey(() => Racer) + @Column + racerId: number; + + @BelongsTo(() => Racer) + racer: Racer + + @Column + points: number; +} \ No newline at end of file diff --git a/packages/bridge-server/src/season-standings/season-standings.module.ts b/packages/bridge-server/src/season-standings/season-standings.module.ts new file mode 100644 index 0000000..7420b65 --- /dev/null +++ b/packages/bridge-server/src/season-standings/season-standings.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { SeasonStanding } from './season-standing.model'; +import { SeasonStandingsService } from './season-standings.service'; + +@Module({ + imports: [SequelizeModule.forFeature([SeasonStanding])], + providers: [SeasonStandingsService], + exports: [SequelizeModule, SeasonStandingsService] +}) +export class SeasonStandingsModule {} \ No newline at end of file diff --git a/packages/bridge-server/src/season-standings/season-standings.service.spec.ts b/packages/bridge-server/src/season-standings/season-standings.service.spec.ts new file mode 100644 index 0000000..102f799 --- /dev/null +++ b/packages/bridge-server/src/season-standings/season-standings.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SeasonStandingsService } from './season-standings.service'; + +describe('SeasonStandingsService', () => { + let service: SeasonStandingsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [SeasonStandingsService], + }).compile(); + + service = module.get(SeasonStandingsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/packages/bridge-server/src/season-standings/season-standings.service.ts b/packages/bridge-server/src/season-standings/season-standings.service.ts new file mode 100644 index 0000000..dde932d --- /dev/null +++ b/packages/bridge-server/src/season-standings/season-standings.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class SeasonStandingsService {} diff --git a/packages/bridge-server/src/seasons/season.model.ts b/packages/bridge-server/src/seasons/season.model.ts new file mode 100644 index 0000000..7d9e684 --- /dev/null +++ b/packages/bridge-server/src/seasons/season.model.ts @@ -0,0 +1,21 @@ +import { Column, HasMany, Model, Table } from "sequelize-typescript"; +import { Race } from "src/races/race.model"; +import { SeasonStanding } from "src/season-standings/season-standing.model"; + +@Table +export class Season extends Model { + @Column + title: string; + + @Column + subTitle: string; + + @Column + startingDate: Date; + + @HasMany(() => Race) + races: Race[] + + @HasMany(() => SeasonStanding) + standings: SeasonStanding[]; +} \ No newline at end of file diff --git a/packages/bridge-server/src/seasons/seasons.module.ts b/packages/bridge-server/src/seasons/seasons.module.ts new file mode 100644 index 0000000..6f4d316 --- /dev/null +++ b/packages/bridge-server/src/seasons/seasons.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { SequelizeModule } from '@nestjs/sequelize'; +import { Season } from './season.model'; +import { SeasonsController } from './seasons.controller'; +import { SeasonsService } from './seasons.service'; + +@Module({ + imports: [SequelizeModule.forFeature([Season])], + providers: [SeasonsService], + controllers: [SeasonsController], + exports: [SequelizeModule, SeasonsService] +}) +export class SeasonsModule {} diff --git a/packages/bridge-server/src/seasons/seasons.service.spec.ts b/packages/bridge-server/src/seasons/seasons.service.spec.ts new file mode 100644 index 0000000..9e15587 --- /dev/null +++ b/packages/bridge-server/src/seasons/seasons.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { SeasonsService } from './seasons.service'; + +describe('SeasonsService', () => { + let service: SeasonsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [SeasonsService], + }).compile(); + + service = module.get(SeasonsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/packages/bridge-server/src/seasons/seasons.service.ts b/packages/bridge-server/src/seasons/seasons.service.ts new file mode 100644 index 0000000..038d1f7 --- /dev/null +++ b/packages/bridge-server/src/seasons/seasons.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@nestjs/common'; +import { InjectModel } from '@nestjs/sequelize'; +import { Season } from './season.model'; +//import { SeasonStanding } from 'src/season-standings/season-standing.model'; +//import { Race } from 'src/races/race.model'; + +@Injectable() +export class SeasonsService { + constructor( + @InjectModel(Season) private seasonModel: typeof Season, + ) + {} + + async findAll() { + //return this.seasonModel.findAll(); + } + + async findOne(id: number) { + //return this.seasonModel.findOne({ where: {id: id}}/*, include:[Race, SeasonStanding] }*/) + } +} diff --git a/packages/bridge-server/src/trackmania-replays/gbx-header.ts b/packages/bridge-server/src/trackmania-replays/gbx-header.ts new file mode 100644 index 0000000..6ae21de --- /dev/null +++ b/packages/bridge-server/src/trackmania-replays/gbx-header.ts @@ -0,0 +1,78 @@ +class gbxHeader { + + has_magic = true + version = -1 + format = -1 + compressionofRefTable = -1 + compressionofRefBody = -1 + compressionTextFlag = '' + id = -1 + userData = [] + numNodes = 0 + + is_vaild = false + + parse(buff) + { + let header_magic = buff.readString(3); + + if (header_magic != 'GBX') + { + console.log("Header Magic Mismatch: " + header_magic); + return + } + this.has_magic = true + + this.version = buff.readUInt16(); + console.log(this.version) + + if (this.version < 5 || this.version >7 ) + { + console.log("Unsupported version") + return; + } + + this.format = buff.readInt8(); + if (this.format != 66) + { + console.log("Unsupported format") + return; + } + + this.compressionofRefTable = buff.readInt8(); + + if (this.compressionofRefTable != 67 && this.compressionofRefTable != 85) + { + console.log("Unsupported compression format, Ref") + return; + } + + this.compressionofRefBody = buff.readInt8(); + if (this.compressionofRefBody != 67 && this.compressionofRefBody != 85) + { + console.log("Unsupported compression format, Body") + return; + } + + this.compressionTextFlag = ''; + if (this.version >= 4) + { + this.compressionTextFlag = buff.readString(1); + } + + this.id = buff.readUInt32(); + console.log(this.id) + + if (this.version >=6) + { + this.userData = buff.readBytes(); + } + + this.numNodes = buff.readUInt32(); + + this.is_vaild = true + } +} + + +module.exports = gbxHeader; \ No newline at end of file diff --git a/packages/bridge-server/src/trackmania-replays/gbx-replay.ts b/packages/bridge-server/src/trackmania-replays/gbx-replay.ts new file mode 100644 index 0000000..3cad04c --- /dev/null +++ b/packages/bridge-server/src/trackmania-replays/gbx-replay.ts @@ -0,0 +1,384 @@ +interface ChunkInfo { + dwId: number; + dwSize: number; + dwOffset: number; +} + + +class gbxReplay { + + CHUNKS_OFFSET = 17; + HEADER_OFFSET = 21; + UNASSIGNED = 0xFFFFFFFF; + + mapUID = ""; + environment = ""; + author = ""; + bestTime = this.UNASSIGNED; + gamerHandle = "" + login = "" + titleId = "" + + calcChunkOffset(num) { + return (((num) * 8) + this.HEADER_OFFSET) + } + + isNumber(id) { return (((id) & 0xC0000000) == 0)} + isString(id) { return (((id) & 0xC0000000) != 0)} + isUnassigned(id) {return ((id) == this.UNASSIGNED)} + getIndex(id) {return ((id) & 0x3FFFFFFF)} + + parseReplayChunk(buff, chunkInfo) { + buff.seek(0+chunkInfo.dwOffset); + let version = buff.readUInt32(); + let isVSK = version >= 9999 ? true : false; + + let idList = { version: 0, index: 0, list:[]} + + if( chunkInfo.dwSize <= 4) { + return; + } + + if((!isVSK && version >= 3) || (isVSK && version >= 10000)) + { + let result = this.readIdentifier(buff, idList); + if(result.read > 0) + { + this.mapUID = result.str; + console.log("MapUID:\t " + this.mapUID) + } + + result = this.readIdentifier(buff, idList); + if(result.read > 0) + { + this.environment = result.str; + console.log("Environ:\t " + this.environment) + } + + result = this.readIdentifier(buff, idList) + if (result.read > 0) + { + this.author = result.str; + console.log("Author:\t " + this.author) + } + + this.bestTime = buff.readUInt32(); + console.log("BestTime:\t " + this.bestTime); + + result = buff.readNadeoString(); + if (result.read > 0) + { + this.gamerHandle = result.str; + console.log("Gamer Handle:\t " + this.gamerHandle) + } + + if((!isVSK && version >= 6) || (isVSK && version >= 10000)) + { + result = buff.readNadeoString(); + if (result.read > 0) + { + this.login = result.str; + console.log("Login:\t " + this.login) + } + + if((!isVSK && version >= 8) || (isVSK && version >= 10000)) + { + buff.seek(buff.readPos+1); + result = this.readIdentifier(buff, idList) + if (result.read > 0) + { + this.titleId = result.str; + console.log("titleId:\t " + this.titleId) + } + } + } + } + } + + parseAuthorChunk(buff, chunkInfo) { + + } + + parseCommunityChunk(buff, chunkInfo) { + + } + + parse(buff) + { + buff.seek(0+this.CHUNKS_OFFSET); + let numChunks = buff.readUInt32(); + + if(numChunks == 0) { + return true; + } + else if (numChunks > 0xff) { + return false; + } + + let chunkId, chunkSize = 0; + let chunkOffset = this.calcChunkOffset(numChunks) + let chunkVersion: ChunkInfo; + let chunkCommunity: ChunkInfo; + let chunkAuthor: ChunkInfo; + + for (let counter = 1; counter <= numChunks; counter++) { + chunkId = buff.readUInt32(); + chunkSize = buff.readUInt32(); + + chunkSize &= 0x7FFFFFFF; + + switch (chunkId){ + case 0x03093000: // (TM) + case 0x2403F000: // (VSK, TM) + chunkVersion.dwId = chunkId; + chunkVersion.dwSize = chunkSize; + chunkVersion.dwOffset = chunkOffset; + chunkOffset += chunkSize; + break; + case 0x03093001: // (TM) + case 0x2403F001: // (VSK, TM) + chunkCommunity.dwId = chunkId; + chunkCommunity.dwSize = chunkSize; + chunkCommunity.dwOffset = chunkOffset; + chunkOffset += chunkSize; + //OutputTextFmt(hwndCtl, szOutput, _countof(szOutput), g_szChunk, dwCouter, dwChunkId, dwChunkSize); + break; + + case 0x03093002: // (MP) + chunkAuthor.dwId = chunkId; + chunkAuthor.dwSize = chunkSize; + chunkAuthor.dwOffset = chunkOffset; + chunkOffset += chunkSize; + //OutputTextFmt(hwndCtl, szOutput, _countof(szOutput), g_szChunk, dwCouter, dwChunkId, dwChunkSize); + break; + + default: + chunkOffset += chunkSize; + //OutputTextFmt(hwndCtl, szOutput, _countof(szOutput), g_szChunk, dwCouter, dwChunkId, dwChunkSize); + } + } + + if (chunkVersion.dwSize > 0) { + this.parseReplayChunk(buff, chunkVersion); + } + + if (chunkCommunity.dwSize > 0) { + this.parseCommunityChunk(buff, chunkCommunity); + } + + if (chunkAuthor.dwSize > 0) { + this.parseAuthorChunk(buff, chunkAuthor); + } + } + + readIdentifier(buff, idList) + { + if ( idList.version < 3 ) + { + idList.version = buff.readUInt32(); + + if (idList.version < 2) + { + return {read:-1, str:""}; + } + } + + let id = buff.readUInt32(); + if(this.isUnassigned(id)) + { + return {read:0, str:""}; + } + + if(this.isNumber(id)) + { + return this.getCollectionString(id); + } + + if(idList.version == 2) + { + return buff.readNadeoString(); + } + + if(this.isString(id) && this.getIndex(id) == 0) + { + let result = buff.readNadeoString(); + + if (result.read > 0 && idList.index < 8) + { + idList.list[idList.index] = result.str; + idList.index++; + } + + return result; + } + + let index = this.getIndex(id); + if( index == 0 || index > 8) + { + return {read:0, str:""}; + } + + let latest = idList.list[idList.index-1]; + return {read:latest.length, str:latest}; + } + + getCollectionString(id) + { + let outString = "" + switch (id) + { + case 0: // Speed + outString = "Desert"; + break; + case 1: // Alpine + outString = "Snow"; + break; + case 2: // Rally + outString = "Rally"; + break; + case 3: // Island + outString = "Island"; + break; + case 4: // Bay + outString = "Bay"; + break; + case 5: // Coast + outString = "Coast"; + break; + case 6: // StadiumMP4 + outString = "Stadium"; + break; + case 7: // Basic + outString = "Basic"; + break; + case 8: // Plain + outString = "Plain"; + break; + case 9: // Moon + outString = "Moon"; + break; + case 10: // Toy + outString = "Toy"; + break; + case 11: // Valley + outString = "Valley"; + break; + case 12: // Canyon + outString = "Canyon"; + break; + case 13: // Lagoon + outString = "Lagoon"; + break; + case 14: // Deprecated_Arena + outString = "Arena"; + break; + case 15: // TMTest8 + outString = "TMTest8"; + break; + case 16: // TMTest9 + outString = "TMTest9"; + break; + case 17: // TMCommon + outString = "TMCommon"; + break; + case 18: // Canyon4 + outString = "Canyon4"; + break; + case 19: // Canyon256 + outString = "Canyon256"; + break; + case 20: // Valley4 + outString = "Valley4"; + break; + case 21: // Valley256 + outString = "Valley256"; + break; + case 22: // Lagoon4 + outString = "Lagoon4"; + break; + case 23: // Lagoon256 + outString = "Lagoon256"; + break; + case 24: // Stadium4 + outString = "Stadium4"; + break; + case 25: // Stadium256 + outString = "Stadium256"; + break; + case 26: // Stadium + outString = "Stadium"; + break; + case 27: // Voxel + outString = "Voxel"; + break; + case 100: // History + outString = "History"; + break; + case 101: // Society + outString = "Society"; + break; + case 102: // Galaxy + outString = "Galaxy"; + break; + case 103: // QMTest1 + outString = "QMTest1"; + break; + case 104: // QMTest2 + outString = "QMTest2"; + break; + case 105: // QMTest3 + outString = "QMTest3"; + break; + case 200: // Gothic + outString = "Gothic"; + break; + case 201: // Paris + outString = "Paris"; + break; + case 202: // Storm + outString = "Storm"; + break; + case 203: // Cryo + outString = "Cryo"; + break; + case 204: // Meteor + outString = "Meteor"; + break; + case 205: // Meteor4 + outString = "Meteor4"; + break; + case 206: // Meteor256 + outString = "Meteor256"; + break; + case 207: // SMTest3 + outString = "SMTest3"; + break; + case 299: // SMCommon + outString = "SMCommon"; + break; + case 10000: // Vehicles + outString = "Vehicles"; + break; + case 10001: // Orbital + outString = "Orbital"; + break; + case 10002: // Actors + outString = "Actors"; + break; + case 10003: // Common + outString = "Common"; + break; + case this.UNASSIGNED: + outString = "_Unassigned"; + break; + default: + { + return {read:0, str:""}; + } + } + + return {read:outString.length, str:outString} + } +} + +module.exports = gbxReplay; \ No newline at end of file diff --git a/packages/bridge-server/src/utilities/advanceable-buffer.ts b/packages/bridge-server/src/utilities/advanceable-buffer.ts new file mode 100644 index 0000000..913a5bd --- /dev/null +++ b/packages/bridge-server/src/utilities/advanceable-buffer.ts @@ -0,0 +1,75 @@ +class NadeoStringResult { + read: number; + str: string; +} + +class Advancablebuffer { + readPos: number = 0; + internalBuffer: Buffer; + littleEndian: boolean = true + + constructor(buffer: Buffer, useBigEndian: boolean) + { + this.internalBuffer = buffer; + this.readPos = 0; + this.littleEndian = !useBigEndian; + } + + seek(seekPos: number): void + { + this.readPos = seekPos + } + + readString(numBytes: number): string + { + let t = this.internalBuffer.subarray(this.readPos, this.readPos+=numBytes); + return t.toString(); + } + + readInt8(): number + { + let value = this.internalBuffer.readInt8(this.readPos); + this.readPos += 1; + return value; + } + + readUInt16(): number + { + let value = this.littleEndian ? this.internalBuffer.readUInt16LE(this.readPos) : this.internalBuffer.readUInt16BE(this.readPos); + this.readPos += 2; + return value; + } + + readUInt32(): number + { + let value = this.littleEndian ? this.internalBuffer.readUInt32LE(this.readPos) : this.internalBuffer.readUInt32BE(this.readPos); + this.readPos += 4; + return value; + } + + readBytes(): Buffer + { + let length = this.readUInt32() + let sub = this.internalBuffer.subarray(this.readPos, this.readPos+=length); + return sub; + } + + readNadeoString(): NadeoStringResult + { + let length = this.readUInt32() + if(length >= 0xFFFF) + { + return {read:-1, str:""}; + } + + if (length == 0) + { + return {read:0, str:""}; + } + + let outString = this.readString(length); + return {read:outString.length, str:outString}; + } +} + +module.exports = {Advancablebuffer, NadeoStringResult}; \ No newline at end of file