Skip to content

Commit 5b01ac1

Browse files
committed
Add startup scripts guide & event-side docs
1 parent 4a10b10 commit 5b01ac1

35 files changed

Lines changed: 1428 additions & 113 deletions
99 KB
Loading
34.6 KB
Loading
89.1 KB
Loading
46.1 KB
Loading
46.1 KB
Loading

docs/en/ide.mdx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,26 @@ When the Project panel is focused, these shortcuts are available:
3737

3838
![Project tree and context menu](/hollowengine/pictures/ide/project-tree.webp)
3939

40+
## Creating scripts
41+
42+
Right-clicking the `scripts` folder or any folder inside it shows the **New Script** item. Hover over it and pick a type:
43+
44+
| Item | File | What it contains |
45+
|--------------------------|---------------------------------------|----------------------------------------------------|
46+
| **Script** | `.kts` | a function and a call to it |
47+
| **Server Reload Script** | `.reload.kts` | a chat greeting for joining players |
48+
| **Client Reload Script** | `.reload.kts` with `@file:ClientSide` | a line of text on the HUD |
49+
| **Startup Script** | `.startup.kts` | an item registered under the file's name |
50+
| **Node Script** | `.node.kts` | start, stop, and once-a-second handlers |
51+
| **UI Script** | `.ui.kts` | a simple screen |
52+
| **Dialogue** | `.story` | a dialogue with two answers |
53+
54+
Then enter the file name. The extension can be omitted, the IDE adds it. The new file opens in the editor right away with a working example to start from.
55+
56+
![The new script menu](/hollowengine/pictures/ide/new-script-menu.webp)
57+
58+
The item is only offered inside `scripts`, because the engine loads scripts and dialogues from there only.
59+
4060
## Code editor
4161

4262
Opening `.kts`, `.story`, `.hss`, and other supported text files starts the built-in editor. Depending on the file type, it provides syntax highlighting, diagnostics, completion, signature help, inlay hints, and navigation. Diagnostics are shown in the editor and in a resizable problems panel.
@@ -59,8 +79,9 @@ Useful editor shortcuts:
5979

6080
Saving a file writes it to the `hollowengine` directory. What must be reloaded depends on the file:
6181

62-
- use **File > Reload Client Resources** or `F3 + T` for models, textures, HSS, UI declarations, and other client resources;
63-
- use **File > Reload Server Resources** or `/reload` for datapack content and reloadable server scripts;
82+
- use **File > Reload Client Resources** or `F3 + T` for models, textures, HSS, UI declarations, client reloadable scripts (`@file:ClientSide`), and other client resources;
83+
- use **File > Reload Server Resources** or `/reload` for datapack content and server reloadable scripts;
84+
- `.startup.kts` changes only apply after restarting the game;
6485
- ordinary `.kts` scripts are started explicitly with `/hollowengine scripting run <path>`.
6586

6687
The compiler addon is required to compile edited scripts. A modpack can instead ship scripts that were compiled ahead of time.

docs/en/scripting/events/block_events.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ order: 3
1111

1212
## Placement
1313

14+
**Side:** both sides
15+
1416
*This event can be canceled (`event.isCanceled = true`).*
1517

