mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-21 03:10:54 -04:00
Add mob conversion event (#3511)
* Add mob conversion event * spacing * use a smarter mixin strategy * add pig and villager lightning triggers * tyop Co-authored-by: haykam821 <24855774+haykam821@users.noreply.github.com> * handle tadpole -> frog conversion - update javadoc to clarify the handled cases - document keepEquipment parameter - improve mixin handler names --------- Co-authored-by: haykam821 <24855774+haykam821@users.noreply.github.com>
This commit is contained in:
parent
a462da68c6
commit
44c0f8c656
7 changed files with 213 additions and 3 deletions
fabric-entity-events-v1/src
main
java/net/fabricmc/fabric
api/entity/event/v1
mixin/entity/event
resources
testmod/java/net/fabricmc/fabric/test/entity/event
|
@ -18,6 +18,7 @@ package net.fabricmc.fabric.api.entity.event.v1;
|
|||
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
@ -73,6 +74,21 @@ public final class ServerLivingEntityEvents {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event that is called when a mob has been converted to another type.
|
||||
*
|
||||
* <p>When this event is called, the old instance has not yet been discarded, and the new one has not yet been spawned.
|
||||
* Mods may use this event to copy some of the old entity's data to the converted one.</p>
|
||||
*
|
||||
* <p>This event only handles cases where the entity type changes, requiring a new instance. Notably it does not
|
||||
* cover mooshrooms changing color from lightning, creepers getting charged, or wolves being tamed.</p>
|
||||
*/
|
||||
public static final Event<MobConversion> MOB_CONVERSION = EventFactory.createArrayBacked(MobConversion.class, callbacks -> (previous, converted, keepEquipment) -> {
|
||||
for (MobConversion callback : callbacks) {
|
||||
callback.onConversion(previous, converted, keepEquipment);
|
||||
}
|
||||
});
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AllowDamage {
|
||||
/**
|
||||
|
@ -112,6 +128,18 @@ public final class ServerLivingEntityEvents {
|
|||
void afterDeath(LivingEntity entity, DamageSource damageSource);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MobConversion {
|
||||
/**
|
||||
* Called when a mob is converted to another type.
|
||||
*
|
||||
* @param previous the previous entity instance
|
||||
* @param converted the new instance for the converted entity
|
||||
* @param keepEquipment whether the converted entity should keep the previous one's equipment, like armor
|
||||
*/
|
||||
void onConversion(MobEntity previous, MobEntity converted, boolean keepEquipment);
|
||||
}
|
||||
|
||||
private ServerLivingEntityEvents() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 com.llamalad7.mixinextras.sugar.Local;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
|
||||
|
||||
@Mixin(MobEntity.class)
|
||||
public class MobEntityMixin {
|
||||
@ModifyArg(method = "convertTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z"))
|
||||
private Entity afterEntityConverted(Entity converted, @Local(argsOnly = true) boolean keepEquipment) {
|
||||
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion((MobEntity) (Object) this, (MobEntity) converted, keepEquipment);
|
||||
return converted;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.ModifyArg;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.passive.AnimalEntity;
|
||||
import net.minecraft.entity.passive.PigEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
|
||||
|
||||
@Mixin(PigEntity.class)
|
||||
abstract class PigEntityMixin extends AnimalEntity {
|
||||
protected PigEntityMixin(EntityType<? extends AnimalEntity> entityType, World world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
method = "onStruckByLightning",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;spawnEntity(Lnet/minecraft/entity/Entity;)Z")
|
||||
)
|
||||
private Entity afterPiglinConversion(Entity converted) {
|
||||
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion(this, (MobEntity) converted, false);
|
||||
return converted;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.ModifyArg;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.passive.FishEntity;
|
||||
import net.minecraft.entity.passive.TadpoleEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
|
||||
|
||||
@Mixin(TadpoleEntity.class)
|
||||
abstract class TadpoleEntityMixin extends FishEntity {
|
||||
TadpoleEntityMixin(EntityType<? extends FishEntity> entityType, World world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
method = "growUp",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;spawnEntityAndPassengers(Lnet/minecraft/entity/Entity;)V")
|
||||
)
|
||||
private Entity afterGrowingUpToFrog(Entity converted) {
|
||||
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion(this, (MobEntity) converted, false);
|
||||
return converted;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.ModifyArg;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.passive.MerchantEntity;
|
||||
import net.minecraft.entity.passive.VillagerEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
|
||||
|
||||
@Mixin(VillagerEntity.class)
|
||||
abstract class VillagerEntityMixin extends MerchantEntity {
|
||||
VillagerEntityMixin(EntityType<? extends MerchantEntity> entityType, World world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
method = "onStruckByLightning",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;spawnEntityAndPassengers(Lnet/minecraft/entity/Entity;)V")
|
||||
)
|
||||
private Entity afterWitchConversion(Entity converted) {
|
||||
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion(this, (MobEntity) converted, false);
|
||||
return converted;
|
||||
}
|
||||
}
|
|
@ -3,13 +3,17 @@
|
|||
"package": "net.fabricmc.fabric.mixin.entity.event",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"elytra.LivingEntityMixin",
|
||||
"elytra.PlayerEntityMixin",
|
||||
"EntityMixin",
|
||||
"LivingEntityMixin",
|
||||
"MobEntityMixin",
|
||||
"PigEntityMixin",
|
||||
"PlayerEntityMixin",
|
||||
"PlayerManagerMixin",
|
||||
"ServerPlayerEntityMixin"
|
||||
"ServerPlayerEntityMixin",
|
||||
"TadpoleEntityMixin",
|
||||
"VillagerEntityMixin",
|
||||
"elytra.LivingEntityMixin",
|
||||
"elytra.PlayerEntityMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1,
|
||||
|
|
|
@ -114,6 +114,10 @@ public final class EntityEventTests implements ModInitializer {
|
|||
LOGGER.info("{} died due to {} damage source", entity.getName().getString(), source.getName());
|
||||
});
|
||||
|
||||
ServerLivingEntityEvents.MOB_CONVERSION.register((previous, converted, keepEquipment) -> {
|
||||
LOGGER.info("{} is being converted to {} [{}]", previous.getName().getString(), converted.getName().getString(), keepEquipment);
|
||||
});
|
||||
|
||||
EntitySleepEvents.ALLOW_SLEEPING.register((player, sleepingPos) -> {
|
||||
// Can't sleep if holds blue wool
|
||||
if (player.getStackInHand(Hand.MAIN_HAND).isOf(Items.BLUE_WOOL)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue