API done (I hope)

This commit is contained in:
Paul Reilly
2023-07-18 00:22:26 -05:00
parent a84bbeea94
commit 216d65fd38
57 changed files with 1293 additions and 1111 deletions

View File

@ -2,16 +2,15 @@ package app.simplexdev.arcanumocculta;
import org.bukkit.plugin.java.JavaPlugin;
public final class ArcanumOcculta extends JavaPlugin {
public class ArcanumOcculta extends JavaPlugin
{
@Override
public void onEnable() {
// Plugin startup logic
}
@Override
public void onDisable() {
// Plugin shutdown logic
public static ArcanumOcculta getInstance()
{
return JavaPlugin.getPlugin(ArcanumOcculta.class);
}
}

View File

@ -1,32 +0,0 @@
package app.simplexdev.arcanumocculta.api.book;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public interface SpellBook {
String getBookName();
void setBookName(final String name);
String getBookDescription();
void setBookDescription(final String description);
ItemStack getBookItem();
void setBookItem(final ItemStack itemStack);
List<Spell> getSpells();
void addSpell(Spell spell);
void removeSpell(Spell spell);
Spell getSpell(final String name);
Spell getSpell(final int index);
int getSpellCount();
}

View File

@ -1,14 +0,0 @@
package app.simplexdev.arcanumocculta.api.book;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import org.bukkit.inventory.ItemStack;
public interface SpellTome {
String getTomeName();
String getTomeDescription();
ItemStack getTomeItem();
Spell getContainedSpell();
}

View File

@ -0,0 +1,137 @@
package app.simplexdev.arcanumocculta.api.caster;
import app.simplexdev.arcanumocculta.api.wand.Wand;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public abstract class AbstractCaster implements Caster
{
private final SpellBook spellBook;
private final UUID playerUUID;
private final String name;
private Wand wand;
private CasterLevel level;
private double currentExperience;
private double currentMana;
private double maxMana;
protected AbstractCaster(final Player player, final Wand wand, final SpellBook spellBook, final CasterLevel level)
{
this.spellBook = spellBook;
this.playerUUID = player.getUniqueId();
this.name = player.getName();
this.wand = wand;
this.level = level;
}
@Override
public Wand getWand()
{
return this.wand;
}
public void setWand(final Wand wand)
{
this.wand = wand;
}
@Override
public SpellBook getSpellBook()
{
return this.spellBook;
}
@Override
public UUID getUniqueId()
{
return this.playerUUID;
}
@Override
public String getName()
{
return this.name;
}
@Override
public CasterLevel getCurrentLevel()
{
return this.level;
}
public void setCurrentLevel(final CasterLevel level)
{
this.level = level;
}
@Override
public double getCurrentExperience()
{
return this.currentExperience;
}
public void setCurrentExperience(final double experience)
{
this.currentExperience = experience;
}
@Override
public double getCurrentMana()
{
return this.currentMana;
}
public void setCurrentMana(final double mana)
{
this.currentMana = mana;
}
@Override
public double getMaxMana()
{
return this.maxMana;
}
@Override
public void setMaxMana(final double mana)
{
this.maxMana = mana;
}
public void addExperience(final double experience)
{
this.currentExperience = this.currentExperience + experience;
}
public void removeExperience(final double experience)
{
this.currentExperience = this.currentExperience - experience;
}
public void addMana(final double mana)
{
this.currentMana = this.currentMana + mana;
}
public void removeMana(final double mana)
{
this.currentMana = this.currentMana - mana;
}
public void setManaToMax()
{
this.currentMana = this.maxMana;
}
public void setExperienceToZero()
{
this.currentExperience = 0;
}
@Override
public Player bukkit()
{
return Bukkit.getPlayer(this.playerUUID);
}
}

View File

@ -0,0 +1,97 @@
package app.simplexdev.arcanumocculta.api.caster;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.SplittableRandom;
import java.util.UUID;
public abstract class AbstractSpellBook implements SpellBook
{
private final List<Spell> spells = new ArrayList<>();
@Override
public boolean hasSpell(final Spell spell)
{
return getSpells().contains(spell);
}
@Override
public List<Spell> getSpells()
{
return this.spells;
}
@Override
public void addSpell(Spell spell)
{
this.spells.add(spell);
}
@Override
public void removeSpell(Spell spell)
{
this.spells.remove(spell);
}
@Override
public Spell getSpell(String id)
{
return getSpells().stream()
.filter(spell -> spell.getId().equalsIgnoreCase(id))
.findFirst()
.orElse(getSpells().get(0));
}
public Spell getSpell(UUID uuid)
{
return getSpells().stream()
.filter(spell -> spell.getUniqueId().equals(uuid))
.findFirst()
.orElse(getSpells().get(0));
}
@Override
public Spell getSpell(int index)
{
if (index < 0 || index > getSpells().size() - 1)
return getSpells().get(0);
return getSpells().get(index);
}
@Override
public int getSpellCount()
{
return getSpells().size();
}
@Override
public void setSpell(int index, Spell spell)
{
this.spells.set(index, spell);
}
@Override
public void setSpell(String name, Spell spell)
{
this.spells.set(getSpells().indexOf(getSpell(name)), spell);
}
@Override
public void clearSpells()
{
this.spells.clear();
}
public void addAll(Collection<? extends Spell> spells) {
this.spells.addAll(spells);
}
@Override
public Spell randomSpell()
{
final SplittableRandom random = new SplittableRandom();
return getSpells().get(random.nextInt(getSpells().size()));
}
}

View File

@ -0,0 +1,44 @@
package app.simplexdev.arcanumocculta.api.caster;
import app.simplexdev.arcanumocculta.api.wand.Wand;
import java.util.UUID;
import org.bukkit.entity.Player;
public interface Caster
{
Wand getWand();
void setWand(Wand wand);
SpellBook getSpellBook();
String getName();
UUID getUniqueId();
double getCurrentMana();
void setCurrentMana(double mana);
double getMaxMana();
void setMaxMana(double maxMana);
CasterLevel getCurrentLevel();
void setCurrentLevel(CasterLevel level);
double getCurrentExperience();
void setCurrentExperience(double experience);
void addMana(double mana);
void removeMana(double mana);
void addExperience(double experience);
void removeExperience(double experience);
Player bukkit();
}

View File

@ -0,0 +1,81 @@
package app.simplexdev.arcanumocculta.api.caster;
import java.text.MessageFormat;
import java.util.stream.Stream;
import org.bukkit.ChatColor;
public enum CasterLevel
{
APPRENTICE(1, 250D, "Apprentice", "an Apprentice", ChatColor.WHITE, "Lvl1"),
PRIMARY(2, 500D, "Primary", "a Primary", ChatColor.RED, "Lvl2"),
SCHOLAR(3, 750D, "Scholar", "a Scholar", ChatColor.AQUA, "Lvl3"),
PREFECT(4, 1000D, "Prefect", "a Prefect", ChatColor.BLUE, "Lvl4"),
GRADUATE(5, 1250D, "Graduate", "a Graduate", ChatColor.GRAY, "Lvl5"),
ADEPT(6, 1500D, "Adept", "an Adept", ChatColor.DARK_PURPLE, "Lvl6"),
MAGISTRATE(7, 1750D, "Magister", "a Magister", ChatColor.DARK_GREEN, "Lvl7"),
HEADMASTER(8, 2000D, "Headmaster", "a Headmaster", ChatColor.GOLD, "Lvl8"),
ARCH_MAGE(9, 4000D, "Arch-Mage", "an Arch-Mage", ChatColor.BLACK, "Lvl9");
private final int level;
private final double experienceMarker;
private final String name;
private final String plural;
private final ChatColor rankColor;
private final String suffix;
CasterLevel(final int level, final double experienceMarker, final String name, final String plural,
final ChatColor rankColor,
final String suffix)
{
this.experienceMarker = experienceMarker;
this.level = level;
this.name = name;
this.plural = plural;
this.rankColor = rankColor;
this.suffix = MessageFormat.format("{0}[{1}{2}{3}]{4}",
ChatColor.DARK_GRAY,
rankColor,
suffix,
ChatColor.DARK_GRAY,
ChatColor.RESET);
}
public static CasterLevel fromOrdinal(final int ordinal)
{
return Stream.of(CasterLevel.values())
.filter(lvl -> lvl.getLevel() == ordinal)
.findFirst()
.orElse(CasterLevel.APPRENTICE);
}
public int getLevel()
{
return this.level;
}
public String getName()
{
return this.name;
}
public String getPlural()
{
return this.plural;
}
public ChatColor getRankColor()
{
return this.rankColor;
}
public String getSuffix()
{
return this.suffix;
}
public double getExperienceMarker()
{
return this.experienceMarker;
}
}

View File

@ -0,0 +1,29 @@
package app.simplexdev.arcanumocculta.api.caster;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import java.util.List;
public interface SpellBook
{
List<Spell> getSpells();
void addSpell(Spell spell);
void removeSpell(Spell spell);
Spell getSpell(String name);
Spell getSpell(int index);
int getSpellCount();
void setSpell(int index, Spell spell);
void setSpell(String name, Spell spell);
void clearSpells();
Spell randomSpell();
boolean hasSpell(final Spell spell);
}

View File

@ -1,24 +0,0 @@
package app.simplexdev.arcanumocculta.api.display;
import app.simplexdev.arcanumocculta.api.player.Caster;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.entity.Display;
public interface SpellDisplay<T extends Display> {
T getDisplay();
Location getLocation();
World getWorld();
Caster getWhoCast();
Spell getCastSpell();
Particle[] getParticles();
void display(boolean force);
}

View File

@ -1,7 +0,0 @@
package app.simplexdev.arcanumocculta.api.effect;
import org.bukkit.potion.PotionEffectType;
public interface CompoundEffect extends Effect {
PotionEffectType[] getEffectTypes();
}

View File

@ -1,14 +0,0 @@
package app.simplexdev.arcanumocculta.api.effect;
import java.time.Duration;
public interface Effect
{
Duration getDuration();
float getAmplifier();
boolean isAmbient();
boolean forceDisplay();
}

View File

@ -1,5 +0,0 @@
package app.simplexdev.arcanumocculta.api.effect;
public interface EffectProvider<T extends Effect> {
T getEffect(Class<T> type);
}

View File

@ -1,12 +0,0 @@
package app.simplexdev.arcanumocculta.api.effect;
import app.simplexdev.arcanumocculta.api.player.Caster;
public interface PassiveEffect extends Effect
{
Caster getWandHolder();
void onTick();
PassiveEffects getPassiveEffect();
}

View File

@ -1,30 +0,0 @@
package app.simplexdev.arcanumocculta.api.effect;
import java.time.Duration;
public enum PassiveEffects {
MANA_REGEN(Duration.ofSeconds(10L), 2.0),
LIFE_STEAL(Duration.ofSeconds(5L), 1.0),
ABSORPTION(Duration.ofSeconds(30L), 4.0),
SPELL_SHIELD(Duration.ofSeconds(5L), 5.0),
IMMUNITY(Duration.ofSeconds(5L), 100.0),
WITHER(Duration.ofSeconds(5L), 2.0),
DAMAGE_BOOST(Duration.ofSeconds(5L), 2.75),
IMPROVED_ACCURACY(Duration.ofSeconds(5L), 5.0);
private final Duration duration;
private final double amount;
PassiveEffects(final Duration duration, final double amount) {
this.duration = duration;
this.amount = amount;
}
Duration getDuration() {
return this.duration;
}
double getAmount() {
return this.amount;
}
}

View File

@ -1,7 +0,0 @@
package app.simplexdev.arcanumocculta.api.effect;
import org.bukkit.entity.LivingEntity;
public interface SpecialEffect extends Effect {
void applyEffect(final LivingEntity target);
}

View File

@ -1,7 +0,0 @@
package app.simplexdev.arcanumocculta.api.effect;
import org.bukkit.potion.PotionEffectType;
public interface SpellEffect extends Effect {
PotionEffectType getEffectType();
}

View File

@ -1,96 +0,0 @@
package app.simplexdev.arcanumocculta.api.player;
import app.simplexdev.arcanumocculta.api.book.SpellBook;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.UUID;
public interface Caster {
/**
* @return The {@link UUID} of the caster.
*/
UUID getCasterUUID();
/**
* @return The name of the caster.
*/
String getDisplayName();
/**
* @return The {@link Player} associated with this caster.
*/
Player bukkit();
/**
* @return The amount of maximum mana the caster is allowed to have.
*/
double getMaximumMana();
/**
* Sets the maximum amount of mana the caster is allowed to have.
*
* @param mana The amount of mana to set the maximum to.
*/
void setMaximumMana(final double mana);
/**
* @return The amount of mana the caster currently has.
*/
double getCurrentMana();
/**
* Adds mana to the caster.
*
* @param mana The amount of mana to add.
* @return The players updated {@link #getCurrentMana()}.
*/
double addMana(final double mana);
/**
* Increases the amount of maximum mana this caster is allowed to have.
*
* @param mana The amount of mana to increase the maximum by.
* @return The players updated {@link #getMaximumMana()}.
*/
double increaseMaximumMana(final double mana);
/**
* Removes mana from the caster.
*
* @param mana The amount of mana to remove.
* @return The players updated {@link #getCurrentMana()}.
*/
double removeMana(final double mana);
/**
* Decreases the amount of maximum mana this caster is allowed to have.
*
* @param mana The amount of mana to decrease the maximum by.
* @return The players updated {@link #getMaximumMana()}.
*/
double decreaseMaximumMana(final double mana);
/**
* Sets the amount of mana the caster currently has.
*
* @param mana The amount of mana to set the user's current mana to.
*/
void setMana(final double mana);
/**
* @return The {@link SpellBook} of the caster.
*/
SpellBook getSpellbook();
/**
* @return A list of {@link SpellResistance}s the caster has.
*/
List<SpellResistance> getSpellResistances();
void addSpellResistance(SpellResistance resistance);
void removeSpellResistance(SpellResistance resistance);
boolean hasResistance(int spellOrdinal);
}

View File

@ -1,9 +0,0 @@
package app.simplexdev.arcanumocculta.api.player;
public interface SpellResistance {
String getSpellName();
double getResistance();
int getOrdinal();
}

View File

@ -1,18 +0,0 @@
package app.simplexdev.arcanumocculta.api.player;
import app.simplexdev.arcanumocculta.api.effect.PassiveEffect;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public interface Wand {
String getWandName();
String getWandDescription();
ItemStack getWandItem();
double getManaPenalty();
List<PassiveEffect> getPassiveEffects();
}

View File

@ -0,0 +1,109 @@
package app.simplexdev.arcanumocculta.api.spell;
import app.simplexdev.arcanumocculta.api.caster.Caster;
import java.util.SplittableRandom;
import org.bukkit.Bukkit;
public abstract class AbstractSpell implements Spell
{
private final String name;
private final String id;
private final String description;
private final int levelRequirement;
private final double baseDamage;
private final long effectDuration;
private final double manaCost;
private final long coolDown;
private final SplittableRandom random = new SplittableRandom();
protected AbstractSpell(final String name, final String id,
final String description, final int levelRequirement,
final double baseDamage, final long effectDuration, final double manaCost,
final long coolDown)
{
this.name = name;
this.id = id;
this.description = description;
this.levelRequirement = levelRequirement;
this.baseDamage = baseDamage;
this.effectDuration = effectDuration;
this.manaCost = manaCost;
this.coolDown = coolDown;
}
@Override
public String getName()
{
return name;
}
@Override
public String getId()
{
return this.id;
}
@Override
public String getDescription()
{
return description;
}
@Override
public int getLevelRequirement()
{
return levelRequirement;
}
@Override
public double baseDamage()
{
return baseDamage;
}
@Override
public long effectDuration()
{
return effectDuration;
}
@Override
public double manaCost()
{
return manaCost;
}
@Override
public long coolDown()
{
return coolDown;
}
@Override
public Spell dupe()
{
try
{
return this.getClass()
.getDeclaredConstructor()
.newInstance();
}
catch (ReflectiveOperationException e)
{
Bukkit.getLogger().severe(e.getMessage());
return null;
}
}
@Override
public boolean isUnlocked(Caster caster)
{
return caster.getSpellBook().hasSpell(this)
&& caster.getCurrentLevel().getLevel() >= this.levelRequirement;
}
protected SplittableRandom random()
{
return random;
}
}

View File

@ -1,23 +1,43 @@
package app.simplexdev.arcanumocculta.api.spell;
import app.simplexdev.arcanumocculta.api.effect.Effect;
import app.simplexdev.arcanumocculta.api.effect.EffectProvider;
import org.bukkit.entity.Projectile;
import app.simplexdev.arcanumocculta.api.caster.Caster;
import app.simplexdev.arcanumocculta.api.wand.Wand;
import java.util.UUID;
import java.time.Duration;
public interface Spell
{
String getName();
public interface Spell<T extends Effect> {
String getSpellName();
String getId();
String getSpellDescription();
default UUID getUniqueId()
{
return UUID.nameUUIDFromBytes(this.getName().getBytes());
}
double getManaCost();
String getDescription();
Duration getCoolDown();
int getLevelRequirement();
int getSpellLevel();
double baseDamage();
SpellProjectile<? extends Projectile> getSpellProjectile();
SpellEffect[] getSpellEffects();
T getEffect();
long effectDuration();
double manaCost();
long coolDown();
boolean isUnlocked(final Caster caster);
void cast(final Caster caster, final Wand wand);
/**
* Used to create a copy of the spell for player spell books.
* Should only ever be used by the primary list when initializing a player's spell book.
*
* @return a copy of the spell.
*/
Spell dupe();
}

View File

@ -0,0 +1,10 @@
package app.simplexdev.arcanumocculta.api.spell;
import app.simplexdev.arcanumocculta.api.caster.Caster;
import org.bukkit.entity.LivingEntity;
@FunctionalInterface
public interface SpellEffect
{
void apply(final LivingEntity target, final Caster caster);
}

View File

@ -1,18 +0,0 @@
package app.simplexdev.arcanumocculta.api.spell;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Projectile;
import java.util.List;
public interface SpellProjectile<T extends Projectile> {
Class<T> getProjectileType();
List<Particle> getParticles();
void cast(final Location target);
void cast(final LivingEntity target);
}

View File

@ -0,0 +1,18 @@
package app.simplexdev.arcanumocculta.api.spell;
public enum SpellTypes
{
SOUL_PEBBLE, SOUL_SHARD, LARGE_SOUL_SHARD, SOUL_COMET_SHARD, SOUL_COMET, SOUL_SHARD_SPIRAL, SOUL_STARS,
SOUL_STAR_SHOWER, SOUL_ARC, SOUL_BARRAGE, SOUL_BURST, SOUL_CANNON, SOUL_HAMMER, SOUL_BLAST, SOUL_EXPLOSION,
SOUL_LAMP, SOUL_PHALANX, GREAT_SOUL_PHALANX, SOUL_MIST, ARS_NOVA, ARS_ENIGMA, ARS_ULTIMA,
FLAME_SLING, FLAME_BURST, CATCH_FLAME, FLAME_BARRAGE, FIREBALL, METEORITE, METEOR, FLAME_WHIP, FLAME_FAN,
FLAME_ORB, FLAME_PILLARS, FLAME_WHIRLWIND,
WITHER_BURST, WITHER_SHOT, WITHER_SHARD, WITHER_COMET, WITHER_METEORITE,
HEALING, GREATER_HEALING, HEAL_OTHER, HEALING_HANDS, HEALING_WAVE, GUARDIAN_PROTECTION, SAVIORS_BLESSING,
DIVING_BLESSING, DIVINE_GRACE, ULTIMATE_HEALING, DIVINE_INTERVENTION, DIVINE_RETRIBUTION,
LIGHTNING_BOLT, LIGHTNING_STORM, STAR_SHOWER, STORM_CALL, LIGHTNING_BARRAGE;
}

View File

@ -0,0 +1,69 @@
package app.simplexdev.arcanumocculta.api.wand;
import org.bukkit.inventory.ItemStack;
public abstract class AbstractWand implements Wand
{
private final ItemStack item;
private final CapType capType;
private final CoreType coreType;
private final GemType gemType;
private final String name;
private final String description;
protected AbstractWand(String name,
String description, ItemStack item, CapType capType,
CoreType coreType, GemType gemType)
{
this.name = name;
this.description = description;
this.item = item;
this.capType = capType;
this.coreType = coreType;
this.gemType = gemType;
}
@Override
public String getName()
{
return name;
}
@Override
public String getDescription()
{
return description;
}
@Override
public ItemStack getItem()
{
return item;
}
@Override
public double getSpellBonus()
{
return getCapType().getSpellBoost()
+ getCoreType().getSpellBoost()
+ getGemType().getSpellBoost();
}
@Override
public CapType getCapType()
{
return capType;
}
@Override
public CoreType getCoreType()
{
return coreType;
}
@Override
public GemType getGemType()
{
return gemType;
}
}

View File

@ -0,0 +1,28 @@
package app.simplexdev.arcanumocculta.api.wand;
import org.bukkit.Material;
public enum CapType
{
IRON(Material.IRON_NUGGET, 1.0),
GOLD(Material.GOLD_NUGGET, 2.5),
DIAMOND(Material.DIAMOND, 3.0),
OBSIDIAN(Material.OBSIDIAN, 4.5),
NETHERITE(Material.NETHERITE_INGOT, 6.0);
private final Material material;
private final double spellBoost;
CapType(final Material material, final double spellBoost) {
this.material = material;
this.spellBoost = spellBoost;
}
public final Material getMaterial() {
return this.material;
}
public final double getSpellBoost() {
return this.spellBoost;
}
}

View File

@ -0,0 +1,32 @@
package app.simplexdev.arcanumocculta.api.wand;
import org.bukkit.Material;
public enum CoreType
{
WOOD(Material.STICK, 1.0),
IRON(Material.IRON_INGOT, 1.25),
GOLD(Material.GOLD_INGOT, 1.5),
OBSIDIAN(Material.OBSIDIAN, 1.75),
BLAZE(Material.BLAZE_ROD, 2.0),
ENDER(Material.END_ROD, 2.5);
private final Material material;
private final double spellBoost;
CoreType(final Material material, final double spellBoost)
{
this.spellBoost = spellBoost;
this.material = material;
}
public Material getMaterial()
{
return this.material;
}
public double getSpellBoost()
{
return spellBoost;
}
}

View File

@ -0,0 +1,32 @@
package app.simplexdev.arcanumocculta.api.wand;
import org.bukkit.Material;
public enum GemType
{
NONE(Material.AIR, 1.0),
LAPIS(Material.LAPIS_LAZULI, 1.25),
REDSTONE(Material.REDSTONE, 1.5),
EMERALD(Material.EMERALD, 2.0),
DIAMOND(Material.DIAMOND, 3.0),
QUARTZ(Material.QUARTZ, 4.0);
private final Material material;
private final double spellBoost;
GemType(final Material material, final double spellBoost)
{
this.spellBoost = spellBoost;
this.material = material;
}
public Material getMaterial()
{
return this.material;
}
public double getSpellBoost()
{
return spellBoost;
}
}

View File

@ -0,0 +1,20 @@
package app.simplexdev.arcanumocculta.api.wand;
import org.bukkit.inventory.ItemStack;
public interface Wand
{
String getName();
String getDescription();
ItemStack getItem();
double getSpellBonus();
CapType getCapType();
CoreType getCoreType();
GemType getGemType();
}

View File

@ -0,0 +1,19 @@
package app.simplexdev.arcanumocculta.base;
import app.simplexdev.arcanumocculta.api.caster.AbstractCaster;
import app.simplexdev.arcanumocculta.api.caster.CasterLevel;
import app.simplexdev.arcanumocculta.api.caster.SpellBook;
import app.simplexdev.arcanumocculta.api.wand.Wand;
import org.bukkit.entity.Player;
public class SimpleCaster extends AbstractCaster
{
public SimpleCaster(Player player, Wand wand,
SpellBook spellBook,
CasterLevel level)
{
super(player, wand, spellBook, level);
}
}

View File

@ -0,0 +1,7 @@
package app.simplexdev.arcanumocculta.base;
import app.simplexdev.arcanumocculta.api.caster.AbstractSpellBook;
public class SimpleSpellBook extends AbstractSpellBook
{
}

View File

@ -0,0 +1,18 @@
package app.simplexdev.arcanumocculta.base;
import app.simplexdev.arcanumocculta.api.wand.AbstractWand;
import app.simplexdev.arcanumocculta.api.wand.CapType;
import app.simplexdev.arcanumocculta.api.wand.CoreType;
import app.simplexdev.arcanumocculta.api.wand.GemType;
import org.bukkit.inventory.ItemStack;
public class SimpleWand extends AbstractWand
{
public SimpleWand(String name, String description, ItemStack item,
CapType capType,
CoreType coreType,
GemType gemType)
{
super(name, description, item, capType, coreType, gemType);
}
}

View File

@ -1,99 +0,0 @@
package app.simplexdev.arcanumocculta.base.book;
import app.simplexdev.arcanumocculta.api.book.SpellBook;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractSpellBook implements SpellBook {
private final List<Spell> spellbook = new ArrayList<>();
private String name;
private String description;
private ItemStack itemStack;
protected AbstractSpellBook(final String name) {
this.name = name;
this.description = ChatColor.BLUE + "A simple spell book.";
final ItemStack stack = new ItemStack(Material.WRITTEN_BOOK, 1);
ItemMeta meta = stack.getItemMeta();
if (meta != null) {
meta.setDisplayName(name);
meta.setLore(List.of(description));
stack.setItemMeta(meta);
}
this.itemStack = stack;
}
@Override
public String getBookName() {
return name;
}
@Override
public void setBookName(String name) {
this.name = name;
}
@Override
public String getBookDescription() {
return description;
}
@Override
public void setBookDescription(String description) {
this.description = description;
}
@Override
public ItemStack getBookItem() {
return itemStack;
}
@Override
public void setBookItem(final ItemStack stack) {
this.itemStack = stack;
}
@Override
public List<Spell> getSpells() {
return this.spellbook;
}
@Override
public void addSpell(Spell spell) {
this.spellbook.add(spell);
}
@Override
public void removeSpell(Spell spell) {
this.spellbook.remove(spell);
}
@Override
public Spell getSpell(String name) {
return getSpells()
.stream()
.filter(spell -> spell.getSpellName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
@Override
public Spell getSpell(int index) {
return getSpells().get(index);
}
@Override
public int getSpellCount() {
return getSpells().size();
}
}

View File

@ -1,50 +0,0 @@
package app.simplexdev.arcanumocculta.base.book;
import app.simplexdev.arcanumocculta.api.book.SpellTome;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.List;
public abstract class AbstractSpellTome implements SpellTome {
private final Spell containedSpell;
private final String name;
private final String description;
private final ItemStack item;
protected AbstractSpellTome(final String name, final String description, final Spell containedSpell) {
this.containedSpell = containedSpell;
this.name = name;
this.description = description;
final ItemStack stack = new ItemStack(Material.BOOK, 1);
final ItemMeta meta = stack.getItemMeta();
if (meta != null) {
meta.setDisplayName(name);
meta.setLore(List.of(description));
stack.setItemMeta(meta);
}
this.item = stack;
}
@Override
public String getTomeName() {
return this.name;
}
@Override
public String getTomeDescription() {
return this.description;
}
@Override
public ItemStack getTomeItem() {
return this.item;
}
@Override
public Spell getContainedSpell() {
return this.containedSpell;
}
}

View File

@ -1,40 +0,0 @@
package app.simplexdev.arcanumocculta.base.effect;
import app.simplexdev.arcanumocculta.api.effect.CompoundEffect;
import org.bukkit.potion.PotionEffectType;
import java.time.Duration;
public abstract class AbstractCompoundEffect extends AbstractEffect implements CompoundEffect {
private final PotionEffectType[] effectTypes;
protected AbstractCompoundEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay, PotionEffectType... effectTypes) {
super(duration, amplifier, ambient, forceDisplay);
this.effectTypes = effectTypes;
}
protected AbstractCompoundEffect(Duration duration, float amplifier, boolean forceDisplay, PotionEffectType... effectTypes) {
super(duration, amplifier, forceDisplay);
this.effectTypes = effectTypes;
}
protected AbstractCompoundEffect(Duration duration, float amplifier, PotionEffectType... effectTypes) {
super(duration, amplifier);
this.effectTypes = effectTypes;
}
protected AbstractCompoundEffect(Duration duration, PotionEffectType... effectTypes) {
super(duration);
this.effectTypes = effectTypes;
}
protected AbstractCompoundEffect(PotionEffectType... effectTypes) {
super();
this.effectTypes = effectTypes;
}
@Override
public PotionEffectType[] getEffectTypes() {
return new PotionEffectType[0];
}
}

View File

@ -1,55 +0,0 @@
package app.simplexdev.arcanumocculta.base.effect;
import app.simplexdev.arcanumocculta.api.effect.Effect;
import java.time.Duration;
public abstract class AbstractEffect implements Effect {
private final Duration duration;
private final float amplifier;
private final boolean ambient;
private final boolean forceDisplay;
protected AbstractEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay) {
this.duration = duration;
this.amplifier = amplifier;
this.ambient = ambient;
this.forceDisplay = forceDisplay;
}
protected AbstractEffect(Duration duration, float amplifier, boolean forceDisplay) {
this(duration, amplifier, false, forceDisplay);
}
protected AbstractEffect(Duration duration, float amplifier) {
this(duration, amplifier, false, false);
}
protected AbstractEffect(Duration duration) {
this(duration, 1, false, false);
}
protected AbstractEffect() {
this(Duration.ofSeconds(5L), 1, false, false);
}
@Override
public Duration getDuration() {
return duration;
}
@Override
public float getAmplifier() {
return amplifier;
}
@Override
public boolean isAmbient() {
return ambient;
}
@Override
public boolean forceDisplay() {
return forceDisplay;
}
}

View File

@ -1,53 +0,0 @@
package app.simplexdev.arcanumocculta.base.effect;
import app.simplexdev.arcanumocculta.api.effect.PassiveEffect;
import app.simplexdev.arcanumocculta.api.effect.PassiveEffects;
import app.simplexdev.arcanumocculta.api.player.Caster;
import java.time.Duration;
public abstract class AbstractPassiveEffect extends AbstractEffect implements PassiveEffect {
private final Caster wandHolder;
private final PassiveEffects passiveEffect;
protected AbstractPassiveEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay, Caster wandHolder, PassiveEffects passiveEffect) {
super(duration, amplifier, ambient, forceDisplay);
this.wandHolder = wandHolder;
this.passiveEffect = passiveEffect;
}
public AbstractPassiveEffect(Duration duration, float amplifier, boolean forceDisplay, Caster wandHolder, PassiveEffects passiveEffect) {
super(duration, amplifier, forceDisplay);
this.wandHolder = wandHolder;
this.passiveEffect = passiveEffect;
}
protected AbstractPassiveEffect(Duration duration, float amplifier, Caster wandHolder, PassiveEffects passiveEffect) {
super(duration, amplifier);
this.wandHolder = wandHolder;
this.passiveEffect = passiveEffect;
}
protected AbstractPassiveEffect(Duration duration, Caster wandHolder, PassiveEffects passiveEffect) {
super(duration);
this.wandHolder = wandHolder;
this.passiveEffect = passiveEffect;
}
protected AbstractPassiveEffect(Caster wandHolder, PassiveEffects passiveEffect) {
super();
this.wandHolder = wandHolder;
this.passiveEffect = passiveEffect;
}
@Override
public Caster getWandHolder() {
return wandHolder;
}
@Override
public PassiveEffects getPassiveEffect() {
return passiveEffect;
}
}

View File

@ -1,40 +0,0 @@
package app.simplexdev.arcanumocculta.base.effect;
import app.simplexdev.arcanumocculta.api.effect.SpellEffect;
import org.bukkit.potion.PotionEffectType;
import java.time.Duration;
public abstract class AbstractSpellEffect extends AbstractEffect implements SpellEffect {
private final PotionEffectType effectType;
protected AbstractSpellEffect(Duration duration, float amplifier, boolean ambient, boolean forceDisplay, PotionEffectType effectType) {
super(duration, amplifier, ambient, forceDisplay);
this.effectType = effectType;
}
protected AbstractSpellEffect(Duration duration, float amplifier, boolean forceDisplay, PotionEffectType effectType) {
super(duration, amplifier, forceDisplay);
this.effectType = effectType;
}
protected AbstractSpellEffect(Duration duration, float amplifier, PotionEffectType effectType) {
super(duration, amplifier);
this.effectType = effectType;
}
protected AbstractSpellEffect(Duration duration, PotionEffectType effectType) {
super(duration);
this.effectType = effectType;
}
protected AbstractSpellEffect(PotionEffectType effectType) {
super();
this.effectType = effectType;
}
@Override
public PotionEffectType getEffectType() {
return effectType;
}
}

View File

@ -1,124 +0,0 @@
package app.simplexdev.arcanumocculta.base.player;
import app.simplexdev.arcanumocculta.api.book.SpellBook;
import app.simplexdev.arcanumocculta.api.player.Caster;
import app.simplexdev.arcanumocculta.api.player.SpellResistance;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public abstract class AbstractCaster implements Caster {
private final String name;
private final UUID uuid;
private final SpellBook spellBook;
private final List<SpellResistance> spellResistances = new ArrayList<>();
private double maximumMana;
private double currentMana;
protected AbstractCaster(final Player player, SpellBook spellBook) {
this.name = player.getName();
this.uuid = player.getUniqueId();
this.spellBook = spellBook;
this.maximumMana = 20;
this.currentMana = maximumMana;
}
@Override
public UUID getCasterUUID() {
return uuid;
}
@Override
public String getDisplayName() {
return name;
}
@Override
public double getMaximumMana() {
return maximumMana;
}
@Override
public void setMaximumMana(double mana) {
this.maximumMana = mana;
}
@Override
public double getCurrentMana() {
return currentMana;
}
@Override
public double addMana(double mana) {
this.currentMana += mana;
return getCurrentMana();
}
@Override
public double increaseMaximumMana(double mana) {
this.maximumMana += mana;
return getMaximumMana();
}
@Override
public double removeMana(double mana) {
final double newMana = currentMana - mana;
if (newMana < 0) {
currentMana = 0;
} else {
currentMana = newMana;
}
return getCurrentMana();
}
@Override
public double decreaseMaximumMana(double mana) {
final double newMana = maximumMana - mana;
if (newMana < 0) {
maximumMana = 0;
} else {
maximumMana = newMana;
}
return getMaximumMana();
}
@Override
public void setMana(double mana) {
if (mana > getMaximumMana()) {
currentMana = getMaximumMana();
} else if (mana < 0) {
currentMana = 0;
} else {
currentMana = mana;
}
}
@Override
public SpellBook getSpellbook() {
return spellBook;
}
@Override
public List<SpellResistance> getSpellResistances() {
return spellResistances;
}
@Override
public void addSpellResistance(SpellResistance resistance) {
this.spellResistances.add(resistance);
}
@Override
public void removeSpellResistance(SpellResistance resistance) {
this.spellResistances.remove(resistance);
}
@Override
public boolean hasResistance(int ordinal) {
return getSpellResistances().stream().anyMatch(resistance -> resistance.getOrdinal() == ordinal);
}
}

View File

@ -1,48 +0,0 @@
package app.simplexdev.arcanumocculta.base.player;
import app.simplexdev.arcanumocculta.api.effect.PassiveEffect;
import app.simplexdev.arcanumocculta.api.player.Wand;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractWand implements Wand {
private final List<PassiveEffect> passiveEffects = new ArrayList<>();
private String name;
private String description;
private ItemStack item;
private double manaPenalty;
protected AbstractWand(String name, String description, ItemStack item, double manaPenalty) {
this.name = name;
this.description = description;
this.item = item;
this.manaPenalty = manaPenalty;
}
@Override
public String getWandName() {
return name;
}
@Override
public String getWandDescription() {
return description;
}
@Override
public ItemStack getWandItem() {
return item;
}
@Override
public double getManaPenalty() {
return manaPenalty;
}
@Override
public List<PassiveEffect> getPassiveEffects() {
return passiveEffects;
}
}

View File

@ -1,30 +0,0 @@
package app.simplexdev.arcanumocculta.base.player;
import app.simplexdev.arcanumocculta.api.player.SpellResistance;
public class SimpleSpellResistance implements SpellResistance {
private final String name;
private final double resistance;
private final int ordinal;
public SimpleSpellResistance(String spellName, double resistance, int ordinal) {
this.name = spellName;
this.resistance = resistance;
this.ordinal = ordinal;
}
@Override
public String getSpellName() {
return name;
}
@Override
public double getResistance() {
return resistance;
}
@Override
public int getOrdinal() {
return ordinal;
}
}

View File

@ -1,68 +0,0 @@
package app.simplexdev.arcanumocculta.base.spell;
import app.simplexdev.arcanumocculta.api.effect.Effect;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import java.time.Duration;
public abstract class AbstractSpell<T extends Effect> implements Spell<T> {
private final String name;
private final String description;
private final double manaCost;
private final Duration coolDown;
private final int spellLevel;
private final T spellEffect;
private long coolDownEnd;
protected AbstractSpell(String name, String description, double manaCost, Duration coolDown, int spellLevel, T effect) {
this.name = name;
this.description = description;
this.manaCost = manaCost;
this.coolDown = coolDown;
this.spellLevel = spellLevel;
this.spellEffect = effect;
}
protected AbstractSpell(String name, String description, double manaCost, Duration coolDown, T effect) {
this(name, description, manaCost, coolDown, 1, effect);
}
protected AbstractSpell(String name, String description, double manaCost, T effect) {
this(name, description, manaCost, Duration.ofSeconds(10L), effect);
}
protected AbstractSpell(String name, String description, T effect) {
this(name, description, 5.0, effect);
}
@Override
public String getSpellName() {
return name;
}
@Override
public String getSpellDescription() {
return description;
}
@Override
public double getManaCost() {
return manaCost;
}
@Override
public Duration getCoolDown() {
return coolDown;
}
@Override
public int getSpellLevel() {
return spellLevel;
}
@Override
public T getEffect() {
return spellEffect;
}
}

View File

@ -1,143 +0,0 @@
package app.simplexdev.arcanumocculta.base.spell;
import app.simplexdev.arcanumocculta.api.effect.CompoundEffect;
import app.simplexdev.arcanumocculta.api.effect.Effect;
import app.simplexdev.arcanumocculta.api.effect.SpecialEffect;
import app.simplexdev.arcanumocculta.api.effect.SpellEffect;
import app.simplexdev.arcanumocculta.api.player.Caster;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import app.simplexdev.arcanumocculta.api.spell.SpellProjectile;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Projectile;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public abstract class AbstractSpellProjectile<T extends Projectile> implements SpellProjectile<T> {
private static final List<EntityType> accepted = List.of(
EntityType.ARROW,
EntityType.SPECTRAL_ARROW,
EntityType.FIREBALL,
EntityType.DRAGON_FIREBALL,
EntityType.SMALL_FIREBALL,
EntityType.WITHER_SKULL,
EntityType.ENDER_PEARL,
EntityType.SNOWBALL,
EntityType.EGG,
EntityType.TRIDENT,
EntityType.FIREWORK,
EntityType.LLAMA_SPIT,
EntityType.SHULKER_BULLET,
EntityType.FISHING_HOOK,
EntityType.SPLASH_POTION,
EntityType.THROWN_EXP_BOTTLE);
private final Class<T> projectile;
private final List<Particle> particles;
private final Caster caster;
private final Spell<?> spell;
protected AbstractSpellProjectile(final Spell<?> spell, final Caster caster, final Class<T> projectile, final Particle... particles) {
this.projectile = projectile;
this.particles = Arrays.asList(particles);
this.caster = caster;
this.spell = spell;
}
@Override
public Class<T> getProjectileType() {
return projectile;
}
@Override
public List<Particle> getParticles() {
return particles;
}
@Override
public void cast(Location target) {
final Vector velocity = caster.bukkit().getEyeLocation().getDirection().multiply(2);
final T launched = caster.bukkit().launchProjectile(getProjectileType(), velocity);
while (!launched.isDead()) {
final double randomXOffset = Math.sin((Math.random() * 10 - 2) % Math.PI) * 5;
final double randomYOffset = ((Math.random() * 10 - 2) % Math.PI) * 5;
final double randomZOffset = Math.cos((Math.random() * 10 - 2) % (2 * Math.PI)) * 5;
particles.forEach(particle -> launched.getWorld().spawnParticle(particle, launched.getLocation(), 1, randomXOffset, randomYOffset, randomZOffset));
if (launched.isOnGround()
|| launched.isDead()
|| launched.getTicksLived() > 100
|| launched.getLocation().clone().equals(target)) {
break;
}
}
final Effect effect = spell.getEffect();
if (effect instanceof SpellEffect sp) {
PotionEffect e = sp.getEffectType().createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier());
AreaEffectCloud cloud = (AreaEffectCloud) target.getWorld().spawnEntity(target, EntityType.AREA_EFFECT_CLOUD);
cloud.addCustomEffect(e, true);
cloud.setRadius(2.5F);
cloud.setDuration((int) sp.getDuration().getSeconds());
cloud.setSource(caster.bukkit());
} else if (effect instanceof CompoundEffect sp) {
final List<PotionEffect> effects = new ArrayList<>();
for (PotionEffectType type : sp.getEffectTypes()) {
PotionEffect e = type.createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier());
effects.add(e);
}
AreaEffectCloud cloud = (AreaEffectCloud) target.getWorld().spawnEntity(target, EntityType.AREA_EFFECT_CLOUD);
for (PotionEffect e : effects) {
cloud.addCustomEffect(e, true);
}
cloud.setRadius(2.5F);
cloud.setDuration((int) sp.getDuration().getSeconds());
cloud.setSource(caster.bukkit());
}
}
@Override
public void cast(LivingEntity target) {
final Vector velocity = caster.bukkit().getEyeLocation().getDirection().multiply(2);
final T launched = caster.bukkit().launchProjectile(getProjectileType(), velocity);
while (!launched.isDead()) {
final double randomXOffset = Math.sin((Math.random() * 10 - 2) % Math.PI) * 5;
final double randomYOffset = ((Math.random() * 10 - 2) % Math.PI) * 5;
final double randomZOffset = Math.cos((Math.random() * 10 - 2) % (2 * Math.PI)) * 5;
particles.forEach(particle -> launched.getWorld().spawnParticle(particle, launched.getLocation(), 1, randomXOffset, randomYOffset, randomZOffset));
if (launched.isOnGround()
|| launched.isDead()
|| launched.getTicksLived() > 100
|| launched.getLocation().clone().equals(target)) {
break;
}
}
final Effect effect = spell.getEffect();
if (effect instanceof SpellEffect sp) {
PotionEffect e = sp.getEffectType().createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier());
target.addPotionEffect(e);
} else if (effect instanceof CompoundEffect sp) {
final List<PotionEffect> effects = new ArrayList<>();
for (PotionEffectType type : sp.getEffectTypes()) {
PotionEffect e = type.createEffect((int) sp.getDuration().getSeconds(), (int) sp.getAmplifier());
effects.add(e);
}
target.addPotionEffects(effects);
} else if (effect instanceof SpecialEffect sp) {
sp.applyEffect(target);
}
}
}

View File

@ -0,0 +1,32 @@
package app.simplexdev.arcanumocculta.cooldown;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import java.util.HashSet;
import java.util.Set;
public class CooldownService
{
private final Set<CooldownStatus> cooldowns = new HashSet<>();
public void tick()
{
cooldowns.removeIf(CooldownStatus::hasExpired);
}
public void include(final CooldownStatus status)
{
cooldowns.add(status);
}
public void exclude(final CooldownStatus status)
{
cooldowns.remove(status);
}
public boolean isOnCooldown(final Spell spell)
{
this.cooldowns.removeIf(CooldownStatus::hasExpired);
return cooldowns.stream()
.anyMatch(status -> status.getSpellUUID().equals(spell.getUniqueId()));
}
}

View File

@ -0,0 +1,31 @@
package app.simplexdev.arcanumocculta.cooldown;
import java.time.Duration;
import java.time.Instant;
import java.util.UUID;
public class CooldownStatus
{
private final Duration duration;
private final Instant currentTime;
private final Instant endTime;
private final UUID spellUUID;
public CooldownStatus(final UUID spellUUID, final Duration duration)
{
this.duration = duration;
this.currentTime = Instant.now();
this.endTime = this.currentTime.plus(duration);
this.spellUUID = spellUUID;
}
public UUID getSpellUUID()
{
return spellUUID;
}
public boolean hasExpired()
{
return Instant.now().isAfter(this.endTime);
}
}

View File

@ -1,23 +0,0 @@
package app.simplexdev.arcanumocculta.spell;
import app.simplexdev.arcanumocculta.api.effect.SpellEffect;
import app.simplexdev.arcanumocculta.api.player.Caster;
import app.simplexdev.arcanumocculta.base.spell.AbstractSpell;
import app.simplexdev.arcanumocculta.spell.effect.FireballEffect;
import app.simplexdev.arcanumocculta.spell.projectile.FireballProjectile;
import java.time.Duration;
public final class FireballSpell extends AbstractSpell<FireballEffect> {
private final Caster caster;
public FireballSpell(final Caster caster) {
super("Fireball", "Fires a fireball in the direction you're facing.", new FireballEffect(Duration.ofSeconds(1), 1));
this.caster = caster;
}
@Override
public FireballProjectile getSpellProjectile() {
return new FireballProjectile(this, this.caster);
}
}

View File

@ -1,12 +0,0 @@
package app.simplexdev.arcanumocculta.spell.effect;
import app.simplexdev.arcanumocculta.base.effect.AbstractSpellEffect;
import org.bukkit.potion.PotionEffectType;
import java.time.Duration;
public class FireballEffect extends AbstractSpellEffect {
public FireballEffect(Duration duration, float amplifier) {
super(duration, amplifier, PotionEffectType.HARM);
}
}

View File

@ -1,15 +0,0 @@
package app.simplexdev.arcanumocculta.spell.projectile;
import app.simplexdev.arcanumocculta.api.player.Caster;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import app.simplexdev.arcanumocculta.base.spell.AbstractSpellProjectile;
import app.simplexdev.arcanumocculta.spell.FireballSpell;
import org.bukkit.Particle;
import org.bukkit.entity.Fireball;
public class FireballProjectile extends AbstractSpellProjectile<Fireball> {
public FireballProjectile(FireballSpell spell,
Caster caster) {
super(spell, caster, Fireball.class, Particle.FLAME, Particle.SMALL_FLAME, Particle.LAVA);
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2023 Simplex Development Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* with the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package app.simplexdev.arcanumocculta.spells;
import app.simplexdev.arcanumocculta.api.caster.AbstractSpellBook;
import app.simplexdev.arcanumocculta.api.spell.AbstractSpell;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import app.simplexdev.arcanumocculta.util.SpellUtils;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
public class PrimarySpellList extends AbstractSpellBook
{
public PrimarySpellList()
{
Set<Class<? extends AbstractSpell>> spellClasses = m0().getSubTypesOf(AbstractSpell.class);
final Set<Spell> v0 = new HashSet<>();
spellClasses.forEach(spellClass ->
{
try
{
final Spell spell = spellClass.getDeclaredConstructor().newInstance();
v0.add(spell);
}
catch (ReflectiveOperationException e)
{
Bukkit.getLogger().severe(e.getMessage());
}
});
this.addAll(v0);
}
private Reflections m0()
{
final Reflections v0 = new Reflections(SpellUtils.SPELL_PACKAGE + ".flame",
Scanners.SubTypes);
final Reflections v1 = new Reflections(SpellUtils.SPELL_PACKAGE + ".soul",
Scanners.SubTypes);
final Reflections v2 = new Reflections(SpellUtils.SPELL_PACKAGE + ".wither", Scanners.SubTypes);
return v0.merge(v1).merge(v2);
}
}

View File

@ -0,0 +1,75 @@
package app.simplexdev.arcanumocculta.spells.soul;
import app.simplexdev.arcanumocculta.util.SpellUtils;
import app.simplexdev.arcanumocculta.api.caster.Caster;
import app.simplexdev.arcanumocculta.api.caster.CasterLevel;
import app.simplexdev.arcanumocculta.api.spell.AbstractSpell;
import app.simplexdev.arcanumocculta.api.spell.SpellEffect;
import app.simplexdev.arcanumocculta.api.wand.Wand;
import org.bukkit.Particle;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
public final class SoulPebble extends AbstractSpell
{
public SoulPebble()
{
super("Soul Pebble",
"soul_pebble",
"Fires a small soul pebble",
1,
1.0,
1L,
10.0,
5L);
}
@Override
public SpellEffect[] getSpellEffects()
{
final SpellEffect[] effects = new SpellEffect[1];
effects[0] = (target, caster) ->
{
final Wand wand = caster.getWand();
final double damage = wand.getSpellBonus() * this.baseDamage();
SpellUtils.damage(target, caster.bukkit(), damage);
};
return effects;
}
@Override
public void cast(Caster caster, Wand wand)
{
if (this.manaCost() > caster.getCurrentMana())
{
caster.bukkit().sendMessage("You do not have enough mana to cast this spell!");
return;
}
final Player player = caster.bukkit();
final double expMod = CasterLevel.fromOrdinal(this.getLevelRequirement()).getExperienceMarker();
final Projectile projectile = player.launchProjectile(Projectile.class);
projectile.setVelocity(player.getLocation().getDirection().multiply(2));
caster.removeMana(this.manaCost());
caster.addExperience(random().nextDouble(expMod * 0.25));
while (!projectile.isOnGround() || !projectile.isDead())
{
projectile.getWorld().spawnParticle(Particle.SOUL, projectile.getLocation(), 10,
random().nextGaussian() * 0.8,
random().nextGaussian() * 0.8,
random().nextGaussian() * 0.8);
}
projectile.getNearbyEntities(1, 1, 1)
.stream()
.filter(LivingEntity.class::isInstance)
.map(LivingEntity.class::cast)
.forEach(entity -> SpellUtils.applyEffects(
this.getSpellEffects(),
entity,
caster));
}
}

View File

@ -0,0 +1,95 @@
package app.simplexdev.arcanumocculta.storage.local;
import app.simplexdev.arcanumocculta.ArcanumOcculta;
import app.simplexdev.arcanumocculta.api.caster.Caster;
import app.simplexdev.arcanumocculta.api.caster.CasterLevel;
import app.simplexdev.arcanumocculta.api.caster.SpellBook;
import app.simplexdev.arcanumocculta.api.wand.CapType;
import app.simplexdev.arcanumocculta.api.wand.CoreType;
import app.simplexdev.arcanumocculta.api.wand.GemType;
import app.simplexdev.arcanumocculta.api.wand.Wand;
import app.simplexdev.arcanumocculta.base.SimpleCaster;
import app.simplexdev.arcanumocculta.base.SimpleSpellBook;
import app.simplexdev.arcanumocculta.base.SimpleWand;
import app.simplexdev.arcanumocculta.util.SpellUtils;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class PlayerYaml
{
private final YamlHolder yamlHolder;
public PlayerYaml(final ArcanumOcculta plugin, final String name)
{
this.yamlHolder = new YamlHolder(plugin, "player-default.yml", name, plugin.getDataFolder(), false);
}
public YamlHolder getYamlHolder()
{
return yamlHolder;
}
public Wand retrieveWand()
{
ConfigurationSection wandSection = yamlHolder.getConfigurationSection("wand");
String name = wandSection.getString("name");
String description = wandSection.getString("description");
Material material = Material.getMaterial(wandSection.getString("item"));
CoreType core = CoreType.valueOf(wandSection.getString("core"));
CapType cap = CapType.valueOf(wandSection.getString("cap"));
ItemStack item = new ItemStack(material, 1);
ItemMeta meta = item.getItemMeta();
if (meta != null)
{
meta.setDisplayName(name);
meta.setLore(List.of(description));
item.setItemMeta(meta);
}
GemType gem = GemType.valueOf(wandSection.getString("gem"));
return new SimpleWand(name, description, item, cap, core, gem);
}
public void saveWand(final Wand wand)
{
ConfigurationSection wandSection = yamlHolder.getConfigurationSection("wand");
wandSection.set("name", wand.getName());
wandSection.set("description", wand.getDescription());
wandSection.set("item", wand.getItem().getType().name());
wandSection.set("core", wand.getCoreType().name());
wandSection.set("cap", wand.getCapType().name());
wandSection.set("gem", wand.getGemType().name());
yamlHolder.save();
}
public Caster fetchCaster(final Player player)
{
ConfigurationSection caster = yamlHolder.getConfigurationSection("caster");
CasterLevel level = CasterLevel.fromOrdinal(caster.getInt("caster_rank"));
double xp = caster.getDouble("current_experience");
double currentMana = caster.getDouble("current_mana");
double maxMana = caster.getDouble("max_mana");
final Wand wand = retrieveWand();
final SpellBook spellBook = retrieveSpellBook();
Caster c = new SimpleCaster(player, wand, spellBook, level);
c.setCurrentExperience(xp);
c.setCurrentMana(currentMana);
c.setMaxMana(maxMana);
return c;
}
public SpellBook retrieveSpellBook()
{
final SpellBook book = new SimpleSpellBook();
List<String> spellBook = yamlHolder.getStringList("spellbook");
for (String spell : spellBook)
{
book.addSpell(SpellUtils.copyFromPrimaryList(spell));
}
return book;
}
}

View File

@ -0,0 +1,106 @@
package app.simplexdev.arcanumocculta.storage.local;
import app.simplexdev.arcanumocculta.ArcanumOcculta;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.List;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
public class YamlHolder
{
private final YamlConfiguration configuration;
private final ArcanumOcculta plugin;
public YamlHolder(final ArcanumOcculta plugin, final String resourceLocation, final String fileName,
final File parentFolder,
final boolean copyDefaults)
{
final File file = new File(parentFolder, fileName);
this.plugin = plugin;
try
{
if (file.createNewFile() || copyDefaults)
{
final String creatingFile = String.format("Creating %s...", fileName);
plugin.getLogger().info(creatingFile);
plugin.saveResource(resourceLocation, true);
}
}
catch (IOException ex)
{
plugin.getLogger().severe(ex.getMessage());
}
this.configuration = YamlConfiguration.loadConfiguration(file);
}
public String getString(final String path)
{
return this.configuration.getString(path);
}
public boolean getBoolean(final String path)
{
return this.configuration.getBoolean(path);
}
public int getInt(final String path)
{
return this.configuration.getInt(path);
}
public double getDouble(final String path)
{
return this.configuration.getDouble(path);
}
public ConfigurationSection getConfigurationSection(final String path)
{
return this.configuration.getConfigurationSection(path);
}
public List<String> getStringList(final String path)
{
return this.configuration.getStringList(path);
}
public void set(final String path, final Object value)
{
this.configuration.set(path, value);
}
public void save()
{
try
{
this.configuration.save(this.configuration.getCurrentPath());
}
catch (IOException ex)
{
final String message = MessageFormat.format("Failed to save {0}!", this.configuration.getCurrentPath());
plugin.getLogger().severe(message);
}
}
public void load()
{
try
{
this.configuration.load(this.configuration.getCurrentPath());
}
catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex)
{
final String message = MessageFormat.format("Failed to load {0}!", this.configuration.getCurrentPath());
plugin.getLogger().severe(message);
}
}
public void reload()
{
this.save();
this.load();
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2023 Simplex Development Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* with the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package app.simplexdev.arcanumocculta.util;
import app.simplexdev.arcanumocculta.api.caster.Caster;
import app.simplexdev.arcanumocculta.api.spell.Spell;
import app.simplexdev.arcanumocculta.api.spell.SpellEffect;
import app.simplexdev.arcanumocculta.spells.PrimarySpellList;
import org.bukkit.entity.Damageable;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
public final class SpellUtils
{
public static final String SPELL_PACKAGE = PrimarySpellList.class.getPackageName();
private static final PrimarySpellList primarySpellList = new PrimarySpellList();
private SpellUtils()
{
throw new AssertionError();
}
public static void damage(final Damageable target, final LivingEntity damager, final double damage)
{
if (target instanceof Player)
target.damage(damage % 20.0, damager);
else
target.damage(damage);
}
public static void applyEffects(final SpellEffect[] effects, final LivingEntity target, final Caster caster)
{
for (final SpellEffect effect : effects)
effect.apply(target, caster);
}
public static Spell copyFromPrimaryList(final String id) {
return SpellUtils.primarySpellList.getSpell(id).dupe();
}
}

View File

@ -0,0 +1,18 @@
caster:
caster_rank: 1
current_experience: 0
current_mana: 100
max_mana: 100
spell_influence: 0
spell_points: 0
spellbook:
- FIREBALL
wand:
name: Basic Wand
description: A basic wand
item: STICK
core: WOOD
gem: NONE
cap: IRON

View File

@ -3,3 +3,5 @@ version: '${version}'
main: app.simplexdev.arcanumocculta.ArcanumOcculta
api-version: '1.20'
load: STARTUP
libraries:
- org.reflections:reflections:0.10.2