Refactor projectile event handlers

This commit is contained in:
Sollace 2022-12-04 22:46:45 +00:00
parent 9421587f9d
commit 8a16a8b501
17 changed files with 119 additions and 114 deletions

View file

@ -11,7 +11,6 @@ import net.minecraft.entity.Entity;
public interface SpellPredicate<T extends Spell> extends Predicate<Spell> {
SpellPredicate<IllusionarySpell> CAN_SUPPRESS = s -> s instanceof IllusionarySpell;
SpellPredicate<PlaceableSpell> IS_PLACED = s -> s instanceof PlaceableSpell;
SpellPredicate<ProjectileSpell> HAS_PROJECTILE_EVENTS = s -> s instanceof ProjectileSpell;
SpellPredicate<AbstractDisguiseSpell> IS_DISGUISE = s -> s instanceof AbstractDisguiseSpell;
SpellPredicate<MimicSpell> IS_MIMIC = s -> s instanceof MimicSpell;
SpellPredicate<ShieldSpell> IS_SHIELD_LIKE = spell -> spell instanceof ShieldSpell;

View file

@ -13,14 +13,12 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
public abstract class AbstractDelegatingSpell implements ProjectileSpell {
private static final Function<Object, ProjectileSpell> PROJECTILE_SPELL = a -> a instanceof ProjectileSpell p ? p : null;
private static final Function<Object, ProjectileDelegate> PROJECTILE_DELEGATE = a -> a instanceof ProjectileDelegate p ? p : null;
public abstract class AbstractDelegatingSpell implements Spell,
ProjectileDelegate.ConfigurationListener, ProjectileDelegate.BlockHitListener, ProjectileDelegate.EntityHitListener {
private boolean isDirty;
@ -36,12 +34,12 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
@Override
public boolean equalsOrContains(UUID id) {
return ProjectileSpell.super.equalsOrContains(id) || getDelegates().stream().anyMatch(s -> s.equalsOrContains(id));
return Spell.super.equalsOrContains(id) || getDelegates().stream().anyMatch(s -> s.equalsOrContains(id));
}
@Override
public Stream<Spell> findMatches(Predicate<Spell> predicate) {
return Stream.concat(ProjectileSpell.super.findMatches(predicate), getDelegates().stream().flatMap(s -> s.findMatches(predicate)));
return Stream.concat(Spell.super.findMatches(predicate), getDelegates().stream().flatMap(s -> s.findMatches(predicate)));
}
@Override
@ -95,18 +93,18 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
getDelegates(PROJECTILE_DELEGATE).forEach(a -> a.onImpact(projectile, pos, state));
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
getDelegates(BlockHitListener.PREDICATE).forEach(a -> a.onImpact(projectile, hit));
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
getDelegates(PROJECTILE_DELEGATE).forEach(a -> a.onImpact(projectile, entity));
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
getDelegates(EntityHitListener.PREDICATE).forEach(a -> a.onImpact(projectile, hit));
}
@Override
public void configureProjectile(MagicProjectileEntity projectile, Caster<?> caster) {
getDelegates(PROJECTILE_SPELL).forEach(a -> a.configureProjectile(projectile, caster));
getDelegates(ConfigurationListener.PREDICATE).forEach(a -> a.configureProjectile(projectile, caster));
}
@Override

View file

@ -1,22 +0,0 @@
package com.minelittlepony.unicopia.ability.magic.spell;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
/**
* Magic effects that can be thrown.
*/
public interface ProjectileSpell extends Spell, ProjectileDelegate {
@Override
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (!projectile.isClient()) {
tick(projectile, Situation.PROJECTILE);
}
}
default void configureProjectile(MagicProjectileEntity projectile, Caster<?> caster) { }
}

View file

@ -5,7 +5,6 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.effect.*;
import com.minelittlepony.unicopia.block.data.ModificationType;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleHandle;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.util.MagicalDamageSource;

View file

@ -9,16 +9,18 @@ import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class AttractiveSpell extends ShieldSpell implements ProjectileSpell, HomingSpell, TimedSpell {
public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSpell, ProjectileDelegate.EntityHitListener {
private final EntityReference<Entity> target = new EntityReference<>();
@ -140,10 +142,10 @@ public class AttractiveSpell extends ShieldSpell implements ProjectileSpell, Hom
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
if (!isDead() && getTraits().get(Trait.CHAOS) > 0) {
setDead();
Caster.of(entity).ifPresent(getTypeAndTraits()::apply);
Caster.of(hit.getEntity()).ifPresent(getTypeAndTraits()::apply);
}
}

View file

@ -5,18 +5,19 @@ import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.mixin.MixinFallingBlockEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.Trace;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@ -24,7 +25,7 @@ import net.minecraft.world.World;
/**
* Picks up and throws an entity or block.
*/
public class CatapultSpell extends AbstractSpell implements ProjectileSpell {
public class CatapultSpell extends AbstractSpell implements ProjectileDelegate.BlockHitListener, ProjectileDelegate.EntityHitListener {
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
.with(Trait.FOCUS, 50)
.with(Trait.KNOWLEDGE, 1)
@ -40,16 +41,16 @@ public class CatapultSpell extends AbstractSpell implements ProjectileSpell {
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (!projectile.isClient() && projectile.canModifyAt(pos)) {
createBlockEntity(projectile.world, pos, e -> apply(projectile, e));
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
if (!projectile.isClient() && projectile.canModifyAt(hit.getBlockPos())) {
createBlockEntity(projectile.world, hit.getBlockPos(), e -> apply(projectile, e));
}
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
if (!projectile.isClient()) {
apply(projectile, entity);
apply(projectile, hit.getEntity());
}
}

View file

@ -5,7 +5,6 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.magic.Affine;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
@ -18,7 +17,6 @@ import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.entity.damage.DamageSource;
@ -29,6 +27,8 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.explosion.Explosion.DestructionType;
@ -40,7 +40,7 @@ import net.minecraft.world.explosion.Explosion.DestructionType;
* - Garbage bin
* - Link with a teleportation spell to create a wormhole
*/
public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell {
public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelegate.BlockHitListener {
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
.with(Trait.CHAOS, 5)
.with(Trait.KNOWLEDGE, 1)
@ -58,8 +58,9 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
if (!projectile.isClient()) {
BlockPos pos = hit.getBlockPos();
projectile.world.createExplosion(projectile, pos.getX(), pos.getY(), pos.getZ(), 3, DestructionType.NONE);
toPlaceable().tick(projectile, Situation.BODY);
}
@ -212,8 +213,8 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell
if (target instanceof MagicProjectileEntity projectile) {
Item item = projectile.getStack().getItem();
if (item instanceof ProjectileDelegate p && master != null) {
p.onImpact(projectile, master);
if (item instanceof ProjectileDelegate.EntityHitListener p && master != null) {
p.onImpact(projectile, new EntityHitResult(master));
}
} else if (target instanceof PersistentProjectileEntity) {
if (master != null) {

View file

@ -3,18 +3,21 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.HomingSpell;
import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.EntityReference;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.entity.Entity;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.util.hit.EntityHitResult;
public class FireBoltSpell extends AbstractSpell implements ProjectileSpell, HomingSpell {
public class FireBoltSpell extends AbstractSpell implements HomingSpell,
ProjectileDelegate.ConfigurationListener, ProjectileDelegate.EntityHitListener {
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
.with(Trait.FOCUS, 10)
.with(Trait.CHAOS, 1)
@ -35,8 +38,8 @@ public class FireBoltSpell extends AbstractSpell implements ProjectileSpell, Hom
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
entity.setOnFireFor(90);
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
hit.getEntity().setOnFireFor(90);
}
@Override

View file

@ -6,12 +6,12 @@ import com.minelittlepony.unicopia.EquinePredicates;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell;
import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.block.state.StateMaps;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.VecHelper;
import com.minelittlepony.unicopia.util.shape.Sphere;
@ -29,6 +29,8 @@ import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@ -37,7 +39,7 @@ import net.minecraft.world.explosion.Explosion.DestructionType;
/**
* Simple fire spell that triggers an effect when used on a block.
*/
public class FireSpell extends AbstractAreaEffectSpell implements ProjectileSpell {
public class FireSpell extends AbstractAreaEffectSpell implements ProjectileDelegate.BlockHitListener, ProjectileDelegate.EntityHitListener {
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
.with(Trait.FIRE, 15)
.build();
@ -47,16 +49,18 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileSpel
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
if (!projectile.isClient()) {
projectile.getReferenceWorld().createExplosion(projectile.getEntity(), pos.getX(), pos.getY(), pos.getZ(), 2, DestructionType.DESTROY);
Vec3d pos = hit.getPos();
projectile.getReferenceWorld().createExplosion(projectile.getOwner(), pos.getX(), pos.getY(), pos.getZ(), 2, DestructionType.DESTROY);
}
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
if (!projectile.isClient()) {
projectile.getReferenceWorld().createExplosion(entity, entity.getX(), entity.getY(), entity.getZ(), 2, DestructionType.DESTROY);
Entity entity = hit.getEntity();
projectile.getReferenceWorld().createExplosion(projectile.getOwner(), entity.getX(), entity.getY(), entity.getZ(), 2, DestructionType.DESTROY);
}
}

View file

@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.block.state.StateMaps;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.PosHelper;
import com.minelittlepony.unicopia.util.shape.Sphere;
@ -14,7 +15,7 @@ import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class ScorchSpell extends FireSpell {
public class ScorchSpell extends FireSpell implements ProjectileDelegate.ConfigurationListener {
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
.with(Trait.FIRE, 10)
.build();

View file

@ -9,10 +9,10 @@ import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell;
import com.minelittlepony.unicopia.entity.UEntities;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.Registries;
import net.minecraft.entity.Entity;
@ -21,12 +21,13 @@ import net.minecraft.entity.SpawnGroup;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.Util;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.world.World;
/**
* Transforms whatever entity it strikes into a random other entity.
*/
public class TransformationSpell extends AbstractSpell implements ProjectileSpell {
public class TransformationSpell extends AbstractSpell implements ProjectileDelegate.EntityHitListener {
protected TransformationSpell(CustomisedSpellType<?> type) {
super(type);
}
@ -37,10 +38,11 @@ public class TransformationSpell extends AbstractSpell implements ProjectileSpel
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
if (projectile.world.isClient) {
return;
}
Entity entity = hit.getEntity();
pickType(entity.getType(), entity.world).flatMap(type -> convert(entity, type)).ifPresentOrElse(e -> {
entity.playSound(USounds.SPELL_TRANSFORM_TRANSMUTE_ENTITY, 1, 1);
}, () -> {

View file

@ -21,6 +21,7 @@ import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.WorldEvents;
@ -51,8 +52,10 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
super.onImpact(projectile, entity);
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
super.onImpact(projectile, hit);
Entity entity = hit.getEntity();
if (!entity.isAttackable() || !(projectile instanceof FlyingItemEntity)) {
return;
@ -121,7 +124,7 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
}
@Override
protected void onImpact(MagicProjectileEntity projectile) {
public void onImpact(MagicProjectileEntity projectile) {
ItemStack stack = getAppearanceStack(projectile.getStack());
stack.damage(1, projectile.world.random, null);
projectile.dropStack(stack);

View file

@ -6,8 +6,8 @@ import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.entity.PhysicsBodyProjectileEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.BlockState;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.dispenser.ProjectileDispenserBehavior;
import net.minecraft.entity.FlyingItemEntity;
@ -16,12 +16,12 @@ import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Position;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
public class HeavyProjectileItem extends ProjectileItem {
public class HeavyProjectileItem extends ProjectileItem implements ProjectileDelegate.BlockHitListener {
public HeavyProjectileItem(Settings settings, float projectileDamage) {
super(settings, projectileDamage);
@ -52,13 +52,13 @@ public class HeavyProjectileItem extends ProjectileItem {
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
if (projectile.world.getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
float damage = projectile instanceof FlyingItemEntity ? getProjectileDamage(((FlyingItemEntity)projectile).getStack()) : 0;
if (damage > 0 && projectile.world.random.nextInt(90) == 0) {
if (state.isIn(UTags.FRAGILE)) {
projectile.world.breakBlock(pos, true);
if (projectile.world.getBlockState(hit.getBlockPos()).isIn(UTags.FRAGILE)) {
projectile.world.breakBlock(hit.getBlockPos(), true);
}
}
}

View file

@ -7,11 +7,10 @@ import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LightningEntity;
@ -20,13 +19,12 @@ import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;
import net.minecraft.world.WorldEvents;
public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallback {
public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallback, ProjectileDelegate.HitListener {
private final boolean rain;
private final boolean thunder;
@ -82,16 +80,7 @@ public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallba
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
onImpact(projectile);
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
onImpact(projectile);
}
protected void onImpact(MagicProjectileEntity projectile) {
public void onImpact(MagicProjectileEntity projectile) {
if (!projectile.world.isClient()) {
ServerWorld world = (ServerWorld)projectile.world;

View file

@ -3,7 +3,6 @@ package com.minelittlepony.unicopia.item;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.util.SoundEmitter;
import net.minecraft.entity.player.PlayerEntity;
@ -17,7 +16,7 @@ import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
abstract class ProjectileItem extends Item implements ProjectileDelegate {
abstract class ProjectileItem extends Item {
private final float projectileDamage;

View file

@ -1,6 +1,8 @@
package com.minelittlepony.unicopia.projectile;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
@ -10,7 +12,6 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.Levelled;
import com.minelittlepony.unicopia.ability.magic.SpellContainer;
import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
import com.minelittlepony.unicopia.entity.EntityPhysics;
@ -273,7 +274,7 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
protected void onBlockHit(BlockHitResult hit) {
super.onBlockHit(hit);
forEachDelegates(effect -> effect.onImpact(this, hit.getBlockPos(), world.getBlockState(hit.getBlockPos())));
forEachDelegates(effect -> effect.onImpact(this, hit), ProjectileDelegate.BlockHitListener.PREDICATE);
}
@Override
@ -291,20 +292,16 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
entity.damage(DamageSource.thrownProjectile(this, getOwner()), getThrowDamage());
}
forEachDelegates(effect -> effect.onImpact(this, entity));
forEachDelegates(effect -> effect.onImpact(this, hit), ProjectileDelegate.EntityHitListener.PREDICATE);
}
}
protected void forEachDelegates(Consumer<ProjectileDelegate> consumer) {
protected <T extends ProjectileDelegate> void forEachDelegates(Consumer<T> consumer, Function<Object, T> predicate) {
getSpellSlot().forEach(spell -> {
if (SpellPredicate.HAS_PROJECTILE_EVENTS.test(spell)) {
consumer.accept((ProjectileDelegate)spell);
}
Optional.ofNullable(predicate.apply(spell)).ifPresent(consumer);
return Operation.SKIP;
}, world.isClient);
if (getItem().getItem() instanceof ProjectileDelegate) {
consumer.accept(((ProjectileDelegate)getItem().getItem()));
}
Optional.ofNullable(predicate.apply(getItem().getItem())).ifPresent(consumer);
}
@Override

View file

@ -1,17 +1,46 @@
package com.minelittlepony.unicopia.projectile;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import java.util.function.Function;
import com.minelittlepony.unicopia.ability.magic.Caster;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
public interface ProjectileDelegate {
/**
* Called once the projectile lands either hitting the ground or an entity.
*/
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {}
interface ConfigurationListener extends ProjectileDelegate {
Function<Object, ConfigurationListener> PREDICATE = a -> a instanceof ConfigurationListener ? (ConfigurationListener)a : null;
/**
* Called once the projectile lands either hitting the ground or an entity.
*/
default void onImpact(MagicProjectileEntity projectile, Entity entity) {}
void configureProjectile(MagicProjectileEntity projectile, Caster<?> caster);
}
interface HitListener extends BlockHitListener, EntityHitListener {
@Override
default void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
onImpact(projectile);
}
@Override
default void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
onImpact(projectile);
}
void onImpact(MagicProjectileEntity projectile);
}
interface BlockHitListener extends ProjectileDelegate {
Function<Object, BlockHitListener> PREDICATE = a -> a instanceof BlockHitListener ? (BlockHitListener)a : null;
/**
* Called once the projectile lands either hitting the ground or an entity.
*/
void onImpact(MagicProjectileEntity projectile, BlockHitResult hit);
}
interface EntityHitListener extends ProjectileDelegate {
Function<Object, EntityHitListener> PREDICATE = a -> a instanceof EntityHitListener ? (EntityHitListener)a : null;
/**
* Called once the projectile lands either hitting the ground or an entity.
*/
void onImpact(MagicProjectileEntity projectile, EntityHitResult hit);
}
}