Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,40 @@ npx @gamemaker/gm-cli@latest login <my key>
gm-cli manual open "sprites" --language=es
```

### Publish to GX.Games
Use `gm-cli gxgames` to publish a game to [gx.games](https://gx.games). Run `gm-cli gxgames --help` for the full list of subcommands.

The flow:

1. **Package** the game as an OperaGX zip:
```sh
npx @gamemaker/gm-cli@latest package --target=operagx --output=game.zip
```
2. **Link** the project to a studio and game (opens the browser to sign in on first use):
```sh
npx @gamemaker/gm-cli@latest gxgames link --studioid=<id> --gameid=<id>
```
Omit the flags to pick interactively.
3. **Upload** the zip (prompts for a `X.Y.Z.B` version if `--version` is omitted):
```sh
npx @gamemaker/gm-cli@latest gxgames upload --file=game.zip --version=1.0.0.0
```
4. **Set metadata** required for publishing — title (must be unique across GX.Games), description, age rating, platforms, 16:9 cover, and 16:9 screenshot. Cover and graphic must have an **exact** 16:9 aspect ratio (e.g. 1920×1080):
```sh
npx @gamemaker/gm-cli@latest gxgames meta \
--title="My Game" \
--description="A short description" \
--age-rating=EVERYONE \
--platforms=DESKTOP,MOBILE \
--cover=cover_1920x1080.png \
--graphic=screenshot_1920x1080.png
```
Each flag overrides one field; omitted flags keep the current server value.
5. **Publish** to make the game public (opens the published page on success):
```sh
npx @gamemaker/gm-cli@latest gxgames publish
```

## Near future
> Note: The GameMaker CLI is made for the community and we welcome your feedback! Please suggest features or tell us about any issues you are having.

Expand All @@ -81,10 +115,6 @@ The `ask` subcommand displays an article directly in your terminal,
gm-cli manual ask "data structures"
```

### Publishing games to the web

Direct integration with [gx.games](https://gx.games) to share your games!

### A library to make your own tools
`gm-cli` will expose its internals as a TypeScript library that you can use to more easily make your own editor tools.

Expand Down
6 changes: 3 additions & 3 deletions src/commands/gxgames/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const gxgamesUploadCommand = buildCommand({
brief: "Upload a game bundle to GX.Games",
fullDescription:
"Uploads a zip bundle to GX.Games. " +
"Produce the zip with `gm-cli package --target operagx`. " +
"Prompts for the version number if --version is not provided.",
},
});
Expand All @@ -85,7 +86,7 @@ const gxgamesMetaCommand = buildCommand({
brief: "Game title",
optional: true,
},
agerating: {
ageRating: {
kind: "parsed",
parse: String,
brief:
Expand Down Expand Up @@ -124,8 +125,7 @@ const gxgamesMetaCommand = buildCommand({
brief: "Set or update game metadata required for publishing",
fullDescription:
"Set or update metadata for your GX.Games game. " +
"Run without flags for an interactive prompt, or pass flags to set specific fields. " +
"All flags are optional — omit any flag to be prompted for it interactively.",
"Each flag overrides the corresponding field; omitted flags keep their current server value.",
},
});

Expand Down
4 changes: 2 additions & 2 deletions src/commands/gxgames/commands/meta-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import type {

interface MetaFlags {
title?: string;
agerating?: string;
ageRating?: string;
description?: string;
platforms?: string;
cover?: string;
Expand Down Expand Up @@ -59,7 +59,7 @@ export default async function (
title: flags.title ?? game.title,
shortDescription: flags.description ?? game.shortDescription,
ageRating:
(flags.agerating?.toUpperCase() as
(flags.ageRating?.toUpperCase() as
| GameDevUpdateGameRequestAgeRatingEnum
| undefined) ??
(game.ageRating as GameDevUpdateGameRequestAgeRatingEnum),
Expand Down
11 changes: 11 additions & 0 deletions src/commands/gxgames/commands/upload-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ import type { ProjectPath } from "~/project";

import { LinkStorage } from "../api";

const VERSION_RE = /^\d+\.\d+\.\d+\.\d+$/;
const validateVersion = (v: string | undefined): string | undefined =>
v && VERSION_RE.test(v)
? undefined
: "Version must be X.Y.Z.B (e.g. 1.0.0.0)";

export default async function (
this: Context,
flags: { file: string; version?: string },
Expand All @@ -49,12 +55,17 @@ export default async function (

let version: string;
if (flags.version != null) {
const err = validateVersion(flags.version);
if (err) {
throw new KnownError(err);
}
version = flags.version;
} else {
const v = await p.text({
message: "Version",
placeholder: "0.0.1.0",
defaultValue: previousVersion,
validate: validateVersion,
});
if (p.isCancel(v)) {
return process.exit(0);
Expand Down
Loading