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;
import java.util.Collection;
import java.util.UUID;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
@ -20,6 +19,8 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.BlockPos;
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;
@ -57,6 +58,7 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
public SpellTraits getTraits() {
return getDelegates().stream().map(Spell::getTraits).reduce(SpellTraits.EMPTY, SpellTraits::union);
}
@Override
public UUID getUuid() {
return uuid;
@ -84,35 +86,27 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
@Override
public void onDestroyed(Caster<?> caster) {
getDelegates().forEach(spell -> spell.onDestroyed(caster));
getDelegates().forEach(a -> a.onDestroyed(caster));
}
@Override
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
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> {
((ProjectileDelegate<MagicProjectileEntity>)a).onImpact(projectile, pos, state);
});
getDelegates(PROJECTILE_DELEGATE).forEach(a -> a.onImpact(projectile, pos, state));
}
@SuppressWarnings("unchecked")
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
getDelegates().stream().filter(a -> a instanceof ProjectileDelegate).forEach(a -> {
((ProjectileDelegate<MagicProjectileEntity>)a).onImpact(projectile, entity);
});
getDelegates(PROJECTILE_DELEGATE).forEach(a -> a.onImpact(projectile, entity));
}
@Override
public void configureProjectile(MagicProjectileEntity projectile, Caster<?> caster) {
getDelegates().stream().filter(a -> a instanceof ProjectileSpell).forEach(a -> {
((ProjectileSpell)a).configureProjectile(projectile, caster);
});
getDelegates(PROJECTILE_SPELL).forEach(a -> a.configureProjectile(projectile, caster));
}
@Override
@ -134,6 +128,10 @@ public abstract class AbstractDelegatingSpell implements ProjectileSpell {
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) {
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.
*/
public interface ProjectileSpell extends Spell, ProjectileDelegate<MagicProjectileEntity> {
public interface ProjectileSpell extends Spell, ProjectileDelegate {
@Override
default void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (!projectile.isClient()) {

View file

@ -24,7 +24,6 @@ import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.Item;
import net.minecraft.nbt.NbtCompound;
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;
}
@SuppressWarnings("unchecked")
@Override
protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) {
@ -212,10 +210,10 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileSpell
@Nullable
Entity master = source.getMaster();
if (target instanceof MagicProjectileEntity) {
Item item = ((MagicProjectileEntity)target).getStack().getItem();
if (item instanceof ProjectileDelegate && master != null) {
((ProjectileDelegate<ProjectileEntity>) item).onImpact(((ProjectileEntity)target), master);
if (target instanceof MagicProjectileEntity projectile) {
Item item = projectile.getStack().getItem();
if (item instanceof ProjectileDelegate p && master != null) {
p.onImpact(projectile, master);
}
} else if (target instanceof PersistentProjectileEntity) {
if (master != null) {

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.Block;
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.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.world.ServerWorld;
@ -50,7 +50,7 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
}
@Override
public void onImpact(ProjectileEntity projectile, Entity entity) {
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
super.onImpact(projectile, entity);
if (!entity.isAttackable() || !(projectile instanceof FlyingItemEntity)) {
@ -119,11 +119,8 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
}
@Override
protected void onImpact(ProjectileEntity projectile) {
if (!(projectile instanceof FlyingItemEntity)) {
return;
}
ItemStack stack = getAppearanceStack(((FlyingItemEntity)projectile).getStack());
protected void onImpact(MagicProjectileEntity projectile) {
ItemStack stack = getAppearanceStack(projectile.getStack());
stack.damage(1, projectile.world.random, null);
projectile.dropStack(stack);
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.UTags;
import com.minelittlepony.unicopia.entity.PhysicsBodyProjectileEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.DispenserBlock;
@ -51,7 +52,7 @@ public class HeavyProjectileItem extends ProjectileItem {
}
@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)) {
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.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -13,7 +15,6 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
@ -81,16 +82,16 @@ public class JarItem extends ProjectileItem implements ItemImpl.GroundTickCallba
}
@Override
public void onImpact(ProjectileEntity projectile, BlockPos pos, BlockState state) {
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
onImpact(projectile);
}
@Override
public void onImpact(ProjectileEntity projectile, Entity entity) {
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
onImpact(projectile);
}
protected void onImpact(ProjectileEntity projectile) {
protected void onImpact(MagicProjectileEntity projectile) {
if (!projectile.world.isClient()) {
ServerWorld world = (ServerWorld)projectile.world;

View file

@ -16,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<ProjectileEntity> {
abstract class ProjectileItem extends Item implements ProjectileDelegate {
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<MagicProjectileEntity>> consumer) {
protected void forEachDelegates(Consumer<ProjectileDelegate> consumer) {
getSpellSlot().forEach(spell -> {
if (SpellPredicate.HAS_PROJECTILE_EVENTS.test(spell)) {
consumer.accept((ProjectileDelegate<MagicProjectileEntity>)spell);
consumer.accept((ProjectileDelegate)spell);
}
return Operation.SKIP;
}, true);
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.entity.Entity;
import net.minecraft.entity.projectile.ProjectileEntity;
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.
*/
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.
*/
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.
*/
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) {
if (throwable instanceof ProjectileEntity) {
((ProjectileEntity)throwable).setVelocity(heading.x, heading.y, heading.z, velocity, inaccuracy);
if (throwable instanceof ProjectileEntity p) {
p.setVelocity(heading.x, heading.y, heading.z, velocity, inaccuracy);
} else {
heading = heading.normalize().multiply(velocity);