Simplify projectile delegate code

This commit is contained in:
Sollace 2022-09-14 11:53:31 +02:00
parent 8e65a265f9
commit 89e8f0dccc
10 changed files with 39 additions and 47 deletions

View file

@ -1,7 +1,6 @@
package com.minelittlepony.unicopia.ability.magic.spell; package com.minelittlepony.unicopia.ability.magic.spell;
import java.util.Collection; import java.util.*;
import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -20,6 +19,8 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
public abstract class AbstractDelegatingSpell implements ProjectileSpell { 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;
private boolean isDirty; private boolean isDirty;
@ -57,6 +58,7 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
public SpellTraits getTraits() { public SpellTraits getTraits() {
return getDelegates().stream().map(Spell::getTraits).reduce(SpellTraits.EMPTY, SpellTraits::union); return getDelegates().stream().map(Spell::getTraits).reduce(SpellTraits.EMPTY, SpellTraits::union);
} }
@Override @Override
public UUID getUuid() { public UUID getUuid() {
return uuid; return uuid;
@ -84,35 +86,27 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
@Override @Override
public void onDestroyed(Caster<?> caster) { public void onDestroyed(Caster<?> caster) {
getDelegates().forEach(spell -> spell.onDestroyed(caster)); getDelegates().forEach(a -> a.onDestroyed(caster));
} }
@Override @Override
public boolean tick(Caster<?> source, Situation situation) { public boolean tick(Caster<?> source, Situation situation) {
return execute(getDelegates().stream(), spell -> spell.tick(source, situation)); return execute(getDelegates().stream(), a -> a.tick(source, situation));
} }
@SuppressWarnings("unchecked")
@Override @Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> { getDelegates(PROJECTILE_DELEGATE).forEach(a -> a.onImpact(projectile, pos, state));
((ProjectileDelegate<MagicProjectileEntity>)a).onImpact(projectile, pos, state);
});
} }
@SuppressWarnings("unchecked")
@Override @Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) { public void onImpact(MagicProjectileEntity projectile, Entity entity) {
getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> { getDelegates(PROJECTILE_DELEGATE).forEach(a -> a.onImpact(projectile, entity));
((ProjectileDelegate<MagicProjectileEntity>)a).onImpact(projectile, entity);
});
} }
@Override @Override
public void configureProjectile(MagicProjectileEntity projectile, Caster<?> caster) { public void configureProjectile(MagicProjectileEntity projectile, Caster<?> caster) {
getDelegates().stream().filter(a -> a instanceof ProjectileSpell).forEach(a -> { getDelegates(PROJECTILE_SPELL).forEach(a -> a.configureProjectile(projectile, caster));
((ProjectileSpell)a).configureProjectile(projectile, caster);
});
} }
@Override @Override
@ -134,6 +128,10 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
protected abstract void saveDelegates(NbtCompound compound); protected abstract void saveDelegates(NbtCompound compound);
private <T> Stream<T> getDelegates(Function<? super Spell, T> cast) {
return getDelegates().stream().map(cast).filter(Objects::nonNull);
}
private static boolean execute(Stream<Spell> spells, Function<Spell, Boolean> action) { private static boolean execute(Stream<Spell> spells, Function<Spell, Boolean> action) {
return spells.reduce(false, (u, a) -> action.apply(a), (a, b) -> a || b); return spells.reduce(false, (u, a) -> action.apply(a), (a, b) -> a || b);
} }

View file

