@kradle/cli 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/commands/challenge/run.d.ts +0 -1
- package/dist/commands/challenge/run.js +9 -6
- package/dist/lib/arguments.d.ts +6 -2
- package/dist/lib/arguments.js +17 -5
- package/oclif.manifest.json +52 -60
- package/package.json +1 -1
- package/static/ai_docs/LLM_API_REFERENCE.md +86 -22
- package/static/ai_docs/LLM_CLI_REFERENCE.md +7 -2
package/README.md
CHANGED
|
@@ -128,6 +128,7 @@ Run a challenge in production or studio environment:
|
|
|
128
128
|
```bash
|
|
129
129
|
kradle challenge run <challenge-name>
|
|
130
130
|
kradle challenge run <challenge-name> --studio # Run in local studio environment
|
|
131
|
+
kradle challenge run <team-name>:<challenge-name> # Run a public challenge from another team
|
|
131
132
|
```
|
|
132
133
|
|
|
133
134
|
## Experiment Commands
|
|
@@ -11,7 +11,6 @@ export default class Run extends Command {
|
|
|
11
11
|
"web-url": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
"studio-api-url": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
13
|
"studio-url": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
"challenges-path": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
14
|
studio: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
15
|
open: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
16
|
};
|
|
@@ -2,7 +2,6 @@ import { Command, Flags } from "@oclif/core";
|
|
|
2
2
|
import pc from "picocolors";
|
|
3
3
|
import { ApiClient } from "../../lib/api-client.js";
|
|
4
4
|
import { getChallengeSlugArgument } from "../../lib/arguments.js";
|
|
5
|
-
import { Challenge } from "../../lib/challenge.js";
|
|
6
5
|
import { getConfigFlags } from "../../lib/flags.js";
|
|
7
6
|
import { loadTemplateRun, openInBrowser } from "../../lib/utils.js";
|
|
8
7
|
export default class Run extends Command {
|
|
@@ -10,27 +9,31 @@ export default class Run extends Command {
|
|
|
10
9
|
static examples = [
|
|
11
10
|
"<%= config.bin %> <%= command.id %> my-challenge",
|
|
12
11
|
"<%= config.bin %> <%= command.id %> my-challenge --studio",
|
|
12
|
+
"<%= config.bin %> <%= command.id %> team-name:my-challenge",
|
|
13
13
|
];
|
|
14
14
|
static args = {
|
|
15
|
-
challengeSlug: getChallengeSlugArgument({
|
|
15
|
+
challengeSlug: getChallengeSlugArgument({
|
|
16
|
+
description: "Challenge slug to run (e.g., 'my-challenge' or 'team-name:my-challenge')",
|
|
17
|
+
allowTeam: true,
|
|
18
|
+
}),
|
|
16
19
|
};
|
|
17
20
|
static flags = {
|
|
18
21
|
studio: Flags.boolean({ char: "s", description: "Run in studio environment", default: false }),
|
|
19
22
|
open: Flags.boolean({ char: "o", description: "Open the run URL in the browser", default: false }),
|
|
20
|
-
...getConfigFlags("api-key", "api-url", "
|
|
23
|
+
...getConfigFlags("api-key", "api-url", "web-url", "studio-url", "studio-api-url"),
|
|
21
24
|
};
|
|
22
25
|
async run() {
|
|
23
26
|
const { args, flags } = await this.parse(Run);
|
|
24
27
|
const apiUrl = flags.studio ? flags["studio-api-url"] : flags["api-url"];
|
|
25
28
|
const studioApi = new ApiClient(apiUrl, flags["api-key"], flags.studio);
|
|
26
|
-
const
|
|
29
|
+
const challengeSlug = args.challengeSlug;
|
|
27
30
|
try {
|
|
28
31
|
const { participants } = (await loadTemplateRun());
|
|
29
32
|
const template = {
|
|
30
|
-
challenge:
|
|
33
|
+
challenge: challengeSlug,
|
|
31
34
|
participants,
|
|
32
35
|
};
|
|
33
|
-
this.log(pc.blue(`>> Running challenge: ${
|
|
36
|
+
this.log(pc.blue(`>> Running challenge: ${challengeSlug}${flags.studio ? " (studio)" : ""}...`));
|
|
34
37
|
const response = await studioApi.runChallenge(template);
|
|
35
38
|
if (response.runIds && response.runIds.length > 0) {
|
|
36
39
|
const baseUrl = flags.studio ? flags["studio-url"] : flags["web-url"];
|
package/dist/lib/arguments.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { Arg } from "@oclif/core/interfaces";
|
|
2
2
|
/**
|
|
3
|
-
* Returns a "challenge slug" argument,
|
|
3
|
+
* Returns a "challenge slug" argument, validating it to be a valid challenge slug.
|
|
4
|
+
* @param description - Description for the argument
|
|
5
|
+
* @param required - Whether the argument is required (default: true)
|
|
6
|
+
* @param allowTeam - Whether to allow namespaced slugs like "team-name:my-challenge" (default: false)
|
|
4
7
|
*/
|
|
5
|
-
export declare function getChallengeSlugArgument<R extends boolean = true>({ description, required, }: {
|
|
8
|
+
export declare function getChallengeSlugArgument<R extends boolean = true>({ description, required, allowTeam, }: {
|
|
6
9
|
description: string;
|
|
7
10
|
required?: R;
|
|
11
|
+
allowTeam?: boolean;
|
|
8
12
|
}): Arg<R extends true ? string : string | undefined>;
|
package/dist/lib/arguments.js
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { Args } from "@oclif/core";
|
|
2
|
-
|
|
2
|
+
// Base pattern for a slug segment (lowercase alphanumeric with hyphens, no leading/trailing hyphens)
|
|
3
|
+
const SLUG_SEGMENT = "[a-z0-9]+(?:-[a-z0-9]+)*";
|
|
4
|
+
// Local challenge slug pattern: just the challenge name (no namespace)
|
|
5
|
+
const LOCAL_SLUG_REGEX = new RegExp(`^${SLUG_SEGMENT}$`);
|
|
6
|
+
// Full challenge slug pattern: optional namespace prefix (e.g., "team-name:") followed by the challenge slug
|
|
7
|
+
const NAMESPACED_SLUG_REGEX = new RegExp(`^(?:${SLUG_SEGMENT}:)?${SLUG_SEGMENT}$`);
|
|
3
8
|
/**
|
|
4
|
-
* Returns a "challenge slug" argument,
|
|
9
|
+
* Returns a "challenge slug" argument, validating it to be a valid challenge slug.
|
|
10
|
+
* @param description - Description for the argument
|
|
11
|
+
* @param required - Whether the argument is required (default: true)
|
|
12
|
+
* @param allowTeam - Whether to allow namespaced slugs like "team-name:my-challenge" (default: false)
|
|
5
13
|
*/
|
|
6
|
-
export function getChallengeSlugArgument({ description, required, }) {
|
|
14
|
+
export function getChallengeSlugArgument({ description, required, allowTeam = false, }) {
|
|
15
|
+
const regex = allowTeam ? NAMESPACED_SLUG_REGEX : LOCAL_SLUG_REGEX;
|
|
16
|
+
const errorMessage = allowTeam
|
|
17
|
+
? "Challenge slugs must be lowercase alphanumeric characters and hyphens, and must not start or end with a hyphen. Optionally, a team prefix can be provided (e.g., 'team-name:my-challenge')."
|
|
18
|
+
: "Challenge slugs must be lowercase alphanumeric characters and hyphens, and must not start or end with a hyphen.";
|
|
7
19
|
const arg = Args.string({
|
|
8
20
|
description,
|
|
9
21
|
required: required ?? true,
|
|
10
22
|
parse: async (input) => {
|
|
11
|
-
if (!
|
|
12
|
-
throw new Error(`Invalid challenge slug: ${input}.
|
|
23
|
+
if (!regex.test(input)) {
|
|
24
|
+
throw new Error(`Invalid challenge slug: ${input}. ${errorMessage}`);
|
|
13
25
|
}
|
|
14
26
|
return input;
|
|
15
27
|
},
|
package/oclif.manifest.json
CHANGED
|
@@ -86,54 +86,6 @@
|
|
|
86
86
|
"list.js"
|
|
87
87
|
]
|
|
88
88
|
},
|
|
89
|
-
"ai-docs:api": {
|
|
90
|
-
"aliases": [],
|
|
91
|
-
"args": {},
|
|
92
|
-
"description": "Output the Kradle API reference documentation for LLMs",
|
|
93
|
-
"examples": [
|
|
94
|
-
"<%= config.bin %> <%= command.id %>"
|
|
95
|
-
],
|
|
96
|
-
"flags": {},
|
|
97
|
-
"hasDynamicHelp": false,
|
|
98
|
-
"hiddenAliases": [],
|
|
99
|
-
"id": "ai-docs:api",
|
|
100
|
-
"pluginAlias": "@kradle/cli",
|
|
101
|
-
"pluginName": "@kradle/cli",
|
|
102
|
-
"pluginType": "core",
|
|
103
|
-
"strict": true,
|
|
104
|
-
"enableJsonFlag": false,
|
|
105
|
-
"isESM": true,
|
|
106
|
-
"relativePath": [
|
|
107
|
-
"dist",
|
|
108
|
-
"commands",
|
|
109
|
-
"ai-docs",
|
|
110
|
-
"api.js"
|
|
111
|
-
]
|
|
112
|
-
},
|
|
113
|
-
"ai-docs:cli": {
|
|
114
|
-
"aliases": [],
|
|
115
|
-
"args": {},
|
|
116
|
-
"description": "Output the Kradle CLI reference documentation for LLMs",
|
|
117
|
-
"examples": [
|
|
118
|
-
"<%= config.bin %> <%= command.id %>"
|
|
119
|
-
],
|
|
120
|
-
"flags": {},
|
|
121
|
-
"hasDynamicHelp": false,
|
|
122
|
-
"hiddenAliases": [],
|
|
123
|
-
"id": "ai-docs:cli",
|
|
124
|
-
"pluginAlias": "@kradle/cli",
|
|
125
|
-
"pluginName": "@kradle/cli",
|
|
126
|
-
"pluginType": "core",
|
|
127
|
-
"strict": true,
|
|
128
|
-
"enableJsonFlag": false,
|
|
129
|
-
"isESM": true,
|
|
130
|
-
"relativePath": [
|
|
131
|
-
"dist",
|
|
132
|
-
"commands",
|
|
133
|
-
"ai-docs",
|
|
134
|
-
"cli.js"
|
|
135
|
-
]
|
|
136
|
-
},
|
|
137
89
|
"challenge:build": {
|
|
138
90
|
"aliases": [],
|
|
139
91
|
"args": {
|
|
@@ -409,7 +361,7 @@
|
|
|
409
361
|
"aliases": [],
|
|
410
362
|
"args": {
|
|
411
363
|
"challengeSlug": {
|
|
412
|
-
"description": "Challenge slug to run",
|
|
364
|
+
"description": "Challenge slug to run (e.g., 'my-challenge' or 'team-name:my-challenge')",
|
|
413
365
|
"name": "challengeSlug",
|
|
414
366
|
"required": true
|
|
415
367
|
}
|
|
@@ -417,7 +369,8 @@
|
|
|
417
369
|
"description": "Run a challenge",
|
|
418
370
|
"examples": [
|
|
419
371
|
"<%= config.bin %> <%= command.id %> my-challenge",
|
|
420
|
-
"<%= config.bin %> <%= command.id %> my-challenge --studio"
|
|
372
|
+
"<%= config.bin %> <%= command.id %> my-challenge --studio",
|
|
373
|
+
"<%= config.bin %> <%= command.id %> team-name:my-challenge"
|
|
421
374
|
],
|
|
422
375
|
"flags": {
|
|
423
376
|
"studio": {
|
|
@@ -453,15 +406,6 @@
|
|
|
453
406
|
"multiple": false,
|
|
454
407
|
"type": "option"
|
|
455
408
|
},
|
|
456
|
-
"challenges-path": {
|
|
457
|
-
"description": "Absolute path to the challenges directory",
|
|
458
|
-
"env": "KRADLE_CHALLENGES_PATH",
|
|
459
|
-
"name": "challenges-path",
|
|
460
|
-
"default": "~/Documents/kradle-studio/challenges",
|
|
461
|
-
"hasDynamicHelp": false,
|
|
462
|
-
"multiple": false,
|
|
463
|
-
"type": "option"
|
|
464
|
-
},
|
|
465
409
|
"web-url": {
|
|
466
410
|
"description": "Kradle Web URL, used to display the run URL",
|
|
467
411
|
"env": "KRADLE_WEB_URL",
|
|
@@ -574,6 +518,54 @@
|
|
|
574
518
|
"watch.js"
|
|
575
519
|
]
|
|
576
520
|
},
|
|
521
|
+
"ai-docs:api": {
|
|
522
|
+
"aliases": [],
|
|
523
|
+
"args": {},
|
|
524
|
+
"description": "Output the Kradle API reference documentation for LLMs",
|
|
525
|
+
"examples": [
|
|
526
|
+
"<%= config.bin %> <%= command.id %>"
|
|
527
|
+
],
|
|
528
|
+
"flags": {},
|
|
529
|
+
"hasDynamicHelp": false,
|
|
530
|
+
"hiddenAliases": [],
|
|
531
|
+
"id": "ai-docs:api",
|
|
532
|
+
"pluginAlias": "@kradle/cli",
|
|
533
|
+
"pluginName": "@kradle/cli",
|
|
534
|
+
"pluginType": "core",
|
|
535
|
+
"strict": true,
|
|
536
|
+
"enableJsonFlag": false,
|
|
537
|
+
"isESM": true,
|
|
538
|
+
"relativePath": [
|
|
539
|
+
"dist",
|
|
540
|
+
"commands",
|
|
541
|
+
"ai-docs",
|
|
542
|
+
"api.js"
|
|
543
|
+
]
|
|
544
|
+
},
|
|
545
|
+
"ai-docs:cli": {
|
|
546
|
+
"aliases": [],
|
|
547
|
+
"args": {},
|
|
548
|
+
"description": "Output the Kradle CLI reference documentation for LLMs",
|
|
549
|
+
"examples": [
|
|
550
|
+
"<%= config.bin %> <%= command.id %>"
|
|
551
|
+
],
|
|
552
|
+
"flags": {},
|
|
553
|
+
"hasDynamicHelp": false,
|
|
554
|
+
"hiddenAliases": [],
|
|
555
|
+
"id": "ai-docs:cli",
|
|
556
|
+
"pluginAlias": "@kradle/cli",
|
|
557
|
+
"pluginName": "@kradle/cli",
|
|
558
|
+
"pluginType": "core",
|
|
559
|
+
"strict": true,
|
|
560
|
+
"enableJsonFlag": false,
|
|
561
|
+
"isESM": true,
|
|
562
|
+
"relativePath": [
|
|
563
|
+
"dist",
|
|
564
|
+
"commands",
|
|
565
|
+
"ai-docs",
|
|
566
|
+
"cli.js"
|
|
567
|
+
]
|
|
568
|
+
},
|
|
577
569
|
"experiment:create": {
|
|
578
570
|
"aliases": [],
|
|
579
571
|
"args": {
|
|
@@ -808,5 +800,5 @@
|
|
|
808
800
|
]
|
|
809
801
|
}
|
|
810
802
|
},
|
|
811
|
-
"version": "0.2.
|
|
803
|
+
"version": "0.2.4"
|
|
812
804
|
}
|
package/package.json
CHANGED
|
@@ -261,7 +261,7 @@ current_y_position: {
|
|
|
261
261
|
type: "individual",
|
|
262
262
|
objective_type: "dummy",
|
|
263
263
|
updater: (value) => {
|
|
264
|
-
|
|
264
|
+
value.set(Actions.getCurrentPlayerPosition().y)
|
|
265
265
|
},
|
|
266
266
|
}
|
|
267
267
|
```
|
|
@@ -323,6 +323,8 @@ score.lowerOrEqualThan(number | Score);
|
|
|
323
323
|
|
|
324
324
|
### Lifecycle Events
|
|
325
325
|
|
|
326
|
+
All lifecycle events run globally (not per-player).
|
|
327
|
+
|
|
326
328
|
#### `start_challenge`
|
|
327
329
|
|
|
328
330
|
Runs once when the challenge starts. Use for global setup.
|
|
@@ -337,19 +339,19 @@ start_challenge: () => {
|
|
|
337
339
|
|
|
338
340
|
#### `init_participants`
|
|
339
341
|
|
|
340
|
-
Runs
|
|
342
|
+
Runs 1 second after start_challenge. Use for player setup. It still runs globally.
|
|
341
343
|
|
|
342
344
|
```typescript
|
|
343
345
|
init_participants: () => {
|
|
344
|
-
Actions.give({ target: "
|
|
345
|
-
Actions.setAttribute({ target: "
|
|
346
|
-
Actions.teleport({ target: "
|
|
346
|
+
Actions.give({ target: "all", item: "minecraft:diamond_sword", count: 1 });
|
|
347
|
+
Actions.setAttribute({ target: "all", attribute_: "generic.max_health", value: 40 });
|
|
348
|
+
Actions.teleport({ target: "all", x: 0, y: 100, z: 0, absolute: true });
|
|
347
349
|
}
|
|
348
350
|
```
|
|
349
351
|
|
|
350
352
|
#### `on_tick`
|
|
351
353
|
|
|
352
|
-
Runs every tick
|
|
354
|
+
Runs every tick. Use sparingly for performance.
|
|
353
355
|
|
|
354
356
|
```typescript
|
|
355
357
|
on_tick: () => {
|
|
@@ -402,7 +404,7 @@ Score events watch a variable and trigger when it reaches a specified target val
|
|
|
402
404
|
```typescript
|
|
403
405
|
{
|
|
404
406
|
score: variables.death_count,
|
|
405
|
-
mode: "fire_once", // Triggers once when death_count changes from
|
|
407
|
+
mode: "fire_once", // Triggers once when death_count changes away from initial value
|
|
406
408
|
actions: () => {
|
|
407
409
|
Actions.announce({ message: "First death!" });
|
|
408
410
|
},
|
|
@@ -417,6 +419,8 @@ Score events watch a variable and trigger when it reaches a specified target val
|
|
|
417
419
|
|
|
418
420
|
Advancement events trigger when a Minecraft advancement criterion is met. Internally, an advancement is created that grants when the criterion triggers, which then fires the event. The `criteria` array follows the [Minecraft Advancement JSON format](https://minecraft.fandom.com/wiki/Advancement/JSON_format).
|
|
419
421
|
|
|
422
|
+
Advancement-based events always fire per-player.
|
|
423
|
+
|
|
420
424
|
**Parameters:**
|
|
421
425
|
- `criteria` (required): Array of advancement trigger objects with optional conditions
|
|
422
426
|
- `mode` (required): `"fire_once"` or `"repeatable"`
|
|
@@ -476,6 +480,13 @@ See the [Minecraft Wiki](https://minecraft.fandom.com/wiki/Advancement/JSON_form
|
|
|
476
480
|
|
|
477
481
|
## Actions
|
|
478
482
|
|
|
483
|
+
Actions are higher-level functions that wrap common Minecraft operations. They provide:
|
|
484
|
+
- Automatic target mapping (`"all"`, `"self"`, team names → proper selectors)
|
|
485
|
+
- Integration with Kradle's interface (e.g., `Actions.announce` messages appear in Kradle)
|
|
486
|
+
- Consistent API for common operations
|
|
487
|
+
|
|
488
|
+
For advanced use cases not covered by Actions, you can fall back to Sandstone's lower-level functions directly (`give`, `tellraw`, `effect`, `kill`, `execute`, etc.). See [Sandstone Integration](#sandstone-integration).
|
|
489
|
+
|
|
479
490
|
All actions are called via the `Actions` object:
|
|
480
491
|
|
|
481
492
|
```typescript
|
|
@@ -497,28 +508,44 @@ Broadcast message to all players with KRADLE tag.
|
|
|
497
508
|
|
|
498
509
|
```typescript
|
|
499
510
|
Actions.announce({
|
|
500
|
-
message:
|
|
511
|
+
message: JSONTextComponent; // Message (string or formatted object)
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// Simple string:
|
|
515
|
+
Actions.announce({ message: "Game starting!" });
|
|
516
|
+
|
|
517
|
+
// Formatted JSONTextComponent:
|
|
518
|
+
Actions.announce({
|
|
519
|
+
message: [
|
|
520
|
+
{ text: "Player ", color: "white" },
|
|
521
|
+
{ selector: "@s", color: "gold", bold: true },
|
|
522
|
+
{ text: " won the game!", color: "green" }
|
|
523
|
+
]
|
|
501
524
|
});
|
|
502
525
|
```
|
|
503
526
|
|
|
504
527
|
#### `Actions.tellraw(params)`
|
|
505
528
|
|
|
506
|
-
Send formatted message to specific target.
|
|
529
|
+
Send formatted message to specific target. **Note:** These messages are only visible to players in-game and will not appear in Kradle's interface. Use `Actions.announce` for messages that should be visible in Kradle.
|
|
507
530
|
|
|
508
531
|
```typescript
|
|
509
532
|
Actions.tellraw({
|
|
510
|
-
target: TargetNames;
|
|
511
|
-
message:
|
|
533
|
+
target: TargetNames; // "all", "self", or any selector
|
|
534
|
+
message: JSONTextComponent; // Message (string or formatted object)
|
|
512
535
|
});
|
|
513
536
|
|
|
514
|
-
//
|
|
537
|
+
// Examples:
|
|
515
538
|
Actions.tellraw({
|
|
516
539
|
target: "all",
|
|
517
540
|
message: ["Hello, ", { text: "world!", color: "gold", bold: true }]
|
|
518
541
|
});
|
|
519
542
|
Actions.tellraw({
|
|
520
543
|
target: "self",
|
|
521
|
-
message:
|
|
544
|
+
message: "You won!"
|
|
545
|
+
});
|
|
546
|
+
Actions.tellraw({
|
|
547
|
+
target: "self",
|
|
548
|
+
message: { text: "Critical hit!", color: "red", bold: true }
|
|
522
549
|
});
|
|
523
550
|
```
|
|
524
551
|
|
|
@@ -611,6 +638,39 @@ variables.my_diamond_count.set(count);
|
|
|
611
638
|
|
|
612
639
|
**Note:** This action creates a temporary variable internally using `Variable()` and uses `execute.store.result.score` with `clear` command (count 0) to count items without removing them from the inventory.
|
|
613
640
|
|
|
641
|
+
#### `Actions.getCurrentPlayerPosition()`
|
|
642
|
+
|
|
643
|
+
Get the current player's position as x, y, z Score variables. Must be called in a player context (e.g., inside `forEveryPlayer`, individual variables updaters, or when `@s` is a player). This is the prefered way of checking a player's position.
|
|
644
|
+
|
|
645
|
+
```typescript
|
|
646
|
+
Actions.getCurrentPlayerPosition(): { x: Score; y: Score; z: Score }
|
|
647
|
+
|
|
648
|
+
// Example - Check if player is above Y=100:
|
|
649
|
+
const pos = Actions.getCurrentPlayerPosition();
|
|
650
|
+
_.if(pos.y.greaterThan(100), () => {
|
|
651
|
+
Actions.announce({ message: "You reached the sky!" });
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// Example - Store position in custom variables:
|
|
655
|
+
const { x, y, z } = Actions.getCurrentPlayerPosition();
|
|
656
|
+
variables.player_x.set(x);
|
|
657
|
+
variables.player_y.set(y);
|
|
658
|
+
variables.player_z.set(z);
|
|
659
|
+
|
|
660
|
+
// Example - Check if player is in a specific area:
|
|
661
|
+
const pos = Actions.getCurrentPlayerPosition();
|
|
662
|
+
_.if(_.and(
|
|
663
|
+
pos.x.greaterThan(0),
|
|
664
|
+
pos.x.lowerThan(100),
|
|
665
|
+
pos.z.greaterThan(0),
|
|
666
|
+
pos.z.lowerThan(100)
|
|
667
|
+
), () => {
|
|
668
|
+
Actions.announce({ message: "You're in the zone!" });
|
|
669
|
+
});
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
**Note:** This returns integer coordinates (block position). The values are truncated from the player's exact floating-point position.
|
|
673
|
+
|
|
614
674
|
### Entities
|
|
615
675
|
|
|
616
676
|
#### `Actions.summonMultiple(params)`
|
|
@@ -1045,7 +1105,7 @@ createChallenge({
|
|
|
1045
1105
|
Actions.announce({ message: "First to kill 2 pigs wins!" });
|
|
1046
1106
|
},
|
|
1047
1107
|
init_participants: () => {
|
|
1048
|
-
Actions.give({ target: "
|
|
1108
|
+
Actions.give({ target: "all", item: "minecraft:iron_sword", count: 1 });
|
|
1049
1109
|
},
|
|
1050
1110
|
}))
|
|
1051
1111
|
.custom_events(({ pigs_farmed }) => [
|
|
@@ -1080,7 +1140,7 @@ createChallenge({
|
|
|
1080
1140
|
type: "individual",
|
|
1081
1141
|
objective_type: "dummy",
|
|
1082
1142
|
updater: (value) => {
|
|
1083
|
-
|
|
1143
|
+
value.set(Actions.getCurrentPlayerPosition().y)
|
|
1084
1144
|
},
|
|
1085
1145
|
},
|
|
1086
1146
|
max_height: {
|
|
@@ -1124,8 +1184,8 @@ createChallenge({
|
|
|
1124
1184
|
Actions.announce({ message: "Climb as high as you can!" });
|
|
1125
1185
|
},
|
|
1126
1186
|
init_participants: () => {
|
|
1127
|
-
Actions.give({ target: "
|
|
1128
|
-
Actions.give({ target: "
|
|
1187
|
+
Actions.give({ target: "all", item: "minecraft:cobblestone", count: 64 });
|
|
1188
|
+
Actions.give({ target: "all", item: "minecraft:cobblestone", count: 64 });
|
|
1129
1189
|
},
|
|
1130
1190
|
}))
|
|
1131
1191
|
.custom_events(() => [])
|
|
@@ -1176,9 +1236,9 @@ createChallenge({
|
|
|
1176
1236
|
Actions.announce({ message: "Last player standing wins!" });
|
|
1177
1237
|
},
|
|
1178
1238
|
init_participants: () => {
|
|
1179
|
-
Actions.give({ target: "
|
|
1180
|
-
Actions.give({ target: "
|
|
1181
|
-
Actions.give({ target: "
|
|
1239
|
+
Actions.give({ target: "all", item: "minecraft:stone_sword", count: 1 });
|
|
1240
|
+
Actions.give({ target: "all", item: "minecraft:leather_chestplate", count: 1 });
|
|
1241
|
+
Actions.give({ target: "all", item: "minecraft:cooked_beef", count: 10 });
|
|
1182
1242
|
},
|
|
1183
1243
|
}))
|
|
1184
1244
|
.custom_events(({ kills }) => [
|
|
@@ -1237,7 +1297,7 @@ createChallenge({
|
|
|
1237
1297
|
},
|
|
1238
1298
|
init_participants: () => {
|
|
1239
1299
|
// Different items based on role would be set via role-specific logic
|
|
1240
|
-
Actions.give({ target: "
|
|
1300
|
+
Actions.give({ target: "all", item: "minecraft:wooden_sword", count: 1 });
|
|
1241
1301
|
},
|
|
1242
1302
|
}))
|
|
1243
1303
|
.custom_events(() => [])
|
|
@@ -1301,7 +1361,7 @@ createChallenge({
|
|
|
1301
1361
|
Actions.announce({ message: "Capture the enemy flag and return to base!" });
|
|
1302
1362
|
},
|
|
1303
1363
|
init_participants: () => {
|
|
1304
|
-
Actions.give({ target: "
|
|
1364
|
+
Actions.give({ target: "all", item: "minecraft:iron_sword", count: 1 });
|
|
1305
1365
|
},
|
|
1306
1366
|
}))
|
|
1307
1367
|
.custom_events(({ captured_flag }) => [
|
|
@@ -1378,6 +1438,10 @@ current_y: {
|
|
|
1378
1438
|
type: "individual",
|
|
1379
1439
|
objective_type: "dummy",
|
|
1380
1440
|
updater: (value) => {
|
|
1441
|
+
// Prefered way: using the dedicated Action
|
|
1442
|
+
value.set(Actions.getCurrentPlayerPosition().y)
|
|
1443
|
+
|
|
1444
|
+
// Alternative way: using execute.store + data.get
|
|
1381
1445
|
execute.as("@s").store.result.score(value).run.data.get.entity("@s", "Pos[1]");
|
|
1382
1446
|
},
|
|
1383
1447
|
}
|
|
@@ -260,17 +260,19 @@ Runs a challenge with configured participants.
|
|
|
260
260
|
```bash
|
|
261
261
|
kradle challenge run <challenge-name>
|
|
262
262
|
kradle challenge run <challenge-name> --studio
|
|
263
|
+
kradle challenge run <team-name>:<challenge-name>
|
|
263
264
|
```
|
|
264
265
|
|
|
265
266
|
**Arguments:**
|
|
266
267
|
| Argument | Description | Required |
|
|
267
268
|
|----------|-------------|----------|
|
|
268
|
-
| `challenge-name` | Challenge to run | Yes |
|
|
269
|
+
| `challenge-name` | Challenge to run. Can be a short slug (e.g., `my-challenge`) or include a team/user namespace (e.g., `team-name:my-challenge`). The namespace is useful for running public challenges owned by other teams. If no namespace is provided, it defaults to the user's own namespace. | Yes |
|
|
269
270
|
|
|
270
271
|
**Flags:**
|
|
271
272
|
| Flag | Description | Default |
|
|
272
273
|
|------|-------------|---------|
|
|
273
274
|
| `--studio` | Run in local studio environment instead of production | false |
|
|
275
|
+
| `--open` | Open the run URL in the browser | false |
|
|
274
276
|
|
|
275
277
|
**Prerequisites:**
|
|
276
278
|
- `template-run.json` must exist in project root with participant configuration
|
|
@@ -294,9 +296,12 @@ kradle challenge run <challenge-name> --studio
|
|
|
294
296
|
|
|
295
297
|
**Examples:**
|
|
296
298
|
```bash
|
|
297
|
-
# Run in production
|
|
299
|
+
# Run your own challenge in production
|
|
298
300
|
kradle challenge run my-challenge
|
|
299
301
|
|
|
302
|
+
# Run a public challenge from another team
|
|
303
|
+
kradle challenge run team-kradle:battle-royale
|
|
304
|
+
|
|
300
305
|
# Run in local studio
|
|
301
306
|
kradle challenge run my-challenge --studio
|
|
302
307
|
```
|