@kradle/challenges 0.0.2 → 0.2.0
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/AGENTS.md +273 -0
- package/CLAUDE.md +1 -0
- package/LLM_README.md +1380 -0
- package/README.md +498 -1
- package/dist/actions.d.ts +31 -21
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +77 -85
- package/dist/actions.js.map +1 -1
- package/dist/challenge.js +12 -12
- package/dist/challenge.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -6
- package/dist/constants.js.map +1 -1
- package/dist/types.d.ts +2 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/actions.ts +86 -94
- package/src/challenge.ts +12 -12
- package/src/constants.ts +4 -6
- package/src/types.ts +2 -3
package/README.md
CHANGED
|
@@ -1 +1,498 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- This file is for human consumption. If you are an LLM or any AI Agent, make sure to read LLM_README.md for an exhaustive explanation of this package. -->
|
|
2
|
+
|
|
3
|
+
# @kradle/challenges
|
|
4
|
+
|
|
5
|
+
A TypeScript framework for creating Minecraft datapack-based challenges with event-driven game logic, score tracking, and player role management. Built on top of [Sandstone](https://sandstone.dev/).
|
|
6
|
+
|
|
7
|
+
## Getting started
|
|
8
|
+
|
|
9
|
+
We strongly recommend using [Kradle's CLI](https://github.com/kradle-ai/cli) to create challenges with the CLI. Make sure to read the CLI's README
|
|
10
|
+
|
|
11
|
+
If you still want to perform a manual installation, you also need to install the Sandstone peer-dependency:
|
|
12
|
+
```bash
|
|
13
|
+
npm install @kradle/challenges sandstone@0.14.0-alpha.13
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
Like for installation, we strongly recommend using Kradle's CLI to bootstrap a challenge:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Will create a challenge in challenges/my-challenge/
|
|
22
|
+
kradle challenge create my-challenge
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { createChallenge, Actions } from "@kradle/challenges";
|
|
27
|
+
|
|
28
|
+
createChallenge({
|
|
29
|
+
name: "my-challenge",
|
|
30
|
+
kradle_challenge_path: "./output",
|
|
31
|
+
roles: ["player"] as const,
|
|
32
|
+
GAME_DURATION: 2 * 60 * 20, // 2 minutes in ticks
|
|
33
|
+
custom_variables: {
|
|
34
|
+
diamonds_collected: {
|
|
35
|
+
type: "individual",
|
|
36
|
+
objective_type: "minecraft.picked_up:minecraft.diamond",
|
|
37
|
+
default: 0,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
.events(({ diamonds_collected }) => ({
|
|
42
|
+
start_challenge: () => {
|
|
43
|
+
Actions.setTime({ time: "day" });
|
|
44
|
+
Actions.announce({ message: "Collect as many diamonds as possible!" });
|
|
45
|
+
},
|
|
46
|
+
init_participants: () => {
|
|
47
|
+
Actions.give({ item: "iron_pickaxe", count: 1 });
|
|
48
|
+
},
|
|
49
|
+
}))
|
|
50
|
+
.custom_events(({ diamonds_collected }) => [
|
|
51
|
+
{
|
|
52
|
+
score: diamonds_collected,
|
|
53
|
+
target: 10,
|
|
54
|
+
mode: "fire_once",
|
|
55
|
+
actions: () => {
|
|
56
|
+
Actions.announce({ message: "Someone collected 10 diamonds!" });
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
])
|
|
60
|
+
.end_condition(({ game_timer }) => game_timer.greaterThan(2 * 60 * 20))
|
|
61
|
+
.win_conditions(({ diamonds_collected }, { player }) => ({
|
|
62
|
+
[player]: diamonds_collected.greaterThan(0),
|
|
63
|
+
}));
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## API Overview
|
|
67
|
+
|
|
68
|
+
### `createChallenge(config)`
|
|
69
|
+
|
|
70
|
+
Creates a new challenge with the specified configuration.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
createChallenge({
|
|
74
|
+
name: string; // Challenge name (used for datapack)
|
|
75
|
+
kradle_challenge_path: string; // Output directory for generated datapack
|
|
76
|
+
roles: readonly string[]; // Player roles (e.g., ["attacker", "defender"])
|
|
77
|
+
GAME_DURATION?: number; // Duration in ticks (default: 6000 = 5 minutes)
|
|
78
|
+
custom_variables: Record<string, VariableDefinition>;
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Fluent Builder Methods
|
|
83
|
+
|
|
84
|
+
The challenge builder uses a fluent API:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
createChallenge(config)
|
|
88
|
+
.events(callback) // Define lifecycle event handlers
|
|
89
|
+
.custom_events(callback) // Define score/advancement-triggered events
|
|
90
|
+
.end_condition(callback) // Define when the game ends
|
|
91
|
+
.win_conditions(callback) // Define win conditions per role
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Variables
|
|
95
|
+
|
|
96
|
+
Variables are the core mechanism for tracking game state. All variables are automatically updated each tick.
|
|
97
|
+
|
|
98
|
+
### Built-in Variables
|
|
99
|
+
|
|
100
|
+
These variables are always available:
|
|
101
|
+
|
|
102
|
+
| Variable | Type | Description |
|
|
103
|
+
|----------|------|-------------|
|
|
104
|
+
| `death_count` | individual | Number of times the player has died |
|
|
105
|
+
| `has_never_died` | individual | 1 if player hasn't died, 0 otherwise |
|
|
106
|
+
| `alive_players` | global | Count of living participants |
|
|
107
|
+
| `main_score` | individual | Primary score displayed on sidebar |
|
|
108
|
+
| `game_timer` | global | Ticks elapsed since game start |
|
|
109
|
+
| `game_state` | global | Current state (0=CREATED, 1=OFF, 2=ON) |
|
|
110
|
+
| `player_count` | global | Total number of participants |
|
|
111
|
+
| `player_number` | individual | Unique player ID (1 to N) |
|
|
112
|
+
|
|
113
|
+
### Custom Variable Types
|
|
114
|
+
|
|
115
|
+
#### Individual Variables (per-player)
|
|
116
|
+
|
|
117
|
+
Track values for each player separately.
|
|
118
|
+
|
|
119
|
+
**Objective-based** (uses Minecraft statistics):
|
|
120
|
+
```typescript
|
|
121
|
+
pigs_killed: {
|
|
122
|
+
type: "individual",
|
|
123
|
+
objective_type: "minecraft.killed:minecraft.pig",
|
|
124
|
+
default: 0,
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Dummy** (computed values):
|
|
129
|
+
```typescript
|
|
130
|
+
current_height: {
|
|
131
|
+
type: "individual",
|
|
132
|
+
objective_type: "dummy",
|
|
133
|
+
updater: (value) => {
|
|
134
|
+
execute.as("@s").store.result.score(value).run.data.get.entity("@s", "Pos[1]");
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### Global Variables (shared)
|
|
140
|
+
|
|
141
|
+
Track values across all players.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
max_score: {
|
|
145
|
+
type: "global",
|
|
146
|
+
hidden: false, // optional: hide from scoreboard
|
|
147
|
+
default: 0,
|
|
148
|
+
updater: (value, { main_score }) => {
|
|
149
|
+
value.set(0);
|
|
150
|
+
forEveryPlayer(() => {
|
|
151
|
+
_.if(main_score.greaterThan(value), () => {
|
|
152
|
+
value.set(main_score);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Updater Functions
|
|
160
|
+
|
|
161
|
+
Updaters run every tick and receive `(currentValue, allVariables)`:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
updater: (value, { main_score, death_count, game_timer }) => {
|
|
165
|
+
// Set value based on other variables
|
|
166
|
+
value.set(0);
|
|
167
|
+
_.if(main_score.greaterThan(10), () => {
|
|
168
|
+
value.set(1);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
If you track a Minecraft objective, you do not need an updater!
|
|
174
|
+
|
|
175
|
+
## Events
|
|
176
|
+
|
|
177
|
+
### Lifecycle Events
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
.events((variables, roles) => ({
|
|
181
|
+
start_challenge: () => {
|
|
182
|
+
// Runs once when the challenge starts
|
|
183
|
+
Actions.setTime({ time: "day" });
|
|
184
|
+
Actions.announce({ message: "Game starting!" });
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
init_participants: () => {
|
|
188
|
+
// Runs once per player after challenge starts
|
|
189
|
+
Actions.give({ item: "diamond_sword", count: 1 });
|
|
190
|
+
Actions.setAttribute({ attribute: "max_health", value: 40 });
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
on_tick: () => {
|
|
194
|
+
// Runs every tick for each player
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
end_challenge: () => {
|
|
198
|
+
// Runs when the challenge ends
|
|
199
|
+
Actions.announce({ message: "Game over!" });
|
|
200
|
+
},
|
|
201
|
+
}))
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Custom Events
|
|
205
|
+
|
|
206
|
+
Custom events trigger actions based on score thresholds or Minecraft advancements.
|
|
207
|
+
|
|
208
|
+
#### Score-based events
|
|
209
|
+
|
|
210
|
+
Score events watch a variable and trigger when it reaches a target value.
|
|
211
|
+
|
|
212
|
+
- **`score`**: The variable to watch
|
|
213
|
+
- **`target`** (optional): The target value. If omitted, triggers on any score change
|
|
214
|
+
- **`mode`**:
|
|
215
|
+
- `"fire_once"`: Triggers once when the score reaches the target (per player for individual variables)
|
|
216
|
+
- `"repeatable"`: Triggers every tick while the score is at target
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
.custom_events((variables, roles) => [
|
|
220
|
+
{
|
|
221
|
+
score: variables.diamonds,
|
|
222
|
+
target: 5,
|
|
223
|
+
mode: "fire_once",
|
|
224
|
+
actions: () => {
|
|
225
|
+
Actions.announce({ message: "Someone collected 5 diamonds!" });
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
])
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
If `target` is omitted, the event triggers whenever the score changes (useful for reacting to any increment).
|
|
232
|
+
|
|
233
|
+
#### Advancement-based events
|
|
234
|
+
|
|
235
|
+
Advancement events trigger when a Minecraft advancement criterion is met (e.g., player attacks, item picked up). The criteria follow the [Minecraft Advancement JSON format](https://minecraft.fandom.com/wiki/Advancement/JSON_format).
|
|
236
|
+
|
|
237
|
+
- **`criteria`**: Array of advancement triggers with optional conditions
|
|
238
|
+
- **`mode`**:
|
|
239
|
+
- `"fire_once"`: Triggers once per player when the advancement is granted
|
|
240
|
+
- `"repeatable"`: Triggers every time the advancement criterion is met (advancement is auto-revoked to allow re-triggering)
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
.custom_events((variables, roles) => [
|
|
244
|
+
{
|
|
245
|
+
criteria: [
|
|
246
|
+
{
|
|
247
|
+
trigger: "minecraft:player_hurt_entity",
|
|
248
|
+
conditions: {
|
|
249
|
+
entity: { type: "minecraft:player" } // Only PvP hits
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
],
|
|
253
|
+
mode: "repeatable",
|
|
254
|
+
actions: () => {
|
|
255
|
+
Actions.increment({ score: variables.pvp_hits });
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
])
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## End Conditions
|
|
262
|
+
|
|
263
|
+
Define when the game ends:
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
.end_condition(({ objective_complete }) => objective_complete.equalTo(1))
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Multiple conditions can be combined:
|
|
270
|
+
```typescript
|
|
271
|
+
.end_condition(({ alive_players, objective_complete }) =>
|
|
272
|
+
_.or(
|
|
273
|
+
alive_players.equalTo(1),
|
|
274
|
+
objective_complete.equalTo(1)
|
|
275
|
+
)
|
|
276
|
+
)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Ending conditions are evaluated once per tick, at the global level (not individually). It means you should not check for individual variables here - instead, you should aggregate these individual variables into a global custom variable, that you then check in the ending condition.
|
|
280
|
+
|
|
281
|
+
## Win Conditions
|
|
282
|
+
|
|
283
|
+
Define how winners are determined per role:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
.win_conditions((variables, { attacker, defender }) => ({
|
|
287
|
+
[attacker]: variables.kills.greaterOrEqualThan(5),
|
|
288
|
+
[defender]: variables.survived.equalTo(1),
|
|
289
|
+
}))
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Actions
|
|
293
|
+
|
|
294
|
+
Pre-built actions for common game operations:
|
|
295
|
+
|
|
296
|
+
### Communication
|
|
297
|
+
```typescript
|
|
298
|
+
Actions.announce({ message: "Hello everyone!" });
|
|
299
|
+
Actions.tellraw({ target: "@a", message: { text: "Hello", color: "gold" } });
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Items & Inventory
|
|
303
|
+
```typescript
|
|
304
|
+
Actions.give({ item: "diamond_sword", count: 1 });
|
|
305
|
+
Actions.give({ item: "diamond_sword", count: 1, nbt: { Enchantments: [...] } });
|
|
306
|
+
Actions.giveLoot({ loot_table: "minecraft:chests/simple_dungeon", count: 3 });
|
|
307
|
+
Actions.clear({ item: "diamond" });
|
|
308
|
+
|
|
309
|
+
// Count items - returns a Score variable
|
|
310
|
+
const count = Actions.countItems({ target: "self", item: "minecraft:diamond" });
|
|
311
|
+
// Use in conditions or set to custom variables
|
|
312
|
+
_.if(count.greaterThan(5), () => { /* ... */ });
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Entities
|
|
316
|
+
```typescript
|
|
317
|
+
Actions.summonMultiple({ entity: "zombie", count: 5, pos: [0, 64, 0] });
|
|
318
|
+
Actions.kill({ target: "@e[type=zombie]" });
|
|
319
|
+
Actions.teleport({ target: "@s", pos: [0, 100, 0] });
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### World
|
|
323
|
+
```typescript
|
|
324
|
+
Actions.setBlock({ pos: [0, 64, 0], block: "diamond_block" });
|
|
325
|
+
Actions.fill({
|
|
326
|
+
start: [0, 64, 0],
|
|
327
|
+
end: [10, 64, 10],
|
|
328
|
+
block: "stone",
|
|
329
|
+
mode: "fill" // "fill", "line", or "pyramid"
|
|
330
|
+
});
|
|
331
|
+
Actions.setTime({ time: "day" }); // or "night" or specific tick value
|
|
332
|
+
Actions.gamerule({ rule: "doDaylightCycle", value: false });
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Scores
|
|
336
|
+
```typescript
|
|
337
|
+
Actions.set({ score: variables.main_score, value: 10 });
|
|
338
|
+
Actions.set({ score: variables.main_score, source: variables.diamonds });
|
|
339
|
+
Actions.increment({ score: variables.counter });
|
|
340
|
+
Actions.decrement({ score: variables.counter });
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Player Attributes
|
|
344
|
+
```typescript
|
|
345
|
+
Actions.setAttribute({ attribute: "max_health", value: 40 });
|
|
346
|
+
Actions.setAttribute({ attribute: "movement_speed", value: 0.2 });
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Custom Commands
|
|
350
|
+
```typescript
|
|
351
|
+
Actions.custom({ action: () => {
|
|
352
|
+
// Any Sandstone code here
|
|
353
|
+
execute.as("@a").run.effect.give("@s", "speed", 10, 1);
|
|
354
|
+
}});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Utilities
|
|
358
|
+
|
|
359
|
+
### `forEveryPlayer(callback)`
|
|
360
|
+
|
|
361
|
+
Execute code for each participant at their location:
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
import { forEveryPlayer } from "@kradle/challenges";
|
|
365
|
+
|
|
366
|
+
forEveryPlayer(() => {
|
|
367
|
+
// Runs as each player, at their position
|
|
368
|
+
execute.run.particle("minecraft:flame", rel(0, 1, 0));
|
|
369
|
+
});
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Example: Battle Royale
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { createChallenge, Actions, forEveryPlayer } from "@kradle/challenges";
|
|
376
|
+
import { _, Selector } from "sandstone";
|
|
377
|
+
|
|
378
|
+
createChallenge({
|
|
379
|
+
name: "battle-royale",
|
|
380
|
+
kradle_challenge_path: "./output",
|
|
381
|
+
roles: ["fighter"] as const,
|
|
382
|
+
GAME_DURATION: 5 * 60 * 20,
|
|
383
|
+
custom_variables: {
|
|
384
|
+
kills: {
|
|
385
|
+
type: "individual",
|
|
386
|
+
objective_type: "playerKillCount",
|
|
387
|
+
default: 0,
|
|
388
|
+
},
|
|
389
|
+
sole_survivor: {
|
|
390
|
+
type: "individual",
|
|
391
|
+
updater: (value, { alive_players, has_never_died }) => {
|
|
392
|
+
value.set(0);
|
|
393
|
+
_.if(_.and(
|
|
394
|
+
alive_players.equalTo(1),
|
|
395
|
+
has_never_died.equalTo(1)
|
|
396
|
+
), () => {
|
|
397
|
+
value.set(1);
|
|
398
|
+
});
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
})
|
|
403
|
+
.events(() => ({
|
|
404
|
+
start_challenge: () => {
|
|
405
|
+
Actions.setTime({ time: "day" });
|
|
406
|
+
Actions.announce({ message: "Last player standing wins!" });
|
|
407
|
+
},
|
|
408
|
+
init_participants: () => {
|
|
409
|
+
Actions.give({ item: "stone_sword", count: 1 });
|
|
410
|
+
Actions.give({ item: "leather_chestplate", count: 1 });
|
|
411
|
+
},
|
|
412
|
+
}))
|
|
413
|
+
.custom_events(({ kills }) => [
|
|
414
|
+
{
|
|
415
|
+
score: kills,
|
|
416
|
+
target: 1,
|
|
417
|
+
mode: "fire_once",
|
|
418
|
+
actions: () => {
|
|
419
|
+
Actions.announce({ message: "First blood!" });
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
])
|
|
423
|
+
.end_condition(({ alive_players }) => alive_players.equalTo(1))
|
|
424
|
+
.win_conditions(({ sole_survivor }, { fighter }) => ({
|
|
425
|
+
[fighter]: sole_survivor.equalTo(1),
|
|
426
|
+
}));
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Example: Capture the Flag
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { createChallenge, Actions } from "@kradle/challenges";
|
|
433
|
+
import { _, Selector, rel } from "sandstone";
|
|
434
|
+
import type { Score } from "sandstone";
|
|
435
|
+
|
|
436
|
+
createChallenge({
|
|
437
|
+
name: "capture-the-flag",
|
|
438
|
+
kradle_challenge_path: "./output",
|
|
439
|
+
roles: ["red_team", "blue_team"] as const,
|
|
440
|
+
GAME_DURATION: 5 * 60 * 20,
|
|
441
|
+
custom_variables: {
|
|
442
|
+
holds_enemy_flag: {
|
|
443
|
+
type: "individual",
|
|
444
|
+
updater: (value: Score) => {
|
|
445
|
+
value.set(0);
|
|
446
|
+
// Check if player holds the enemy team's banner
|
|
447
|
+
_.if(Selector("@s", {
|
|
448
|
+
nbt: { Inventory: [{ id: "minecraft:red_banner" }] }
|
|
449
|
+
}), () => {
|
|
450
|
+
value.set(1);
|
|
451
|
+
});
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
at_home_base: {
|
|
455
|
+
type: "individual",
|
|
456
|
+
updater: (value: Score) => {
|
|
457
|
+
value.set(0);
|
|
458
|
+
_.if(_.block(rel(0, -1, 0), "minecraft:blue_wool"), () => {
|
|
459
|
+
value.set(1);
|
|
460
|
+
});
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
captured_flag: {
|
|
464
|
+
type: "individual",
|
|
465
|
+
updater: (value, { holds_enemy_flag, at_home_base }) => {
|
|
466
|
+
value.set(0);
|
|
467
|
+
_.if(_.and(
|
|
468
|
+
holds_enemy_flag.equalTo(1),
|
|
469
|
+
at_home_base.equalTo(1)
|
|
470
|
+
), () => {
|
|
471
|
+
value.set(1);
|
|
472
|
+
});
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
})
|
|
477
|
+
.events(() => ({
|
|
478
|
+
start_challenge: () => {
|
|
479
|
+
Actions.announce({ message: "Capture the enemy flag!" });
|
|
480
|
+
},
|
|
481
|
+
}))
|
|
482
|
+
.custom_events(({ captured_flag }) => [
|
|
483
|
+
{
|
|
484
|
+
score: captured_flag,
|
|
485
|
+
target: 1,
|
|
486
|
+
mode: "fire_once",
|
|
487
|
+
actions: () => {
|
|
488
|
+
Actions.announce({ message: "Flag captured!" });
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
])
|
|
492
|
+
.end_condition(({ captured_flag }) => captured_flag.equalTo(1))
|
|
493
|
+
.win_conditions(({ captured_flag }, { red_team, blue_team }) => ({
|
|
494
|
+
[red_team]: captured_flag.equalTo(1),
|
|
495
|
+
[blue_team]: captured_flag.equalTo(0),
|
|
496
|
+
}));
|
|
497
|
+
```
|
|
498
|
+
|
package/dist/actions.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type { ATTRIBUTES, BLOCKS, ENTITY_TYPES, ITEMS } from "sandstone/argument
|
|
|
3
3
|
import type { LiteralStringUnion } from "./utils";
|
|
4
4
|
export type TargetNames = LiteralStringUnion<"all" | "self"> | SelectorClass<any, any>;
|
|
5
5
|
export declare function mapTarget(target: string | SelectorClass): SelectorClass<any, any> | string;
|
|
6
|
-
export type Action = () => unknown;
|
|
7
6
|
export declare const Actions: {
|
|
8
7
|
/**
|
|
9
8
|
* Send a chat message to everyone.
|
|
@@ -11,20 +10,20 @@ export declare const Actions: {
|
|
|
11
10
|
*/
|
|
12
11
|
announce: ({ message }: {
|
|
13
12
|
message: JSONTextComponent;
|
|
14
|
-
}) =>
|
|
13
|
+
}) => void;
|
|
15
14
|
/**
|
|
16
15
|
* Clear the inventory of a target.
|
|
17
16
|
* @param {TargetNames} target - The target to clear the inventory of.
|
|
18
17
|
*/
|
|
19
18
|
clear: ({ target }: {
|
|
20
19
|
target: TargetNames;
|
|
21
|
-
}) =>
|
|
20
|
+
}) => void;
|
|
22
21
|
/**
|
|
23
22
|
* Custom action allowing to run any Sandstone command.
|
|
24
23
|
*
|
|
25
24
|
* @param {() => void} callback - The function to execute.
|
|
26
25
|
*/
|
|
27
|
-
custom: (callback: () => void) =>
|
|
26
|
+
custom: (callback: () => void) => void;
|
|
28
27
|
/**
|
|
29
28
|
* Fill a region with a block.
|
|
30
29
|
* @param {BLOCKS} block - The block to fill the region with.
|
|
@@ -46,7 +45,7 @@ export declare const Actions: {
|
|
|
46
45
|
z2: number;
|
|
47
46
|
absolute: boolean;
|
|
48
47
|
mode: "fill" | "line" | "pyramid";
|
|
49
|
-
}) =>
|
|
48
|
+
}) => void;
|
|
50
49
|
/**
|
|
51
50
|
* Give an item to a target.
|
|
52
51
|
* @param {ITEMS} item - The item to give.
|
|
@@ -57,7 +56,7 @@ export declare const Actions: {
|
|
|
57
56
|
item: ITEMS;
|
|
58
57
|
target: TargetNames;
|
|
59
58
|
count?: number;
|
|
60
|
-
}) =>
|
|
59
|
+
}) => void;
|
|
61
60
|
/**
|
|
62
61
|
* Give loot to a target with a weighted chance for selecting one of the items.
|
|
63
62
|
* @param {{ name: ITEMS, count: number, weight: number }[]} items - The items to give.
|
|
@@ -70,7 +69,7 @@ export declare const Actions: {
|
|
|
70
69
|
weight: number;
|
|
71
70
|
}];
|
|
72
71
|
target: TargetNames;
|
|
73
|
-
}) =>
|
|
72
|
+
}) => void;
|
|
74
73
|
/**
|
|
75
74
|
* Set a gamerule.
|
|
76
75
|
* @param {GAMERULES} rule - The name of the gamerule.
|
|
@@ -79,14 +78,14 @@ export declare const Actions: {
|
|
|
79
78
|
gamerule: ({ rule, value }: {
|
|
80
79
|
rule: GAMERULES;
|
|
81
80
|
value: boolean | number;
|
|
82
|
-
}) =>
|
|
81
|
+
}) => void;
|
|
83
82
|
/**
|
|
84
83
|
* Kill entities matching a selector.
|
|
85
84
|
* @param {SelectorArgument} selector - The entities to kill.
|
|
86
85
|
*/
|
|
87
86
|
kill: ({ selector }: {
|
|
88
87
|
selector: TargetNames;
|
|
89
|
-
}) =>
|
|
88
|
+
}) => void;
|
|
90
89
|
/**
|
|
91
90
|
* Set an attribute for a target.
|
|
92
91
|
* @param {ATTRIBUTES} attribute_ - The attribute to set.
|
|
@@ -97,14 +96,14 @@ export declare const Actions: {
|
|
|
97
96
|
attribute_: ATTRIBUTES;
|
|
98
97
|
value: number;
|
|
99
98
|
target: TargetNames;
|
|
100
|
-
}) =>
|
|
99
|
+
}) => void;
|
|
101
100
|
/**
|
|
102
101
|
* Set the time of day.
|
|
103
102
|
* @param {'day' | 'night'} time_ - The time to set.
|
|
104
103
|
*/
|
|
105
104
|
setTime: ({ time }: {
|
|
106
105
|
time: "day" | "night";
|
|
107
|
-
}) =>
|
|
106
|
+
}) => void;
|
|
108
107
|
/**
|
|
109
108
|
* Summon multiple entities at a specific location.
|
|
110
109
|
*/
|
|
@@ -115,14 +114,14 @@ export declare const Actions: {
|
|
|
115
114
|
y: number;
|
|
116
115
|
z: number;
|
|
117
116
|
absolute: boolean;
|
|
118
|
-
}) =>
|
|
117
|
+
}) => void;
|
|
119
118
|
/**
|
|
120
119
|
* Set the end state of the challenge.
|
|
121
120
|
* @param {string} end_state - The end state to set.
|
|
122
121
|
*/
|
|
123
122
|
setEndState: ({ endState }: {
|
|
124
123
|
endState: string;
|
|
125
|
-
}) =>
|
|
124
|
+
}) => void;
|
|
126
125
|
/**
|
|
127
126
|
* Set a block at a specific location.
|
|
128
127
|
*/
|
|
@@ -132,7 +131,7 @@ export declare const Actions: {
|
|
|
132
131
|
y: number;
|
|
133
132
|
z: number;
|
|
134
133
|
absolute: boolean;
|
|
135
|
-
}) =>
|
|
134
|
+
}) => void;
|
|
136
135
|
/**
|
|
137
136
|
* Teleport entities to a specific location.
|
|
138
137
|
* @param {TargetNames} target - The entities to teleport.
|
|
@@ -147,7 +146,7 @@ export declare const Actions: {
|
|
|
147
146
|
y: number;
|
|
148
147
|
z: number;
|
|
149
148
|
absolute: boolean;
|
|
150
|
-
}) =>
|
|
149
|
+
}) => void;
|
|
151
150
|
/**
|
|
152
151
|
* Send a chat message to a target.
|
|
153
152
|
* @param {string[]} message - The message to send.
|
|
@@ -156,21 +155,21 @@ export declare const Actions: {
|
|
|
156
155
|
tellraw: ({ message, target }: {
|
|
157
156
|
message: string[];
|
|
158
157
|
target: TargetNames;
|
|
159
|
-
}) =>
|
|
158
|
+
}) => void;
|
|
160
159
|
/**
|
|
161
160
|
* Increment a score variable by 1.
|
|
162
161
|
* @param variable - The score variable to increment.
|
|
163
162
|
*/
|
|
164
163
|
increment: ({ variable }: {
|
|
165
164
|
variable: Score;
|
|
166
|
-
}) =>
|
|
165
|
+
}) => void;
|
|
167
166
|
/**
|
|
168
167
|
* Decrement a score variable by 1.
|
|
169
168
|
* @param variable - The score variable to decrement.
|
|
170
169
|
*/
|
|
171
170
|
decrement: ({ variable }: {
|
|
172
171
|
variable: Score;
|
|
173
|
-
}) =>
|
|
172
|
+
}) => void;
|
|
174
173
|
/**
|
|
175
174
|
* Set a score variable to a specific value.
|
|
176
175
|
* @param variable - The score variable to set.
|
|
@@ -179,7 +178,7 @@ export declare const Actions: {
|
|
|
179
178
|
set: ({ variable, value }: {
|
|
180
179
|
variable: Score;
|
|
181
180
|
value: number | Score;
|
|
182
|
-
}) =>
|
|
181
|
+
}) => void;
|
|
183
182
|
/**
|
|
184
183
|
* log a message with the watcher
|
|
185
184
|
* @param {string} message - The message to send.
|
|
@@ -190,7 +189,7 @@ export declare const Actions: {
|
|
|
190
189
|
message: string;
|
|
191
190
|
variable: Score;
|
|
192
191
|
store: boolean;
|
|
193
|
-
}) =>
|
|
192
|
+
}) => void;
|
|
194
193
|
/**
|
|
195
194
|
* Summon an item at a specific location.
|
|
196
195
|
* @param {ITEMS} item - The item to summon.
|
|
@@ -205,6 +204,17 @@ export declare const Actions: {
|
|
|
205
204
|
y: number;
|
|
206
205
|
z: number;
|
|
207
206
|
absolute: boolean;
|
|
208
|
-
}) =>
|
|
207
|
+
}) => void;
|
|
208
|
+
/**
|
|
209
|
+
* Count the number of a specific item in a target's inventory.
|
|
210
|
+
* @param params - The parameters object.
|
|
211
|
+
* @param params.target - The target to count items for.
|
|
212
|
+
* @param params.item - The item to count.
|
|
213
|
+
* @returns The variable containing the item count.
|
|
214
|
+
*/
|
|
215
|
+
countItems: ({ target, item }: {
|
|
216
|
+
target: TargetNames;
|
|
217
|
+
item: ITEMS;
|
|
218
|
+
}) => Score<string | undefined>;
|
|
209
219
|
};
|
|
210
220
|
//# sourceMappingURL=actions.d.ts.map
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,EAMN,KAAK,SAAS,EAGd,KAAK,iBAAiB,EAOtB,KAAK,KAAK,EAEV,aAAa,
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
|