@ -10,8 +10,7 @@ import net.minecraft.util.math.BlockPos;
/** /**
* Magic effects that can be thrown. * Magic effects that can be thrown.
*/ */
public interface ProjectileSpell extends Spell, ProjectileDelegate<MagicProjectileEntity> { public interface ProjectileSpell extends Spell, ProjectileDelegate {
@Override @Override
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (!projectile.isClient()) { if (!projectile.isClient()) {

View file

@ -24,7 +24,6 @@ import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity; import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
@ -198,7 +197,6 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell
return 10 + Math.min(15, Math.min(0.5F + pulse, (float)Math.exp(age) / 8F - 90) + accumulatedMass / 10F) + pulse; return 10 + Math.min(15, Math.min(0.5F + pulse, (float)Math.exp(age) / 8F - 90) + accumulatedMass / 10F) + pulse;
} }
@SuppressWarnings("unchecked")
@Override @Override
protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) { protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) {
@ -212,10 +210,10 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell
@Nullable @Nullable
Entity master = source.getMaster(); Entity master = source.getMaster();
if (target instanceof MagicProjectileEntity) { if (target instanceof MagicProjectileEntity projectile) {
Item item = ((MagicProjectileEntity)target).getStack().getItem(); Item item = projectile.getStack().getItem();
if (item instanceof ProjectileDelegate && master != null) { if (item instanceof ProjectileDelegate p && master != null) {
((ProjectileDelegate<ProjectileEntity>) item).onImpact(((ProjectileEntity)target), master); p.onImpact(projectile, master);
} }
} else if (target instanceof PersistentProjectileEntity) { } else if (target instanceof PersistentProjectileEntity) {
if (master != null) { if (master != null) {

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.entity.IItemEntity; import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -14,7 +15,6 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributeInstance; import net.minecraft.entity.attribute.EntityAttributeInstance;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
@ -50,7 +50,7 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
} }
@Override @Override
public void onImpact(ProjectileEntity projectile, Entity entity) { public void onImpact(MagicProjectileEntity projectile, Entity entity) {
super.onImpact(projectile, entity); super.onImpact(projectile, entity);
if (!entity.isAttackable() || !(projectile instanceof FlyingItemEntity)) { if (!entity.isAttackable() || !(projectile instanceof FlyingItemEntity)) {
@ -119,11 +119,8 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
} }
@Override @Override
protected void onImpact(ProjectileEntity projectile) { protected void onImpact(MagicProjectileEntity projectile) {
if (!(projectile instanceof FlyingItemEntity)) { ItemStack stack = getAppearanceStack(projectile.getStack());
return;
}
ItemStack stack = getAppearanceStack(((FlyingItemEntity)projectile).getStack());
stack.damage(1, projectile.world.random, null); stack.damage(1, projectile.world.random, null);
projectile.dropStack(stack); projectile.dropStack(stack);
projectile.world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, projectile.getBlockPos(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState())); projectile.world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, projectile.getBlockPos(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState()));

View file

@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.entity.PhysicsBodyProjectileEntity; import com.minelittlepony.unicopia.entity.PhysicsBodyProjectileEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.DispenserBlock; import net.minecraft.block.DispenserBlock;
@ -51,7 +52,7 @@ public class HeavyProjectileItem extends ProjectileItem {
} }
@Override @Override
public void onImpact(ProjectileEntity projectile, BlockPos pos, BlockState state) { public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (projectile.world.getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) { if (projectile.world.getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
float damage = projectile instanceof FlyingItemEntity ? getProjectileDamage(((FlyingItemEntity)projectile).getStack()) : 0; float damage = projectile instanceof FlyingItemEntity ? getProjectileDamage(((FlyingItemEntity)projectile).getStack()) : 0;

View file

@ -6,6 +6,8 @@ import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemImpl; import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -13,7 +15,6 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity; import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LightningEntity; import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.entity.Entity.RemovalReason; import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
@ -81,16 +82,16 @@ public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallba
} }
@Override @Override
public void onImpact(ProjectileEntity projectile, BlockPos pos, BlockState state) { public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
onImpact(projectile); onImpact(projectile);
} }
@Override @Override
public void onImpact(ProjectileEntity projectile, Entity entity) { public void onImpact(MagicProjectileEntity projectile, Entity entity) {
onImpact(projectile); onImpact(projectile);
} }
protected void onImpact(ProjectileEntity projectile) { protected void onImpact(MagicProjectileEntity projectile) {
if (!projectile.world.isClient()) { if (!projectile.world.isClient()) {
ServerWorld world = (ServerWorld)projectile.world; ServerWorld world = (ServerWorld)projectile.world;

View file

@ -16,7 +16,7 @@ import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult; import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World; import net.minecraft.world.World;
abstract class ProjectileItem extends Item implements ProjectileDelegate<ProjectileEntity> { abstract class ProjectileItem extends Item implements ProjectileDelegate {
private final float projectileDamage; private final float projectileDamage;

View file

@ -290,16 +290,15 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
} }
} }
@SuppressWarnings("unchecked") protected void forEachDelegates(Consumer<ProjectileDelegate> consumer) {
protected void forEachDelegates(Consumer<ProjectileDelegate<MagicProjectileEntity>> consumer) {
getSpellSlot().forEach(spell -> { getSpellSlot().forEach(spell -> {
if (SpellPredicate.HAS_PROJECTILE_EVENTS.test(spell)) { if (SpellPredicate.HAS_PROJECTILE_EVENTS.test(spell)) {
consumer.accept((ProjectileDelegate<MagicProjectileEntity>)spell); consumer.accept((ProjectileDelegate)spell);
} }
return Operation.SKIP; return Operation.SKIP;
}, true); }, true);
if (getItem().getItem() instanceof ProjectileDelegate) { if (getItem().getItem() instanceof ProjectileDelegate) {
consumer.accept(((ProjectileDelegate<MagicProjectileEntity>)getItem().getItem())); consumer.accept(((ProjectileDelegate)getItem().getItem()));
} }
} }

View file

@ -2,17 +2,16 @@ package com.minelittlepony.unicopia.projectile;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
public interface ProjectileDelegate<T extends ProjectileEntity> { public interface ProjectileDelegate {
/** /**
* Called once the projectile lands either hitting the ground or an entity. * Called once the projectile lands either hitting the ground or an entity.
*/ */
default void onImpact(T projectile, BlockPos pos, BlockState state) {} default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {}
/** /**
* Called once the projectile lands either hitting the ground or an entity. * Called once the projectile lands either hitting the ground or an entity.
*/ */
default void onImpact(T projectile, Entity entity) {} default void onImpact(MagicProjectileEntity projectile, Entity entity) {}
} }

View file

@ -21,7 +21,7 @@ public interface ProjectileUtil {
* Checks if the given entity is a projectile that is not stuck in the ground. * Checks if the given entity is a projectile that is not stuck in the ground.
*/ */
static boolean isFlyingProjectile(Entity e) { static boolean isFlyingProjectile(Entity e) {
return isProjectile(e) && !(e instanceof MixinPersistentProjectileEntity && ((MixinPersistentProjectileEntity)e).isInGround()); return isProjectile(e) && !(e instanceof MixinPersistentProjectileEntity m && m.isInGround());
} }
/** /**
@ -42,8 +42,8 @@ public interface ProjectileUtil {
*/ */
static void setThrowableHeading(Entity throwable, Vec3d heading, float velocity, float inaccuracy) { static void setThrowableHeading(Entity throwable, Vec3d heading, float velocity, float inaccuracy) {
if (throwable instanceof ProjectileEntity) { if (throwable instanceof ProjectileEntity p) {
((ProjectileEntity)throwable).setVelocity(heading.x, heading.y, heading.z, velocity, inaccuracy); p.setVelocity(heading.x, heading.y, heading.z, velocity, inaccuracy);
} else { } else {
heading = heading.normalize().multiply(velocity); heading = heading.normalize().multiply(velocity);