package net.t7seven7t.craftfx.effect; import net.t7seven7t.craftfx.Registry; import net.t7seven7t.craftfx.data.ConfigData; import net.t7seven7t.craftfx.data.effect.DurationData; import net.t7seven7t.craftfx.data.effect.EffectTypeData; import net.t7seven7t.craftfx.data.effect.ExplosionData; import net.t7seven7t.craftfx.data.effect.ExtentData; import net.t7seven7t.craftfx.data.effect.ModifyFoodData; import net.t7seven7t.craftfx.data.effect.ModifyHealthData; import net.t7seven7t.craftfx.data.effect.SoundData; import net.t7seven7t.craftfx.data.effect.SpeedData; import net.t7seven7t.craftfx.data.generic.EntityTypeData; import net.t7seven7t.craftfx.util.MessageUtil; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Creature; import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.List; import java.util.Optional; import static net.t7seven7t.craftfx.effect.ExtentState.END; import static net.t7seven7t.craftfx.effect.ExtentState.START; /** * */ public class EffectRegistry implements Registry<EffectSpec> { /** * List of all effect specs */ private final List<EffectSpec> effectSpecList = new ArrayList<>(); public EffectRegistry() { initDefaults(); } @Override public void register(EffectSpec spec) { for (String alias : spec.getAliases()) { if (getSpec(alias).isPresent()) { throw new IllegalArgumentException("An EffectSpec is already registered " + "with the alias " + alias); } } effectSpecList.add(spec); } @Override public Optional<EffectSpec> getSpec(String alias) { alias = alias.toLowerCase(); for (EffectSpec spec : effectSpecList) { if (spec.getAliases().contains(alias)) return Optional.of(spec); } return Optional.empty(); } private void initDefaults() { register(EffectSpec.builder() .aliases("debug") .effect(c -> { MessageUtil.message(c.getInitiator(), "Triggered %s!", c.getTriggerSpec()); c.forTargets(t -> MessageUtil.message(c.getInitiator(), " - %s", t)); }) .build()); register(EffectSpec.builder() .aliases("fly") .data(new SpeedData()) .data(new ExtentData(null)) .effect(START, c -> { final SpeedData speedData = c.getData(SpeedData.class).get(); c.forTargets(t -> t.getPlayer().ifPresent(p -> { p.setAllowFlight(true); p.setVelocity(p.getVelocity().setY(1f)); p.setFlySpeed(speedData.getSpeed()); c.run(() -> { if (p.getAllowFlight()) p.setFlying(true); }); })); }).effect(END, c -> c.forTargets(t -> t.getPlayer().ifPresent(p -> { p.setAllowFlight(false); p.setFlying(false); }))).build()); register(EffectSpec.builder() .aliases("message", "msg") .effect(c -> { final Optional<String> message = c.getData(ConfigData.class).get() .get("message", String.class); message.ifPresent(m -> c.forTargets( t -> t.getPlayer().ifPresent(p -> MessageUtil.message(p, m)))); }).build()); register(EffectSpec.builder() .aliases("burn") .data(new DurationData(20L)) .effect(c -> { final DurationData data = c.getData(DurationData.class).get(); c.forTargets(t -> { t.getEntity().ifPresent(e -> e.setFireTicks((int) data.getDurationTicks())); t.getBlock().ifPresent(b -> { Block b1 = b.getRelative(BlockFace.UP); if (b1.isEmpty()) b1.setType(Material.FIRE); }); t.getLocation().ifPresent(l -> l.getWorld() .createExplosion(l.getX(), l.getY(), l.getZ(), 2, true, false)); }); }).build()); register(EffectSpec.builder() .aliases("bound armor") .data(new ExtentData(null)) // todo add effect with data for getting armor to equip .build()); register(EffectSpec.builder() .aliases("bukkit effect", "effect") .data(new EffectTypeData(0)) .effect(c -> { final EffectTypeData data = c.getData(EffectTypeData.class).get(); if (data.getEffect() == null) return; c.forTargets(t -> t.getAsLocation().ifPresent(l -> l.getWorld() .playEffect(l, data.getEffect(), data.getEffectData()))); }).build()); register(EffectSpec.builder() .aliases("disarm") .data(new DurationData(40L)) .effect(c -> { final DurationData data = c.getData(DurationData.class).get(); c.forTargets(t -> { t.getPlayer().ifPresent(p -> { final ItemStack item = p.getItemInHand(); if (item == null) return; final Item i = p.getWorld() .dropItemNaturally(p.getLocation(), item); p.setItemInHand(null); i.setPickupDelay((int) data.getDurationTicks()); }); t.getEntity(Creature.class).ifPresent(e -> { final EntityEquipment equipment = e.getEquipment(); final ItemStack item = equipment.getItemInHand(); if (item == null) return; final Item i = e.getWorld() .dropItemNaturally(e.getLocation(), item); equipment.setItemInHand(null); i.setPickupDelay((int) data.getDurationTicks()); }); }); }).build()); register(EffectSpec.builder() .aliases("lightning") .effect(c -> c.forTargets(t -> t.getAsLocation().ifPresent(l -> l.getWorld().strikeLightning(l)))).build()); register(EffectSpec.builder() .aliases("sound") .data(new SoundData()) .effect(c -> { final SoundData data = c.getData(SoundData.class).get(); c.forTargets(t -> t.getPlayer().ifPresent(p -> p.playSound(p.getLocation(), data.getSound(), data.getVolume(), data.getPitch()))); }).build()); register(EffectSpec.builder() .aliases("spawn entity") .data(new EntityTypeData()) .effect(c -> { final EntityTypeData data = c.getData(EntityTypeData.class).get(); if (!data.getEntityType().isPresent()) return; c.forTargets(t -> t.getAsLocation().ifPresent(l -> l.getWorld().spawnEntity(l, data.getEntityType().get()))); }).build()); register(EffectSpec.builder() .aliases("explosion") .data(new ExplosionData(4f, false, false)) .effect(c -> { final ExplosionData data = c.getData(ExplosionData.class).get(); c.forTargets(t -> t.getAsLocation().ifPresent(l -> l.getWorld() .createExplosion(l.getX(), l.getY(), l.getZ(), data.getPower(), data.isSetsFire(), data.isBlockDamage()))); }).build()); register(EffectSpec.builder() .aliases("invisibility") .data(new ExtentData(null)) .effect(START, c -> c.forTargets(t -> t.getPlayer().ifPresent(p -> { for (Player p1 : Bukkit.getOnlinePlayers()) { if (p1 == p) continue; p1.hidePlayer(p); } }))).effect(END, c -> c.forTargets(t -> t.getPlayer().ifPresent(p -> { for (Player p1 : Bukkit.getOnlinePlayers()) { if (p1 == p) continue; p1.showPlayer(p); } }))).build()); register(EffectSpec.builder() .aliases("modify health", "change health") .data(new ModifyHealthData(5)) // +ve damages the entity .effect(c -> { final ModifyHealthData data = c.getData(ModifyHealthData.class).get(); c.forTargets(t -> t.getEntity(LivingEntity.class).ifPresent(e -> { final double newHealth = e.getHealth() - data.getHealthAmount(); e.setHealth(newHealth < 0 ? 0 : newHealth > e.getMaxHealth() ? e.getMaxHealth() : newHealth); })); }).build()); register(EffectSpec.builder() .aliases("modify food level", "satiate") .data(new ModifyFoodData(20)) .effect(c -> { final ModifyFoodData data = c.getData(ModifyFoodData.class).get(); c.forTargets(t -> t.getPlayer().ifPresent(p -> { final int newFoodLevel = p.getFoodLevel() + data.getFeedAmount(); final float saturation = p.getFoodLevel() > newFoodLevel ? p .getSaturation() : p.getFoodLevel(); p.setFoodLevel( newFoodLevel > 20 ? 20 : newFoodLevel < 0 ? 0 : newFoodLevel); p.setSaturation(saturation); })); }).build()); register(EffectSpec.builder() .aliases("modify walk speed", "speed") .data(new ExtentData(null)) .data(new SpeedData()) .effect(START, c -> { final SpeedData data = c.getData(SpeedData.class).get(); c.forTargets(t -> t.getPlayer().ifPresent(p -> p.setWalkSpeed(data.getSpeed()))); }).effect(END, c -> c.forTargets(t -> t.getPlayer().ifPresent(p -> p.setWalkSpeed(0.2f)))) .build()); } }