Skip to content

Commit

Permalink
Add documentation for C2SSelfMessagingComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
Pyrofab committed Jul 20, 2024
1 parent 233365a commit cba6e72
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 4 deletions.
2 changes: 1 addition & 1 deletion public/wiki/cardinal-components-api/modules/block.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ One could write a compound component that can be attached to any `BlockEntity` a

```java
public interface FluidContainerCompound extends Component {
ComponentKey<FluidContainerCompound> KEY = ComponentRegistry.register(new Identifier("mymod:fluid_container_compound"), FluidContainerCompound.class);
ComponentKey<FluidContainerCompound> KEY = ComponentRegistry.register(Identifier.of("mymod:fluid_container_compound"), FluidContainerCompound.class);

FluidContainer get(Direction side);
}
Expand Down
56 changes: 56 additions & 0 deletions public/wiki/cardinal-components-api/modules/entity.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,62 @@ Instead of a specific class, you can also register a component factory with a `P
### Synchronization
Entity components can be automatically synchronized from the server to the client by implementing [`AutoSyncedComponent`](https://github.com/Ladysnake/Cardinal-Components-API/blob/main/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/sync/AutoSyncedComponent.java) - more information is available on [the component synchronization page](../synchronization).

### Client-to-Server networking

Many mods making use of synced components also need to send back messages to the server to affect the state of said components - typically in reaction to a key press or to a GUI click.
Since version 6.0.0, these mods can use the `C2SSelfMessagingComponent` utility interface, removing the need to create and register a custom packet type.

As most use cases apply to a player component sending a message to itself, `C2SSelfMessagingComponent` is tailored for this scenario.
As such, this interface only works when implemented on a component that is attached to a player.
{:.admonition.admonition-important}

To showcase how this interface can be used, here's the basis for a component that lets players use custom powers,
presumably by pressing a key or using a GUI:

```java
public class MyPlayerComponent implements C2SSelfMessagingComponent, AutoSyncedComponent, ServerTickingComponent {
private final PlayerEntity player;
private List<String> powers; // String for the demo but this should store actual objects
private int cooldown;

public MyPlayerComponent(PlayerEntity player) {
this.player = player;
this.powers = List.of("fire", "water", "air", "earth");
this.cooldown = 0;
}

/** Method to call clientside when a player uses a keybind or clicks in a GUI */
public void usePower(int chosenPower) {
sendC2SMessage(buf -> buf.writeVarInt(chosenPower));
}

@Override
public void handleC2SMessage(RegistryByteBuf buf) {
int chosenPower = buf.readVarInt();

// ALWAYS MAKE SURE TO VALIDATE THE CLIENT'S INPUT IN THIS METHOD
// regardless of your clientside checks, a malicious or buggy client can always send a bad packet

// Obligatory check to avoid crashing the server
if (chosenPower < 0 || chosenPower >= this.powers.size()) return;
// Arbitrary check, let's assume our powers have a cooldown to avoid spamming them
if (this.cooldown > 0) return;
// Arbitrary check, let's assume players can't use fire in water
if ("fire".equals(this.powers.get(chosenPower)) && this.player.isTouchingWater()) return;

player.sendMessage("Used power " + powers.get(chosenPower));
cooldown = 40;
}

// serialization and ticking methods elided for brevity
}
```

The serverside validation part is crucial here, just like with any client-to-server packet,
without it your mod becomes an open door for all kinds of hacks and glitches.
In particular, your mod should **never** call `readFromNbt` from the `handleC2SMessage` method.
{:.admonition.admonition-warning.admonition-icon}

### Ticking
Entity components support both [server](https://github.com/Ladysnake/Cardinal-Components-API/blob/main/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/tick/ServerTickingComponent.java) and [client](https://github.com/Ladysnake/Cardinal-Components-API/blob/main/cardinal-components-base/src/main/java/org/ladysnake/cca/api/v3/component/tick/ClientTickingComponent.java) ticking.
Components get ticked right after the entity they are attached to, provided the latter gets ticked through `(Server/Client)World#tickEntity`.
Expand Down
4 changes: 2 additions & 2 deletions public/wiki/cardinal-components-api/registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ For example, if you created an `IntComponent` class like in the [Implementing th
```java
// retrieving a type for my component or for a required dependency's
public static final ComponentKey<IntComponent> MAGIK =
ComponentRegistry.getOrCreate(new Identifier("mymod", "magik"), IntComponent.class);
ComponentRegistry.getOrCreate(Identifier.of("mymod", "magik"), IntComponent.class);
```

### Retrieval of an existing key
Expand All @@ -81,7 +81,7 @@ The following example demonstrates retrieving a component that another mod regis
```java
// retrieving a component type registered by an optional dependency
public static final Lazy<@Nullable ComponentKey<?>> BLUE =
new Lazy<>(() -> ComponentRegistry.get(new Identifier("theirmod:blue")));
new Lazy<>(() -> ComponentRegistry.get(Identifier.of("theirmod:blue")));
```

## 2) Attaching your component
Expand Down
9 changes: 8 additions & 1 deletion public/wiki/cardinal-components-api/synchronization.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ layout: cca_wiki
tags: ['AutoSyncedComponent']
---

Storing data is all well and good, but sometimes you need clients to be aware of what you put there. Most often it will be for visual effects, although it can be required for various clientside behaviour like player movement. And while you can set up your own packets and callbacks to keep your players updated, Cardinal Components API offers you facilities to handle synchronization with little to no effort.
Storing data is all well and good, but sometimes you need clients to be aware of what you put there.
Most often it will be for visual effects, although it can be required for various clientside behaviour like player movement.
And while you can set up your own packets and callbacks to keep your players updated,
Cardinal Components API offers you facilities to handle synchronization with little to no effort.

Trying to send an update from the client to the server? Check out the new [Client-to-Server networking API](./modules/entity#client-to-server-networking)
in the entity module.
{:.admonition.admonition-note.admonition-icon}

## Synchronizing a Component

Expand Down

0 comments on commit cba6e72

Please sign in to comment.