1618
```kotlin
@@ -26,6 +28,8 @@ fun onBlockPlace(event: BlockEvent.Placed) {
2628

2729
## Breaking
2830

31+
**Side:** server
32+
2933
*This event can be canceled (`event.isCanceled = true`).*
3034

3135
```kotlin
@@ -42,6 +46,8 @@ fun onBlockBreak(event: BlockEvent.Break) {
4246

4347
## Updates
4448

49+
**Side:** server
50+
4551
*This event can be canceled (`event.isCanceled = true`).*
4652

4753
```kotlin

docs/en/scripting/events/entity_events.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ order: 4
1111

1212
## Spawned in the world
1313

14+
**Side:** server
15+
1416
```kotlin
1517
@SubscribeEvent
1618
fun onEntitySpawn(event: EntityLoadedEvent) {
@@ -23,6 +25,8 @@ fun onEntitySpawn(event: EntityLoadedEvent) {
2325

2426
## Entity death
2527

28+
**Side:** server
29+
2630
*This event can be canceled (`event.isCanceled = true`).*
2731

2832
```kotlin
@@ -37,6 +41,8 @@ fun onEntitySpawn(event: LivingEntityDeathEvent) {
3741

3842
## Moving between dimensions
3943

44+
**Side:** server
45+
4046
```kotlin
4147
@SubscribeEvent
4248
fun onEntityTeleport(event: EntityEvent.ChangeDimension) {
@@ -55,6 +61,8 @@ Typed [`.data`](/docs/hollowengine/scripting/npc/data) carries over on its own,
5561

5662
## Taking damage
5763

64+
**Side:** server
65+
5866
*This event can be canceled (`event.isCanceled = true`).*
5967

6068
```kotlin
@@ -70,6 +78,8 @@ fun onEntityHurt(event: EntityEvent.Hurt) {
7078

7179
## Entity breeding
7280

81+
**Side:** server
82+
7383
*This event can be canceled (`event.isCanceled = true`).*
7484

7585
```kotlin

docs/en/scripting/events/index.mdx

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,66 @@ order: 1
1111

1212
The HollowEngine event system lets you inject custom logic into specific in-game actions, including player actions, entity actions, block updates, and more.
1313

14+
## Which side an event fires on
15+
16+
Minecraft is split into two sides: the **server** runs the world and the players, the **client** draws the picture and takes input. Even singleplayer runs a separate server inside. That is why every event in this section states its side, and it has to be listened to from a matching script:
17+
18+
| Side | Where to listen |
19+
|------------------|-----------------------------------------------------------------------------------|
20+
| **Server** | a plain `.reload.kts` |
21+
| **Client** | a `.reload.kts` with `@file:ClientSide` |
22+
| **Both sides** | either of them: a server script gets the server copy of the event, a client script the client copy |
23+
| **Game startup** | only `.startup.kts`: the event fires once, before any reloadable script exists |
24+
25+
If you subscribe to an event from the wrong side, the engine logs an error when the script starts. That makes it easy to see why a handler "does not fire on the server".
26+
27+
:::advice
28+
`.startup.kts` scripts and addons are not bound to a side and receive events of both sides. When such code listens to a "both sides" event, check the side yourself, for example with `event.player.level().isClientSide`.
29+
:::
30+
1431
## Creating a handler
1532

16-
There are two ways to create a handler: automatically (see [reloadable scripts](/docs/hollowengine/scripting/reload)) or manually by creating and registering a function:
33+
The simplest way to subscribe is the `@SubscribeEvent` annotation in a [reloadable script](/docs/hollowengine/scripting/reload). If a handler has to be added from code, for example only under some condition, subscribe through the script's scope:
1734

1835
```kotlin
1936
fun onPlayerJoin(event: PlayerEvent.Join) {
2037
event.player.send("Welcome back!")
2138
}
2239

23-
val handle = PlayerEvent.Join.register(::onPlayerJoin) // Start listening for the event and store the handler
24-
PlayerEvent.Join.unregister(handle) // Stop listening for the event (the method will no longer be called)
40+
PlayerEvent.Join.subscribe(this, listener = ::onPlayerJoin)
2541

2642
// You can also pass a lambda instead of a function:
27-
PlayerEvent.Join.register { event ->
43+
PlayerEvent.Join.subscribe(this) { event ->
2844
event.player.send("Welcome back!")
2945
}
3046
```
3147

48+
`this` here is the reloadable script itself: the subscription lives as long as the script and is removed when it restarts. It respects the script's side just like `@SubscribeEvent`.
49+
50+
:::warning
51+
`PlayerEvent.Join.register { ... }` without a scope subscribes forever, until the game exits. In scripts such a handler is not removed on `/reload` and fires once more after every restart.
52+
:::
53+
3254
## Priorities
3355

3456
Sometimes an event needs to run before other handlers, especially if it may cancel the event.
35-
You can change the handler order by configuring its priority:
57+
Pass a priority: the higher it is, the earlier the handler runs. The default priority is zero.
3658

3759
```kotlin
38-
val handler = eventListenerOf(10, ::onPlayerJoin)
60+
@SubscribeEvent(10)
61+
fun onPlayerJoin(event: PlayerEvent.Join) { }
3962

40-
PlayerEvent.Join.register(handler)
41-
PlayerEvent.Join.unregister(handler)
63+
// Or when subscribing from code:
64+
PlayerEvent.Join.subscribe(this, priority = 10) { event -> }
4265
```
4366

4467
## Canceling events
4568

4669
Some events are cancelable, meaning their default action can be prevented. For example:
4770

4871
```kotlin
49-
BlockEvent.Break.register { event ->
72+
@SubscribeEvent
73+
fun onBreak(event: BlockEvent.Break) {
5074
event.player.send("You cannot break blocks!")
5175
event.isCanceled = true
5276
}

docs/en/scripting/events/jei_events.mdx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ order: 6
55

66
*Events that allow integration with Just Enough Items (JEI): registering categories and recipes, hiding them, or adding item descriptions.*
77

8+
**Side:** client (every event on this page)
9+
10+
:::warning
11+
JEI only runs in the player's game, so these events have to be listened to from a client script: add `@file:ClientSide` at the top of the `.reload.kts`. A server script cannot subscribe to them, and the engine logs an error saying so.
12+
:::
13+
14+
```kotlin
15+
@file:ClientSide
16+
17+
import ru.hollowhorizon.hollowengine.common.events.ModifyRecipeViewerEvent
18+
19+
@SubscribeEvent
20+
fun onRuntimeAvailable(event: ModifyRecipeViewerEvent.RegisterOnRuntimeAvailable) {
21+
// ...
22+
}
23+
```
24+
825
## Registering subtypes and ingredients
926

1027
### Registering item subtypes

0 commit comments

Comments
 (0)