Skip to content

Commit

Permalink
Create basic teiserver maps data
Browse files Browse the repository at this point in the history
Map data to be pushed to teiserver for the need of multiplayer
games and matchmaking.
  • Loading branch information
p2004a committed Jan 21, 2025
1 parent 3cbc13b commit a46abdd
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 8 deletions.
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Default target ran by make
all: gen/map_list.validated.json gen/mapDetails.lua gen/live_maps.validated.json gen/mapBoxes.conf gen/mapLists.conf gen/custom_map_lists.json gen/discordPresenceThumb gen/mapPresets.conf gen/mapBattlePresets.conf gen/lobby_maps.validated.json
all: gen/map_list.validated.json gen/mapDetails.lua gen/live_maps.validated.json gen/mapBoxes.conf gen/mapLists.conf gen/custom_map_lists.json gen/discordPresenceThumb gen/mapPresets.conf gen/mapBattlePresets.conf gen/lobby_maps.validated.json gen/teiserver_maps.validated.json

# Rules for doing generic data files conversion, e.g yaml to json
gen/%.json: %.yaml
Expand All @@ -10,7 +10,11 @@ gen/%.validated.json: gen/schemas/%.json gen/%.json

gen/types/%.d.ts: gen/schemas/%.json
mkdir -p gen/types
json2ts --cwd gen/schemas $< > $@
json2ts --cwd gen/schemas $< $@

# Additional explicit dependencies
gen/schemas/teiserver_maps.json: gen/schemas/map_modoptions.json gen/schemas/map_list.json
gen/schemas/lobby_maps.json: gen/schemas/map_list.json

# Output targets
gen/mapDetails.lua: gen/map_list.validated.json gen/types/map_list.d.ts
Expand Down Expand Up @@ -40,6 +44,9 @@ gen/mapPresets.conf gen/mapBattlePresets.conf &: gen/map_modoptions.validated.js
gen/lobby_maps.json: gen/map_list.validated.json gen/cdn_maps.validated.json gen/types/map_list.d.ts gen/types/lobby_maps.d.ts
tsx scripts/js/src/gen_lobby_maps.ts $@

gen/teiserver_maps.json: gen/map_list.validated.json gen/types/map_list.d.ts gen/map_modoptions.validated.json gen/types/map_modoptions.d.ts gen/types/teiserver_maps.d.ts
tsx scripts/js/src/gen_teiserver_maps.ts $@

# Tests on data
checks = $(notdir $(basename $(wildcard scripts/js/src/check_*.ts)))
test: typecheck_scripts $(checks)
Expand Down
16 changes: 10 additions & 6 deletions schemas/map_modoptions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ items:
springName:
type: string
modoptions:
type: object
patternProperties:
'^mapmetadata_[a-z0-9_]+$':
type: string
$comment: The pattern is really to be on the safe side, it can be less restrictive likely
pattern: '^[a-zA-Z0-9_.-]+$'
$ref: "#/$defs/mapModoptions"
required:
- springName
- modoptions
additionalProperties: false
$defs:
mapModoptions:
title: MapModoptions
type: object
patternProperties:
'^mapmetadata_[a-z0-9_]+$':
type: string
$comment: The pattern is really to be on the safe side, it can be less restrictive likely
pattern: '^[a-zA-Z0-9_.-]+$'
40 changes: 40 additions & 0 deletions schemas/teiserver_maps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: https://maps-metadata.beyondallreason.dev/latest/schemas/teiserver_maps.json
description: Map information for https://github.com/beyond-all-reason/teiserver
type: object
title: TeiserverMaps
properties:
maps:
type: array
items:
$ref: "#/$defs/teiserverMapInfo"
required:
- maps
$defs:
teiserverMapInfo:
title: TeiserverMapInfo
type: object
properties:
springName:
type: string
modoptions:
$ref: "map_modoptions.json#/$defs/mapModoptions"
default: {}
matchmakingQueues:
type: array
items:
type: string
# Values from https://github.com/beyond-all-reason/teiserver/blob/778450852dd63e087174a62853aae563b6723479/lib/teiserver/matchmaking/queue_supervisor.ex#L9
# will need to figure out how to evolve it over time
enum:
- 1v1
- 2v2
uniqueItems: true
default: []
startboxesSet:
type: array
items:
$ref: "map_list.json#/$defs/startboxesInfo"
required:
- springName
- startboxesSet
52 changes: 52 additions & 0 deletions scripts/js/src/gen_teiserver_maps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { readMapList } from "./maps_metadata.js";
import fs from "node:fs/promises";
import { program } from "@commander-js/extra-typings";
import stringify from "json-stable-stringify";
import type {
TeiserverMapInfo,
TeiserverMaps,
} from "../../../gen/types/teiserver_maps.js";
import { MapModoptions } from '../../../gen/types/map_modoptions.js';

async function readMapModoptions(): Promise<{[springName: string]: MapModoptions['modoptions']}> {
const contents = await fs.readFile('gen/map_modoptions.validated.json', { 'encoding': 'utf8' });
const mapModoptions = JSON.parse(contents) as MapModoptions[];
return Object.fromEntries(mapModoptions.map((m) => [m.springName, m.modoptions]));
}

async function genTeiserverMaps(): Promise<string> {
const maps = await readMapList();
const mapModoptions = await readMapModoptions();

const tMaps: TeiserverMapInfo[] = [];
for (const [_rowyId, map] of Object.entries(maps)) {
if (!map.inPool) {
continue;
}

// TODO: Do some better mapping, maybe add dedicated clear map lists
// in Rowy for exactly this purpose. Atm just reusing the one that
// exists for competitive 1v1.
const matchmakingQueues: TeiserverMapInfo["matchmakingQueues"] = [];
if (map.mapLists?.includes("competitive2p")) {
matchmakingQueues.push("1v1");
}

tMaps.push({
springName: map.springName,
startboxesSet: Object.values(map.startboxesSet || {}),
matchmakingQueues,
modoptions: mapModoptions[map.springName]
});
}

tMaps.sort((a, b) => a.springName.localeCompare(b.springName));
const teiserverMaps: TeiserverMaps = { maps: tMaps };
return stringify(teiserverMaps);
}

const prog = program
.argument("<teiserverMaps>", "Lobby maps output path.")
.parse();
const [teiserverMapsPath] = prog.processedArgs;
await fs.writeFile(teiserverMapsPath, await genTeiserverMaps());

0 comments on commit a46abdd

Please sign in to comment.