Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,30 @@ for (const std::string &name: falcon::Server::plugins())
logger().info(name + " " + falcon::Server::pluginVersion(name).value_or("?"));
```

### Player and entity events

| Event | Cancellable | Carries |
|---|---|---|
| `PlayerTeleportEvent` | yes | from, to (can change), cause: `command`, `ender_pearl`, `chorus_fruit`, `end_gateway`, `plugin` |
| `PlayerItemUseEvent` | yes | a copy of the held item, for any item used in the air |
| `PlayerBucketFillEvent`, `PlayerBucketEmptyEvent` | yes | the bucket and the block it takes from or fills |
| `PlayerFishEvent` | yes | the hook and the entity it holds, or a caught fish |
| `PlayerArmorChangeEvent` | no | the slot, the new and the previous item |
| `PlayerEmoteEvent` | yes | the emote id |
| `EntityEffectAddEvent` | yes | the effect |
| `EntityHealEvent` | yes | the amount (can change), cause: `heal`, `regeneration`, `self_heal`, `totem` |
| `EntityBreedEvent` | yes | both parents and the baby's type |
| `EntityTameEvent` | yes | the mob and its tamer |
| `EntityMountEvent`, `EntityDismountEvent` | mount only | the rider and the vehicle |
| `EntityTeleportEvent` | yes | from, to (can change), cause: `end_gateway`, `follow_owner`, `plugin` |

```cpp
events().on<falcon::PlayerTeleportEvent>([](falcon::PlayerTeleportEvent &event) {
if (event.cause() == "ender_pearl" && event.to().y > 200)
event.cancel();
});
```

### C# plugins

The `dotnet` runtime is deprecated. Write new plugins for Wasm, native C++ or Java.
Expand Down
9 changes: 9 additions & 0 deletions java/src/main/java/falcon/api/ArmorSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,13 @@ public enum ArmorSlot {
public int value() {
return mValue;
}

public static ArmorSlot of(int value) {
for (ArmorSlot slot : values()) {
if (slot.mValue == value) {
return slot;
}
}
throw new IllegalArgumentException("Unknown armor slot " + value);
}
}
2 changes: 1 addition & 1 deletion java/src/main/java/falcon/api/Effect.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public record Effect(EffectType type, int duration, int amplifier, boolean showParticles, boolean ambient) {
public static final int INFINITE = FalconAbi.EFFECT_INFINITE;

static Effect read(MemorySegment segment) {
public static Effect read(MemorySegment segment) {
return new Effect(EffectType.of(segment.get(ValueLayout.JAVA_INT, FalconAbi.Effect.TYPE)),
segment.get(ValueLayout.JAVA_INT, FalconAbi.Effect.DURATION),
segment.get(ValueLayout.JAVA_INT, FalconAbi.Effect.AMPLIFIER),
Expand Down
28 changes: 28 additions & 0 deletions java/src/main/java/falcon/api/event/EntityBreedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package falcon.api.event;

import falcon.api.Entity;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;
import java.util.Optional;

/**
* Two mobs in love make a baby; cancellable.
*/
public final class EntityBreedEvent extends Event {
EntityBreedEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Entity entity() {
return eventEntity();
}

public Optional<Entity> partner() {
return eventTarget();
}

public String babyType() {
return eventCause();
}
}
24 changes: 24 additions & 0 deletions java/src/main/java/falcon/api/event/EntityDismountEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package falcon.api.event;

import falcon.api.Entity;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;
import java.util.Optional;

/**
* An entity or player gets off a vehicle; not cancellable.
*/
public final class EntityDismountEvent extends Event {
EntityDismountEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Entity entity() {
return eventEntity();
}

public Optional<Entity> vehicle() {
return eventTarget();
}
}
24 changes: 24 additions & 0 deletions java/src/main/java/falcon/api/event/EntityEffectAddEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package falcon.api.event;

import falcon.api.Effect;
import falcon.api.Entity;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;

/**
* An entity or player gets a potion effect; cancellable.
*/
public final class EntityEffectAddEvent extends Event {
EntityEffectAddEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Entity entity() {
return eventEntity();
}

public Effect effect() {
return eventEffect();
}
}
31 changes: 31 additions & 0 deletions java/src/main/java/falcon/api/event/EntityHealEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package falcon.api.event;

import falcon.api.Entity;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;

/**
* An entity or player regains health; cancellable, the amount can change.
*/
public final class EntityHealEvent extends Event {
EntityHealEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Entity entity() {
return eventEntity();
}

public double amount() {
return eventAmount();
}

public void setAmount(double value) {
eventSetAmount(value);
}

public String cause() {
return eventCause();
}
}
24 changes: 24 additions & 0 deletions java/src/main/java/falcon/api/event/EntityMountEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package falcon.api.event;

import falcon.api.Entity;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;
import java.util.Optional;

/**
* An entity or player gets on a vehicle; cancellable.
*/
public final class EntityMountEvent extends Event {
EntityMountEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Entity entity() {
return eventEntity();
}

public Optional<Entity> vehicle() {
return eventTarget();
}
}
24 changes: 24 additions & 0 deletions java/src/main/java/falcon/api/event/EntityTameEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package falcon.api.event;

import falcon.api.Entity;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;
import java.util.Optional;

/**
* A mob is tamed; cancellable.
*/
public final class EntityTameEvent extends Event {
EntityTameEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Entity entity() {
return eventEntity();
}

public Optional<Entity> tamer() {
return eventTarget();
}
}
36 changes: 36 additions & 0 deletions java/src/main/java/falcon/api/event/EntityTeleportEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package falcon.api.event;

import falcon.api.Entity;
import falcon.api.Vec3;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;

/**
* An entity other than a player is moved by an end gateway, a pet following its owner or a plugin; cancellable.
*/
public final class EntityTeleportEvent extends Event {
EntityTeleportEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Entity entity() {
return eventEntity();
}

public Vec3 from() {
return eventFrom();
}

public Vec3 to() {
return eventTo();
}

public void setTo(Vec3 position) {
eventSetTo(position);
}

public String cause() {
return eventCause();
}
}
14 changes: 14 additions & 0 deletions java/src/main/java/falcon/api/event/Event.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package falcon.api.event;

import falcon.api.BlockPos;
import falcon.api.Effect;
import falcon.api.Entity;
import falcon.api.Item;
import falcon.api.Level;
import falcon.api.Player;
import falcon.api.Vec3;
import falcon.api.internal.FalconAbi;
import falcon.api.internal.Interop;
import falcon.api.internal.NativeApi;
import falcon.api.internal.PluginContext;
Expand Down Expand Up @@ -175,6 +177,18 @@ Optional<Entity> eventTarget() {
return optionalEntity(api().eventTarget(mHandle));
}

Effect eventEffect() {
try (Arena arena = Arena.ofConfined()) {
MemorySegment out = arena.allocate(FalconAbi.Effect.LAYOUT);
api().eventEffect(mHandle, out);
return Effect.read(out);
}
}

String eventWorldName() {
return Interop.string(api().eventWorldName(mHandle));
}

Item eventResult() {
return Item.borrow(api().eventResult(mHandle));
}
Expand Down
14 changes: 14 additions & 0 deletions java/src/main/java/falcon/api/event/EventType.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ final class EventType<T extends Event> {
register(PlayerChangeWorldEvent.class, FalconAbi.EVENT_PLAYER_CHANGE_WORLD, PlayerChangeWorldEvent::new);
register(ConnectionOpenEvent.class, FalconAbi.EVENT_CONNECTION_OPEN, ConnectionOpenEvent::new);
register(PlayerFormResponseEvent.class, FalconAbi.EVENT_PLAYER_FORM_RESPONSE, PlayerFormResponseEvent::new);
register(PlayerTeleportEvent.class, FalconAbi.EVENT_PLAYER_TELEPORT, PlayerTeleportEvent::new);
register(PlayerItemUseEvent.class, FalconAbi.EVENT_PLAYER_ITEM_USE, PlayerItemUseEvent::new);
register(PlayerBucketFillEvent.class, FalconAbi.EVENT_PLAYER_BUCKET_FILL, PlayerBucketFillEvent::new);
register(PlayerBucketEmptyEvent.class, FalconAbi.EVENT_PLAYER_BUCKET_EMPTY, PlayerBucketEmptyEvent::new);
register(PlayerFishEvent.class, FalconAbi.EVENT_PLAYER_FISH, PlayerFishEvent::new);
register(PlayerArmorChangeEvent.class, FalconAbi.EVENT_PLAYER_ARMOR_CHANGE, PlayerArmorChangeEvent::new);
register(PlayerEmoteEvent.class, FalconAbi.EVENT_PLAYER_EMOTE, PlayerEmoteEvent::new);
register(EntityEffectAddEvent.class, FalconAbi.EVENT_ENTITY_EFFECT_ADD, EntityEffectAddEvent::new);
register(EntityHealEvent.class, FalconAbi.EVENT_ENTITY_HEAL, EntityHealEvent::new);
register(EntityBreedEvent.class, FalconAbi.EVENT_ENTITY_BREED, EntityBreedEvent::new);
register(EntityTameEvent.class, FalconAbi.EVENT_ENTITY_TAME, EntityTameEvent::new);
register(EntityMountEvent.class, FalconAbi.EVENT_ENTITY_MOUNT, EntityMountEvent::new);
register(EntityDismountEvent.class, FalconAbi.EVENT_ENTITY_DISMOUNT, EntityDismountEvent::new);
register(EntityTeleportEvent.class, FalconAbi.EVENT_ENTITY_TELEPORT, EntityTeleportEvent::new);
}

private final int mId;
Expand Down
33 changes: 33 additions & 0 deletions java/src/main/java/falcon/api/event/PlayerArmorChangeEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package falcon.api.event;

import falcon.api.ArmorSlot;
import falcon.api.Item;
import falcon.api.Player;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;

/**
* An armor slot of a player changed through the inventory or by equipping the held item; not cancellable.
*/
public final class PlayerArmorChangeEvent extends Event {
PlayerArmorChangeEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Player player() {
return eventPlayer();
}

public ArmorSlot slot() {
return ArmorSlot.of(eventDestinationSlot());
}

public Item item() {
return eventItem();
}

public Item previousItem() {
return eventResult();
}
}
33 changes: 33 additions & 0 deletions java/src/main/java/falcon/api/event/PlayerBucketEmptyEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package falcon.api.event;

import falcon.api.BlockPos;
import falcon.api.Item;
import falcon.api.Player;
import falcon.api.internal.PluginContext;

import java.lang.foreign.MemorySegment;

/**
* A player empties a bucket into the world or a cauldron; cancellable. The block is where the content goes.
*/
public final class PlayerBucketEmptyEvent extends Event {
PlayerBucketEmptyEvent(PluginContext context, MemorySegment handle) {
super(context, handle);
}

public Player player() {
return eventPlayer();
}

public Item bucket() {
return eventItem();
}

public BlockPos block() {
return eventBlockPosition();
}

public String blockName() {
return eventBlockName();
}
}
Loading
Loading