Skip to content

Commit bfd7c41

Browse files
committed
Merge branch 'main' into dev
2 parents 0955c85 + 7977e23 commit bfd7c41

11 files changed

Lines changed: 373 additions & 22 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
/build
1212
*.tsbuildinfo
1313

14+
# JetBrains IDEs
15+
.idea/
16+
1417
# misc
1518
.DS_Store
1619
*.pem

content/docs/en/guides/ecs/entity-component-system.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,4 @@ Systems contains the logic for your game (or in this case, a mod).
6666

6767
For example:
6868
- A "WinConditionSystem" may process every Entity that contains the components "Position" and "Velocity"
69-
- If an entity reaches the position `(0, 0, 0)`, the system will trigger a "You Won!" message.
69+
- If an entity reaches the position `(0, 0, 0)`, the system will trigger a "You Won!" message.

content/docs/en/guides/plugin/block-components.mdx

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,57 @@ public class ExampleBlock implements Component<ChunkStore> {
4848
}
4949
```
5050

51-
ExampleBlock stores the behavior for the block. Here, it simply places an Ice Block at `x + 1` relative to its current position when it ticks.
51+
ExampleBlock is a custom component that stores the behavior and data for your ticking block. Here, it simply places an Ice Block at x + 1 relative to its current position when it ticks.
5252

5353
---
5454

55-
### 2. ExampleSystem - handles ticking
55+
### 2. ExampleInitializer - marks blocks as ticking when placed
56+
57+
```java
58+
public class ExampleInitializer extends RefSystem {
59+
60+
@Override
61+
public void onEntityAdded(@Nonnull Ref ref, @Nonnull AddReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer) {
62+
BlockModule.BlockStateInfo info = (BlockModule.BlockStateInfo) commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
63+
if (info == null) return;
64+
65+
ExampleBlock generator = (ExampleBlock) commandBuffer.getComponent(ref, ExamplePlugin.get().getExampleBlockComponentType());
66+
if (generator != null) {
67+
int x = ChunkUtil.xFromBlockInColumn(info.getIndex());
68+
int y = ChunkUtil.yFromBlockInColumn(info.getIndex());
69+
int z = ChunkUtil.zFromBlockInColumn(info.getIndex());
70+
71+
WorldChunk worldChunk = (WorldChunk) commandBuffer.getComponent(info.getChunkRef(), WorldChunk.getComponentType());
72+
if (worldChunk != null) {
73+
worldChunk.setTicking(x, y, z, true);
74+
}
75+
}
76+
}
77+
78+
@Override
79+
public void onEntityRemove(@Nonnull Ref ref, @Nonnull RemoveReason reason, @Nonnull Store store, @Nonnull CommandBuffer commandBuffer) {
80+
}
81+
82+
@Override
83+
public Query getQuery() {
84+
return Query.and(BlockModule.BlockStateInfo.getComponentType(), ExamplePlugin.get().getExampleBlockComponentType());
85+
}
86+
}
87+
```
88+
89+
ExampleSystemInitializer is a RefSystem that reacts when block entities with the ExampleBlock component are added or removed. This is crucial for marking blocks as ticking when they're first placed.
90+
91+
**Key Points:**
92+
93+
* Tells the game that this block should tick, allowing `ExampleSystem` to process it.
94+
95+
```java
96+
worldChunk.setTicking(x, y, z, true);
97+
```
98+
99+
---
100+
101+
### 3. ExampleSystem - handles ticking
56102
57103
```java
58104
public class ExampleSystem extends EntityTickingSystem {
@@ -104,6 +150,9 @@ public class ExampleSystem extends EntityTickingSystem {
104150
}
105151
```
106152
153+
ExampleSystem is an EntityTickingSystem that runs every tick to execute the logic for all ticking blocks with the ExampleBlock component.
154+
155+
**Key Points:**
107156
108157
* **Get the block component**
109158
@@ -132,7 +181,7 @@ return BlockTickStrategy.CONTINUE;
132181
133182
---
134183
135-
### 3. ExamplePlugin - registers components and systems
184+
### 4. ExamplePlugin - registers components and systems
136185
137186
```java
138187
public class ExamplePlugin extends JavaPlugin {
@@ -164,7 +213,9 @@ public class ExamplePlugin extends JavaPlugin {
164213
}
165214
```
166215
167-
### 4. Configure In-Game
216+
---
217+
218+
### 5. Configure In-Game
168219
169220
![block-component-1](/assets/guides/block-component-1.png)
170221

content/docs/en/guides/plugin/item-interaction.mdx

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "Custom Item and Interaction"
2+
title: "Create Custom Item and Interaction"
33
description: "Learn how you can create a custom item interactions for your custom items"
44
authors:
55
- name: "Marcel-TO"
@@ -212,5 +212,110 @@ public class SendMessageInteraction extends SimpleInstantInteraction {
212212
}
213213
```
214214
215+
## Advanced Interaction Features
216+
Interactions are highly flexible. Since they are nested, you can combine multiple interactions to create complex behaviors. For example, you could have an interaction that first checks certain conditions (like player health or environment) before executing another interaction. Afterwards, you can chain interactions to create a sequence of actions triggered by a single item use. Or you could create interactions that need to be charged over time before they activate.
217+
218+
To get your creative juices flowing, here are some examples of interaction types:
219+
220+
1. **Condition**: Check specific conditions before allowing the interaction to proceed (e.g., only if player crouches):
221+
```json
222+
{
223+
"Type": "Condition",
224+
"Crouching": true, // only allow if player is crouching example
225+
"Failed": "Block_Secondary",
226+
"Next": {
227+
... // next interaction to run if condition is met
228+
}
229+
}
230+
```
231+
232+
2. **Charge**: Require the player to hold the interaction for a certain duration before it activates (This behavior for example is called if the player eats food):
233+
```json
234+
{
235+
"Type": "Charging",
236+
"FailsOnDamage": true, // cancel if player takes damage
237+
"HorizontalSpeedMultiplier": 0.4, // reduce speed while charging
238+
"Next": {
239+
"2.5" : { // interaction after 2.5 seconds of charging
240+
... // interaction to run after charge time
241+
},
242+
},
243+
"Failed": {
244+
... // interaction to run if charging fails
245+
}
246+
}
247+
```
248+
249+
3. **Serial**: Execute a series of interactions in order, one after the other:
250+
```json
251+
{
252+
"Type": "Serial",
253+
"Interactions": [
254+
{
255+
... // first interaction
256+
},
257+
{
258+
... // second interaction
259+
}
260+
]
261+
}
262+
```
263+
264+
4. **Replace**: Replace the default behavior of the item (e.g., inherited from parent) with a custom interaction:
265+
```json
266+
{
267+
"Type": "Replace",
268+
"Var": "Item_Default_Interaction",
269+
"DefaultValue": {
270+
"Interactions": [
271+
{
272+
... // default interaction that replaces the original
273+
}
274+
]
275+
}
276+
}
277+
```
278+
279+
5. **Simple**: Simple Interaction that performs a single action, such as sending a message or applying an effect:
280+
```json
281+
{
282+
"Type": "Simple"
283+
}
284+
```
285+
286+
### Advanced Interaction Example
287+
Here is an example of a more complex interaction that requires the player to crouch and charge for 2.5 seconds before executing the custom action:
288+
289+
```json
290+
{
291+
... // existing item properties from above
292+
"Interactions": {
293+
"Secondary": {
294+
"Interactions": [
295+
{
296+
"Type": "Condition",
297+
"Crouching": true,
298+
"Failed": "Block_Secondary",
299+
"Next": {
300+
"Type": "Charging",
301+
"FailsOnDamage": true,
302+
"HorizontalSpeedMultiplier": 0.5,
303+
"Next": {
304+
"2.5": {
305+
"Type": "my_custom_interaction_id",
306+
}
307+
},
308+
"Failed": {
309+
"Type": "Simple"
310+
}
311+
}
312+
}
313+
]
314+
}
315+
}
316+
}
317+
```
318+
319+
215320
## Conclusion
216-
You have now created a custom item with a unique interaction in your Hytale plugin. You can expand upon this foundation to create more complex items and interactions as needed for your mod.
321+
You have now created a custom item with a unique interaction in your Hytale plugin. You can expand upon this foundation to create more complex items and interactions as needed for your mod. Keep experimenting, chain interactions, and explore the possibilities to enhance gameplay!

content/docs/en/guides/plugin/meta.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
{
22
"title": "Server Plugins",
33
"pages": [
4+
"---Getting Started---",
45
"setting-up-env.mdx",
56
"build-and-test.mdx",
67
"browsing-serverjar.mdx",
8+
"logging.mdx",
9+
"---Core Concepts---",
710
"creating-commands.mdx",
811
"creating-events.mdx",
12+
"playing-sounds.mdx",
13+
"sending-notifications.mdx",
914
"chat-formatting.mdx",
15+
"---More Topics---",
1016
"..."
1117
],
1218
"icon": "Terminal"
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
title: "Player Stats"
3+
description: "A simple guide on how to edit player stats."
4+
authors:
5+
- name: "Bird"
6+
link: "https://discord.com/users/495709580068651009"
7+
---
8+
9+
# Overview
10+
11+
This guide shows you how to read and modify player stats like health and stamina using the `EntityStatMap` component.
12+
13+
## Available Stats
14+
15+
Hytale provides several default stats via `DefaultEntityStatTypes`:
16+
17+
- **Health**: `DefaultEntityStatTypes.getHealth()`
18+
- **Stamina**: `DefaultEntityStatTypes.getStamina()`
19+
- **Mana**: `DefaultEntityStatTypes.getMana()`
20+
- **Oxygen**: `DefaultEntityStatTypes.getOxygen()`
21+
- **Signature Energy**: `DefaultEntityStatTypes.getSignatureEnergy()`
22+
- **Ammo**: `DefaultEntityStatTypes.getAmmo()`
23+
24+
---
25+
26+
## Example 1: Heal Command
27+
28+
This command restores the player's health to its maximum value.
29+
30+
31+
```java
32+
public class HealCommand extends CommandBase {
33+
public HealCommand() {
34+
super("heal", "Restores your health to maximum.");
35+
this.setPermissionGroup(GameMode.Adventure);
36+
}
37+
38+
@Override
39+
protected void executeSync(@Nonnull CommandContext ctx) {
40+
// 1. Get the player reference
41+
Ref<EntityStore> playerRef = ctx.senderAsPlayerRef();
42+
if (playerRef == null) return;
43+
44+
// 2. Get the store and the world
45+
Store<EntityStore> store = playerRef.getStore();
46+
EntityStore entityStore = store.getExternalData();
47+
World world = entityStore.getWorld();
48+
49+
// 3. Perform modification on the world thread
50+
world.execute(() -> {
51+
EntityStatMap statMap = (EntityStatMap) store.getComponent(playerRef, EntityStatMap.getComponentType());
52+
if (statMap != null) {
53+
statMap.maximizeStatValue(DefaultEntityStatTypes.getHealth());
54+
ctx.sendMessage(Message.raw("Your health has been restored!"));
55+
}
56+
});
57+
}
58+
}
59+
```
60+
61+
---
62+
63+
## Example 2: Damage Self Command
64+
65+
This command removes a specific amount of health from the player.
66+
67+
```java
68+
public class DamageSelfCommand extends CommandBase {
69+
private final Argument amountArg;
70+
71+
public DamageSelfCommand() {
72+
super("damageself", "Damages yourself by a specific amount.");
73+
this.setPermissionGroup(GameMode.Adventure);
74+
this.amountArg = this.withRequiredArg("amount", "Amount of damage", ArgTypes.FLOAT);
75+
}
76+
77+
@Override
78+
protected void executeSync(@Nonnull CommandContext ctx) {
79+
// 1. Get the player reference
80+
Ref<EntityStore> playerRef = ctx.senderAsPlayerRef();
81+
if (playerRef == null) return;
82+
83+
// 2. Get command arg
84+
Float amount = (Float) this.amountArg.get(ctx);
85+
if (amount == null) return;
86+
87+
// 3. Get the store and the world
88+
Store<EntityStore> store = playerRef.getStore();
89+
EntityStore entityStore = store.getExternalData();
90+
World world = entityStore.getWorld();
91+
92+
// 4. Perform modification on the world thread
93+
world.execute(() -> {
94+
EntityStatMap statMap = (EntityStatMap) store.getComponent(playerRef, EntityStatMap.getComponentType());
95+
if (statMap != null) {
96+
statMap.subtractStatValue(DefaultEntityStatTypes.getHealth(), amount);
97+
ctx.sendMessage(Message.raw("Ouch! You took " + amount + " damage."));
98+
}
99+
});
100+
}
101+
}
102+
```
103+
104+
---
105+
106+
## Useful Methods
107+
108+
Common methods available on `EntityStatMap`:
109+
110+
- **Set**: `statMap.setStatValue(statIndex, value)`
111+
- **Add**: `statMap.addStatValue(statIndex, amount)`
112+
- **Subtract**: `statMap.subtractStatValue(statIndex, amount)`
113+
- **Maximize**: `statMap.maximizeStatValue(statIndex)`
114+
- **Reset**: `statMap.resetStatValue(statIndex)`

0 commit comments

Comments
 (0)