mirror of
https://github.com/FabricMC/fabric.git
synced 2025-07-28 15:09:35 -04:00
Entity Events v1 (#957)
* Entity Events v1.
First up is an event fired after a living entity is damaged. All vanilla living entities except armor stands work with this event.
* Events related to killing of entities, changing world, player respawn/copyFrom
Death related:
an entity killing something and an entity being killed by an adversary
Player related:
After respawn, copy to
* Adversary stuff isn't needed
* checkstyle again
* Call AFTER_KILLED_OTHER on a ServerPlayerEntity upon death.
* Add event which is fired when a player first joined a server and add functional interface annotations
* Update build.gradle
* mispelled
* Some renames, test events, drop damage event
Damage events need further consideration in future
* Comments and null check
* Update for mappings
* Warning comment
* Remove first join event and teleport helper
First join does not work atm and teleport is in dimensions pr
* Module dependencies
* Javadoc tweaks
* The serverening
(cherry picked from commit 79b23bee5b
)
This commit is contained in:
parent
60e92d82df
commit
1d561d2678
15 changed files with 567 additions and 0 deletions
fabric-entity-events-v1
settings.gradle
10
fabric-entity-events-v1/build.gradle
Normal file
10
fabric-entity-events-v1/build.gradle
Normal file
|
@ -0,0 +1,10 @@
|
|||
archivesBaseName = "fabric-entity-events-v1"
|
||||
version = getSubprojectVersion(project, "1.0.0")
|
||||
|
||||
moduleDependencies(project, [
|
||||
'fabric-api-base'
|
||||
])
|
||||
|
||||
dependencies {
|
||||
testmodCompile project(path: ':fabric-command-api-v1', configuration: 'dev')
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.entity.event.v1;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Events related to entities in combat.
|
||||
*/
|
||||
public final class ServerEntityCombatEvents {
|
||||
/**
|
||||
* An event that is called after an entity is directly responsible for killing another entity.
|
||||
*
|
||||
* @see Entity#onKilledOther(ServerWorld, LivingEntity)
|
||||
*/
|
||||
public static final Event<AfterKilledOtherEntity> AFTER_KILLED_OTHER_ENTITY = EventFactory.createArrayBacked(AfterKilledOtherEntity.class, callbacks -> (world, entity, killedEntity) -> {
|
||||
for (AfterKilledOtherEntity callback : callbacks) {
|
||||
callback.afterKilledOtherEntity(world, entity, killedEntity);
|
||||
}
|
||||
});
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AfterKilledOtherEntity {
|
||||
/**
|
||||
* Called after an entity has killed another entity.
|
||||
*
|
||||
* @param world the world
|
||||
* @param entity the entity
|
||||
* @param killedEntity the entity which was killed by the {@code entity}
|
||||
*/
|
||||
void afterKilledOtherEntity(ServerWorld world, Entity entity, LivingEntity killedEntity);
|
||||
}
|
||||
|
||||
private ServerEntityCombatEvents() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.entity.event.v1;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Events related to an entity being moved to another world.
|
||||
*
|
||||
* @apiNote For a {@link ServerPlayerEntity}, please use {@link ServerEntityWorldChangeEvents#AFTER_PLAYER_CHANGE_WORLD}.
|
||||
*/
|
||||
public final class ServerEntityWorldChangeEvents {
|
||||
/**
|
||||
* An event which is called after an entity has been moved to a different world.
|
||||
*
|
||||
* <p>All entities are copied to the destination and the old entity removed.
|
||||
* This event does not apply to the {@link ServerPlayerEntity} since players are physically moved to the new world instead of being copied over.
|
||||
*
|
||||
* <p>A mod may use this event for reference cleanup if it is tracking an entity's current world.
|
||||
*
|
||||
* @see ServerEntityWorldChangeEvents#AFTER_PLAYER_CHANGE_WORLD
|
||||
*/
|
||||
public static final Event<AfterEntityChange> AFTER_ENTITY_CHANGE_WORLD = EventFactory.createArrayBacked(AfterEntityChange.class, callbacks -> (originalEntity, newEntity, origin, destination) -> {
|
||||
for (AfterEntityChange callback : callbacks) {
|
||||
callback.afterChangeWorld(originalEntity, newEntity, origin, destination);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event which is called after a player has been moved to a different world.
|
||||
*
|
||||
* <p>This is similar to {@link ServerEntityWorldChangeEvents#AFTER_ENTITY_CHANGE_WORLD} but is only called for players.
|
||||
* This is because the player is physically moved to the new world instead of being recreated at the destination.
|
||||
*
|
||||
* @see ServerEntityWorldChangeEvents#AFTER_ENTITY_CHANGE_WORLD
|
||||
*/
|
||||
public static final Event<AfterPlayerChange> AFTER_PLAYER_CHANGE_WORLD = EventFactory.createArrayBacked(AfterPlayerChange.class, callbacks -> (player, origin, destination) -> {
|
||||
for (AfterPlayerChange callback : callbacks) {
|
||||
callback.afterChangeWorld(player, origin, destination);
|
||||
}
|
||||
});
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AfterEntityChange {
|
||||
/**
|
||||
* Called after an entity has been recreated at the destination when being moved to a different world.
|
||||
*
|
||||
* <p>Note this event is not called if the entity is a {@link ServerPlayerEntity}.
|
||||
* {@link AfterPlayerChange} should be used to track when a player has changed worlds.
|
||||
*
|
||||
* @param originalEntity the original entity
|
||||
* @param newEntity the new entity at the destination
|
||||
* @param origin the world the original entity is in
|
||||
* @param destination the destination world the new entity is in
|
||||
*/
|
||||
void afterChangeWorld(Entity originalEntity, Entity newEntity, ServerWorld origin, ServerWorld destination);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AfterPlayerChange {
|
||||
/**
|
||||
* Called after a player has been moved to different world.
|
||||
*
|
||||
* @param player the player
|
||||
* @param origin the original world the player was in
|
||||
* @param destination the new world the player was moved to
|
||||
*/
|
||||
void afterChangeWorld(ServerPlayerEntity player, ServerWorld origin, ServerWorld destination);
|
||||
}
|
||||
|
||||
private ServerEntityWorldChangeEvents() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.entity.event.v1;
|
||||
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
public final class ServerPlayerEvents {
|
||||
/**
|
||||
* An event that is called when the data from an old player is copied to a new player.
|
||||
*
|
||||
* <p>This event is typically called before a player is completely respawned.
|
||||
* Mods may use this event to copy old player data to a new player.
|
||||
*/
|
||||
public static final Event<ServerPlayerEvents.CopyFrom> COPY_FROM = EventFactory.createArrayBacked(ServerPlayerEvents.CopyFrom.class, callbacks -> (oldPlayer, newPlayer, alive) -> {
|
||||
for (CopyFrom callback : callbacks) {
|
||||
callback.copyFromPlayer(oldPlayer, newPlayer, alive);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event that is called after a player has been respawned.
|
||||
*
|
||||
* <p>Mods may use this event for reference clean up on the old player.
|
||||
*/
|
||||
public static final Event<ServerPlayerEvents.AfterRespawn> AFTER_RESPAWN = EventFactory.createArrayBacked(ServerPlayerEvents.AfterRespawn.class, callbacks -> (oldPlayer, newPlayer, alive) -> {
|
||||
for (AfterRespawn callback : callbacks) {
|
||||
callback.afterRespawn(oldPlayer, newPlayer, alive);
|
||||
}
|
||||
});
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CopyFrom {
|
||||
/**
|
||||
* Called when player data is copied to a new player.
|
||||
*
|
||||
* @param oldPlayer the old player
|
||||
* @param newPlayer the new player
|
||||
* @param alive whether the old player is still alive
|
||||
*/
|
||||
void copyFromPlayer(ServerPlayerEntity oldPlayer, ServerPlayerEntity newPlayer, boolean alive);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AfterRespawn {
|
||||
/**
|
||||
* Called after player a has been respawned.
|
||||
*
|
||||
* @param oldPlayer the old player
|
||||
* @param newPlayer the new player
|
||||
* @param alive whether the old player is still alive
|
||||
*/
|
||||
void afterRespawn(ServerPlayerEntity oldPlayer, ServerPlayerEntity newPlayer, boolean alive);
|
||||
}
|
||||
|
||||
private ServerPlayerEvents() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.entity.event;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
abstract class EntityMixin {
|
||||
@Shadow
|
||||
public World world;
|
||||
|
||||
@Inject(method = "moveToWorld", at = @At(value = "RETURN", ordinal = 1))
|
||||
private void afterWorldChanged(ServerWorld destination, CallbackInfoReturnable<Entity> cir) {
|
||||
ServerEntityWorldChangeEvents.AFTER_ENTITY_CHANGE_WORLD.invoker().afterChangeWorld((Entity) (Object) this, cir.getReturnValue(), (ServerWorld) this.world, (ServerWorld) cir.getReturnValue().world);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.entity.event;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
abstract class LivingEntityMixin extends EntityMixin {
|
||||
@Inject(method = "onDeath", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;onKilledOther(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/entity/LivingEntity;)V", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
|
||||
private void onEntityKilledOther(DamageSource source, CallbackInfo ci, Entity attacker) {
|
||||
ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.invoker().afterKilledOtherEntity(((ServerWorld) this.world), attacker, (LivingEntity) (Object) this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.entity.event;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
|
||||
|
||||
@Mixin(PlayerManager.class)
|
||||
abstract class PlayerManagerMixin {
|
||||
@Inject(method = "respawnPlayer", at = @At("TAIL"))
|
||||
private void afterRespawn(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfoReturnable<ServerPlayerEntity> cir) {
|
||||
ServerPlayerEvents.AFTER_RESPAWN.invoker().afterRespawn(oldPlayer, cir.getReturnValue(), alive);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.entity.event;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
|
||||
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
abstract class ServerPlayerEntityMixin extends LivingEntityMixin {
|
||||
@Shadow
|
||||
public abstract ServerWorld getServerWorld();
|
||||
|
||||
/**
|
||||
* Minecraft by default does not call Entity#onKilledOther for a ServerPlayerEntity being killed.
|
||||
* This is a Mojang bug.
|
||||
* This is implements the method call on the server player entity and then calls the corresponding event.
|
||||
*/
|
||||
@Inject(method = "onDeath", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;getPrimeAdversary()Lnet/minecraft/entity/LivingEntity;"))
|
||||
private void callOnKillForPlayer(DamageSource source, CallbackInfo ci) {
|
||||
final Entity attacker = source.getAttacker();
|
||||
|
||||
// If the damage source that killed the player was an entity, then fire the event.
|
||||
if (attacker != null) {
|
||||
attacker.onKilledOther(this.getServerWorld(), (ServerPlayerEntity) (Object) this);
|
||||
ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.invoker().afterKilledOtherEntity(this.getServerWorld(), attacker, (ServerPlayerEntity) (Object) this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called by both "moveToWorld" and "teleport".
|
||||
* So this is suitable to handle the after event from both call sites.
|
||||
*/
|
||||
@Inject(method = "worldChanged(Lnet/minecraft/server/world/ServerWorld;)V", at = @At("TAIL"))
|
||||
private void afterWorldChanged(ServerWorld origin, CallbackInfo ci) {
|
||||
ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.invoker().afterChangeWorld((ServerPlayerEntity) (Object) this, origin, this.getServerWorld());
|
||||
}
|
||||
|
||||
@Inject(method = "copyFrom", at = @At("TAIL"))
|
||||
private void onCopyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) {
|
||||
ServerPlayerEvents.COPY_FROM.invoker().copyFromPlayer(oldPlayer, (ServerPlayerEntity) (Object) this, alive);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.entity.event;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Coerce;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.command.TeleportCommand;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
|
||||
|
||||
@Mixin(TeleportCommand.class)
|
||||
abstract class TeleportCommandMixin {
|
||||
/**
|
||||
* We need to fire the change world event for entities that are teleported using the `/teleport` command.
|
||||
*/
|
||||
@Inject(method = "teleport", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setRemoved(Lnet/minecraft/entity/Entity$RemovalReason;)V"), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
|
||||
private static void afterEntityTeleportedToWorld(ServerCommandSource source, Entity originalEntity, ServerWorld destination, double x, double y, double z, Set<PlayerPositionLookS2CPacket.Flag> movementFlags, float yaw, float pitch, @Coerce Object facingLocation, CallbackInfo ci, float clampedYaw, float clampedPitch, float h, Entity newEntity) {
|
||||
ServerEntityWorldChangeEvents.AFTER_ENTITY_CHANGE_WORLD.invoker().afterChangeWorld(originalEntity, newEntity, ((ServerWorld) originalEntity.world), destination);
|
||||
}
|
||||
}
|
Binary file not shown.
After ![]() (image error) Size: 1.5 KiB |
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.entity.event",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"EntityMixin",
|
||||
"LivingEntityMixin",
|
||||
"PlayerManagerMixin",
|
||||
"ServerPlayerEntityMixin",
|
||||
"TeleportCommandMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
25
fabric-entity-events-v1/src/main/resources/fabric.mod.json
Normal file
25
fabric-entity-events-v1/src/main/resources/fabric.mod.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-entity-events-v1",
|
||||
"name": "Fabric Entity Events (v1)",
|
||||
"version": "${version}",
|
||||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"icon": "assets/fabric-entity-events-v1/icon.png",
|
||||
"contact": {
|
||||
"homepage": "https://fabricmc.net",
|
||||
"irc": "irc://irc.esper.net:6667/fabric",
|
||||
"issues": "https://github.com/FabricMC/fabric/issues",
|
||||
"sources": "https://github.com/FabricMC/fabric"
|
||||
},
|
||||
"authors": [
|
||||
"FabricMC"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.8.2"
|
||||
},
|
||||
"description": "Events to hook into entities.",
|
||||
"mixins": [
|
||||
"fabric-entity-events-v1.mixins.json"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.test.entity.event;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
|
||||
|
||||
public final class EntityEventTests implements ModInitializer {
|
||||
private static final Logger LOGGER = LogManager.getLogger(EntityEventTests.class);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.register((world, entity, killed) -> {
|
||||
LOGGER.info("Entity Killed: {}", killed);
|
||||
});
|
||||
|
||||
ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.register((player, origin, destination) -> {
|
||||
LOGGER.info("Moved player {}: [{} -> {}]", player, origin.getRegistryKey().getValue(), destination.getRegistryKey().getValue());
|
||||
});
|
||||
|
||||
ServerEntityWorldChangeEvents.AFTER_ENTITY_CHANGE_WORLD.register((originalEntity, newEntity, origin, destination) -> {
|
||||
LOGGER.info("Moved entity {} -> {}: [({} -> {}]", originalEntity, newEntity, origin.getRegistryKey().getValue(), destination.getRegistryKey().getValue());
|
||||
});
|
||||
|
||||
ServerPlayerEvents.COPY_FROM.register((oldPlayer, newPlayer, alive) -> {
|
||||
LOGGER.info("Copied data for {} from {} to {}", oldPlayer.getGameProfile().getName(), oldPlayer, newPlayer);
|
||||
});
|
||||
|
||||
ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> {
|
||||
LOGGER.info("Respawned {}, [{}, {}]", oldPlayer.getGameProfile().getName(), oldPlayer.getServerWorld().getRegistryKey().getValue(), newPlayer.getServerWorld().getRegistryKey().getValue());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-entity-events-v1-testmod",
|
||||
"name": "Fabric Entity Events (v1) Test Mod",
|
||||
"version": "1.0.0",
|
||||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"depends": {
|
||||
"fabric-entity-events-v1": "*",
|
||||
"fabric-command-api-v1":"*"
|
||||
},
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.entity.event.EntityEventTests"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ include 'fabric-containers-v0'
|
|||
include 'fabric-content-registries-v0'
|
||||
include 'fabric-crash-report-info-v1'
|
||||
include 'fabric-dimensions-v1'
|
||||
include 'fabric-entity-events-v1'
|
||||
include 'fabric-events-interaction-v0'
|
||||
include 'fabric-events-lifecycle-v0'
|
||||
include 'fabric-game-rule-api-v1'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue