diff --git a/images/textures/crystal_alchemical_sefi_yellow.png b/images/textures/crystal_alchemical_sefi_yellow.png new file mode 100644 index 00000000..543e4fe0 Binary files /dev/null and b/images/textures/crystal_alchemical_sefi_yellow.png differ diff --git a/images/textures/crystal_animal_sefi_blue.png b/images/textures/crystal_animal_sefi_blue.png new file mode 100644 index 00000000..5d8f00b7 Binary files /dev/null and b/images/textures/crystal_animal_sefi_blue.png differ diff --git a/images/textures/crystal_celestial_sefi_white.png b/images/textures/crystal_celestial_sefi_white.png new file mode 100644 index 00000000..e340b56b Binary files /dev/null and b/images/textures/crystal_celestial_sefi_white.png differ diff --git a/images/textures/crystal_elemental_sefi_red.png b/images/textures/crystal_elemental_sefi_red.png new file mode 100644 index 00000000..4296339e Binary files /dev/null and b/images/textures/crystal_elemental_sefi_red.png differ diff --git a/images/textures/crystal_historical_sefi_green.png b/images/textures/crystal_historical_sefi_green.png new file mode 100644 index 00000000..a7433c59 Binary files /dev/null and b/images/textures/crystal_historical_sefi_green.png differ diff --git a/images/textures/crystal_human_sefi_teal.png b/images/textures/crystal_human_sefi_teal.png new file mode 100644 index 00000000..b0f4fa98 Binary files /dev/null and b/images/textures/crystal_human_sefi_teal.png differ diff --git a/images/textures/crystal_mechanical_sefi_orange.png b/images/textures/crystal_mechanical_sefi_orange.png new file mode 100644 index 00000000..ef3fd32a Binary files /dev/null and b/images/textures/crystal_mechanical_sefi_orange.png differ diff --git a/images/textures/crystal_philosophical_sefi_purple.png b/images/textures/crystal_philosophical_sefi_purple.png new file mode 100644 index 00000000..8d28bdb4 Binary files /dev/null and b/images/textures/crystal_philosophical_sefi_purple.png differ diff --git a/images/textures/crystal_void_sefi_grey.png b/images/textures/crystal_void_sefi_grey.png new file mode 100644 index 00000000..57009232 Binary files /dev/null and b/images/textures/crystal_void_sefi_grey.png differ diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/CrystamaeHistoria.java b/src/main/java/io/github/sefiraat/crystamaehistoria/CrystamaeHistoria.java index 5706d0cf..0aefc4e1 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/CrystamaeHistoria.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/CrystamaeHistoria.java @@ -10,7 +10,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.runnables.RunnableManager; import io.github.sefiraat.crystamaehistoria.runnables.spells.SpellTickRunnable; -import io.github.sefiraat.crystamaehistoria.slimefun.Structure; +import io.github.sefiraat.crystamaehistoria.slimefun.ItemGroups; +import io.github.sefiraat.crystamaehistoria.slimefun.Machines; +import io.github.sefiraat.crystamaehistoria.slimefun.Materials; +import io.github.sefiraat.crystamaehistoria.slimefun.Tools; import io.github.sefiraat.crystamaehistoria.stories.StoriesManager; import io.github.sefiraat.crystamaehistoria.utils.CrystaTag; import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; @@ -27,7 +30,6 @@ public class CrystamaeHistoria extends AbstractAddon { private static CrystamaeHistoria instance; - private Structure structure; private ConfigManager configManager; private StoriesManager storiesManager; private ListenerManager listenerManager; @@ -43,10 +45,6 @@ public static CrystamaeHistoria getInstance() { return instance; } - public static Structure getStructure() { - return instance.structure; - } - public static ListenerManager getListenerManager() { return instance.listenerManager; } @@ -119,7 +117,6 @@ public void enable() { getLogger().info(" Crystamae Historia - By Sefiraat "); getLogger().info("########################################"); - this.structure = new Structure(); this.configManager = new ConfigManager(); this.storiesManager = new StoriesManager(); this.listenerManager = new ListenerManager(); @@ -127,7 +124,8 @@ public void enable() { this.spellMemory = new SpellMemory(); this.effectManager = new EffectManager(this); - structure.setup(); + setupSlimefun(); + configManager.setupConfigs(); new Metrics(this, 12065); @@ -141,4 +139,12 @@ protected void disable() { saveConfig(); instance = null; } + + private void setupSlimefun() { + new ItemGroups(); + new Materials(); + new Machines(); + new Tools(); + } + } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/SpellMemory.java b/src/main/java/io/github/sefiraat/crystamaehistoria/SpellMemory.java index f4ccde5d..3fd47ef4 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/SpellMemory.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/SpellMemory.java @@ -52,7 +52,7 @@ public void clearAll() { removeBlocks(true); blocksToRemove.clear(); - // Remove all temporary blocks + // Remove and disable all players flight removeFlight(true); playersWithFlight.clear(); } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/config/ConfigManager.java b/src/main/java/io/github/sefiraat/crystamaehistoria/config/ConfigManager.java index 43d624f0..54eb872a 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/config/ConfigManager.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/config/ConfigManager.java @@ -1,6 +1,8 @@ package io.github.sefiraat.crystamaehistoria.config; import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.sefiraat.crystamaehistoria.magic.SpellType; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import lombok.Getter; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; @@ -16,6 +18,7 @@ public class ConfigManager { private final FileConfiguration stories; private final FileConfiguration research; private final FileConfiguration blockColors; + private final FileConfiguration spells; public ConfigManager() { this.blocks = getConfig("blocks.yml"); @@ -26,13 +29,14 @@ public ConfigManager() { this.research.options().copyDefaults(true); this.blockColors = getConfig("block_colors.yml"); this.blockColors.options().copyDefaults(true); + this.spells = getConfig("spells.yml"); + this.spells.options().copyDefaults(true); } /** * @noinspection ResultOfMethodCallIgnored */ private FileConfiguration getConfig(String fileName) { - // Todo remove commented code and add config diff CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); File file = new File(plugin.getDataFolder(), fileName); if (!file.exists()) { @@ -56,4 +60,25 @@ public void saveResearches() { exception.printStackTrace(); } } + + public boolean spellEnabled(Spell spell) { + return spells.getBoolean(spell.getId()); + } + + public void setupConfigs() { + // Spells + for (SpellType spellType : SpellType.getCachedValues()) { + Spell spell = spellType.getSpell(); + if (!spells.contains(spell.getId())) { + try { + final File file = new File(CrystamaeHistoria.getInstance().getDataFolder(), "spells.yml"); + spells.set(spell.getId(), true); + spells.save(file); + } catch (IOException exception) { + exception.printStackTrace(); + } + } + } + } + } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/listeners/SpellEffectListener.java b/src/main/java/io/github/sefiraat/crystamaehistoria/listeners/SpellEffectListener.java index ab3c2ec6..e2bbc310 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/listeners/SpellEffectListener.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/listeners/SpellEffectListener.java @@ -27,8 +27,6 @@ import org.bukkit.event.entity.EntityInteractEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerEggThrowEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.weather.LightningStrikeEvent; import org.bukkit.inventory.ItemStack; @@ -56,6 +54,17 @@ public void onProjectileHit(ProjectileHitEvent event) { final Entity hitEntity = event.getHitEntity(); event.setCancelled(true); + + // We don't want magic projectiles to hit their own passengers. + List passengers = magicProjectile.getProjectile().getPassengers(); + if (event.getHitEntity() != null && !passengers.isEmpty()) { + for (Entity entity : passengers) { + if (entity.getUniqueId() == event.getHitEntity().getUniqueId()) { + return; + } + } + } + castInfo.setProjectileLocation(magicProjectile.getLocation()); if (entityHitAllowed(castInfo, hitEntity)) { diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastInformation.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastInformation.java index e909f81c..68b94c8b 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastInformation.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastInformation.java @@ -5,6 +5,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -34,6 +35,12 @@ public class CastInformation { private Block hitBlock; @Getter @Setter + private Block targetedBlockOnCast; + @Getter + @Setter + private BlockFace targetedBlockFaceOnCast; + @Getter + @Setter private Location projectileLocation; @Getter @Setter @@ -56,6 +63,8 @@ public CastInformation(Player caster, int staveLevel) { this.caster = caster.getUniqueId(); this.staveLevel = staveLevel; this.castLocation = caster.getLocation().clone(); + this.targetedBlockOnCast = caster.getTargetBlockExact(50); + this.targetedBlockFaceOnCast = caster.getTargetBlockFace(50); } public Player getCasterAsPlayer() { diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastResult.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastResult.java index cf10923e..0be6e18d 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastResult.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/CastResult.java @@ -6,7 +6,8 @@ public enum CastResult { CAST_SUCCESS("Successful"), CAST_FAIL_NO_CRYSTA("Not enough Crystamae in plate"), CAST_FAIL_SLOT_EMPTY("No plate in slot"), - ON_COOLDOWN("Spell on cooldown"); + ON_COOLDOWN("Spell on cooldown"), + SPELL_DISABLED("This spell has been disabled"); @Getter protected static final CastResult[] cachedValues = values(); diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/SpellType.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/SpellType.java index 27cbfcf6..97f983b5 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/SpellType.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/SpellType.java @@ -1,18 +1,22 @@ package io.github.sefiraat.crystamaehistoria.magic; +import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.AirNova; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.AirSprite; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.AncientDefence; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Animaniacs; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.AntiPrism; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.BatteringRam; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.BloodMagics; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Bobulate; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Break; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Bright; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.CallLightning; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Cascada; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Chaos; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Compass; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.CurificationRitual; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Deity; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Gravity; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Hearthstone; @@ -25,17 +29,23 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Fireball; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.FlameSprite; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.FrostNova; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Gravity; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Gyroscopic; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.HarmonysSonata; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.HarvestMoon; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Heal; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.HealingMist; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Hearthstone; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Hellscape; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.HolyCow; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.ImbueVoid; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.KnowledgeShare; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.LavaLake; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.LeechBomb; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.LovePotion; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Oviparous; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.PhantomsFlight; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.PhilosophersStone; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.PoisonNova; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Prism; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Protectorate; @@ -48,12 +58,14 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.SpawnFiends; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Squall; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.StarFall; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.StripMine; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.SummonGolem; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Teleport; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Tempest; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.TimeCompression; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.TimeDilation; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Tracer; +import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.TunnelBore; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.Vacuum; import io.github.sefiraat.crystamaehistoria.magic.spells.tier1.WitherWeather; import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.LiquefactionBasinCache; @@ -62,6 +74,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Arrays; public enum SpellType { @@ -71,13 +84,16 @@ public enum SpellType { ANCIENT_DEFENCE(new AncientDefence()), ANIMANIACS(new Animaniacs()), ANTI_PRISM(new AntiPrism()), + BATTERING_RAM(new BatteringRam()), BLOOD_MAGICS(new BloodMagics()), BOBULATE(new Bobulate()), BREAK(new Break()), BRIGHT(new Bright()), CALL_LIGHTNING(new CallLightning()), + CASCADA(new Cascada()), CHAOS(new Chaos()), COMPASS(new Compass()), + CURIFICATION_RITUAL(new CurificationRitual()), DEITY(new Deity()), EARTH_NOVA(new EarthNova()), ENDERMANS_VEIL(new EndermansVeil()), @@ -93,14 +109,17 @@ public enum SpellType { HEARTHSTONE(new Hearthstone()), HELLSCAPE(new Hellscape()), HOLY_COW(new HolyCow()), + IMBUE_VOID(new ImbueVoid()), GYROSCOPIC(new Gyroscopic()), HARMONYS_SONATA(new HarmonysSonata()), + HARVEST_MOON(new HarvestMoon()), KNOWLEDGE_SHARE(new KnowledgeShare()), LAVA_LAKE(new LavaLake()), LEECH_BOMB(new LeechBomb()), LOVE_POTION(new LovePotion()), OVIPAROUS(new Oviparous()), PHANTOMS_FLIGHT(new PhantomsFlight()), + PHILOSOPHERS_STONE(new PhilosophersStone()), POISON_NOVA(new PoisonNova()), PRISM(new Prism()), PROTECTORATE(new Protectorate()), @@ -113,24 +132,33 @@ public enum SpellType { SPAWN_FIENDS(new SpawnFiends()), SQUALL(new Squall()), STAR_FALL(new StarFall()), + STRIP_MINE(new StripMine()), SUMMON_GOLEM(new SummonGolem()), TELEPORT(new Teleport()), TEMPEST(new Tempest()), TIME_COMPRESSION(new TimeCompression()), TIME_DILATION(new TimeDilation()), TRACER(new Tracer()), + TUNNEL_BORE(new TunnelBore()), VACUUM(new Vacuum()), WITHER_WEATHER(new WitherWeather()); @Getter protected static final SpellType[] cachedValues = values(); @Getter + protected static final SpellType[] enabledSpells = Arrays.stream(values()) + .filter(spellType -> spellType.getSpell().isEnabled()) + .toArray(SpellType[]::new); + @Getter private final Spell spell; @ParametersAreNonnullByDefault SpellType(Spell spell) { + spell.setEnabled(CrystamaeHistoria.getConfigManager().spellEnabled(spell)); + if (spell.isEnabled()) { + LiquefactionBasinCache.addSpellRecipe(this, spell.getRecipe()); + } this.spell = spell; - LiquefactionBasinCache.addSpellRecipe(this, spell.getRecipe()); } @Nullable diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/InstancePlate.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/InstancePlate.java index 2db0d83e..5fedf3b8 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/InstancePlate.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/InstancePlate.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; @Getter public class InstancePlate { @@ -32,10 +31,8 @@ public InstancePlate(int tier, SpellType storedSpell, int crysta) { } public static void setPlateLore(ItemStack itemStack, InstancePlate instancePlate) { - - String magic = instancePlate != null ? ThemeType.toTitleCase(instancePlate.storedSpell.getId()) : "None"; - String crysta = instancePlate != null ? String.valueOf(instancePlate.crysta) : "0"; - + final String magic = instancePlate != null ? ThemeType.toTitleCase(instancePlate.storedSpell.getId()) : "None"; + final String crysta = instancePlate != null ? String.valueOf(instancePlate.crysta) : "0"; final String[] lore = new String[]{ "A magically charged plate storing magic", "potential.", @@ -43,8 +40,9 @@ public static void setPlateLore(ItemStack itemStack, InstancePlate instancePlate ThemeType.CLICK_INFO.getColor() + "Magic Framework : " + ThemeType.NOTICE.getColor() + magic, ThemeType.CLICK_INFO.getColor() + "Stored Crysta : " + ThemeType.NOTICE.getColor() + crysta }; - ChatColor passiveColor = ThemeType.PASSIVE.getColor(); - List finalLore = new ArrayList<>(); + final ChatColor passiveColor = ThemeType.PASSIVE.getColor(); + final List finalLore = new ArrayList<>(); + final ItemMeta itemMeta = itemStack.getItemMeta(); finalLore.add(""); for (String s : lore) { @@ -53,32 +51,42 @@ public static void setPlateLore(ItemStack itemStack, InstancePlate instancePlate finalLore.add(""); finalLore.add(ThemeType.applyThemeToString(ThemeType.CLICK_INFO, ThemeType.CRAFTING.getLoreLine())); - final ItemMeta itemMeta = itemStack.getItemMeta(); itemMeta.setLore(finalLore); itemStack.setItemMeta(itemMeta); } public CastResult tryCastSpell(CastInformation castInformation) { - castInformation.setSpellType(storedSpell); - Spell spell = storedSpell.getSpell(); - int crystaCost = spell.getCrystaCost(castInformation); - if (crysta >= crystaCost) { - if (cooldown <= System.currentTimeMillis()) { - spell.castSpell(castInformation); - this.crysta -= crystaCost; - final long cdSeconds = (long) (spell.getCooldownSeconds(castInformation) * 1000); - CrystamaeHistoria.log(Level.WARNING, String.valueOf(cdSeconds)); - this.cooldown = System.currentTimeMillis() + cdSeconds; - return CastResult.CAST_SUCCESS; - } else { - return CastResult.ON_COOLDOWN; - } - } else { + final Spell spell = storedSpell.getSpell(); + final int crystaCost = spell.getCrystaCost(castInformation); + + // Is spell disabled in the spells.yml? + if (!CrystamaeHistoria.getConfigManager().spellEnabled(spell)) { + return CastResult.SPELL_DISABLED; + } + + // Is enough crysta currently stored in the plate? + if (crysta < crystaCost) { return CastResult.CAST_FAIL_NO_CRYSTA; } + + // Is the spell still on cooldown? + if (cooldown > System.currentTimeMillis()) { + return CastResult.ON_COOLDOWN; + } + + castInformation.setSpellType(storedSpell); + spell.castSpell(castInformation); + this.crysta -= crystaCost; + final long cdSeconds = (long) (spell.getCooldownSeconds(castInformation) * 1000); + this.cooldown = System.currentTimeMillis() + cdSeconds; + return CastResult.CAST_SUCCESS; } public void addCrysta(int amount) { this.crysta += amount; } + + public void removeCrysta(int amount) { + this.crysta -= amount; + } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/Spell.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/Spell.java index 1f5c4692..95ba8cc9 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/Spell.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/core/Spell.java @@ -3,23 +3,16 @@ import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.runnables.spells.SpellTickRunnable; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.utils.theme.ThemeType; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; -import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair; -import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; import lombok.Getter; import lombok.Setter; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.OfflinePlayer; -import org.bukkit.Particle; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeInstance; -import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.LightningStrike; import org.bukkit.entity.LivingEntity; @@ -30,10 +23,8 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.util.ArrayList; import java.util.HashSet; @@ -41,13 +32,15 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; public abstract class Spell { @Getter @Setter private SpellCore spellCore; + @Getter + @Setter + private boolean enabled; @Nonnull public abstract String getId(); @@ -59,7 +52,7 @@ public abstract class Spell { public abstract Material getMaterial(); @Nonnull - public abstract SpellRecipe getRecipe(); + public abstract RecipeSpell getRecipe(); @Nonnull public SlimefunItemStack getThemedStack() { @@ -173,125 +166,6 @@ protected void setLastDamageToCaster(@Nonnull LivingEntity damagedEntity, @Nonnu } } - @ParametersAreNonnullByDefault - protected void displayParticleEffect(Entity entity, Particle particle, double rangeRadius) { - displayParticleEffect(entity.getLocation(), particle, rangeRadius, 5); - } - - @ParametersAreNonnullByDefault - protected void displayParticleEffect(Entity entity, Particle particle, double rangeRadius, int numberOfParticles) { - displayParticleEffect(entity.getLocation().clone().add(0, 1, 0), particle, rangeRadius, numberOfParticles); - } - - @ParametersAreNonnullByDefault - protected void displayParticleEffect(Location location, Particle particle, double rangeRadius) { - displayParticleEffect(location, particle, rangeRadius, 5); - } - - @ParametersAreNonnullByDefault - protected void displayParticleEffect(Location location, Particle particle, double rangeRadius, int numberOfParticles) { - for (int i = 0; i < numberOfParticles; i++) { - double x = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); - double y = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); - double z = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); - location.getWorld().spawnParticle(particle, location.clone().add(x, y, z), 1); - } - } - - @ParametersAreNonnullByDefault - protected void displayParticleEffect(Entity entity, double rangeRadius, int numberOfParticles, Particle.DustOptions dustOptions) { - displayParticleEffect(entity.getLocation(), rangeRadius, numberOfParticles, dustOptions); - } - - @ParametersAreNonnullByDefault - protected void displayParticleEffect(Entity entity, double rangeRadius, Particle.DustOptions dustOptions) { - displayParticleEffect(entity.getLocation(), rangeRadius, 5, dustOptions); - } - - @ParametersAreNonnullByDefault - protected void displayParticleEffect(Location location, double rangeRadius, int numberOfParticles, Particle.DustOptions dustOptions) { - for (int i = 0; i < numberOfParticles; i++) { - double x = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); - double y = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); - double z = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); - location.getWorld().spawnParticle(Particle.REDSTONE, location.clone().add(x, y, z), 1, dustOptions); - } - } - - @ParametersAreNonnullByDefault - protected boolean tryBreakBlock(UUID caster, Block block) { - Player player = Bukkit.getPlayer(caster); - if (player != null - && hasPermission(caster, block, Interaction.BREAK_BLOCK) - && block.getType().getHardness() < 100 - ) { - block.breakNaturally(player.getInventory().getItemInMainHand()); - return true; - } - return false; - } - - @ParametersAreNonnullByDefault - protected boolean pullEntity(UUID caster, Location pullToLocation, Entity pushed, double force) { - Vector vector = pushed.getLocation().toVector() - .subtract(pullToLocation.toVector()) - .normalize() - .multiply(-force); - return pushEntity(caster, vector, pushed); - } - - @ParametersAreNonnullByDefault - protected boolean pushEntity(UUID caster, Location pushFromLocation, Entity pushed, double force) { - Vector vector = pushed.getLocation().toVector() - .subtract(pushFromLocation.toVector()) - .normalize() - .multiply(force); - return pushEntity(caster, vector, pushed); - } - - @ParametersAreNonnullByDefault - protected boolean pushEntity(UUID caster, Vector vector, Entity pushed) { - Interaction interaction = pushed instanceof Player ? Interaction.ATTACK_PLAYER : Interaction.INTERACT_ENTITY; - if (hasPermission(caster, pushed.getLocation(), interaction)) { - pushed.setVelocity(vector); - return true; - } - return false; - } - - @ParametersAreNonnullByDefault - protected boolean damageEntity(LivingEntity livingEntity, UUID caster, double damage) { - return damageEntity(livingEntity, caster, damage, null, 0); - } - - @ParametersAreNonnullByDefault - protected boolean damageEntity(LivingEntity livingEntity, UUID caster, double damage, @Nullable Location knockbackOrigin, double knockbackForce) { - Interaction interaction = livingEntity instanceof Player ? Interaction.ATTACK_PLAYER : Interaction.ATTACK_ENTITY; - if (hasPermission(caster, livingEntity.getLocation(), interaction)) { - Player player = Bukkit.getPlayer(caster); - livingEntity.damage(damage, player); - if (knockbackOrigin != null && knockbackForce > 0) { - pushEntity(caster, knockbackOrigin, livingEntity, knockbackForce); - } - return true; - } - return false; - } - - /** - * Heal the entity by the provided amount - * - * @param livingEntity The {@link LivingEntity} to heal - * @param healAmount The amount to heal by - */ - @ParametersAreNonnullByDefault - protected void healEntity(LivingEntity livingEntity, double healAmount) { - AttributeInstance attribute = livingEntity.getAttribute(Attribute.GENERIC_MAX_HEALTH); - if (attribute != null) { - livingEntity.setHealth(Math.min(attribute.getValue(), livingEntity.getHealth() + healAmount)); - } - } - /** * Used to register the projectile's events to the definition and then * the projectile/definition to the projectileMap. Used when detecting @@ -401,21 +275,4 @@ protected Set getTargets(CastInformation castInformation, double r } return livingEntities; } - - protected boolean hasPermission(Player player, Block block, Interaction interaction) { - return hasPermission(player.getUniqueId(), block.getLocation(), interaction); - } - - protected boolean hasPermission(Player player, Location location, Interaction interaction) { - return hasPermission(player.getUniqueId(), location, interaction); - } - - protected boolean hasPermission(UUID player, Block block, Interaction interaction) { - return hasPermission(player, block.getLocation(), interaction); - } - - protected boolean hasPermission(UUID player, Location location, Interaction interaction) { - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player); - return Slimefun.getProtectionManager().hasPermission(offlinePlayer, location, interaction); - } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirNova.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirNova.java index 895d4561..b1c6c1d1 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirNova.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirNova.java @@ -4,8 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -49,14 +51,14 @@ public void fireProjectiles(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity( + GeneralUtils.damageEntity( livingEntity, castInformation.getCaster(), getDamage(castInformation), castInformation.getProjectileLocation().clone().subtract(0, 1, 0), getKnockback(castInformation) ); - displayParticleEffect(livingEntity, Particle.SWEEP_ATTACK, 1, 5); + ParticleUtils.displayParticleEffect(livingEntity, Particle.SWEEP_ATTACK, 1, 5); } } @@ -83,8 +85,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.MECHANICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirSprite.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirSprite.java index 83cb60aa..90316051 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirSprite.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AirSprite.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.BoringGoal; import org.bukkit.Location; @@ -49,7 +50,7 @@ public void cast(CastInformation castInformation) { } public void onTick(MagicSummon magicSummon) { - displayParticleEffect(magicSummon.getMob(), Particle.CLOUD, 1, 2); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.CLOUD, 1, 2); } @Nonnull @@ -75,8 +76,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AncientDefence.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AncientDefence.java index 8ce8967d..28d6d052 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AncientDefence.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AncientDefence.java @@ -3,7 +3,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; @@ -36,7 +36,7 @@ public void cast(CastInformation castInformation) { final double z = Math.sin(a) * r; final Block block = location.clone().add(x, y, z).getBlock(); if (block.getType() == Material.AIR - && hasPermission(castInformation.getCaster(), block, Interaction.PLACE_BLOCK) + && GeneralUtils.hasPermission(castInformation.getCaster(), block, Interaction.PLACE_BLOCK) ) { block.setType(Material.RED_STAINED_GLASS); GeneralUtils.markBlockForRemoval(block, 5); @@ -68,8 +68,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Animaniacs.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Animaniacs.java index b948420f..b3652b0a 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Animaniacs.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Animaniacs.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; import org.bukkit.Location; @@ -75,7 +76,7 @@ public void projectileHit(CastInformation castInformation) { final Location entityLocation = entity.getLocation(); final EntityType entityType = entity.getType(); if (CONVERTIBLE_LIST.contains(entityType) - && hasPermission(castInformation.getCaster(), entityLocation, Interaction.INTERACT_ENTITY) + && GeneralUtils.hasPermission(castInformation.getCaster(), entityLocation, Interaction.INTERACT_ENTITY) ) { final EntityType convertTo = CONVERTIBLE_LIST.get(ThreadLocalRandom.current().nextInt(CONVERTIBLE_LIST.size())); final String name = entity.getCustomName(); @@ -108,8 +109,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AntiPrism.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AntiPrism.java index 36d56908..1d7df952 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AntiPrism.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/AntiPrism.java @@ -4,9 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.Keys; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI; import org.bukkit.Location; @@ -61,7 +62,7 @@ public void projectileHit(CastInformation castInformation) { final double x = Math.cos(a) * r; final double z = Math.sin(a) * r; final Location point = castInformation.getProjectileLocation().clone().add(x, y, z); - displayParticleEffect(point, Particle.SOUL, 0.1, 1); + ParticleUtils.displayParticleEffect(point, Particle.SOUL, 0.1, 1); } } @@ -71,7 +72,7 @@ public void projectileHit(CastInformation castInformation) { } PersistentDataAPI.setBoolean(entity, Keys.newKey("ANTIPRISM"), true); applyNegativeEffects(entity, castInformation); - displayParticleEffect(entity, Particle.CRIMSON_SPORE, range, 20); + ParticleUtils.displayParticleEffect(entity, Particle.CRIMSON_SPORE, range, 20); } } @@ -98,8 +99,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/BatteringRam.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/BatteringRam.java new file mode 100644 index 00000000..89732116 --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/BatteringRam.java @@ -0,0 +1,84 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; +import io.github.sefiraat.crystamaehistoria.utils.mobgoals.BatteringRamGoal; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Mob; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.UUID; + +public class BatteringRam extends Spell { + + public BatteringRam() { + SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(5, true, 3, true, 50, true) + .makeInstantSpell(this::cast) + .makeEffectingSpell(true, false); + setSpellCore(spellCoreBuilder.build()); + } + + @ParametersAreNonnullByDefault + public void cast(CastInformation castInformation) { + final UUID caster = castInformation.getCaster(); + final Location location = castInformation.getCastLocation(); + final Vector direction = location.getDirection().clone(); + final int range = (int) getRange(castInformation); + direction.setY(0); + final Location spawnLocation = location.clone().add(location.getDirection().clone().add(new Vector(0, 1, 0))); + final MagicSummon magicSummon = SpellUtils.summonTemporaryMob( + EntityType.GOAT, + caster, + spawnLocation, + new BatteringRamGoal(caster), + range + ); + Mob mob = magicSummon.getMob(); + mob.setGravity(false); + mob.setVelocity(location.getDirection().multiply(2)); + mob.setInvulnerable(true); + } + + @Nonnull + @Override + public String getId() { + return "BATTERING_RAM"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Summons a battering ram to decimate", + "all in your way." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.GOAT_SPAWN_EGG; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.ELEMENTAL, + StoryType.ALCHEMICAL, + StoryType.ANIMAL + ); + } + +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/BloodMagics.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/BloodMagics.java index b54ab8d4..5a8b1a05 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/BloodMagics.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/BloodMagics.java @@ -3,8 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; @@ -42,16 +44,16 @@ private void castBlood(CastInformation castInformation, Location location, doubl && entity.getUniqueId() != castInformation.getCaster() ) { final LivingEntity livingEntity = (LivingEntity) entity; - damageEntity( + GeneralUtils.damageEntity( livingEntity, castInformation.getCaster(), getDamage(castInformation) ); - displayParticleEffect(livingEntity, 2, 10, dustOptions); + ParticleUtils.displayParticleEffect(livingEntity, 2, 10, dustOptions); if (iteration <= 5) { if (livingEntity.getHealth() <= 0) { - pushEntity(castInformation.getCaster(), castInformation.getCastLocation(), entity, 5); - displayParticleEffect(livingEntity, 4, 20, dustOptions); + GeneralUtils.pushEntity(castInformation.getCaster(), castInformation.getCastLocation(), entity, 5); + ParticleUtils.displayParticleEffect(livingEntity, 4, 20, dustOptions); entity.remove(); castBlood(castInformation, livingEntity.getLocation(), 2, iteration + 1); } @@ -83,8 +85,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bobulate.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bobulate.java index fd17fda1..539fd3c5 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bobulate.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bobulate.java @@ -4,9 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.CrystaTag; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; @@ -85,7 +86,7 @@ public void projectileHit(CastInformation castInformation) { for (Entity entity : entities) { if (entity instanceof Colorable - && hasPermission(caster, pointLocation, Interaction.INTERACT_ENTITY) + && GeneralUtils.hasPermission(caster, pointLocation, Interaction.INTERACT_ENTITY) ) { final int randomValue = ThreadLocalRandom.current().nextInt( 0, @@ -101,7 +102,7 @@ && hasPermission(caster, pointLocation, Interaction.INTERACT_ENTITY) } private void convertBlock(UUID caster, Block block, Tag tag) { - if (hasPermission(caster, block, Interaction.PLACE_BLOCK)) { + if (GeneralUtils.hasPermission(caster, block, Interaction.PLACE_BLOCK)) { final List list = tag.getValues().stream().toList(); final int randomValue = ThreadLocalRandom.current().nextInt(0, list.size()); block.setType(list.get(randomValue)); @@ -131,8 +132,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.ALCHEMICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Break.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Break.java index e468c6d9..eb1353cd 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Break.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Break.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -25,7 +26,7 @@ public Break() { public void cast(CastInformation castInformation) { Player player = castInformation.getCasterAsPlayer(); Block block = player.getTargetBlockExact((int) getRange(castInformation)); - tryBreakBlock(castInformation.getCaster(), block); + GeneralUtils.tryBreakBlock(castInformation.getCaster(), block); } @Nonnull @@ -50,8 +51,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.MECHANICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bright.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bright.java index 31f290df..7fba5486 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bright.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Bright.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -29,7 +30,7 @@ public void cast(CastInformation castInformation) { if (caster != null) { caster.getWorld().setThundering(false); caster.getWorld().setStorm(false); - displayParticleEffect(caster, Particle.FALLING_NECTAR, 2, 30); + ParticleUtils.displayParticleEffect(caster, Particle.FALLING_NECTAR, 2, 30); caster.getWorld().playEffect(caster.getLocation(), Effect.BONE_MEAL_USE, 1); } } @@ -56,8 +57,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/CallLightning.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/CallLightning.java index 0295804d..ac754037 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/CallLightning.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/CallLightning.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -51,7 +52,7 @@ public void beforeProjectileHit(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation), castInformation.getDamageLocation(), getKnockback(castInformation)); + GeneralUtils.damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation), castInformation.getDamageLocation(), getKnockback(castInformation)); } } @@ -77,8 +78,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.MECHANICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Cascada.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Cascada.java new file mode 100644 index 00000000..e17a253e --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Cascada.java @@ -0,0 +1,108 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; +import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class Cascada extends Spell { + + public Cascada() { + final SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(60, true, 0, false, 50, false) + .makeProjectileSpell(this::fireProjectile, 2, false, 0, false) + .makeProjectileVsBlockSpell(this::projectileHit) + .makeProjectileVsEntitySpell(this::projectileHit); + setSpellCore(spellCoreBuilder.build()); + } + + @ParametersAreNonnullByDefault + public void fireProjectile(CastInformation castInformation) { + final Location location = castInformation.getCastLocation(); + final Location aimLocation = location.clone().add(0, 1.5, 0).add(location.getDirection().multiply(2)); + final MagicProjectile magicProjectile = SpellUtils.summonMagicProjectile(castInformation, EntityType.SNOWBALL, aimLocation); + magicProjectile.setVelocity(location.getDirection(), 1.5); + magicProjectile.disableGravity(); + } + + public void projectileHit(CastInformation castInformation) { + final UUID caster = castInformation.getCaster(); + final Location location = castInformation.getProjectileLocation(); + final int range = (int) getProjectileAoe(castInformation) + castInformation.getStaveLevel(); + final List blocks = new ArrayList<>(); + + for (int y = -range; y < range; y++) { + for (int x = -range; x < range; x++) { + for (int z = -range; z < range; z++) { + if (Math.sqrt((double) (x * x) + (y * y) + (z * z)) <= range) { + final Block block = location.getWorld().getBlockAt( + x + location.getBlockX(), + y + location.getBlockY(), + z + location.getBlockZ()); + if (!blocks.contains(block) + && GeneralUtils.hasPermission(caster, block, Interaction.BREAK_BLOCK) + ) { + blocks.add(block); + } + } + } + } + } + + for (Block block : blocks) { + final BlockData blockData = block.getBlockData(); + final Entity entity = block.getWorld().spawnFallingBlock(block.getLocation().add(0.5, 0.5, 0.5), blockData); + entity.setVelocity(new Vector(0, 2, 0)); + block.setType(Material.AIR, false); + } + } + + @Nonnull + @Override + public String getId() { + return "CASCADA"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Turns the ground inside out to damage foes." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.PODZOL; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.MECHANICAL, + StoryType.HISTORICAL, + StoryType.PHILOSOPHICAL + ); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Chaos.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Chaos.java index 7b0d6d7f..5a0ec801 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Chaos.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Chaos.java @@ -4,8 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -58,11 +60,11 @@ public void cast(CastInformation castInformation) { } public void onTick(MagicProjectile magicProjectile) { - displayParticleEffect(magicProjectile.getProjectile(), Particle.GLOW, 0.2, 1); + ParticleUtils.displayParticleEffect(magicProjectile.getProjectile(), Particle.GLOW, 0.2, 1); } public void onHitEntity(CastInformation castInformation) { - damageEntity( + GeneralUtils.damageEntity( castInformation.getMainTarget(), castInformation.getCaster(), getDamage(castInformation), @@ -72,7 +74,7 @@ public void onHitEntity(CastInformation castInformation) { } public void onHitBlock(CastInformation castInformation) { - tryBreakBlock(castInformation.getCaster(), castInformation.getHitBlock()); + GeneralUtils.tryBreakBlock(castInformation.getCaster(), castInformation.getHitBlock()); } @Nonnull @@ -99,8 +101,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Compass.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Compass.java index d14ba579..218d304a 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Compass.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Compass.java @@ -4,7 +4,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Color; @@ -38,7 +38,11 @@ public void onTick(CastInformation castInformation) { if (material != Material.AIR && material.isBlock()) { final Block foundBlock = tryGetBlock(player, material, (int) getRange(castInformation)); if (foundBlock == null) { - displayParticleEffect(location.add(location.getDirection()), Particle.VILLAGER_ANGRY, 1, 10); + ParticleUtils.displayParticleEffect(location.add(location.getDirection()), + Particle.VILLAGER_ANGRY, + 1, + 10 + ); } else { final Location foundBlockLocation = foundBlock.getLocation().add(0.5, 0.5, 0.5); final List list = (List) CrystamaeHistoria.getConfigManager().getBlockColors().getList(material.name()); @@ -89,8 +93,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.ALCHEMICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/CurificationRitual.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/CurificationRitual.java new file mode 100644 index 00000000..7ac3fe05 --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/CurificationRitual.java @@ -0,0 +1,85 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.entity.ZombieVillager; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Collection; + +public class CurificationRitual extends Spell { + + public CurificationRitual() { + SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(60, false, 10, true, 100, true) + .makeInstantSpell(this::cast) + .makeDamagingSpell(2, true, 0, false); + setSpellCore(spellCoreBuilder.build()); + } + + @ParametersAreNonnullByDefault + public void cast(CastInformation castInformation) { + final double range = getRange(castInformation); + final Player caster = castInformation.getCasterAsPlayer(); + final Collection zombies = caster.getWorld().getNearbyEntities( + caster.getLocation(), + range, + range, + range + ); + for (Entity entity : zombies) { + if (entity instanceof ZombieVillager) { + ParticleUtils.displayParticleEffect(entity, Particle.WAX_OFF, 2, 10); + ZombieVillager zombieVillager = (ZombieVillager) entity; + zombieVillager.setConversionTime(100); + zombieVillager.setConversionPlayer(caster); + } else if (entity instanceof Zombie) { + Zombie zombie = (Zombie) entity; + GeneralUtils.damageEntity(zombie, castInformation.getCaster(), getDamage(castInformation)); + } + } + } + + @Nonnull + @Override + public String getId() { + return "CURIFICATION_RITUAL"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Cures nearby zombie villagers while", + "damaging other zombies in the process." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.GOLDEN_APPLE; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.HUMAN, + StoryType.ANIMAL, + StoryType.CELESTIAL + ); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Deity.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Deity.java index b0987610..9c9aaaf3 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Deity.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Deity.java @@ -4,7 +4,7 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.DeityGoal; @@ -70,8 +70,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EarthNova.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EarthNova.java index 4b51adc8..964025be 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EarthNova.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EarthNova.java @@ -4,8 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -53,9 +55,9 @@ public void fireProjectiles(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); + GeneralUtils.damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); applyNegativeEffects(livingEntity, castInformation); - displayParticleEffect(livingEntity, Particle.SPORE_BLOSSOM_AIR, 1, 2); + ParticleUtils.displayParticleEffect(livingEntity, Particle.SPORE_BLOSSOM_AIR, 1, 2); } } @@ -82,8 +84,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.MECHANICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EndermansVeil.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EndermansVeil.java index 252b7306..b63d9b8b 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EndermansVeil.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EndermansVeil.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -34,7 +35,7 @@ public void cast(CastInformation castInformation) { if (teleportToLocation != null) { caster.teleport(teleportToLocation); - displayParticleEffect(caster, Particle.END_ROD, 1, 10); + ParticleUtils.displayParticleEffect(caster, Particle.END_ROD, 1, 10); } else { caster.sendMessage(CrystamaeHistoria.getInstance().getConfig().getString("messages.spells.teleport_no_suitable_location")); } @@ -94,8 +95,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EtherealFlow.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EtherealFlow.java index 5c1331b0..294e5313 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EtherealFlow.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/EtherealFlow.java @@ -3,7 +3,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import org.bukkit.Effect; import org.bukkit.Location; @@ -51,8 +51,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HISTORICAL, StoryType.VOID, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FanOfArrows.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FanOfArrows.java index 0ca0aada..24fa6747 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FanOfArrows.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FanOfArrows.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -46,7 +47,7 @@ public void fireProjectiles(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { - damageEntity(castInformation.getMainTarget(), castInformation.getCaster(), getDamage(castInformation)); + GeneralUtils.damageEntity(castInformation.getMainTarget(), castInformation.getCaster(), getDamage(castInformation)); } @Nonnull @@ -72,8 +73,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FireNova.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FireNova.java index fa519de8..ea0eb8a1 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FireNova.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FireNova.java @@ -4,8 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -50,13 +52,13 @@ public void fireProjectiles(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); + GeneralUtils.damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); } } @ParametersAreNonnullByDefault public void afterProjectileHit(CastInformation castInformation) { - displayParticleEffect(castInformation.getMainTarget(), Particle.EXPLOSION_NORMAL, 1.0, 5); + ParticleUtils.displayParticleEffect(castInformation.getMainTarget(), Particle.EXPLOSION_NORMAL, 1.0, 5); } @Nonnull @@ -82,8 +84,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.CELESTIAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Fireball.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Fireball.java index bed216f5..5c39142c 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Fireball.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Fireball.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -45,7 +46,12 @@ public void beforeProjectileHit(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation), castInformation.getDamageLocation(), getKnockback(castInformation)); + GeneralUtils.damageEntity(livingEntity, + castInformation.getCaster(), + getDamage(castInformation), + castInformation.getDamageLocation(), + getKnockback(castInformation) + ); } } @@ -72,8 +78,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FlameSprite.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FlameSprite.java index f24b412f..7cfce502 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FlameSprite.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FlameSprite.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.BoringGoal; import org.bukkit.Location; @@ -49,7 +50,7 @@ public void cast(CastInformation castInformation) { } public void onTick(MagicSummon magicSummon) { - displayParticleEffect(magicSummon.getMob(), Particle.FLAME, 1, 4); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.FLAME, 1, 4); } @Nonnull @@ -75,8 +76,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FrostNova.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FrostNova.java index 3a32d0b6..3a60f55e 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FrostNova.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/FrostNova.java @@ -4,8 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -50,9 +52,9 @@ public void fireProjectiles(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); + GeneralUtils.damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); livingEntity.setFreezeTicks(60); - displayParticleEffect(livingEntity, Particle.SNOW_SHOVEL, 1, 5); + ParticleUtils.displayParticleEffect(livingEntity, Particle.SNOW_SHOVEL, 1, 5); } } @@ -79,8 +81,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.MECHANICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gravity.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gravity.java index 3be884ab..d1432b61 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gravity.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gravity.java @@ -4,14 +4,12 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; -import org.bukkit.Bukkit; -import org.bukkit.Location; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; @@ -31,7 +29,7 @@ public Gravity() { public void tick(CastInformation castInformation) { Player player = castInformation.getCasterAsPlayer(); player.setVelocity(player.getLocation().getDirection().add(new Vector(0, 5, 0))); - displayParticleEffect(player, Particle.GLOW_SQUID_INK, 2, 10); + ParticleUtils.displayParticleEffect(player, Particle.GLOW_SQUID_INK, 2, 10); } @ParametersAreNonnullByDefault @@ -41,7 +39,7 @@ public void afterAllTicks(CastInformation castInformation) { player.setFlying(true); long expiry = System.currentTimeMillis() + ((castInformation.getStaveLevel() * 30L) * 1000); CrystamaeHistoria.getActiveStorage().getPlayersWithFlight().put(player.getUniqueId(), expiry); - displayParticleEffect(player, Particle.FALLING_OBSIDIAN_TEAR, 2, 20); + ParticleUtils.displayParticleEffect(player, Particle.FALLING_OBSIDIAN_TEAR, 2, 20); } @Nonnull @@ -67,8 +65,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.ALCHEMICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gyroscopic.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gyroscopic.java index 7f6c41c1..af7c6276 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gyroscopic.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Gyroscopic.java @@ -3,8 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; import org.bukkit.Location; import org.bukkit.Material; @@ -38,19 +40,19 @@ public void cast(CastInformation castInformation) { final double x = Math.cos(a) * r; final double z = Math.sin(a) * r; final Location point = location.clone().add(x, y, z); - displayParticleEffect(point, Particle.GLOW, 0.1, 1); + ParticleUtils.displayParticleEffect(point, Particle.GLOW, 0.1, 1); } } for (Entity entity : location.getWorld().getNearbyEntities(location, effectRange, effectRange, effectRange)) { if (entity instanceof LivingEntity - && hasPermission(castInformation.getCaster(), entity.getLocation(), Interaction.INTERACT_ENTITY) + && GeneralUtils.hasPermission(castInformation.getCaster(), entity.getLocation(), Interaction.INTERACT_ENTITY) && entity.getUniqueId() != castInformation.getCaster() ) { // Todo mobs dont spin? Location newLocation = entity.getLocation().clone(); newLocation.setYaw(entity.getLocation().getYaw() + 10F); entity.teleport(newLocation); - displayParticleEffect(entity, Particle.SPELL, 1, 1); + ParticleUtils.displayParticleEffect(entity, Particle.SPELL, 1, 1); } } } @@ -77,8 +79,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HarmonysSonata.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HarmonysSonata.java index 22d26847..05d5a2dd 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HarmonysSonata.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HarmonysSonata.java @@ -3,8 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import org.bukkit.Location; @@ -41,7 +43,7 @@ public void onTick(CastInformation castInformation) { final Block block = location.getBlock(); if (block.getType() == Material.AIR && SlimefunTag.DIRT_VARIANTS.isTagged(block.getRelative(BlockFace.DOWN).getType()) - && hasPermission(castInformation.getCaster(), block, Interaction.PLACE_BLOCK) + && GeneralUtils.hasPermission(castInformation.getCaster(), block, Interaction.PLACE_BLOCK) ) { final Set set = Tag.FLOWERS.getValues(); final Material material = set.stream() @@ -66,7 +68,7 @@ && hasPermission(castInformation.getCaster(), block, Interaction.PLACE_BLOCK) block.setType(material); } block.getRelative(BlockFace.DOWN).setType(Material.GRASS_BLOCK); - displayParticleEffect(block.getLocation(), Particle.FIREWORKS_SPARK, 0.5, 3); + ParticleUtils.displayParticleEffect(block.getLocation(), Particle.FIREWORKS_SPARK, 0.5, 3); } } @@ -92,8 +94,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.ALCHEMICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HarvestMoon.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HarvestMoon.java new file mode 100644 index 00000000..36f8bdd6 --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HarvestMoon.java @@ -0,0 +1,90 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.concurrent.ThreadLocalRandom; + +public class HarvestMoon extends Spell { + + public HarvestMoon() { + SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(40, true, 5, true, 50, true) + .makeTickingSpell(this::cast, 20, true, 10, false); + setSpellCore(spellCoreBuilder.build()); + } + + @ParametersAreNonnullByDefault + public void cast(CastInformation castInformation) { + final Location location = castInformation.getCasterAsPlayer().getLocation().clone().add(0, 1, 0); + final double range = getRange(castInformation); + final int density = (int) (3 * range); + // Particles + for (double height = 0; height <= Math.PI; height += Math.PI / density) { + final double r = range * Math.sin(height); + final double y = range * Math.cos(height); + for (double a = 0; a < Math.PI * 2; a += Math.PI / density) { + final double x = Math.cos(a) * r; + final double z = Math.sin(a) * r; + final Location point = location.clone().add(x, y, z); + ParticleUtils.displayParticleEffect(point, Particle.WAX_OFF, 0.1, 1); + } + } + + // Bonemealing + for (int i = 0; i < castInformation.getStaveLevel() * 3; i++) { + final int x = (int) ThreadLocalRandom.current().nextDouble(-range, range); + final int z = (int) ThreadLocalRandom.current().nextDouble(-range, range); + final Block potentialBlock = location.add(x, 0, z).getBlock(); + if (Tag.CROPS.isTagged(potentialBlock.getType())) { + potentialBlock.applyBoneMeal(BlockFace.UP); + } + } + } + + @Nonnull + @Override + public String getId() { + return "HARVEST_MOON"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Speaks to the spirit of nature", + "to speed up the growth of nearby", + "crops. Crops must have direct access", + "to the sun." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.WHEAT; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.ELEMENTAL, + StoryType.HUMAN, + StoryType.ANIMAL + ); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Heal.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Heal.java index fe3465ac..5f531517 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Heal.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Heal.java @@ -3,8 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Particle; @@ -26,8 +28,8 @@ public Heal() { @ParametersAreNonnullByDefault public void cast(CastInformation castInformation) { Player caster = Bukkit.getPlayer(castInformation.getCaster()); - healEntity(caster, getHealAmount(castInformation)); - displayParticleEffect(caster, Particle.HEART, 2, 10); + GeneralUtils.healEntity(caster, getHealAmount(castInformation)); + ParticleUtils.displayParticleEffect(caster, Particle.HEART, 2, 10); } @Nonnull @@ -52,8 +54,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HUMAN, StoryType.CELESTIAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HealingMist.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HealingMist.java index a025c1f7..51781a09 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HealingMist.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HealingMist.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; @@ -33,8 +34,8 @@ public void cast(CastInformation castInformation) { for (Entity entity : location.getWorld().getNearbyEntities(location, range, range, range, Player.class::isInstance)) { Player player = (Player) entity; applyPositiveEffects(player, castInformation); - displayParticleEffect(player, Particle.HEART, 2, 5); - displayParticleEffect(player, Particle.CLOUD, 2, 2); + ParticleUtils.displayParticleEffect(player, Particle.HEART, 2, 5); + ParticleUtils.displayParticleEffect(player, Particle.CLOUD, 2, 2); } } @@ -62,8 +63,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.CELESTIAL, StoryType.VOID, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hearthstone.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hearthstone.java index 6244f1d9..6e86ee34 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hearthstone.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hearthstone.java @@ -1,17 +1,15 @@ package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; import io.github.sefiraat.crystamaehistoria.magic.CastInformation; -import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; -import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent; import org.jetbrains.annotations.NotNull; @@ -38,7 +36,7 @@ public void tick(CastInformation castInformation) { int sx = (int) (sizeCast * Math.cos(angle)); int sz = (int) (sizeCast * Math.sin(angle)); Location spawn = middle.clone().add(sx, 0, sz); - displayParticleEffect(spawn, Particle.DRIPPING_HONEY, 0.1, 1); + ParticleUtils.displayParticleEffect(spawn, Particle.DRIPPING_HONEY, 0.1, 1); } } @@ -48,7 +46,7 @@ public void afterAllTicks(CastInformation castInformation) { Location location = caster.getBedSpawnLocation(); if (location == null) { Location casterLocation = caster.getLocation(); - displayParticleEffect(casterLocation.add(casterLocation.getDirection()), Particle.VILLAGER_ANGRY, 1, 10); + ParticleUtils.displayParticleEffect(casterLocation.add(casterLocation.getDirection()), Particle.VILLAGER_ANGRY, 1, 10); } else { caster.teleportAsync(location, PlayerTeleportEvent.TeleportCause.PLUGIN); } @@ -78,8 +76,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hellscape.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hellscape.java index 2da6923a..44126a2c 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hellscape.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Hellscape.java @@ -4,8 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -50,7 +52,7 @@ public void fireProjectiles(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity( + GeneralUtils.damageEntity( livingEntity, castInformation.getCaster(), getDamage(castInformation), @@ -62,13 +64,13 @@ public void projectileHit(CastInformation castInformation) { @ParametersAreNonnullByDefault public void afterProjectileHit(CastInformation castInformation) { - displayParticleEffect(castInformation.getMainTarget(), Particle.VILLAGER_ANGRY, 1.0, 5); + ParticleUtils.displayParticleEffect(castInformation.getMainTarget(), Particle.VILLAGER_ANGRY, 1.0, 5); } @ParametersAreNonnullByDefault public void onTick(MagicProjectile magicProjectile) { - displayParticleEffect(magicProjectile.getProjectile(), Particle.SWEEP_ATTACK, 0.5, 1); - displayParticleEffect(magicProjectile.getProjectile(), Particle.VILLAGER_ANGRY, 0.5, 1); + ParticleUtils.displayParticleEffect(magicProjectile.getProjectile(), Particle.SWEEP_ATTACK, 0.5, 1); + ParticleUtils.displayParticleEffect(magicProjectile.getProjectile(), Particle.VILLAGER_ANGRY, 0.5, 1); } @Nonnull @@ -93,8 +95,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.ALCHEMICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HolyCow.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HolyCow.java index 85ed2a9e..841c1333 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HolyCow.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/HolyCow.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.HolyCowGoal; import org.bukkit.Location; @@ -49,7 +50,7 @@ public void cast(CastInformation castInformation) { } public void onTick(MagicSummon magicSummon) { - displayParticleEffect(magicSummon.getMob(), Particle.GLOW, 1, 4); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.GLOW, 1, 4); } @Nonnull @@ -75,8 +76,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ANIMAL, StoryType.CELESTIAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/ImbueVoid.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/ImbueVoid.java new file mode 100644 index 00000000..eb0ad3e4 --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/ImbueVoid.java @@ -0,0 +1,83 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; +import io.github.sefiraat.crystamaehistoria.utils.mobgoals.BoringGoal; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.concurrent.ThreadLocalRandom; + +public class ImbueVoid extends Spell { + + public ImbueVoid() { + SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(240, false, 3, false, 30, true) + .makeTickingSpell(this::onTick, 5, false, 40, false) + .addPositiveEffect(PotionEffectType.SLOW, 99, 5) + .addPositiveEffect(PotionEffectType.SLOW_DIGGING, 99, 5); + setSpellCore(spellCoreBuilder.build()); + + } + + @ParametersAreNonnullByDefault + public void onTick(CastInformation castInformation) { + final double range = getRange(castInformation); + final Location location = castInformation.getCastLocation().clone().add( + ThreadLocalRandom.current().nextDouble(-range, range), + 0, + ThreadLocalRandom.current().nextDouble(-range, range) + ); + for (int i = 0; i < castInformation.getStaveLevel(); i++) { + SpellUtils.summonTemporaryMob( + EntityType.ENDERMITE, + castInformation.getCaster(), + location, + new BoringGoal(castInformation.getCaster()), + 5 + ); + } + applyPositiveEffects(castInformation.getCasterAsPlayer(), castInformation); + } + + @Nonnull + @Override + public String getId() { + return "IMBUE_VOID"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Spawns a hoard of endermites to fight on", + "you behalf. During this spell you cannot", + "move or attack." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.ENDERMITE_SPAWN_EGG; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.HUMAN, + StoryType.VOID, + StoryType.PHILOSOPHICAL + ); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/KnowledgeShare.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/KnowledgeShare.java index 95e81a0c..ab4da1a5 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/KnowledgeShare.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/KnowledgeShare.java @@ -3,7 +3,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import org.bukkit.Bukkit; import org.bukkit.Effect; @@ -75,8 +75,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HISTORICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LavaLake.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LavaLake.java index 9f789a2e..3e8f869b 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LavaLake.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LavaLake.java @@ -3,7 +3,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; @@ -29,7 +29,7 @@ public void cast(CastInformation castInformation) { final double size = getRange(castInformation); final Block standingBlock = location.getBlock(); - if (hasPermission(castInformation.getCaster(), standingBlock, Interaction.PLACE_BLOCK) + if (GeneralUtils.hasPermission(castInformation.getCaster(), standingBlock, Interaction.PLACE_BLOCK) && standingBlock.getType() == Material.AIR ) { standingBlock.setType(Material.NETHER_BRICKS); @@ -40,7 +40,7 @@ public void cast(CastInformation castInformation) { for (double x = -size; x < size; x++) { for (double z = -size; z < size; z++) { final Block potentialLava = location.clone().add(x, 0, z).getBlock(); - if (hasPermission(castInformation.getCaster(), potentialLava, Interaction.PLACE_BLOCK) + if (GeneralUtils.hasPermission(castInformation.getCaster(), potentialLava, Interaction.PLACE_BLOCK) && potentialLava.getType() == Material.AIR ) { potentialLava.setType(Material.LAVA); @@ -72,8 +72,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.ALCHEMICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LeechBomb.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LeechBomb.java index 081e0777..e3b78512 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LeechBomb.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LeechBomb.java @@ -5,8 +5,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.LeechGoal; import org.bukkit.Location; @@ -71,7 +72,7 @@ public void onTick(MagicSummon magicSummon) { ) { mob.teleport(player.getLocation()); } - displayParticleEffect(magicSummon.getMob(), Particle.SPORE_BLOSSOM_AIR, 1, 1); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.SPORE_BLOSSOM_AIR, 1, 1); } @Nonnull @@ -97,8 +98,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LovePotion.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LovePotion.java index ac3c4550..89b52c71 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LovePotion.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/LovePotion.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; @@ -32,7 +33,7 @@ public void cast(CastInformation castInformation) { Animals animals = (Animals) entity; if (animals.isAdult() && animals.canBreed()) { animals.setLoveModeTicks(120); - displayParticleEffect(entity, Particle.HEART, 1, 5); + ParticleUtils.displayParticleEffect(entity, Particle.HEART, 1, 5); } } } @@ -59,8 +60,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Oviparous.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Oviparous.java index e73fad46..8af75134 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Oviparous.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Oviparous.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; @@ -42,7 +43,7 @@ public void cast(CastInformation castInformation) { Color.fromRGB(190, 170, 115), 2F ); - displayParticleEffect(location, 1, 5, dustOptions); + ParticleUtils.displayParticleEffect(location, 1, 5, dustOptions); entity.setVelocity(new Vector(0, 1, 0)); } if (entity instanceof Turtle) { @@ -55,7 +56,7 @@ public void cast(CastInformation castInformation) { Color.fromRGB(95, 160, 80), 2F ); - displayParticleEffect(location, 1, 5, dustOptions); + ParticleUtils.displayParticleEffect(location, 1, 5, dustOptions); entity.setVelocity(new Vector(0, 0.5, 0)); } } @@ -84,8 +85,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PhantomsFlight.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PhantomsFlight.java index 476c9989..7aebf4ad 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PhantomsFlight.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PhantomsFlight.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.FlyingPhantomGoal; import org.bukkit.Location; @@ -13,7 +14,6 @@ import org.bukkit.Particle; import org.bukkit.entity.Bat; import org.bukkit.entity.EntityType; -import org.bukkit.entity.Phantom; import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; @@ -54,7 +54,7 @@ public void cast(CastInformation castInformation) { } public void onTick(MagicSummon magicSummon) { - displayParticleEffect(magicSummon.getMob(), Particle.SPORE_BLOSSOM_AIR, 1, 2); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.SPORE_BLOSSOM_AIR, 1, 2); } @Nonnull @@ -81,8 +81,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ANIMAL, StoryType.CELESTIAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PhilosophersStone.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PhilosophersStone.java new file mode 100644 index 00000000..47d1f915 --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PhilosophersStone.java @@ -0,0 +1,115 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.CrystaTag; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; +import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public class PhilosophersStone extends Spell { + + protected static final List MATERIALS_RARE = new ArrayList<>(); + protected static final List MATERIALS_UNCOMMON = new ArrayList<>(); + protected static final List MATERIALS_COMMON = new ArrayList<>(); + + static { + MATERIALS_RARE.add(Material.COPPER_BLOCK); + MATERIALS_RARE.add(Material.IRON_BLOCK); + MATERIALS_RARE.add(Material.EMERALD_BLOCK); + MATERIALS_RARE.add(Material.DIAMOND_BLOCK); + MATERIALS_RARE.add(Material.GOLD_BLOCK); + MATERIALS_UNCOMMON.addAll(SlimefunTag.ORES.getValues()); + MATERIALS_UNCOMMON.addAll(CrystaTag.CONCRETE_BLOCKS.getValues()); + MATERIALS_UNCOMMON.addAll(CrystaTag.GLAZED_TERRACOTTA.getValues()); + MATERIALS_COMMON.addAll(Tag.STONE_ORE_REPLACEABLES.getValues()); + MATERIALS_COMMON.addAll(Tag.DIRT.getValues()); + MATERIALS_COMMON.addAll(Tag.LOGS.getValues()); + MATERIALS_COMMON.addAll(Tag.SAND.getValues()); + MATERIALS_COMMON.addAll(Tag.SNOW.getValues()); + MATERIALS_COMMON.addAll(SlimefunTag.CONCRETE_POWDERS.getValues()); + } + + public PhilosophersStone() { + SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(10, true, 50, true, 5, true) + .makeInstantSpell(this::cast); + setSpellCore(spellCoreBuilder.build()); + } + + @ParametersAreNonnullByDefault + public void cast(CastInformation castInformation) { + final Player player = castInformation.getCasterAsPlayer(); + final Block block = player.getTargetBlockExact((int) getRange(castInformation)); + if (GeneralUtils.hasPermission(player, block, Interaction.BREAK_BLOCK) + && block.getType().getHardness() != -1 + && !block.getType().isAir() + ) { + final Location location = block.getLocation(); + final int random = ThreadLocalRandom.current().nextInt(100); + Material material; + if (random > 95) { + material = MATERIALS_RARE.get(ThreadLocalRandom.current().nextInt(0, MATERIALS_RARE.size())); + } else if (random > 60) { + material = MATERIALS_UNCOMMON.get(ThreadLocalRandom.current().nextInt(0, MATERIALS_UNCOMMON.size())); + } else { + material = MATERIALS_COMMON.get(ThreadLocalRandom.current().nextInt(0, MATERIALS_COMMON.size())); + } + final List list = (List) CrystamaeHistoria.getConfigManager().getBlockColors().getList(material.name()); + final Color color = Color.fromRGB(list.get(0), list.get(1), list.get(2)); + final Particle.DustOptions dustOptionsToBlock = new Particle.DustOptions(color, 1); + ParticleUtils.drawCube(dustOptionsToBlock, location, location.clone().add(1, 1, 1), 0.25); + block.setType(material); + } + } + + @Nonnull + @Override + public String getId() { + return "PHILOSOPHERS_STONE"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Converts the targets block into...", + "something else..." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.GOLD_BLOCK; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.ALCHEMICAL, + StoryType.HUMAN, + StoryType.PHILOSOPHICAL + ); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PoisonNova.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PoisonNova.java index df8e3350..51cf5cec 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PoisonNova.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/PoisonNova.java @@ -4,8 +4,10 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -53,9 +55,12 @@ public void fireProjectile(CastInformation castInformation) { public void projectileHit(CastInformation castInformation) { LivingEntity hit = castInformation.getMainTarget(); if (hit.getHealth() == 1) { - damageEntity(hit, castInformation.getCaster(), getDamage(castInformation)); + GeneralUtils.damageEntity(hit, castInformation.getCaster(), getDamage(castInformation)); } else { - PotionEffect potionEffect = new PotionEffect(PotionEffectType.POISON, castInformation.getStaveLevel() * 100, castInformation.getStaveLevel()); + PotionEffect potionEffect = new PotionEffect(PotionEffectType.POISON, + castInformation.getStaveLevel() * 100, + castInformation.getStaveLevel() + ); hit.addPotionEffect(potionEffect); setLastDamageToCaster(hit, castInformation); } @@ -63,7 +68,11 @@ public void projectileHit(CastInformation castInformation) { @ParametersAreNonnullByDefault public void afterProjectileHit(CastInformation castInformation) { - displayParticleEffect(castInformation.getMainTarget(), Particle.CRIMSON_SPORE, 1.0, 10); + ParticleUtils.displayParticleEffect(castInformation.getMainTarget(), + Particle.CRIMSON_SPORE, + 1.0, + 10 + ); } @Nonnull @@ -90,8 +99,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Prism.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Prism.java index edc0e003..0714a830 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Prism.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Prism.java @@ -3,9 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.Keys; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI; import org.bukkit.Material; import org.bukkit.Particle; @@ -50,7 +51,7 @@ public void cast(CastInformation castInformation) { } PersistentDataAPI.setBoolean(player, Keys.newKey("PRISM"), true); applyPositiveEffects(player, castInformation); - displayParticleEffect(player, Particle.SPELL, 2, 20); + ParticleUtils.displayParticleEffect(player, Particle.SPELL, 2, 20); } @Nonnull @@ -76,8 +77,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Protectorate.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Protectorate.java index c1d6ef98..71669da9 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Protectorate.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Protectorate.java @@ -3,9 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.Keys; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI; import org.bukkit.Location; import org.bukkit.Material; @@ -39,14 +40,14 @@ public void cast(CastInformation castInformation) { final double x = Math.cos(a) * r; final double z = Math.sin(a) * r; final Location point = location.clone().add(x, y, z); - displayParticleEffect(point, Particle.ELECTRIC_SPARK, 0.1, 1); + ParticleUtils.displayParticleEffect(point, Particle.ELECTRIC_SPARK, 0.1, 1); } } // Effects for (Entity entity : location.getWorld().getNearbyEntities(location, effectRange, effectRange, effectRange)) { if (entity instanceof LivingEntity) { PersistentDataAPI.setLong(entity, Keys.PDC_IS_INVULNERABLE, System.currentTimeMillis() + 1050); - displayParticleEffect(entity, Particle.VILLAGER_HAPPY, 1, 3); + ParticleUtils.displayParticleEffect(entity, Particle.VILLAGER_HAPPY, 1, 3); } } } @@ -74,8 +75,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Push.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Push.java index e0f96103..2939b9ce 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Push.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Push.java @@ -3,8 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; @@ -41,8 +43,8 @@ private void push(CastInformation castInformation, double amount) { double range = getRange(castInformation); for (Entity entity : castLocation.getWorld().getNearbyEntities(castLocation, range, 2, range)) { if (entity instanceof LivingEntity && entity.getUniqueId() != castInformation.getCaster()) { - pushEntity(castInformation.getCaster(), castLocation, entity, amount); - displayParticleEffect(entity, Particle.CRIT, 1, 10); + GeneralUtils.pushEntity(castInformation.getCaster(), castLocation, entity, amount); + ParticleUtils.displayParticleEffect(entity, Particle.CRIT, 1, 10); } } } @@ -70,8 +72,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Quake.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Quake.java index ed071763..cf0a75a6 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Quake.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Quake.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; @@ -53,7 +54,7 @@ public void onTick(CastInformation castInformation) { if (entity instanceof LivingEntity && entity.getUniqueId() != castInformation.getCaster()) { LivingEntity livingEntity = (LivingEntity) entity; applyNegativeEffects(livingEntity, castInformation); - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); + GeneralUtils.damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation)); } } } @@ -81,8 +82,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HISTORICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RainOfFire.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RainOfFire.java index 76ca48cb..26df2742 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RainOfFire.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RainOfFire.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -64,7 +65,12 @@ public void beforeProjectileHits(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHits(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation), castInformation.getDamageLocation(), getProjectileKnockback(castInformation)); + GeneralUtils.damageEntity(livingEntity, + castInformation.getCaster(), + getDamage(castInformation), + castInformation.getDamageLocation(), + getProjectileKnockback(castInformation) + ); } } @@ -91,8 +97,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Ravage.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Ravage.java index 6695185e..804fd853 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Ravage.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Ravage.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.RidableGroundGoal; import org.bukkit.Location; @@ -55,7 +56,7 @@ public void cast(CastInformation castInformation) { } public void onTick(MagicSummon magicSummon) { - displayParticleEffect(magicSummon.getMob(), Particle.VILLAGER_ANGRY, 1, 2); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.VILLAGER_ANGRY, 1, 2); } @Nonnull @@ -83,8 +84,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.ALCHEMICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RemnantOfWar.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RemnantOfWar.java index 6ea998a2..83110dac 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RemnantOfWar.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/RemnantOfWar.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.BoringGoal; import org.bukkit.Location; @@ -105,7 +106,7 @@ public void gearZombie(Zombie zombie, int tier) { } public void onTick(MagicSummon magicSummon) { - displayParticleEffect(magicSummon.getMob(), Particle.SOUL, 1, 1); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.SOUL, 1, 1); } @Nonnull @@ -131,8 +132,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HISTORICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Shroud.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Shroud.java index f957b5b6..41339f27 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Shroud.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Shroud.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; @@ -36,7 +37,7 @@ public void cast(CastInformation castInformation) { if (entity instanceof LivingEntity && entity.getUniqueId() != castInformation.getCaster()) { LivingEntity livingEntity = (LivingEntity) entity; applyNegativeEffects(livingEntity, castInformation); - displayParticleEffect(livingEntity, Particle.SLIME, 2, 2); + ParticleUtils.displayParticleEffect(livingEntity, Particle.SLIME, 2, 2); } } } @@ -65,8 +66,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SpawnFiends.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SpawnFiends.java index 61650dda..c55d7c75 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SpawnFiends.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SpawnFiends.java @@ -3,7 +3,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.FiendGoal; @@ -71,8 +71,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ANIMAL, StoryType.VOID, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Squall.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Squall.java index 8241f00d..3baca9ea 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Squall.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Squall.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Material; @@ -29,7 +30,7 @@ public void cast(CastInformation castInformation) { if (caster != null) { caster.getWorld().setThundering(true); caster.getWorld().setStorm(true); - displayParticleEffect(caster, Particle.ELECTRIC_SPARK, 2, 30); + ParticleUtils.displayParticleEffect(caster, Particle.ELECTRIC_SPARK, 2, 30); caster.getWorld().playEffect(caster.getLocation(), Effect.BONE_MEAL_USE, 1); } } @@ -57,8 +58,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/StarFall.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/StarFall.java index e2e97ebc..d3b65a30 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/StarFall.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/StarFall.java @@ -4,7 +4,7 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicProjectile; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; @@ -57,7 +57,7 @@ public void fireProjectiles(CastInformation castInformation) { @ParametersAreNonnullByDefault public void projectileHits(CastInformation castInformation) { for (final LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity( + GeneralUtils.damageEntity( livingEntity, castInformation.getCaster(), getDamage(castInformation), @@ -104,8 +104,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ALCHEMICAL, StoryType.CELESTIAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/StripMine.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/StripMine.java new file mode 100644 index 00000000..e1f33ebc --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/StripMine.java @@ -0,0 +1,86 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; + +public class StripMine extends Spell { + + public StripMine() { + SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(5, true, 10, true, 25, true) + .makeTickingSpell(this::tick, 10, true, 5, false); + setSpellCore(spellCoreBuilder.build()); + } + + @ParametersAreNonnullByDefault + public void tick(CastInformation castInformation) { + + BlockFace blockFace = castInformation.getTargetedBlockFaceOnCast(); + + if (blockFace == BlockFace.UP || blockFace == BlockFace.DOWN) { + return; + } + + int xOffset = 0; + int zOffset = 0; + Vector faceDirection = castInformation.getTargetedBlockFaceOnCast().getDirection(); + if (faceDirection.getX() == 0) { + zOffset = (int) ((castInformation.getCurrentTick() - 1) * -faceDirection.getZ()); + } else if (faceDirection.getZ() == 0) { + xOffset = (int) ((castInformation.getCurrentTick() - 1) * -faceDirection.getX()); + } + + final Block block = castInformation.getTargetedBlockOnCast().getRelative(xOffset, 0, zOffset); + final Block blockBelow = block.getRelative(BlockFace.DOWN); + if (GeneralUtils.tryBreakBlock(castInformation.getCaster(), block)) { + if (GeneralUtils.tryBreakBlock(castInformation.getCaster(), blockBelow) + && castInformation.getCurrentTick() % 5 == 0 + ) { + blockBelow.setType(Material.TORCH); + } + } + } + + @Nonnull + @Override + public String getId() { + return "STRIP_MINE"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Magically strips a mineshaft starting from", + "the targeted block." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.MINECART; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.MECHANICAL, + StoryType.ALCHEMICAL, + StoryType.HISTORICAL + ); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SummonGolem.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SummonGolem.java index 075f60a2..23a97ccd 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SummonGolem.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/SummonGolem.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.spells.core.MagicSummon; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import io.github.sefiraat.crystamaehistoria.utils.SpellUtils; import io.github.sefiraat.crystamaehistoria.utils.mobgoals.GolemGoal; import org.bukkit.Location; @@ -58,7 +59,7 @@ public void onTick(MagicSummon magicSummon) { ) { mob.teleport(player.getLocation()); } - displayParticleEffect(magicSummon.getMob(), Particle.SLIME, 1, 3); + ParticleUtils.displayParticleEffect(magicSummon.getMob(), Particle.SLIME, 1, 3); } @Nonnull @@ -85,8 +86,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Teleport.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Teleport.java index 3adb07d5..97d460ef 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Teleport.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Teleport.java @@ -4,8 +4,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -33,7 +34,7 @@ public void cast(CastInformation castInformation) { if (teleportToLocation != null) { caster.teleport(teleportToLocation); - displayParticleEffect(caster, Particle.END_ROD, 1, 10); + ParticleUtils.displayParticleEffect(caster, Particle.END_ROD, 1, 10); } else { caster.sendMessage(CrystamaeHistoria.getInstance().getConfig().getString("messages.spells.teleport_no_suitable_location")); } @@ -88,8 +89,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tempest.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tempest.java index 3a816016..dc6a9b56 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tempest.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tempest.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.LightningStrike; @@ -60,7 +61,7 @@ public void beforeProjectileHit(CastInformation castInformation) { @ParametersAreNonnullByDefault public void onProjectileHit(CastInformation castInformation) { for (LivingEntity livingEntity : getTargets(castInformation, getProjectileAoe(castInformation), true)) { - damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation), castInformation.getDamageLocation(), getKnockback(castInformation)); + GeneralUtils.damageEntity(livingEntity, castInformation.getCaster(), getDamage(castInformation), castInformation.getDamageLocation(), getKnockback(castInformation)); } } @@ -87,8 +88,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.ELEMENTAL, StoryType.MECHANICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeCompression.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeCompression.java index 27081840..71278cc6 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeCompression.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeCompression.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; @@ -45,7 +46,7 @@ public void cast(CastInformation castInformation) { final double x = Math.cos(a) * r; final double z = Math.sin(a) * r; final Location point = location.clone().add(x, y, z); - displayParticleEffect(point, 0.1, 1, dustOptions); + ParticleUtils.displayParticleEffect(point, 0.1, 1, dustOptions); } } // Effects @@ -80,8 +81,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HISTORICAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeDilation.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeDilation.java index bb324ca2..a9b1a8fb 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeDilation.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TimeDilation.java @@ -3,8 +3,9 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; @@ -45,7 +46,7 @@ public void cast(CastInformation castInformation) { final double x = Math.cos(a) * r; final double z = Math.sin(a) * r; final Location point = location.clone().add(x, y, z); - displayParticleEffect(point, 0.1, 1, dustOptions); + ParticleUtils.displayParticleEffect(point, 0.1, 1, dustOptions); } } // Effects @@ -80,8 +81,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HISTORICAL, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tracer.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tracer.java index 5dfb0011..743edec2 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tracer.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Tracer.java @@ -3,7 +3,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.apache.commons.lang.Validate; @@ -83,7 +83,7 @@ public void onTick(CastInformation castInformation) { dustOptions, location, livingEntity.getLocation(), - 0.2 + 1 ); } } @@ -111,8 +111,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HISTORICAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TunnelBore.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TunnelBore.java new file mode 100644 index 00000000..71e284ab --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/TunnelBore.java @@ -0,0 +1,85 @@ +package io.github.sefiraat.crystamaehistoria.magic.spells.tier1; + +import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.sefiraat.crystamaehistoria.magic.CastInformation; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; +import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; +import io.github.sefiraat.crystamaehistoria.runnables.spells.TunnelBoreRunnable; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Endermite; +import org.bukkit.entity.EntityType; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.UUID; + +public class TunnelBore extends Spell { + + public TunnelBore() { + SpellCoreBuilder spellCoreBuilder = new SpellCoreBuilder(50, true, 1, true, 100, true) + .makeInstantSpell(this::cast); + setSpellCore(spellCoreBuilder.build()); + } + + @ParametersAreNonnullByDefault + public void cast(CastInformation castInformation) { + final UUID caster = castInformation.getCaster(); + final Location location = castInformation.getCastLocation(); + final Vector direction = location.getDirection().clone(); + final int range = (int) getRange(castInformation); + direction.setY(0); + final Location spawnLocation = location.clone().add(0, range, 0); + final Endermite bore = (Endermite) spawnLocation.getWorld().spawnEntity(spawnLocation, + EntityType.ENDERMITE, + CreatureSpawnEvent.SpawnReason.COMMAND, + entity -> { + Endermite mite = (Endermite) entity; + mite.setGravity(false); + mite.setInvulnerable(true); + mite.setInvisible(true); + mite.setVelocity(location.getDirection().multiply(2)); + }); + TunnelBoreRunnable runnable = new TunnelBoreRunnable(bore, range, caster, range * 20); + runnable.runTaskTimer(CrystamaeHistoria.getInstance(), 0, 1); + } + + @Nonnull + @Override + public String getId() { + return "TUNNEL_BORE"; + } + + @Nonnull + @Override + public String[] getLore() { + return new String[]{ + "Uses powerful magics to bore a tunnel", + "in the direction you're facing.", + "Does not drop items." + }; + } + + @Nonnull + @Override + public Material getMaterial() { + return Material.GOAT_SPAWN_EGG; + } + + @NotNull + @Override + public RecipeSpell getRecipe() { + return new RecipeSpell( + 1, + StoryType.ELEMENTAL, + StoryType.ALCHEMICAL, + StoryType.ANIMAL + ); + } + +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Vacuum.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Vacuum.java index 74980651..f80b719a 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Vacuum.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/Vacuum.java @@ -3,8 +3,10 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -44,8 +46,8 @@ private void pull(CastInformation castInformation, double amount) { double range = getRange(castInformation); for (Entity entity : castLocation.getWorld().getNearbyEntities(castLocation, range, 2, range)) { if (entity instanceof LivingEntity && entity.getUniqueId() != castInformation.getCaster()) { - pullEntity(castInformation.getCaster(), castLocation, entity, amount); - displayParticleEffect(entity, Particle.CRIT, 1, 10); + GeneralUtils.pullEntity(castInformation.getCaster(), castLocation, entity, amount); + ParticleUtils.displayParticleEffect(entity, Particle.CRIT, 1, 10); } } } @@ -73,8 +75,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.MECHANICAL, StoryType.HUMAN, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/WitherWeather.java b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/WitherWeather.java index 66316ae6..87a6dc42 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/WitherWeather.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/magic/spells/tier1/WitherWeather.java @@ -3,7 +3,7 @@ import io.github.sefiraat.crystamaehistoria.magic.CastInformation; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCoreBuilder; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.SpellRecipe; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeSpell; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.Keys; import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI; @@ -67,8 +67,8 @@ public Material getMaterial() { @NotNull @Override - public SpellRecipe getRecipe() { - return new SpellRecipe( + public RecipeSpell getRecipe() { + return new RecipeSpell( 1, StoryType.HUMAN, StoryType.ANIMAL, diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/runnables/spells/TemporaryEffectsRunnable.java b/src/main/java/io/github/sefiraat/crystamaehistoria/runnables/spells/TemporaryEffectsRunnable.java index a37cf0e6..ed61c2a7 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/runnables/spells/TemporaryEffectsRunnable.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/runnables/spells/TemporaryEffectsRunnable.java @@ -1,7 +1,7 @@ package io.github.sefiraat.crystamaehistoria.runnables.spells; -import io.github.sefiraat.crystamaehistoria.SpellMemory; import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.sefiraat.crystamaehistoria.SpellMemory; import org.bukkit.scheduler.BukkitRunnable; public class TemporaryEffectsRunnable extends BukkitRunnable { diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/runnables/spells/TunnelBoreRunnable.java b/src/main/java/io/github/sefiraat/crystamaehistoria/runnables/spells/TunnelBoreRunnable.java new file mode 100644 index 00000000..825685fd --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/runnables/spells/TunnelBoreRunnable.java @@ -0,0 +1,67 @@ +package io.github.sefiraat.crystamaehistoria.runnables.spells; + +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; +import io.github.thebusybiscuit.slimefun4.libraries.dough.blocks.BlockPosition; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.entity.LivingEntity; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class TunnelBoreRunnable extends BukkitRunnable { + + private final LivingEntity bore; + private final int radius; + private final UUID owner; + private int iterations; + + public TunnelBoreRunnable(LivingEntity bore, int radius, UUID owner, int iterations) { + this.bore = bore; + this.radius = radius; + this.owner = owner; + this.iterations = iterations; + } + + @Override + public synchronized void cancel() throws IllegalStateException { + super.cancel(); + bore.remove(); + } + + @Override + public void run() { + if (iterations <= 0) { + this.cancel(); + } else { + final Location location = bore.getLocation(); + final List blocks = new ArrayList<>(); + + for (int x = location.getBlockX() - radius; x <= location.getBlockX() + radius; x++) { + for (int y = location.getBlockY() - radius; y <= location.getBlockY() + radius; y++) { + for (int z = location.getBlockZ() - radius; z <= location.getBlockZ() + radius; z++) { + final BlockPosition blockPosition = new BlockPosition(location.getWorld(), x, y, z); + if (!blocks.contains(blockPosition)) { + blocks.add(blockPosition); + } + } + } + } + + for (BlockPosition blockPosition : blocks) { + final Block block = blockPosition.getBlock(); + if (GeneralUtils.blockCanBeBroken(this.owner, block)) { + block.setType(Material.AIR); + } + } + + ParticleUtils.displayParticleEffect(bore, Particle.FALLING_LAVA, radius, 10); + iterations--; + } + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/ItemGroups.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/ItemGroups.java similarity index 81% rename from src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/ItemGroups.java rename to src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/ItemGroups.java index b8c3b85b..4e89b7ac 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/ItemGroups.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/ItemGroups.java @@ -1,15 +1,17 @@ -package io.github.sefiraat.crystamaehistoria.slimefun.itemgroups; +package io.github.sefiraat.crystamaehistoria.slimefun; +import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.DummyItemGroup; +import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.SpellCollectionFlexGroup; +import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.StoryCollectionFlexGroup; import io.github.sefiraat.crystamaehistoria.utils.Keys; import io.github.sefiraat.crystamaehistoria.utils.theme.ThemeType; import io.github.thebusybiscuit.slimefun4.api.items.groups.NestedItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.groups.SubItemGroup; import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack; -import lombok.experimental.UtilityClass; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -@UtilityClass public final class ItemGroups { public static final NestedItemGroup MAIN = new NestedItemGroup( @@ -79,4 +81,12 @@ public final class ItemGroups { ThemeType.MAIN.getColor() + "Dummy Crystamae Historia" ) ); + + public ItemGroups() { + final CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); + + // Slimefun Registry + ItemGroups.STORY_COLLECTION.register(plugin); + ItemGroups.SPELL_COLLECTION.register(plugin); + } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Machines.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Machines.java index 88b13222..ab398adf 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Machines.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Machines.java @@ -1,30 +1,33 @@ package io.github.sefiraat.crystamaehistoria.slimefun; import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; -import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.ItemGroups; import io.github.sefiraat.crystamaehistoria.slimefun.machines.chroniclerpanel.ChroniclerPanel; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.DummyLiquefactionBasinCrafting; import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.LiquefactionBasin; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.LiquefactionBasinCache; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeItem; import io.github.sefiraat.crystamaehistoria.slimefun.machines.realisationaltar.RealisationAltar; import io.github.sefiraat.crystamaehistoria.slimefun.machines.staveconfigurator.StaveConfigurator; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.theme.ThemeType; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import javax.annotation.ParametersAreNonnullByDefault; - public class Machines { - private final CrystamaeHistoria plugin; + public static ChroniclerPanel CHRONICLER_PANEL; + public static RealisationAltar REALISATION_ALTAR; + public static LiquefactionBasin LIQUEFACTION_BASIN; + public static StaveConfigurator STAVE_CONFIGURATOR; - @ParametersAreNonnullByDefault - public Machines(CrystamaeHistoria p) { - this.plugin = p; - } + public Machines() { + + final CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); - public void setup() { - new ChroniclerPanel( + // Chronicler + CHRONICLER_PANEL = new ChroniclerPanel( ItemGroups.MECHANISMS, ThemeType.themedSlimefunItemStack( "CRY_CHRONICLER_PANEL_1", @@ -41,9 +44,10 @@ public void setup() { SlimefunItems.CORINTHIAN_BRONZE_INGOT, new ItemStack(Material.AMETHYST_CLUSTER), SlimefunItems.CORINTHIAN_BRONZE_INGOT, SlimefunItems.MAGIC_LUMP_2, SlimefunItems.MAGIC_LUMP_2, SlimefunItems.MAGIC_LUMP_2, } - ).register(plugin); + ); - new RealisationAltar( + // Realisation + REALISATION_ALTAR = new RealisationAltar( ItemGroups.MECHANISMS, ThemeType.themedSlimefunItemStack( "CRY_REALISATION_ALTAR_1", @@ -60,9 +64,10 @@ null, new ItemStack(Material.BOOK), null, SlimefunItems.CORINTHIAN_BRONZE_INGOT, new ItemStack(Material.AMETHYST_CLUSTER), SlimefunItems.CORINTHIAN_BRONZE_INGOT, SlimefunItems.MAGIC_LUMP_2, SlimefunItems.TALISMAN_MAGICIAN, SlimefunItems.MAGIC_LUMP_2, } - ).register(plugin); + ); - new LiquefactionBasin( + // Liquefaction + LIQUEFACTION_BASIN = new LiquefactionBasin( ItemGroups.MECHANISMS, ThemeType.themedSlimefunItemStack( "CRY_LIQUEFACTION_BASIN_1", @@ -81,13 +86,21 @@ SlimefunItems.CORINTHIAN_BRONZE_INGOT, new ItemStack(Material.AMETHYST_CLUSTER), SlimefunItems.CORINTHIAN_BRONZE_INGOT, new ItemStack(Material.AMETHYST_CLUSTER), SlimefunItems.CORINTHIAN_BRONZE_INGOT, - CrystamaeHistoria.getStructure().getMaterials().amalgamateIngot.getItem(), + Materials.AMALGAMATE_INGOT.getItem(), SlimefunItems.TALISMAN_MAGICIAN, - CrystamaeHistoria.getStructure().getMaterials().amalgamateIngot.getItem(), + Materials.AMALGAMATE_INGOT.getItem(), } - ).register(plugin); + ); - new StaveConfigurator( + + // Stave Configurator + RecipeItem staveConfiguratorRecipe = new RecipeItem( + new ItemStack(Material.COPPER_BLOCK), + StoryType.ELEMENTAL, 1, + StoryType.MECHANICAL, 1, + StoryType.ALCHEMICAL, 1 + ); + STAVE_CONFIGURATOR = new StaveConfigurator( ItemGroups.MECHANISMS, ThemeType.themedSlimefunItemStack( "CRY_STAVE_CONFIGURATOR", @@ -98,19 +111,18 @@ SlimefunItems.CORINTHIAN_BRONZE_INGOT, new ItemStack(Material.AMETHYST_CLUSTER), "to add spell plates into your", "Staves." ), - RecipeType.ENHANCED_CRAFTING_TABLE, - new ItemStack[]{ - SlimefunItems.COPPER_INGOT, - SlimefunItems.COPPER_INGOT, - SlimefunItems.COPPER_INGOT, - SlimefunItems.CORINTHIAN_BRONZE_INGOT, - new ItemStack(Material.AMETHYST_CLUSTER), - SlimefunItems.CORINTHIAN_BRONZE_INGOT, - CrystamaeHistoria.getStructure().getMaterials().amalgamateIngot.getItem(), - Materials.CHARGED_PLATE_T_1.getItem(), - CrystamaeHistoria.getStructure().getMaterials().amalgamateIngot.getItem(), - } - ).register(plugin); + DummyLiquefactionBasinCrafting.TYPE, + staveConfiguratorRecipe.getDisplayRecipe() + ); + + // Slimefun Registry + CHRONICLER_PANEL.register(plugin); + REALISATION_ALTAR.register(plugin); + LIQUEFACTION_BASIN.register(plugin); + STAVE_CONFIGURATOR.register(plugin); + + // Liquefaction Recipes + LiquefactionBasinCache.addCraftingRecipe(STAVE_CONFIGURATOR, staveConfiguratorRecipe); } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Materials.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Materials.java index 9f2106a2..3a30557c 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Materials.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Materials.java @@ -1,7 +1,8 @@ package io.github.sefiraat.crystamaehistoria.slimefun; import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; -import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.ItemGroups; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.LiquefactionBasinCache; +import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.RecipeItem; import io.github.sefiraat.crystamaehistoria.slimefun.machines.realisationaltar.DummyRealisationAltar; import io.github.sefiraat.crystamaehistoria.slimefun.materials.Crystal; import io.github.sefiraat.crystamaehistoria.slimefun.tools.plates.BlankPlate; @@ -13,20 +14,81 @@ import io.github.sefiraat.crystamaehistoria.utils.theme.ThemeType; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import lombok.Getter; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import javax.annotation.ParametersAreNonnullByDefault; import java.util.EnumMap; import java.util.Map; public class Materials { - public static final SlimefunItem INERT_PLATE_T_1; - public static final SlimefunItem CHARGED_PLATE_T_1; + public static final Map DUMMY_CRYSTAL_MAP = new EnumMap<>(StoryType.class); + public static final Map> CRYSTAL_MAP = new EnumMap<>(StoryRarity.class); + + public static SlimefunItem INERT_PLATE_T_1; + public static SlimefunItem CHARGED_PLATE_T_1; + public static SlimefunItem AMALGAMATE_DUST; + public static SlimefunItem AMALGAMATE_INGOT; + + public Materials() { + + CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); + + // Dummy Crystals (for recipe & compendium displays) + for (StoryType type : StoryType.getCachedValues()) { + ThemeType theme = ThemeType.getByType(type); + SlimefunItem sfItem = new Crystal( + ItemGroups.DUMMY_ITEM_GROUP, + ThemeType.themedSlimefunItemStack( + "CRY_CRYSTAL_DUMMY_" + type.toString() + "_" + type.toString(), + Skulls.getByType(type).getPlayerHead(), + ThemeType.CRYSTAL, + theme.getColor() + TextUtils.toTitleCase(type.toString() + " Crystal"), + "Magical Crystamae in it's physical form" + ), + DummyRealisationAltar.TYPE, + new ItemStack[]{}, + StoryRarity.COMMON, + type + ); + sfItem.register(plugin); + DUMMY_CRYSTAL_MAP.put(type, sfItem); + } + + // Live Crystals + for (StoryRarity rarity : StoryRarity.getCachedValues()) { + Map storyTypeSlimefunItemMap = new EnumMap<>(StoryType.class); + for (StoryType type : StoryType.values()) { + ThemeType theme = ThemeType.getByRarity(rarity); + SlimefunItem slimefunItem = new Crystal( + ItemGroups.CRYSTALS, + ThemeType.themedSlimefunItemStack( + "CRY_CRYSTAL_" + rarity.toString() + "_" + type.toString(), + Skulls.getByType(type).getPlayerHead(), + ThemeType.CRYSTAL, + theme.getColor() + TextUtils.toTitleCase(rarity.toString() + " " + type.toString()) + " Crystal", + "Magical Crystamae in it's physical form" + ), + DummyRealisationAltar.TYPE, + new ItemStack[]{null, null, null, null, new ItemStack(Material.AMETHYST_CLUSTER), null, null, null, null}, + rarity, + type + ); + slimefunItem.register(plugin); + storyTypeSlimefunItemMap.put(type, slimefunItem); + CRYSTAL_MAP.put(rarity, storyTypeSlimefunItemMap); + } + } + + // Inert Plate + RecipeItem inertRecipeItem = new RecipeItem( + SlimefunItems.REINFORCED_PLATE.clone(), + StoryType.ELEMENTAL, 10, + StoryType.HUMAN, 10, + StoryType.PHILOSOPHICAL, 10 + ); - static { INERT_PLATE_T_1 = new BlankPlate( ItemGroups.TOOLS, ThemeType.themedSlimefunItemStack( @@ -38,10 +100,12 @@ public class Materials { "store magical energy" ), RecipeType.ORE_WASHER, - new ItemStack[]{null, null, null, null, new ItemStack(Material.AMETHYST_CLUSTER), null, null, null, null}, + inertRecipeItem.getDisplayRecipe(), 1 ); + + // Charged Plate CHARGED_PLATE_T_1 = new ChargedPlate( ItemGroups.TOOLS, ThemeType.themedSlimefunItemStack( @@ -57,32 +121,8 @@ public class Materials { 1 ); - INERT_PLATE_T_1.register(CrystamaeHistoria.getInstance()); - CHARGED_PLATE_T_1.register(CrystamaeHistoria.getInstance()); - - } - - // TODO Create a class to store the value map - @Getter - private final Map> crystalMap = new EnumMap<>(StoryRarity.class); - @Getter - private final Map typeItemMap = new EnumMap<>(StoryType.class); - private final CrystamaeHistoria plugin; - public SlimefunItem amalgamateDust; - public SlimefunItem amalgamateIngot; - - @ParametersAreNonnullByDefault - public Materials(CrystamaeHistoria p) { - this.plugin = p; - } - - public void setup() { - setUpCrystals(); - setUpDummyCrystalTypes(); - - CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); - - amalgamateDust = new SlimefunItem( + // Amalgamate Dust + AMALGAMATE_DUST = new SlimefunItem( ItemGroups.TOOLS, ThemeType.themedSlimefunItemStack( "CRY_AMALGAMATE_DUST", @@ -93,20 +133,20 @@ public void setup() { ), RecipeType.MAGIC_WORKBENCH, new ItemStack[]{ - crystalMap.get(StoryRarity.COMMON).get(StoryType.ELEMENTAL).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.MECHANICAL).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.ALCHEMICAL).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.HISTORICAL).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.HUMAN).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.ANIMAL).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.CELESTIAL).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.VOID).getItem(), - crystalMap.get(StoryRarity.COMMON).get(StoryType.PHILOSOPHICAL).getItem() + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.ELEMENTAL).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.MECHANICAL).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.ALCHEMICAL).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.HISTORICAL).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.HUMAN).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.ANIMAL).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.CELESTIAL).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.VOID).getItem(), + CRYSTAL_MAP.get(StoryRarity.COMMON).get(StoryType.PHILOSOPHICAL).getItem() } ); - amalgamateDust.register(plugin); - amalgamateIngot = new SlimefunItem( + // Amalgamate Ingot + AMALGAMATE_INGOT = new SlimefunItem( ItemGroups.TOOLS, ThemeType.themedSlimefunItemStack( "CRY_AMALGAMATE_INGOT", @@ -117,60 +157,18 @@ public void setup() { ), RecipeType.SMELTERY, new ItemStack[]{ - amalgamateDust.getItem() + AMALGAMATE_DUST.getItem() } ); - amalgamateIngot.register(plugin); - } + // Slimefun Registry + CHARGED_PLATE_T_1.register(CrystamaeHistoria.getInstance()); + INERT_PLATE_T_1.register(CrystamaeHistoria.getInstance()); + AMALGAMATE_DUST.register(plugin); + AMALGAMATE_INGOT.register(plugin); - private void setUpCrystals() { - for (StoryRarity rarity : StoryRarity.getCachedValues()) { - Map storyTypeSlimefunItemMap = new EnumMap<>(StoryType.class); - for (StoryType type : StoryType.values()) { - ThemeType theme = ThemeType.getByRarity(rarity); - SlimefunItem slimefunItem = new Crystal( - ItemGroups.CRYSTALS, - ThemeType.themedSlimefunItemStack( - "CRY_CRYSTAL_" + rarity.toString() + "_" + type.toString(), - Skulls.getByType(type).getPlayerHead(), - ThemeType.CRYSTAL, - theme.getColor() + TextUtils.toTitleCase(rarity.toString() + " " + type.toString()) + " Crystal", - "Magical Crystamae in it's physical form" - ), - DummyRealisationAltar.TYPE, - new ItemStack[]{null, null, null, null, new ItemStack(Material.AMETHYST_CLUSTER), null, null, null, null}, - rarity, - type - ); - slimefunItem.register(plugin); - storyTypeSlimefunItemMap.put(type, slimefunItem); - crystalMap.put(rarity, storyTypeSlimefunItemMap); - } - } - } + // Liquefaction Recipes + LiquefactionBasinCache.addCraftingRecipe(INERT_PLATE_T_1, inertRecipeItem); - private void setUpDummyCrystalTypes() { - for (StoryType type : StoryType.getCachedValues()) { - ThemeType theme = ThemeType.getByType(type); - SlimefunItem sfItem = new Crystal( - ItemGroups.DUMMY_ITEM_GROUP, - ThemeType.themedSlimefunItemStack( - "CRY_CRYSTAL_DUMMY_" + type.toString() + "_" + type.toString(), - Skulls.getByType(type).getPlayerHead(), - ThemeType.CRYSTAL, - theme.getColor() + TextUtils.toTitleCase(type.toString() + " Crystal"), - "Magical Crystamae in it's physical form" - ), - DummyRealisationAltar.TYPE, - new ItemStack[]{null, null, null, null, new ItemStack(Material.AMETHYST_CLUSTER), null, null, null, null}, - StoryRarity.COMMON, - type - ); - sfItem.register(plugin); - typeItemMap.put(type, sfItem); - } } - - } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Spells.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Spells.java deleted file mode 100644 index c0ffbd7d..00000000 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Spells.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.github.sefiraat.crystamaehistoria.slimefun; - -import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; -import io.github.sefiraat.crystamaehistoria.magic.SpellType; -import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.ItemGroups; -import io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin.DummyLiquefactionBasin; -import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; -import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import org.bukkit.inventory.ItemStack; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Map; - -public class Spells { - - private final CrystamaeHistoria plugin; - - @ParametersAreNonnullByDefault - public Spells(CrystamaeHistoria p) { - this.plugin = p; - } - - public void setup() { - for (SpellType spellType : SpellType.getCachedValues()) { - getSlimefunItem(spellType).register(plugin); - } - } - - private SlimefunItem getSlimefunItem(SpellType spellType) { - final Map map = CrystamaeHistoria.getStructure().getMaterials().getTypeItemMap(); - - final StoryType type1 = spellType.getSpell().getRecipe().getInput(0); - final StoryType type2 = spellType.getSpell().getRecipe().getInput(1); - final StoryType type3 = spellType.getSpell().getRecipe().getInput(2); - - final ItemStack stack1 = map.get(type1).getItem(); - final ItemStack stack2 = map.get(type2).getItem(); - final ItemStack stack3 = map.get(type3).getItem(); - - return new SlimefunItem( - ItemGroups.SPELLS, - spellType.getSpell().getThemedStack(), - DummyLiquefactionBasin.TYPE, - new ItemStack[]{ - null, null, null, - stack1, stack2, stack3, - null, null, null - } - ); - } - -} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Structure.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Structure.java deleted file mode 100644 index 4e365675..00000000 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Structure.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.sefiraat.crystamaehistoria.slimefun; - -import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; -import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.ItemGroups; -import lombok.Getter; - -public class Structure { - - @Getter - private final Spells spells; - @Getter - private final Machines machines; - @Getter - private final Materials materials; - @Getter - private final Tools tools; - - public Structure() { - CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); - this.machines = new Machines(plugin); - this.materials = new Materials(plugin); - this.tools = new Tools(plugin); - this.spells = new Spells(plugin); - } - - public void setup() { - CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); - ItemGroups.STORY_COLLECTION.register(plugin); - ItemGroups.SPELL_COLLECTION.register(plugin); - - this.materials.setup(); - this.machines.setup(); - this.tools.setup(); - this.spells.setup(); - } -} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Tools.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Tools.java index 6e6ca8b6..f0743b9e 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Tools.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/Tools.java @@ -1,7 +1,6 @@ package io.github.sefiraat.crystamaehistoria.slimefun; import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; -import io.github.sefiraat.crystamaehistoria.slimefun.itemgroups.ItemGroups; import io.github.sefiraat.crystamaehistoria.slimefun.tools.stave.Stave; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryRarity; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; @@ -10,22 +9,19 @@ import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import javax.annotation.ParametersAreNonnullByDefault; - public class Tools { - private final CrystamaeHistoria plugin; + public static Stave STAVE_BASIC; + public static Stave STAVE_ADVANCED; - @ParametersAreNonnullByDefault - public Tools(CrystamaeHistoria p) { - this.plugin = p; - } + public Tools() { - public void setup() { - final ItemStack elementalCrystal = CrystamaeHistoria.getStructure().getMaterials().getCrystalMap().get(StoryRarity.UNIQUE).get(StoryType.ELEMENTAL).getItem(); - final ItemStack ingot = CrystamaeHistoria.getStructure().getMaterials().amalgamateIngot.getItem(); + final CrystamaeHistoria plugin = CrystamaeHistoria.getInstance(); - Stave basic = new Stave( + // Basic Stave + final ItemStack elementalCrystal = Materials.CRYSTAL_MAP.get(StoryRarity.UNIQUE).get(StoryType.ELEMENTAL).getItem(); + + STAVE_BASIC = new Stave( ItemGroups.TOOLS, ThemeType.themedSlimefunItemStack( "CRY_STAVE_1", @@ -44,7 +40,10 @@ null, new ItemStack(Material.STICK), null, 1 ); - Stave advanced = new Stave( + // Advanced Stave + final ItemStack ingot = Materials.AMALGAMATE_INGOT.getItem(); + + STAVE_ADVANCED = new Stave( ItemGroups.TOOLS, ThemeType.themedSlimefunItemStack( "CRY_STAVE_2", @@ -57,13 +56,14 @@ null, new ItemStack(Material.STICK), null, RecipeType.MAGIC_WORKBENCH, new ItemStack[]{ ingot, ingot, ingot, - ingot, basic.getItem(), ingot, + ingot, STAVE_BASIC.getItem().clone(), ingot, ingot, ingot, ingot }, 2 ); - basic.register(plugin); - advanced.register(plugin); + // Slimefun Registry + STAVE_BASIC.register(plugin); + STAVE_ADVANCED.register(plugin); } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/SpellCollectionFlexGroup.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/SpellCollectionFlexGroup.java index 3f04c58b..15e15e19 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/SpellCollectionFlexGroup.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/SpellCollectionFlexGroup.java @@ -1,9 +1,10 @@ package io.github.sefiraat.crystamaehistoria.slimefun.itemgroups; -import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; import io.github.sefiraat.crystamaehistoria.magic.SpellType; import io.github.sefiraat.crystamaehistoria.magic.spells.core.Spell; import io.github.sefiraat.crystamaehistoria.magic.spells.core.SpellCore; +import io.github.sefiraat.crystamaehistoria.slimefun.ItemGroups; +import io.github.sefiraat.crystamaehistoria.slimefun.Materials; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.ResearchUtils; import io.github.sefiraat.crystamaehistoria.utils.theme.GuiElements; @@ -62,7 +63,7 @@ public class SpellCollectionFlexGroup extends FlexItemGroup { private static final int PROJECTILE_INFO = 42; private static final int EFFECTS = 43; - protected SpellCollectionFlexGroup(NamespacedKey key, ItemStack item) { + public SpellCollectionFlexGroup(NamespacedKey key, ItemStack item) { super(key, item); } @@ -89,7 +90,7 @@ public void open(Player p, PlayerProfile profile, SlimefunGuideMode mode) { } private void setupPage(@Nonnull Player p, @Nonnull PlayerProfile profile, @Nonnull SlimefunGuideMode mode, @Nonnull ChestMenu menu, int page) { - final List spellTypes = Arrays.asList(SpellType.getCachedValues()); + final List spellTypes = Arrays.asList(SpellType.getEnabledSpells()); final int numberOfBlocks = spellTypes.size(); final int totalPages = (int) Math.ceil(numberOfBlocks / (double) PAGE_SIZE); final int start = (page - 1) * PAGE_SIZE; @@ -149,7 +150,7 @@ private void displayDefinition(@Nonnull Player p, @Nonnull PlayerProfile profile for (int i = 0; i < RECIPE.length; i++) { int slot = RECIPE[i]; StoryType storyType = spellType.getSpell().getRecipe().getInput(i); - ItemStack stack = CrystamaeHistoria.getStructure().getMaterials().getTypeItemMap().get(storyType).getItem(); + ItemStack stack = Materials.DUMMY_CRYSTAL_MAP.get(storyType).getItem(); menu.replaceExistingItem(slot, stack); menu.addMenuClickHandler(slot, ((player, slot2, itemStack, clickAction) -> false)); } @@ -265,11 +266,15 @@ private ItemStack getValuesStack(Spell spell) { if (spellCore.isDamagingSpell()) { lore.add(damageMessage); lore.add(damageMulti); + } else { + lore.add(passive + "This spell does not damage."); } if (spellCore.isHealingSpell()) { lore.add(healMessage); lore.add(healMulti); + } else { + lore.add(passive + "This spell does not heal."); } return new CustomItemStack( @@ -328,7 +333,7 @@ private ItemStack getRangeStack(Spell spell) { final String message = MessageFormat.format("{0}Range: {1}{2}", color, passive, spell.getSpellCore().getRange()); final String multiMessage = MessageFormat.format("{0}Range {1} with stave tier", passive, spell.getSpellCore().isRangeMultiplied() ? "increases" : "doesn't increase"); - final String noRange = "Not effected by range"; + final String noRange = passive + "Not effected by range"; if (spell.getSpellCore().getKnockbackAmount() > 0) { lore.add(message); @@ -351,7 +356,7 @@ private ItemStack getKnockBackStack(Spell spell) { final String message = MessageFormat.format("{0}Knockback: {1}{2}", color, passive, spell.getSpellCore().getKnockbackAmount()); final String multiMessage = MessageFormat.format("{0}Amount {1} with stave tier", passive, spell.getSpellCore().isKnockbackMultiplied() ? "increases" : "doesn't increase"); - final String noKnockback = "No direct knockback"; + final String noKnockback = passive + "No direct knockback"; if (spell.getSpellCore().getKnockbackAmount() > 0) { lore.add(message); diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/StoryCollectionFlexGroup.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/StoryCollectionFlexGroup.java index b6968bbf..46ab38b1 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/StoryCollectionFlexGroup.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/itemgroups/StoryCollectionFlexGroup.java @@ -1,6 +1,8 @@ package io.github.sefiraat.crystamaehistoria.slimefun.itemgroups; import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.sefiraat.crystamaehistoria.slimefun.ItemGroups; +import io.github.sefiraat.crystamaehistoria.slimefun.Materials; import io.github.sefiraat.crystamaehistoria.stories.StoriedBlockDefinition; import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; import io.github.sefiraat.crystamaehistoria.utils.ResearchUtils; @@ -57,7 +59,7 @@ public class StoryCollectionFlexGroup extends FlexItemGroup { 45, 46, 47, 48, 49, 50, 51, 52, 53 }; - protected StoryCollectionFlexGroup(NamespacedKey key, ItemStack item) { + public StoryCollectionFlexGroup(NamespacedKey key, ItemStack item) { super(key, item); } @@ -157,7 +159,7 @@ private void displayDefinition(@Nonnull Player p, @Nonnull PlayerProfile profile int amount = entry.getValue(); if (amount > 0) { StoryType type = entry.getKey(); - ItemStack itemStack = CrystamaeHistoria.getStructure().getMaterials().getTypeItemMap().get(type).getItem().clone(); + ItemStack itemStack = Materials.DUMMY_CRYSTAL_MAP.get(type).getItem().clone(); itemStack.setAmount(entry.getValue()); menu.replaceExistingItem(CRYSTAMAE[type.getId() - 1], itemStack); } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasinCrafting.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasinCrafting.java new file mode 100644 index 00000000..95b62d50 --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasinCrafting.java @@ -0,0 +1,26 @@ +package io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin; + +import io.github.sefiraat.crystamaehistoria.utils.Keys; +import io.github.sefiraat.crystamaehistoria.utils.theme.ThemeType; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; +import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public class DummyLiquefactionBasinCrafting { + + public static final SlimefunItemStack STACK = ThemeType.themedSlimefunItemStack( + "CRY_LIQUEFACTION_BASIN_DUMMY_CRAFTING", + new ItemStack(Material.CAULDRON), + ThemeType.MECHANISM, + "Liquefaction Basin", + "Formed by dropping the relevant item", + "into a filled Liquefaction Basin containing", + "the correct Crystamae." + ); + public static final RecipeType TYPE = new RecipeType(Keys.LIQUEFACTION_DUMMY_CRYSTAL, STACK); + + private DummyLiquefactionBasinCrafting() { + throw new IllegalStateException("Utility class"); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasin.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasinSpell.java similarity index 82% rename from src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasin.java rename to src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasinSpell.java index 5b06707c..aa8a97bc 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasin.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/DummyLiquefactionBasinSpell.java @@ -7,7 +7,7 @@ import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -public class DummyLiquefactionBasin { +public class DummyLiquefactionBasinSpell { public static final SlimefunItemStack STACK = ThemeType.themedSlimefunItemStack( "CRY_LIQUEFACTION_BASIN_DUMMY_SPELL", @@ -18,9 +18,9 @@ public class DummyLiquefactionBasin { "filled Liquefaction Basin containing", "the correct Crystamae." ); - public static final RecipeType TYPE = new RecipeType(Keys.REALISATION_DUMMY_CRYSTAL, STACK); + public static final RecipeType TYPE = new RecipeType(Keys.LIQUEFACTION_DUMMY_CRYSTAL, STACK); - private DummyLiquefactionBasin() { + private DummyLiquefactionBasinSpell() { throw new IllegalStateException("Utility class"); } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/LiquefactionBasinCache.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/LiquefactionBasinCache.java index 9273e9a7..51de2369 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/LiquefactionBasinCache.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/LiquefactionBasinCache.java @@ -59,7 +59,8 @@ public class LiquefactionBasinCache extends DisplayStandHolder { public static final double MAX_VOLUME = 1000; protected static final Map RARITY_VALUE_MAP = new EnumMap<>(StoryRarity.class); protected static final String CH_LEVEL_PREFIX = "ch_c_lvl:"; - private static final Map RECIPES_SPELL = new HashMap<>(); + private static final Map RECIPES_SPELL = new HashMap<>(); + private static final Map RECIPES_ITEMS = new HashMap<>(); static { RARITY_VALUE_MAP.put(StoryRarity.COMMON, 1); @@ -82,8 +83,12 @@ public LiquefactionBasinCache(BlockMenu blockMenu) { } } - public static void addSpellRecipe(SpellType spellType, SpellRecipe spellRecipe) { - RECIPES_SPELL.put(spellType, spellRecipe); + public static void addSpellRecipe(SpellType spellType, RecipeSpell recipeSpell) { + RECIPES_SPELL.put(spellType, recipeSpell); + } + + public static void addCraftingRecipe(SlimefunItem slimefunItem, RecipeItem recipeItem) { + RECIPES_ITEMS.put(slimefunItem, recipeItem); } public void setActivePlayer(@Nonnull Player player) { @@ -93,19 +98,28 @@ public void setActivePlayer(@Nonnull Player player) { @ParametersAreNonnullByDefault public void consumeItems() { - Collection entities = getWorld().getNearbyEntities(getLocation().clone().add(0.5, 0.5, 0.5), 0.3, 0.3, 0.3, Item.class::isInstance); + final Collection entities = getWorld().getNearbyEntities( + getLocation().clone().add(0.5, 0.5, 0.5), + 0.3, + 0.3, + 0.3, + Item.class::isInstance + ); + for (Entity entity : entities) { - Item item = (Item) entity; - SlimefunItem slimefunItem = SlimefunItem.getByItem(item.getItemStack()); + final Item item = (Item) entity; + final SlimefunItem slimefunItem = SlimefunItem.getByItem(item.getItemStack()); if (slimefunItem instanceof Crystal) { - Crystal crystal = (Crystal) slimefunItem; + final Crystal crystal = (Crystal) slimefunItem; addCrystamae(crystal.getType(), crystal.getRarity(), item); } else if (slimefunItem instanceof BlankPlate) { processBlankPlate(item, (BlankPlate) slimefunItem); } else if (slimefunItem instanceof ChargedPlate) { processChargedPlate(item, (ChargedPlate) slimefunItem); } else { - rejectItem(item, true); + if (!processOtherItem(item)) { + rejectItem(item, true); + } } } if (getFillLevel() > 0 && GeneralUtils.testChance(1, 5)) { @@ -115,16 +129,16 @@ public void consumeItems() { @ParametersAreNonnullByDefault private void rejectItem(Item item, boolean punish) { - double velX = ThreadLocalRandom.current().nextDouble(-0.9, 1.1); - double velZ = ThreadLocalRandom.current().nextDouble(-0.9, 1.1); + final double velX = ThreadLocalRandom.current().nextDouble(-0.9, 1.1); + final double velZ = ThreadLocalRandom.current().nextDouble(-0.9, 1.1); item.setVelocity(new Vector(velX, 0.5, velZ)); // TODO Punishment for incorrect usage } @ParametersAreNonnullByDefault private void addCrystamae(StoryType type, StoryRarity rarity, Item item) { - int numberInStack = item.getItemStack().getAmount(); - int amount = LiquefactionBasinCache.RARITY_VALUE_MAP.get(rarity) * numberInStack; + final int numberInStack = item.getItemStack().getAmount(); + final int amount = LiquefactionBasinCache.RARITY_VALUE_MAP.get(rarity) * numberInStack; if (getFillLevel() + amount > MAX_VOLUME) { rejectItem(item, false); } else { @@ -182,8 +196,8 @@ private void emptyBasin() { } private void clearBlockStorage() { - Config c = BlockStorage.getLocationInfo(blockMenu.getLocation()); - List keys = new ArrayList<>(); + final Config c = BlockStorage.getLocationInfo(blockMenu.getLocation()); + final List keys = new ArrayList<>(); for (String key : c.getKeys()) { if (key.startsWith(CH_LEVEL_PREFIX)) { keys.add(key); @@ -211,11 +225,16 @@ public void syncBlock() { @ParametersAreNonnullByDefault private void processBlankPlate(Item item, BlankPlate plate) { - Set set = contentMap.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed()).limit(3).map(Map.Entry::getKey).collect(Collectors.toSet()); - ItemStack itemStack = item.getItemStack(); + final Set set = contentMap.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(3) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + + final ItemStack itemStack = item.getItemStack(); if (set.size() == 3) { SlimefunItem.getByItem(itemStack); - SpellType spellType = getMatchingRecipe(set, plate); + final SpellType spellType = getMatchingRecipe(set, plate); if (spellType != null) { item.getWorld().dropItem(item.getLocation(), ChargedPlate.getChargedPlate(plate.getTier(), spellType, getFillLevel())); if (itemStack.getAmount() > 1) { @@ -239,7 +258,11 @@ private void processBlankPlate(Item item, BlankPlate plate) { private void processChargedPlate(Item item, ChargedPlate plate) { final ItemStack itemStack = item.getItemStack(); final ItemMeta itemMeta = itemStack.getItemMeta(); - final InstancePlate instancePlate = DataTypeMethods.getCustom(itemMeta, Keys.PDC_PLATE_STORAGE, PersistentPlateDataType.TYPE); + final InstancePlate instancePlate = DataTypeMethods.getCustom( + itemMeta, + Keys.PDC_PLATE_STORAGE, + PersistentPlateDataType.TYPE + ); if (instancePlate == null) { CrystamaeHistoria.log( @@ -273,11 +296,45 @@ private void processChargedPlate(Item item, ChargedPlate plate) { } } + @ParametersAreNonnullByDefault + private boolean processOtherItem(Item item) { + final ItemStack itemStack = item.getItemStack(); + + final List typeList = contentMap.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(3) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + final List amountList = contentMap.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(3) + .map(Map.Entry::getValue) + .collect(Collectors.toList()); + + if (typeList.size() == 3) { + SlimefunItem.getByItem(itemStack); + SlimefunItem slimefunItem = getMatchingRecipe(typeList, amountList, itemStack); + if (slimefunItem != null) { + item.getWorld().dropItem(item.getLocation(), slimefunItem.getItem().clone()); + if (itemStack.getAmount() > 1) { + itemStack.setAmount(itemStack.getAmount() - 1); + } else { + item.remove(); + } + summonCatalystParticles(); + emptyBasin(); + return true; + } + } + return false; + } + @Nullable @ParametersAreNonnullByDefault public SpellType getMatchingRecipe(Set set, MagicalPlate magicalPlate) { SpellType spellType = null; - for (Map.Entry recipeEntry : RECIPES_SPELL.entrySet()) { + for (Map.Entry recipeEntry : RECIPES_SPELL.entrySet()) { if (recipeEntry.getValue().recipeMatches(set, magicalPlate.getTier())) { spellType = recipeEntry.getKey(); break; @@ -286,6 +343,19 @@ public SpellType getMatchingRecipe(Set set, MagicalPlate magicalPlate return spellType; } + @Nullable + @ParametersAreNonnullByDefault + public SlimefunItem getMatchingRecipe(List types, List amounts, ItemStack itemStack) { + SlimefunItem slimefunItem = null; + for (Map.Entry recipeEntry : RECIPES_ITEMS.entrySet()) { + if (recipeEntry.getValue().recipeMatches(types, amounts, itemStack)) { + slimefunItem = recipeEntry.getKey(); + break; + } + } + return slimefunItem; + } + public int getFillLevel() { int amount = 0; for (Map.Entry entry : contentMap.entrySet()) { @@ -296,12 +366,28 @@ public int getFillLevel() { private void summonConsumeParticles() { final Location location = getLocation(true).add(0, 0.8, 0); - location.getWorld().spawnParticle(Particle.CAMPFIRE_COSY_SMOKE, location, 0, 0.2, 0, 0.2, 0); + location.getWorld().spawnParticle( + Particle.CAMPFIRE_COSY_SMOKE, + location, + 0, + 0.2, + 0, + 0.2, + 0 + ); } private void summonBoilingParticles() { final Location location = getLocation(true).add(0, 0.8, 0); - location.getWorld().spawnParticle(Particle.SMOKE_NORMAL, location, 0, 0.2, 0, 0.5, 0); + location.getWorld().spawnParticle( + Particle.SMOKE_NORMAL, + location, + 0, + 0.2, + 0, + 0.5, + 0 + ); } private void summonCatalystParticles() { diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/RecipeItem.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/RecipeItem.java new file mode 100644 index 00000000..1ce73bad --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/RecipeItem.java @@ -0,0 +1,74 @@ +package io.github.sefiraat.crystamaehistoria.slimefun.machines.liquefactionbasin; + +import io.github.sefiraat.crystamaehistoria.slimefun.Materials; +import io.github.sefiraat.crystamaehistoria.stories.definition.StoryType; +import io.github.sefiraat.crystamaehistoria.utils.theme.ThemeType; +import lombok.Getter; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class RecipeItem { + + @Getter + private final ItemStack inputItem; + private final List storyTypes; + private final List amounts; + + @ParametersAreNonnullByDefault + public RecipeItem( + ItemStack inputItem, + StoryType type1, int crysta1, + StoryType type2, int crysta2, + StoryType type3, int crysta3 + ) { + this.inputItem = inputItem; + this.storyTypes = Arrays.asList(type1, type2, type3); + this.amounts = Arrays.asList(crysta1, crysta2, crysta3); + } + + public boolean recipeMatches(List testTypes, List testAmounts, ItemStack inputItem) { + int i = 0; + if (!this.inputItem.isSimilar(inputItem)) { + return false; + } + for (StoryType testType : testTypes) { + int index = storyTypes.indexOf(testType); + if (index == -1 || amounts.get(index) > testAmounts.get(i)) { + return false; + } + i++; + } + return true; + } + + public ItemStack[] getDisplayRecipe() { + return new ItemStack[]{ + null, inputItem, null, + getDisplayCrystal(0), getDisplayCrystal(1), getDisplayCrystal(2), + null, null, null + }; + } + + public ItemStack getDisplayCrystal(int index) { + ItemStack itemStack = Materials.DUMMY_CRYSTAL_MAP.get(storyTypes.get(index)).getItem().clone(); + ItemMeta itemMeta = itemStack.getItemMeta(); + List list = new ArrayList<>(); + list.add(ThemeType.CLICK_INFO.getColor() + "Minimum amount: " + ThemeType.PASSIVE.getColor() + amounts.get(index)); + itemMeta.setLore(list); + itemStack.setItemMeta(itemMeta); + return itemStack; + } + + public StoryType getInputType(int index) { + return this.storyTypes.get(index); + } + + public int getInputAmount(int index) { + return this.amounts.get(index); + } +} diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/SpellRecipe.java b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/RecipeSpell.java similarity index 88% rename from src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/SpellRecipe.java rename to src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/RecipeSpell.java index c635afa9..67f5deec 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/SpellRecipe.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/slimefun/machines/liquefactionbasin/RecipeSpell.java @@ -6,12 +6,12 @@ import java.util.List; import java.util.Set; -public class SpellRecipe { +public class RecipeSpell { private final int tier; private final List storyTypes; - public SpellRecipe(int tier, StoryType type1, StoryType type2, StoryType type3) { + public RecipeSpell(int tier, StoryType type1, StoryType type2, StoryType type3) { this.tier = tier; this.storyTypes = Arrays.asList(type1, type2, type3); } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/stories/definition/StoryShardProfile.java b/src/main/java/io/github/sefiraat/crystamaehistoria/stories/definition/StoryShardProfile.java index 20c0b9ef..1f23f4de 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/stories/definition/StoryShardProfile.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/stories/definition/StoryShardProfile.java @@ -1,6 +1,6 @@ package io.github.sefiraat.crystamaehistoria.stories.definition; -import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.sefiraat.crystamaehistoria.slimefun.Materials; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; @@ -34,7 +34,7 @@ public void dropShards(StoryRarity rarity, Location location) { StoryType storyType = entry.getKey(); int amount = entry.getValue(); if (amount > 0) { - ItemStack itemStack = CrystamaeHistoria.getStructure().getMaterials().getCrystalMap().get(rarity).get(storyType).getItem().clone(); + ItemStack itemStack = Materials.CRYSTAL_MAP.get(rarity).get(storyType).getItem().clone(); itemStack.setAmount(amount); location.getWorld().dropItemNaturally(location, itemStack); } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/GeneralUtils.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/GeneralUtils.java index 09254f9a..20c41245 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/GeneralUtils.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/GeneralUtils.java @@ -1,11 +1,27 @@ package io.github.sefiraat.crystamaehistoria.utils; import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; +import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.libraries.dough.blocks.BlockPosition; +import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; import lombok.experimental.UtilityClass; +import me.mrCookieSlime.Slimefun.api.BlockStorage; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; import org.bukkit.block.Block; +import org.bukkit.block.TileState; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @UtilityClass @@ -93,4 +109,105 @@ public static void markBlockForRemoval(Block block, int secondsUntilRemoval) { public static boolean isRemovableBlock(Block block) { return block.hasMetadata("ch"); } + + public static boolean blockCanBeBroken(UUID caster, Block block) { + return hasPermission(caster, block, Interaction.BREAK_BLOCK) + && !BlockStorage.hasBlockInfo(block) + && !(block.getState() instanceof TileState) + && block.getType().getHardness() != -1 + && !block.getType().isAir(); + } + + + public static boolean hasPermission(Player player, Block block, Interaction interaction) { + return hasPermission(player.getUniqueId(), block.getLocation(), interaction); + } + + public static boolean hasPermission(Player player, Location location, Interaction interaction) { + return hasPermission(player.getUniqueId(), location, interaction); + } + + public static boolean hasPermission(UUID player, Block block, Interaction interaction) { + return hasPermission(player, block.getLocation(), interaction); + } + + public static boolean hasPermission(UUID player, Location location, Interaction interaction) { + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player); + return Slimefun.getProtectionManager().hasPermission(offlinePlayer, location, interaction); + } + + + @ParametersAreNonnullByDefault + public boolean pullEntity(UUID caster, Location pullToLocation, Entity pushed, double force) { + Vector vector = pushed.getLocation().toVector() + .subtract(pullToLocation.toVector()) + .normalize() + .multiply(-force); + return pushEntity(caster, vector, pushed); + } + + @ParametersAreNonnullByDefault + public boolean pushEntity(UUID caster, Location pushFromLocation, Entity pushed, double force) { + Vector vector = pushed.getLocation().toVector() + .subtract(pushFromLocation.toVector()) + .normalize() + .multiply(force); + return pushEntity(caster, vector, pushed); + } + + @ParametersAreNonnullByDefault + public boolean pushEntity(UUID caster, Vector vector, Entity pushed) { + Interaction interaction = pushed instanceof Player ? Interaction.ATTACK_PLAYER : Interaction.INTERACT_ENTITY; + if (GeneralUtils.hasPermission(caster, pushed.getLocation(), interaction)) { + pushed.setVelocity(vector); + return true; + } + return false; + } + + @ParametersAreNonnullByDefault + public static boolean tryBreakBlock(UUID caster, Block block) { + Player player = Bukkit.getPlayer(caster); + if (GeneralUtils.blockCanBeBroken(caster, block) + && player != null + ) { + block.breakNaturally(player.getInventory().getItemInMainHand()); + return true; + } + return false; + } + + + @ParametersAreNonnullByDefault + public static boolean damageEntity(LivingEntity livingEntity, UUID caster, double damage) { + return damageEntity(livingEntity, caster, damage, null, 0); + } + + @ParametersAreNonnullByDefault + public static boolean damageEntity(LivingEntity livingEntity, UUID caster, double damage, @Nullable Location knockbackOrigin, double knockbackForce) { + Interaction interaction = livingEntity instanceof Player ? Interaction.ATTACK_PLAYER : Interaction.ATTACK_ENTITY; + if (GeneralUtils.hasPermission(caster, livingEntity.getLocation(), interaction)) { + Player player = Bukkit.getPlayer(caster); + livingEntity.damage(damage, player); + if (knockbackOrigin != null && knockbackForce > 0) { + GeneralUtils.pushEntity(caster, knockbackOrigin, livingEntity, knockbackForce); + } + return true; + } + return false; + } + + /** + * Heal the entity by the provided amount + * + * @param livingEntity The {@link LivingEntity} to heal + * @param healAmount The amount to heal by + */ + @ParametersAreNonnullByDefault + public static void healEntity(LivingEntity livingEntity, double healAmount) { + AttributeInstance attribute = livingEntity.getAttribute(Attribute.GENERIC_MAX_HEALTH); + if (attribute != null) { + livingEntity.setHealth(Math.min(attribute.getValue(), livingEntity.getHealth() + healAmount)); + } + } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Keys.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Keys.java index cec75468..801bb332 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Keys.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Keys.java @@ -24,6 +24,7 @@ public class Keys { // Recipe Types public static final NamespacedKey REALISATION_DUMMY_CRYSTAL = newKey("r_d_c"); + public static final NamespacedKey LIQUEFACTION_DUMMY_CRYSTAL = newKey("r_d_c"); // PDC // Items diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/ParticleUtils.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/ParticleUtils.java index 8f14888d..eb217ef3 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/ParticleUtils.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/ParticleUtils.java @@ -2,12 +2,61 @@ import org.bukkit.Location; import org.bukkit.Particle; +import org.bukkit.World; +import org.bukkit.entity.Entity; import org.bukkit.util.Vector; import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.concurrent.ThreadLocalRandom; public class ParticleUtils { + @ParametersAreNonnullByDefault + public static void displayParticleEffect(Entity entity, Particle particle, double rangeRadius) { + displayParticleEffect(entity.getLocation(), particle, rangeRadius, 5); + } + + @ParametersAreNonnullByDefault + public static void displayParticleEffect(Entity entity, Particle particle, double rangeRadius, int numberOfParticles) { + displayParticleEffect(entity.getLocation().clone().add(0, 1, 0), particle, rangeRadius, numberOfParticles); + } + + @ParametersAreNonnullByDefault + public static void displayParticleEffect(Location location, Particle particle, double rangeRadius) { + displayParticleEffect(location, particle, rangeRadius, 5); + } + + @ParametersAreNonnullByDefault + public static void displayParticleEffect(Location location, Particle particle, double rangeRadius, int numberOfParticles) { + for (int i = 0; i < numberOfParticles; i++) { + double x = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); + double y = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); + double z = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); + location.getWorld().spawnParticle(particle, location.clone().add(x, y, z), 1); + } + } + + @ParametersAreNonnullByDefault + public static void displayParticleEffect(Entity entity, double rangeRadius, int numberOfParticles, Particle.DustOptions dustOptions) { + displayParticleEffect(entity.getLocation(), rangeRadius, numberOfParticles, dustOptions); + } + + @ParametersAreNonnullByDefault + public static void displayParticleEffect(Entity entity, double rangeRadius, Particle.DustOptions dustOptions) { + displayParticleEffect(entity.getLocation(), rangeRadius, 5, dustOptions); + } + + @ParametersAreNonnullByDefault + public static void displayParticleEffect(Location location, double rangeRadius, int numberOfParticles, Particle.DustOptions dustOptions) { + for (int i = 0; i < numberOfParticles; i++) { + double x = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); + double y = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); + double z = ThreadLocalRandom.current().nextDouble(-rangeRadius, rangeRadius + 0.1); + location.getWorld().spawnParticle(Particle.REDSTONE, location.clone().add(x, y, z), 1, dustOptions); + } + } + public static void drawLine(Particle particle, Location start, Location end, double space) { drawLine(particle, start, end, space, null); } @@ -47,4 +96,42 @@ public static void drawLine(Particle particle, Location start, Location end, dou } } + public static void drawCube(Particle particle, Location corner1, Location corner2, double space) { + drawCube(particle, corner1, corner2, space, null); + } + + public static void drawCube(Particle.DustOptions dustOptions, Location corner1, Location corner2, double space) { + drawCube(Particle.REDSTONE, corner1, corner2, space, dustOptions); + } + + /** + * https://www.spigotmc.org/threads/create-particles-in-cube-outline-shape.65991/ + */ + public static void drawCube(Particle particle, Location corner1, Location corner2, double particleDistance, @Nullable Particle.DustOptions dustOptions) { + World world = corner1.getWorld(); + double minX = Math.min(corner1.getX(), corner2.getX()); + double minY = Math.min(corner1.getY(), corner2.getY()); + double minZ = Math.min(corner1.getZ(), corner2.getZ()); + double maxX = Math.max(corner1.getX(), corner2.getX()); + double maxY = Math.max(corner1.getY(), corner2.getY()); + double maxZ = Math.max(corner1.getZ(), corner2.getZ()); + + for (double x = minX; x <= maxX; x += particleDistance) { + for (double y = minY; y <= maxY; y += particleDistance) { + for (double z = minZ; z <= maxZ; z += particleDistance) { + int components = 0; + if (x == minX || x == maxX) components++; + if (y == minY || y == maxY) components++; + if (z == minZ || z == maxZ) components++; + if (components >= 2) { + if (dustOptions != null) { + world.spawnParticle(particle, x, y, z, 1, dustOptions); + } else { + world.spawnParticle(particle, x, y, z, 1); + } + } + } + } + } + } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Skulls.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Skulls.java index 3cd6de3f..226dd135 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Skulls.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/Skulls.java @@ -13,15 +13,15 @@ public enum Skulls { // TODO Replace with heads from Cheesy - CRYSTAL_ELEMENTAL("533a5bfc8a2a3a152d646a5bea694a425ab79db694b214f156c37c7183aa", StoryType.ELEMENTAL), - CRYSTAL_MECHANICAL("adc56355f11ce53e14d374ecf2a0b255301b734d99c674240afacc73e2145c", StoryType.MECHANICAL), - CRYSTAL_ALCHEMICAL("41139b3ef2e4c44a4c983f114cbe948d8ab5d4f879a5c665bb820e7386ac2f", StoryType.ALCHEMICAL), - CRYSTAL_HISTORICAL("c607cffcd7864ff27c78b29a2c5955131a677bef6371f88988d3dcc37ef8873", StoryType.HISTORICAL), - CRYSTAL_HUMAN("85484f4b6367b95bb16288398f1c8dd6c61de988f3a8356d4c3ae73ea38a42", StoryType.HUMAN), - CRYSTAL_ANIMAL("cb9b2a4d59781d1bec2d8278f23985e749c881b72d7876c979e71fda5bd3c", StoryType.ANIMAL), - CRYSTAL_CELESTIAL("caf039bec1fc1fb75196092b26e631f37a87dff143fc18297798d47c5eaaf", StoryType.CELESTIAL), - CRYSTAL_VOID("da3d7a709717d1ffe2402448d867b1a7f32fb8955621cc8977b61f9a3cbc95", StoryType.VOID), - CRYSTAL_PHILOSOPHICAL("a1b9a0a6d1b9912794289eca1e224eae6d76a7cb752ca689f1b991ce970adee", StoryType.PHILOSOPHICAL), + CRYSTAL_ELEMENTAL("3b16a4c438f90e2193ae9877c4ec5d2a13c2bc679c113131ac98684e326c402f", StoryType.ELEMENTAL), + CRYSTAL_MECHANICAL("789f76df5f41dc45df1c1f2aa4acd286a7842fff774c073c27c3f2dda5fe2aa0", StoryType.MECHANICAL), + CRYSTAL_ALCHEMICAL("9caa807ee0b46a5031877438bc4ee5bcc202177b2b2e6fb0e3416438097d9266", StoryType.ALCHEMICAL), + CRYSTAL_HISTORICAL("bfbabc6d29df6ae46706f4a3b7087df3e99cf94bfcfbd147f0bf5d902d82b72a", StoryType.HISTORICAL), + CRYSTAL_HUMAN("edfc9f9546d04e2444899570909b9c5f6cbf7a6095692fcc4555a915b9337c0c", StoryType.HUMAN), + CRYSTAL_ANIMAL("beb1e63fb346afb11e6acc1951a0d3ffdbf72f949d4216f443a6af4500b93564", StoryType.ANIMAL), + CRYSTAL_CELESTIAL("64323e0487b2dabe760b4557fd5bb1f3f99de9287441aa33ba6a26bf557bfdba", StoryType.CELESTIAL), + CRYSTAL_VOID("e754711a50023f5dbc6ed8483d1e760526dd5260a2bb1e559d3658a5163b575f", StoryType.VOID), + CRYSTAL_PHILOSOPHICAL("a3cf04c05d997b85cbfaadd514671a9a28a06df0a584f9e2d4dccb2c35e48b24", StoryType.PHILOSOPHICAL), GUI_TIER_NUMBER_1("d2a6f0e84daefc8b21aa99415b16ed5fdaa6d8dc0c3cd591f49ca832b575", null), GUI_TIER_NUMBER_2("96fab991d083993cb83e4bcf44a0b6cefac647d4189ee9cb823e9cc1571e38", null), GUI_TIER_NUMBER_3("cd319b9343f17a35636bcbc26b819625a9333de3736111f2e932827c8e749", null), diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/SpellUtils.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/SpellUtils.java index 59df9cdc..702edcb8 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/SpellUtils.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/SpellUtils.java @@ -28,23 +28,54 @@ public class SpellUtils { // TODO Wrap projectiles in this also - public static MagicSummon summonTemporaryMob(EntityType entityType, UUID caster, Location location, AbstractGoal goal) { + public static MagicSummon summonTemporaryMob( + EntityType entityType, + UUID caster, + Location location, + @Nullable AbstractGoal goal + ) { return summonTemporaryMob(entityType, caster, location, goal, 30); } - public static MagicSummon summonTemporaryMob(EntityType entityType, UUID caster, Location location, AbstractGoal goal, int timeInSeconds) { + public static MagicSummon summonTemporaryMob( + EntityType entityType, + UUID caster, + Location location, + @Nullable AbstractGoal goal, + int timeInSeconds + ) { return summonTemporaryMob(entityType, caster, location, goal, timeInSeconds * 1000L, null); } - public static MagicSummon summonTemporaryMob(EntityType entityType, UUID caster, Location location, AbstractGoal goal, @Nonnull Consumer tickConsumer) { + public static MagicSummon summonTemporaryMob( + EntityType entityType, + UUID caster, + Location location, + @Nullable AbstractGoal goal, + @Nonnull Consumer tickConsumer + ) { return summonTemporaryMob(entityType, caster, location, goal, 30, tickConsumer); } - public static MagicSummon summonTemporaryMob(EntityType entityType, UUID caster, Location location, AbstractGoal goal, int timeInSeconds, @Nonnull Consumer tickConsumer) { + public static MagicSummon summonTemporaryMob( + EntityType entityType, + UUID caster, + Location location, + @Nullable AbstractGoal goal, + int timeInSeconds, + @Nonnull Consumer tickConsumer + ) { return summonTemporaryMob(entityType, caster, location, goal, timeInSeconds * 1000L, tickConsumer); } - private static MagicSummon summonTemporaryMob(EntityType entityType, UUID caster, Location location, AbstractGoal goal, long duration, @Nullable Consumer tickConsumer) { + private static MagicSummon summonTemporaryMob( + EntityType entityType, + UUID caster, + Location location, + @Nullable AbstractGoal goal, + long duration, + @Nullable Consumer tickConsumer + ) { final T mob = (T) location.getWorld().spawnEntity(location, entityType); final MagicSummon magicSummon = new MagicSummon(mob.getUniqueId(), caster); final MobGoals mobGoals = Bukkit.getMobGoals(); @@ -57,30 +88,60 @@ private static MagicSummon summonTemporaryMob(EntityType entityT CrystamaeHistoria.getSummonedEntityMap().put(magicSummon, System.currentTimeMillis() + duration); DataTypeMethods.setCustom(mob, Keys.PDC_IS_SPAWN_OWNER, PersistentUUIDDataType.TYPE, caster); - goal.setSelf(mob); - mobGoals.addGoal(mob, 1, goal); + if (goal == null) { + mobGoals.removeAllGoals(mob); + } else { + goal.setSelf(mob); + mobGoals.addGoal(mob, 1, goal); + } return magicSummon; } - public static MagicProjectile summonMagicProjectile(CastInformation castInformation, EntityType entityType, Location location) { + public static MagicProjectile summonMagicProjectile( + CastInformation castInformation, + EntityType entityType, + Location location + ) { return summonMagicProjectile(castInformation, entityType, location, 5); } - public static MagicProjectile summonMagicProjectile(CastInformation castInformation, EntityType entityType, Location location, int timeInSeconds) { + public static MagicProjectile summonMagicProjectile( + CastInformation castInformation, + EntityType entityType, + Location location, + int timeInSeconds + ) { return summonMagicProjectile(castInformation, entityType, location, timeInSeconds * 1000L, null); } - public static MagicProjectile summonMagicProjectile(CastInformation castInformation, EntityType entityType, Location location, @Nonnull Consumer tickConsumer) { + public static MagicProjectile summonMagicProjectile( + CastInformation castInformation, + EntityType entityType, + Location location, + @Nonnull Consumer tickConsumer + ) { return summonMagicProjectile(castInformation, entityType, location, 30, tickConsumer); } - public static MagicProjectile summonMagicProjectile(CastInformation castInformation, EntityType entityType, Location location, int timeInSeconds, @Nonnull Consumer tickConsumer) { + public static MagicProjectile summonMagicProjectile( + CastInformation castInformation, + EntityType entityType, + Location location, + int timeInSeconds, + @Nonnull Consumer tickConsumer + ) { return summonMagicProjectile(castInformation, entityType, location, timeInSeconds * 1000L, tickConsumer); } - private static MagicProjectile summonMagicProjectile(CastInformation castInformation, EntityType entityType, Location location, long duration, @Nullable Consumer tickConsumer) { + private static MagicProjectile summonMagicProjectile( + CastInformation castInformation, + EntityType entityType, + Location location, + long duration, + @Nullable Consumer tickConsumer + ) { final Projectile projectile = (Projectile) location.getWorld().spawnEntity(location, entityType); final MagicProjectile magicProjectile = new MagicProjectile(projectile); diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractGoal.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractGoal.java index cc0cc8a8..084ffd74 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractGoal.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractGoal.java @@ -89,8 +89,9 @@ public void tick() { ); if (!entities.isEmpty()) { - int random = ThreadLocalRandom.current().nextInt(entities.size()); - self.setTarget(entities.get(random)); + LivingEntity random = entities.get(ThreadLocalRandom.current().nextInt(entities.size())); + self.setTarget(random); + self.attack(random); return; } } @@ -109,7 +110,6 @@ public void tick() { customActions(player); } - } } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractRidableGoal.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractRidableGoal.java index 6cd3e485..37e68295 100644 --- a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractRidableGoal.java +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/AbstractRidableGoal.java @@ -1,6 +1,5 @@ package io.github.sefiraat.crystamaehistoria.utils.mobgoals; -import io.github.sefiraat.crystamaehistoria.CrystamaeHistoria; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Block; @@ -30,8 +29,7 @@ public void tick() { } else { // Non-flying mobs final Block block = destination.getBlock(); - self.getPathfinder().moveTo(self.getLocation().add(0,0,1)); - + self.getPathfinder().moveTo(self.getLocation().add(0, 0, 1)); } diff --git a/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/BatteringRamGoal.java b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/BatteringRamGoal.java new file mode 100644 index 00000000..5d270436 --- /dev/null +++ b/src/main/java/io/github/sefiraat/crystamaehistoria/utils/mobgoals/BatteringRamGoal.java @@ -0,0 +1,76 @@ +package io.github.sefiraat.crystamaehistoria.utils.mobgoals; + +import io.github.sefiraat.crystamaehistoria.utils.GeneralUtils; +import io.github.sefiraat.crystamaehistoria.utils.ParticleUtils; +import io.github.thebusybiscuit.slimefun4.libraries.dough.blocks.BlockPosition; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Goat; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class BatteringRamGoal extends AbstractGoal { + + public BatteringRamGoal(UUID owningPlayer) { + super(owningPlayer); + } + + @Override + public void tick() { + + double velX = Math.abs(self.getVelocity().getX()); + double velZ = Math.abs(self.getVelocity().getZ()); + if (self.isOnGround() || (velX < 0.1 && velZ < 0.1) + ) { + ParticleUtils.displayParticleEffect(self, Particle.VILLAGER_ANGRY, 1, 5); + self.remove(); + return; + } + + final Location location = self.getLocation().add(0, 0, 0); + final int radius = 2; + final List blocks = new ArrayList<>(); + + for (int x = location.getBlockX() - radius; x <= location.getBlockX() + radius; x++) { + for (int y = location.getBlockY(); y <= location.getBlockY() + radius; y++) { + for (int z = location.getBlockZ() - radius; z <= location.getBlockZ() + radius; z++) { + final BlockPosition blockPosition = new BlockPosition(location.getWorld(), x, y, z); + if (!blocks.contains(blockPosition)) { + blocks.add(blockPosition); + } + } + } + } + + for (BlockPosition blockPosition : blocks) { + final Block block = blockPosition.getBlock(); + final BlockData blockData = block.getBlockData(); + if (GeneralUtils.blockCanBeBroken(this.owner, block)) { + block.setType(Material.AIR); + final FallingBlock fallingBlock = block.getWorld().spawnFallingBlock(block.getLocation(), blockData); + GeneralUtils.pushEntity(this.owner, self.getLocation(), fallingBlock, 0.5); + } + } + } + + @Override + public boolean getTargetsEnemies() { + return false; + } + + @Override + public boolean getTickCondition() { + return false; + } + + @Override + public boolean getFollowsPlayer() { + return false; + } +} diff --git a/src/main/resources/block_colors.yml b/src/main/resources/block_colors.yml index 4d7f5f53..4dc6b761 100644 --- a/src/main/resources/block_colors.yml +++ b/src/main/resources/block_colors.yml @@ -1,3 +1,902 @@ +AIR: [ 0, 0, 0 ] +STONE: [ 112, 112, 112 ] +GRANITE: [ 151, 109, 77 ] +POLISHED_GRANITE: [ 151, 109, 77 ] +DIORITE: [ 255, 252, 245 ] +POLISHED_DIORITE: [ 255, 252, 245 ] +ANDESITE: [ 112, 112, 112 ] +POLISHED_ANDESITE: [ 112, 112, 112 ] +DEEPSLATE: [ 100, 100, 100 ] +COBBLED_DEEPSLATE: [ 100, 100, 100 ] +POLISHED_DEEPSLATE: [ 100, 100, 100 ] +CALCITE: [ 209, 177, 161 ] +TUFF: [ 57, 41, 35 ] +DRIPSTONE_BLOCK: [ 76, 50, 35 ] +GRASS_BLOCK: [ 127, 178, 56 ] +DIRT: [ 151, 109, 77 ] +COARSE_DIRT: [ 151, 109, 77 ] +PODZOL: [ 129, 86, 49 ] +ROOTED_DIRT: [ 151, 109, 77 ] +CRIMSON_NYLIUM: [ 189, 48, 49 ] +WARPED_NYLIUM: [ 22, 126, 134 ] +COBBLESTONE: [ 112, 112, 112 ] +OAK_PLANKS: [ 143, 119, 72 ] +SPRUCE_PLANKS: [ 129, 86, 49 ] +BIRCH_PLANKS: [ 247, 233, 163 ] +JUNGLE_PLANKS: [ 151, 109, 77 ] +ACACIA_PLANKS: [ 216, 127, 51 ] +DARK_OAK_PLANKS: [ 102, 76, 51 ] +CRIMSON_PLANKS: [ 148, 63, 97 ] +WARPED_PLANKS: [ 58, 142, 140 ] +OAK_SAPLING: [ 0, 124, 0 ] +SPRUCE_SAPLING: [ 0, 124, 0 ] +BIRCH_SAPLING: [ 0, 124, 0 ] +JUNGLE_SAPLING: [ 0, 124, 0 ] +ACACIA_SAPLING: [ 0, 124, 0 ] +DARK_OAK_SAPLING: [ 0, 124, 0 ] +BEDROCK: [ 112, 112, 112 ] +SAND: [ 247, 233, 163 ] +RED_SAND: [ 216, 127, 51 ] +GRAVEL: [ 112, 112, 112 ] +COAL_ORE: [ 25, 25, 25 ] +DEEPSLATE_COAL_ORE: [ 25, 25, 25 ] +IRON_ORE: [ 216, 175, 147 ] +DEEPSLATE_IRON_ORE: [ 216, 175, 147 ] +COPPER_ORE: [ 216, 127, 51 ] +DEEPSLATE_COPPER_ORE: [ 216, 127, 51 ] +GOLD_ORE: [ 250, 238, 77 ] +DEEPSLATE_GOLD_ORE: [ 250, 238, 77 ] +REDSTONE_ORE: [ 240, 10, 15 ] +DEEPSLATE_REDSTONE_ORE: [ 240, 10, 15 ] +EMERALD_ORE: [ 0, 217, 58 ] +DEEPSLATE_EMERALD_ORE: [ 0, 217, 58 ] +LAPIS_ORE: [ 74, 128, 255 ] +DEEPSLATE_LAPIS_ORE: [ 74, 128, 255 ] +DIAMOND_ORE: [ 92, 219, 213 ] +DEEPSLATE_DIAMOND_ORE: [ 92, 219, 213 ] +NETHER_GOLD_ORE: [ 250, 238, 77 ] +NETHER_QUARTZ_ORE: [ 112, 2, 0 ] +ANCIENT_DEBRIS: [ 25, 25, 25 ] +COAL_BLOCK: [ 25, 25, 25 ] +RAW_IRON_BLOCK: [ 216, 175, 147 ] +RAW_COPPER_BLOCK: [ 216, 127, 51 ] +RAW_GOLD_BLOCK: [ 250, 238, 77 ] +AMETHYST_BLOCK: [ 127, 63, 178 ] +BUDDING_AMETHYST: [ 127, 63, 178 ] +IRON_BLOCK: [ 167, 167, 167 ] +COPPER_BLOCK: [ 216, 127, 51 ] +GOLD_BLOCK: [ 250, 238, 77 ] +DIAMOND_BLOCK: [ 92, 219, 213 ] +NETHERITE_BLOCK: [ 25, 25, 25 ] +EXPOSED_COPPER: [ 135, 107, 98 ] +WEATHERED_COPPER: [ 58, 142, 140 ] +OXIDIZED_COPPER: [ 22, 126, 134 ] +CUT_COPPER: [ 216, 127, 51 ] +EXPOSED_CUT_COPPER: [ 135, 107, 98 ] +WEATHERED_CUT_COPPER: [ 58, 142, 140 ] +OXIDIZED_CUT_COPPER: [ 22, 126, 134 ] +CUT_COPPER_STAIRS: [ 216, 127, 51 ] +EXPOSED_CUT_COPPER_STAIRS: [ 135, 107, 98 ] +WEATHERED_CUT_COPPER_STAIRS: [ 58, 142, 140 ] +OXIDIZED_CUT_COPPER_STAIRS: [ 22, 126, 134 ] +CUT_COPPER_SLAB: [ 216, 127, 51 ] +EXPOSED_CUT_COPPER_SLAB: [ 135, 107, 98 ] +WEATHERED_CUT_COPPER_SLAB: [ 58, 142, 140 ] +OXIDIZED_CUT_COPPER_SLAB: [ 22, 126, 134 ] +WAXED_COPPER_BLOCK: [ 216, 127, 51 ] +WAXED_EXPOSED_COPPER: [ 135, 107, 98 ] +WAXED_WEATHERED_COPPER: [ 58, 142, 140 ] +WAXED_OXIDIZED_COPPER: [ 22, 126, 134 ] +WAXED_CUT_COPPER: [ 216, 127, 51 ] +WAXED_EXPOSED_CUT_COPPER: [ 135, 107, 98 ] +WAXED_WEATHERED_CUT_COPPER: [ 58, 142, 140 ] +WAXED_OXIDIZED_CUT_COPPER: [ 22, 126, 134 ] +WAXED_CUT_COPPER_STAIRS: [ 216, 127, 51 ] +WAXED_EXPOSED_CUT_COPPER_STAIRS: [ 135, 107, 98 ] +WAXED_WEATHERED_CUT_COPPER_STAIRS: [ 58, 142, 140 ] +WAXED_OXIDIZED_CUT_COPPER_STAIRS: [ 22, 126, 134 ] +WAXED_CUT_COPPER_SLAB: [ 216, 127, 51 ] +WAXED_EXPOSED_CUT_COPPER_SLAB: [ 135, 107, 98 ] +WAXED_WEATHERED_CUT_COPPER_SLAB: [ 58, 142, 140 ] +WAXED_OXIDIZED_CUT_COPPER_SLAB: [ 22, 126, 134 ] +OAK_LOG: [ 143, 119, 72 ] +SPRUCE_LOG: [ 129, 86, 49 ] +BIRCH_LOG: [ 247, 233, 163 ] +JUNGLE_LOG: [ 151, 109, 77 ] +ACACIA_LOG: [ 216, 127, 51 ] +DARK_OAK_LOG: [ 102, 76, 51 ] +CRIMSON_STEM: [ 148, 63, 97 ] +WARPED_STEM: [ 58, 142, 140 ] +STRIPPED_OAK_LOG: [ 143, 119, 72 ] +STRIPPED_SPRUCE_LOG: [ 129, 86, 49 ] +STRIPPED_BIRCH_LOG: [ 247, 233, 163 ] +STRIPPED_JUNGLE_LOG: [ 151, 109, 77 ] +STRIPPED_ACACIA_LOG: [ 216, 127, 51 ] +STRIPPED_DARK_OAK_LOG: [ 102, 76, 51 ] +STRIPPED_CRIMSON_STEM: [ 148, 63, 97 ] +STRIPPED_WARPED_STEM: [ 58, 142, 140 ] +STRIPPED_OAK_WOOD: [ 143, 119, 72 ] +STRIPPED_SPRUCE_WOOD: [ 129, 86, 49 ] +STRIPPED_BIRCH_WOOD: [ 247, 233, 163 ] +STRIPPED_JUNGLE_WOOD: [ 151, 109, 77 ] +STRIPPED_ACACIA_WOOD: [ 216, 127, 51 ] +STRIPPED_DARK_OAK_WOOD: [ 102, 76, 51 ] +STRIPPED_CRIMSON_HYPHAE: [ 92, 25, 29 ] +STRIPPED_WARPED_HYPHAE: [ 86, 44, 62 ] +OAK_WOOD: [ 143, 119, 72 ] +SPRUCE_WOOD: [ 129, 86, 49 ] +BIRCH_WOOD: [ 247, 233, 163 ] +JUNGLE_WOOD: [ 151, 109, 77 ] +ACACIA_WOOD: [ 76, 76, 76 ] +DARK_OAK_WOOD: [ 102, 76, 51 ] +CRIMSON_HYPHAE: [ 92, 25, 29 ] +WARPED_HYPHAE: [ 86, 44, 62 ] +OAK_LEAVES: [ 0, 124, 0 ] +SPRUCE_LEAVES: [ 0, 124, 0 ] +BIRCH_LEAVES: [ 0, 124, 0 ] +JUNGLE_LEAVES: [ 0, 124, 0 ] +ACACIA_LEAVES: [ 0, 124, 0 ] +DARK_OAK_LEAVES: [ 0, 124, 0 ] +AZALEA_LEAVES: [ 0, 124, 0 ] +FLOWERING_AZALEA_LEAVES: [ 0, 124, 0 ] +SPONGE: [ 229, 229, 51 ] +WET_SPONGE: [ 229, 229, 51 ] +GLASS: [ 0, 0, 0 ] +TINTED_GLASS: [ 76, 76, 76 ] +LAPIS_BLOCK: [ 74, 128, 255 ] +SANDSTONE: [ 247, 233, 163 ] +CHISELED_SANDSTONE: [ 247, 233, 163 ] +CUT_SANDSTONE: [ 247, 233, 163 ] +COBWEB: [ 199, 199, 199 ] +GRASS: [ 0, 124, 0 ] +FERN: [ 0, 124, 0 ] +AZALEA: [ 0, 124, 0 ] +FLOWERING_AZALEA: [ 0, 124, 0 ] +DEAD_BUSH: [ 143, 119, 72 ] +SEAGRASS: [ 64, 64, 255 ] +SEA_PICKLE: [ 102, 127, 51 ] +WHITE_WOOL: [ 255, 255, 255 ] +ORANGE_WOOL: [ 216, 127, 51 ] +MAGENTA_WOOL: [ 178, 76, 216 ] +LIGHT_BLUE_WOOL: [ 102, 153, 216 ] +YELLOW_WOOL: [ 229, 229, 51 ] +LIME_WOOL: [ 127, 204, 25 ] +PINK_WOOL: [ 242, 127, 165 ] +GRAY_WOOL: [ 76, 76, 76 ] +LIGHT_GRAY_WOOL: [ 153, 153, 153 ] +CYAN_WOOL: [ 76, 127, 153 ] +PURPLE_WOOL: [ 127, 63, 178 ] +BLUE_WOOL: [ 51, 76, 178 ] +BROWN_WOOL: [ 102, 76, 51 ] +GREEN_WOOL: [ 102, 127, 51 ] +RED_WOOL: [ 153, 51, 51 ] +BLACK_WOOL: [ 25, 25, 25 ] +DANDELION: [ 0, 124, 0 ] +POPPY: [ 0, 124, 0 ] +BLUE_ORCHID: [ 0, 124, 0 ] +ALLIUM: [ 0, 124, 0 ] +AZURE_BLUET: [ 0, 124, 0 ] +RED_TULIP: [ 0, 124, 0 ] +ORANGE_TULIP: [ 0, 124, 0 ] +WHITE_TULIP: [ 0, 124, 0 ] +PINK_TULIP: [ 0, 124, 0 ] +OXEYE_DAISY: [ 0, 124, 0 ] +CORNFLOWER: [ 0, 124, 0 ] +LILY_OF_THE_VALLEY: [ 0, 124, 0 ] +WITHER_ROSE: [ 0, 124, 0 ] +SPORE_BLOSSOM: [ 0, 124, 0 ] +BROWN_MUSHROOM: [ 102, 76, 51 ] +RED_MUSHROOM: [ 153, 51, 51 ] +CRIMSON_FUNGUS: [ 112, 2, 0 ] +WARPED_FUNGUS: [ 76, 127, 153 ] +CRIMSON_ROOTS: [ 112, 2, 0 ] +WARPED_ROOTS: [ 76, 127, 153 ] +NETHER_SPROUTS: [ 76, 127, 153 ] +WEEPING_VINES: [ 112, 2, 0 ] +TWISTING_VINES: [ 76, 127, 153 ] +SUGAR_CANE: [ 0, 124, 0 ] +KELP: [ 64, 64, 255 ] +MOSS_CARPET: [ 102, 127, 51 ] +MOSS_BLOCK: [ 102, 127, 51 ] +HANGING_ROOTS: [ 151, 109, 77 ] +BIG_DRIPLEAF: [ 0, 124, 0 ] +SMALL_DRIPLEAF: [ 0, 124, 0 ] +BAMBOO: [ 0, 124, 0 ] +OAK_SLAB: [ 143, 119, 72 ] +SPRUCE_SLAB: [ 129, 86, 49 ] +BIRCH_SLAB: [ 247, 233, 163 ] +JUNGLE_SLAB: [ 151, 109, 77 ] +ACACIA_SLAB: [ 216, 127, 51 ] +DARK_OAK_SLAB: [ 102, 76, 51 ] +CRIMSON_SLAB: [ 148, 63, 97 ] +WARPED_SLAB: [ 58, 142, 140 ] +STONE_SLAB: [ 112, 112, 112 ] +SMOOTH_STONE_SLAB: [ 112, 112, 112 ] +SANDSTONE_SLAB: [ 247, 233, 163 ] +CUT_SANDSTONE_SLAB: [ 247, 233, 163 ] +PETRIFIED_OAK_SLAB: [ 143, 119, 72 ] +COBBLESTONE_SLAB: [ 112, 112, 112 ] +BRICK_SLAB: [ 153, 51, 51 ] +STONE_BRICK_SLAB: [ 112, 112, 112 ] +NETHER_BRICK_SLAB: [ 112, 2, 0 ] +QUARTZ_SLAB: [ 255, 252, 245 ] +RED_SANDSTONE_SLAB: [ 216, 127, 51 ] +CUT_RED_SANDSTONE_SLAB: [ 216, 127, 51 ] +PURPUR_SLAB: [ 178, 76, 216 ] +PRISMARINE_SLAB: [ 76, 127, 153 ] +PRISMARINE_BRICK_SLAB: [ 92, 219, 213 ] +DARK_PRISMARINE_SLAB: [ 92, 219, 213 ] +SMOOTH_QUARTZ: [ 255, 252, 245 ] +SMOOTH_RED_SANDSTONE: [ 216, 127, 51 ] +SMOOTH_SANDSTONE: [ 247, 233, 163 ] +SMOOTH_STONE: [ 112, 112, 112 ] +BRICKS: [ 153, 51, 51 ] +BOOKSHELF: [ 143, 119, 72 ] +MOSSY_COBBLESTONE: [ 112, 112, 112 ] +OBSIDIAN: [ 25, 25, 25 ] +TORCH: [ 0, 0, 0 ] +END_ROD: [ 0, 0, 0 ] +CHORUS_PLANT: [ 127, 63, 178 ] +CHORUS_FLOWER: [ 127, 63, 178 ] +PURPUR_BLOCK: [ 178, 76, 216 ] +PURPUR_PILLAR: [ 178, 76, 216 ] +PURPUR_STAIRS: [ 178, 76, 216 ] +SPAWNER: [ 112, 112, 112 ] +OAK_STAIRS: [ 143, 119, 72 ] +CHEST: [ 143, 119, 72 ] +CRAFTING_TABLE: [ 143, 119, 72 ] +FARMLAND: [ 151, 109, 77 ] +FURNACE: [ 112, 112, 112 ] +LADDER: [ 0, 0, 0 ] +COBBLESTONE_STAIRS: [ 112, 112, 112 ] +SNOW: [ 255, 255, 255 ] +ICE: [ 160, 160, 255 ] +SNOW_BLOCK: [ 255, 255, 255 ] +CACTUS: [ 0, 124, 0 ] +CLAY: [ 164, 168, 184 ] +JUKEBOX: [ 151, 109, 77 ] +OAK_FENCE: [ 143, 119, 72 ] +SPRUCE_FENCE: [ 129, 86, 49 ] +BIRCH_FENCE: [ 247, 233, 163 ] +JUNGLE_FENCE: [ 151, 109, 77 ] +ACACIA_FENCE: [ 216, 127, 51 ] +DARK_OAK_FENCE: [ 102, 76, 51 ] +CRIMSON_FENCE: [ 148, 63, 97 ] +WARPED_FENCE: [ 58, 142, 140 ] +PUMPKIN: [ 216, 127, 51 ] +CARVED_PUMPKIN: [ 216, 127, 51 ] +JACK_O_LANTERN: [ 216, 127, 51 ] +NETHERRACK: [ 112, 2, 0 ] +SOUL_SAND: [ 102, 76, 51 ] +SOUL_SOIL: [ 102, 76, 51 ] +BASALT: [ 25, 25, 25 ] +POLISHED_BASALT: [ 25, 25, 25 ] +SMOOTH_BASALT: [ 25, 25, 25 ] +SOUL_TORCH: [ 0, 0, 0 ] +GLOWSTONE: [ 247, 233, 163 ] +INFESTED_STONE: [ 164, 168, 184 ] +INFESTED_COBBLESTONE: [ 164, 168, 184 ] +INFESTED_STONE_BRICKS: [ 164, 168, 184 ] +INFESTED_MOSSY_STONE_BRICKS: [ 164, 168, 184 ] +INFESTED_CRACKED_STONE_BRICKS: [ 164, 168, 184 ] +INFESTED_CHISELED_STONE_BRICKS: [ 164, 168, 184 ] +INFESTED_DEEPSLATE: [ 100, 100, 100 ] +STONE_BRICKS: [ 112, 112, 112 ] +MOSSY_STONE_BRICKS: [ 112, 112, 112 ] +CRACKED_STONE_BRICKS: [ 112, 112, 112 ] +CHISELED_STONE_BRICKS: [ 112, 112, 112 ] +DEEPSLATE_BRICKS: [ 100, 100, 100 ] +CRACKED_DEEPSLATE_BRICKS: [ 100, 100, 100 ] +DEEPSLATE_TILES: [ 100, 100, 100 ] +CRACKED_DEEPSLATE_TILES: [ 100, 100, 100 ] +CHISELED_DEEPSLATE: [ 100, 100, 100 ] +BROWN_MUSHROOM_BLOCK: [ 151, 109, 77 ] +RED_MUSHROOM_BLOCK: [ 153, 51, 51 ] +MUSHROOM_STEM: [ 199, 199, 199 ] +IRON_BARS: [ 0, 0, 0 ] +CHAIN: [ 0, 0, 0 ] +GLASS_PANE: [ 0, 0, 0 ] +MELON: [ 127, 204, 25 ] +VINE: [ 0, 124, 0 ] +GLOW_LICHEN: [ 127, 167, 150 ] +BRICK_STAIRS: [ 153, 51, 51 ] +STONE_BRICK_STAIRS: [ 112, 112, 112 ] +MYCELIUM: [ 127, 63, 178 ] +LILY_PAD: [ 0, 124, 0 ] +NETHER_BRICKS: [ 112, 2, 0 ] +CRACKED_NETHER_BRICKS: [ 112, 2, 0 ] +CHISELED_NETHER_BRICKS: [ 112, 2, 0 ] +NETHER_BRICK_FENCE: [ 112, 2, 0 ] +NETHER_BRICK_STAIRS: [ 112, 2, 0 ] +ENCHANTING_TABLE: [ 153, 51, 51 ] +END_PORTAL_FRAME: [ 102, 127, 51 ] +END_STONE: [ 247, 233, 163 ] +END_STONE_BRICKS: [ 247, 233, 163 ] +DRAGON_EGG: [ 25, 25, 25 ] +SANDSTONE_STAIRS: [ 247, 233, 163 ] +ENDER_CHEST: [ 112, 112, 112 ] +EMERALD_BLOCK: [ 0, 217, 58 ] +SPRUCE_STAIRS: [ 129, 86, 49 ] +BIRCH_STAIRS: [ 247, 233, 163 ] +JUNGLE_STAIRS: [ 151, 109, 77 ] +CRIMSON_STAIRS: [ 148, 63, 97 ] +WARPED_STAIRS: [ 58, 142, 140 ] +COMMAND_BLOCK: [ 102, 76, 51 ] +BEACON: [ 92, 219, 213 ] +COBBLESTONE_WALL: [ 112, 112, 112 ] +MOSSY_COBBLESTONE_WALL: [ 112, 112, 112 ] +BRICK_WALL: [ 153, 51, 51 ] +PRISMARINE_WALL: [ 76, 127, 153 ] +RED_SANDSTONE_WALL: [ 216, 127, 51 ] +MOSSY_STONE_BRICK_WALL: [ 112, 112, 112 ] +GRANITE_WALL: [ 151, 109, 77 ] +STONE_BRICK_WALL: [ 112, 112, 112 ] +NETHER_BRICK_WALL: [ 112, 2, 0 ] +ANDESITE_WALL: [ 112, 112, 112 ] +RED_NETHER_BRICK_WALL: [ 112, 2, 0 ] +SANDSTONE_WALL: [ 247, 233, 163 ] +END_STONE_BRICK_WALL: [ 247, 233, 163 ] +DIORITE_WALL: [ 255, 252, 245 ] +BLACKSTONE_WALL: [ 25, 25, 25 ] +POLISHED_BLACKSTONE_WALL: [ 25, 25, 25 ] +POLISHED_BLACKSTONE_BRICK_WALL: [ 25, 25, 25 ] +COBBLED_DEEPSLATE_WALL: [ 100, 100, 100 ] +POLISHED_DEEPSLATE_WALL: [ 100, 100, 100 ] +DEEPSLATE_BRICK_WALL: [ 100, 100, 100 ] +DEEPSLATE_TILE_WALL: [ 100, 100, 100 ] +ANVIL: [ 167, 167, 167 ] +CHIPPED_ANVIL: [ 167, 167, 167 ] +DAMAGED_ANVIL: [ 167, 167, 167 ] +CHISELED_QUARTZ_BLOCK: [ 255, 252, 245 ] +QUARTZ_BLOCK: [ 255, 252, 245 ] +QUARTZ_BRICKS: [ 255, 252, 245 ] +QUARTZ_PILLAR: [ 255, 252, 245 ] +QUARTZ_STAIRS: [ 255, 252, 245 ] +WHITE_TERRACOTTA: [ 209, 177, 161 ] +ORANGE_TERRACOTTA: [ 159, 82, 36 ] +MAGENTA_TERRACOTTA: [ 149, 87, 108 ] +LIGHT_BLUE_TERRACOTTA: [ 112, 108, 138 ] +YELLOW_TERRACOTTA: [ 186, 133, 36 ] +LIME_TERRACOTTA: [ 103, 117, 53 ] +PINK_TERRACOTTA: [ 160, 77, 78 ] +GRAY_TERRACOTTA: [ 57, 41, 35 ] +LIGHT_GRAY_TERRACOTTA: [ 135, 107, 98 ] +CYAN_TERRACOTTA: [ 87, 92, 92 ] +PURPLE_TERRACOTTA: [ 122, 73, 88 ] +BLUE_TERRACOTTA: [ 76, 62, 92 ] +BROWN_TERRACOTTA: [ 76, 50, 35 ] +GREEN_TERRACOTTA: [ 76, 82, 42 ] +RED_TERRACOTTA: [ 142, 60, 46 ] +BLACK_TERRACOTTA: [ 37, 22, 16 ] +BARRIER: [ 0, 0, 0 ] +LIGHT: [ 0, 0, 0 ] +HAY_BLOCK: [ 229, 229, 51 ] +WHITE_CARPET: [ 255, 255, 255 ] +ORANGE_CARPET: [ 216, 127, 51 ] +MAGENTA_CARPET: [ 178, 76, 216 ] +LIGHT_BLUE_CARPET: [ 102, 153, 216 ] +YELLOW_CARPET: [ 229, 229, 51 ] +LIME_CARPET: [ 127, 204, 25 ] +PINK_CARPET: [ 242, 127, 165 ] +GRAY_CARPET: [ 76, 76, 76 ] +LIGHT_GRAY_CARPET: [ 153, 153, 153 ] +CYAN_CARPET: [ 76, 127, 153 ] +PURPLE_CARPET: [ 127, 63, 178 ] +BLUE_CARPET: [ 51, 76, 178 ] +BROWN_CARPET: [ 102, 76, 51 ] +GREEN_CARPET: [ 102, 127, 51 ] +RED_CARPET: [ 153, 51, 51 ] +BLACK_CARPET: [ 25, 25, 25 ] +TERRACOTTA: [ 216, 127, 51 ] +PACKED_ICE: [ 160, 160, 255 ] +ACACIA_STAIRS: [ 216, 127, 51 ] +DARK_OAK_STAIRS: [ 102, 76, 51 ] +DIRT_PATH: [ 151, 109, 77 ] +SUNFLOWER: [ 0, 124, 0 ] +LILAC: [ 0, 124, 0 ] +ROSE_BUSH: [ 0, 124, 0 ] +PEONY: [ 0, 124, 0 ] +TALL_GRASS: [ 0, 124, 0 ] +LARGE_FERN: [ 0, 124, 0 ] +WHITE_STAINED_GLASS: [ 255, 255, 255 ] +ORANGE_STAINED_GLASS: [ 216, 127, 51 ] +MAGENTA_STAINED_GLASS: [ 178, 76, 216 ] +LIGHT_BLUE_STAINED_GLASS: [ 102, 153, 216 ] +YELLOW_STAINED_GLASS: [ 229, 229, 51 ] +LIME_STAINED_GLASS: [ 127, 204, 25 ] +PINK_STAINED_GLASS: [ 242, 127, 165 ] +GRAY_STAINED_GLASS: [ 76, 76, 76 ] +LIGHT_GRAY_STAINED_GLASS: [ 153, 153, 153 ] +CYAN_STAINED_GLASS: [ 76, 127, 153 ] +PURPLE_STAINED_GLASS: [ 127, 63, 178 ] +BLUE_STAINED_GLASS: [ 51, 76, 178 ] +BROWN_STAINED_GLASS: [ 102, 76, 51 ] +GREEN_STAINED_GLASS: [ 102, 127, 51 ] +RED_STAINED_GLASS: [ 153, 51, 51 ] +BLACK_STAINED_GLASS: [ 25, 25, 25 ] +WHITE_STAINED_GLASS_PANE: [ 0, 0, 0 ] +ORANGE_STAINED_GLASS_PANE: [ 0, 0, 0 ] +MAGENTA_STAINED_GLASS_PANE: [ 0, 0, 0 ] +LIGHT_BLUE_STAINED_GLASS_PANE: [ 0, 0, 0 ] +YELLOW_STAINED_GLASS_PANE: [ 0, 0, 0 ] +LIME_STAINED_GLASS_PANE: [ 0, 0, 0 ] +PINK_STAINED_GLASS_PANE: [ 0, 0, 0 ] +GRAY_STAINED_GLASS_PANE: [ 0, 0, 0 ] +LIGHT_GRAY_STAINED_GLASS_PANE: [ 0, 0, 0 ] +CYAN_STAINED_GLASS_PANE: [ 0, 0, 0 ] +PURPLE_STAINED_GLASS_PANE: [ 0, 0, 0 ] +BLUE_STAINED_GLASS_PANE: [ 0, 0, 0 ] +BROWN_STAINED_GLASS_PANE: [ 0, 0, 0 ] +GREEN_STAINED_GLASS_PANE: [ 0, 0, 0 ] +RED_STAINED_GLASS_PANE: [ 0, 0, 0 ] +BLACK_STAINED_GLASS_PANE: [ 0, 0, 0 ] +PRISMARINE: [ 76, 127, 153 ] +PRISMARINE_BRICKS: [ 92, 219, 213 ] +DARK_PRISMARINE: [ 92, 219, 213 ] +PRISMARINE_STAIRS: [ 76, 127, 153 ] +PRISMARINE_BRICK_STAIRS: [ 92, 219, 213 ] +DARK_PRISMARINE_STAIRS: [ 92, 219, 213 ] +SEA_LANTERN: [ 255, 252, 245 ] +RED_SANDSTONE: [ 216, 127, 51 ] +CHISELED_RED_SANDSTONE: [ 216, 127, 51 ] +CUT_RED_SANDSTONE: [ 216, 127, 51 ] +RED_SANDSTONE_STAIRS: [ 216, 127, 51 ] +REPEATING_COMMAND_BLOCK: [ 127, 63, 178 ] +CHAIN_COMMAND_BLOCK: [ 102, 127, 51 ] +MAGMA_BLOCK: [ 112, 2, 0 ] +NETHER_WART_BLOCK: [ 153, 51, 51 ] +WARPED_WART_BLOCK: [ 20, 180, 133 ] +RED_NETHER_BRICKS: [ 112, 2, 0 ] +BONE_BLOCK: [ 247, 233, 163 ] +STRUCTURE_VOID: [ 0, 0, 0 ] +SHULKER_BOX: [ 127, 63, 178 ] +WHITE_SHULKER_BOX: [ 255, 255, 255 ] +ORANGE_SHULKER_BOX: [ 216, 127, 51 ] +MAGENTA_SHULKER_BOX: [ 178, 76, 216 ] +LIGHT_BLUE_SHULKER_BOX: [ 102, 153, 216 ] +YELLOW_SHULKER_BOX: [ 229, 229, 51 ] +LIME_SHULKER_BOX: [ 127, 204, 25 ] +PINK_SHULKER_BOX: [ 242, 127, 165 ] +GRAY_SHULKER_BOX: [ 76, 76, 76 ] +LIGHT_GRAY_SHULKER_BOX: [ 153, 153, 153 ] +CYAN_SHULKER_BOX: [ 76, 127, 153 ] +PURPLE_SHULKER_BOX: [ 122, 73, 88 ] +BLUE_SHULKER_BOX: [ 51, 76, 178 ] +BROWN_SHULKER_BOX: [ 102, 76, 51 ] +GREEN_SHULKER_BOX: [ 102, 127, 51 ] +RED_SHULKER_BOX: [ 153, 51, 51 ] +BLACK_SHULKER_BOX: [ 25, 25, 25 ] +WHITE_GLAZED_TERRACOTTA: [ 255, 255, 255 ] +ORANGE_GLAZED_TERRACOTTA: [ 216, 127, 51 ] +MAGENTA_GLAZED_TERRACOTTA: [ 178, 76, 216 ] +LIGHT_BLUE_GLAZED_TERRACOTTA: [ 102, 153, 216 ] +YELLOW_GLAZED_TERRACOTTA: [ 229, 229, 51 ] +LIME_GLAZED_TERRACOTTA: [ 127, 204, 25 ] +PINK_GLAZED_TERRACOTTA: [ 242, 127, 165 ] +GRAY_GLAZED_TERRACOTTA: [ 76, 76, 76 ] +LIGHT_GRAY_GLAZED_TERRACOTTA: [ 153, 153, 153 ] +CYAN_GLAZED_TERRACOTTA: [ 76, 127, 153 ] +PURPLE_GLAZED_TERRACOTTA: [ 127, 63, 178 ] +BLUE_GLAZED_TERRACOTTA: [ 51, 76, 178 ] +BROWN_GLAZED_TERRACOTTA: [ 102, 76, 51 ] +GREEN_GLAZED_TERRACOTTA: [ 102, 127, 51 ] +RED_GLAZED_TERRACOTTA: [ 153, 51, 51 ] +BLACK_GLAZED_TERRACOTTA: [ 25, 25, 25 ] +WHITE_CONCRETE: [ 255, 255, 255 ] +ORANGE_CONCRETE: [ 216, 127, 51 ] +MAGENTA_CONCRETE: [ 178, 76, 216 ] +LIGHT_BLUE_CONCRETE: [ 102, 153, 216 ] +YELLOW_CONCRETE: [ 229, 229, 51 ] +LIME_CONCRETE: [ 127, 204, 25 ] +PINK_CONCRETE: [ 242, 127, 165 ] +GRAY_CONCRETE: [ 76, 76, 76 ] +LIGHT_GRAY_CONCRETE: [ 153, 153, 153 ] +CYAN_CONCRETE: [ 76, 127, 153 ] +PURPLE_CONCRETE: [ 127, 63, 178 ] +BLUE_CONCRETE: [ 51, 76, 178 ] +BROWN_CONCRETE: [ 102, 76, 51 ] +GREEN_CONCRETE: [ 102, 127, 51 ] +RED_CONCRETE: [ 153, 51, 51 ] +BLACK_CONCRETE: [ 25, 25, 25 ] +WHITE_CONCRETE_POWDER: [ 255, 255, 255 ] +ORANGE_CONCRETE_POWDER: [ 216, 127, 51 ] +MAGENTA_CONCRETE_POWDER: [ 178, 76, 216 ] +LIGHT_BLUE_CONCRETE_POWDER: [ 102, 153, 216 ] +YELLOW_CONCRETE_POWDER: [ 229, 229, 51 ] +LIME_CONCRETE_POWDER: [ 127, 204, 25 ] +PINK_CONCRETE_POWDER: [ 242, 127, 165 ] +GRAY_CONCRETE_POWDER: [ 76, 76, 76 ] +LIGHT_GRAY_CONCRETE_POWDER: [ 153, 153, 153 ] +CYAN_CONCRETE_POWDER: [ 76, 127, 153 ] +PURPLE_CONCRETE_POWDER: [ 127, 63, 178 ] +BLUE_CONCRETE_POWDER: [ 51, 76, 178 ] +BROWN_CONCRETE_POWDER: [ 102, 76, 51 ] +GREEN_CONCRETE_POWDER: [ 102, 127, 51 ] +RED_CONCRETE_POWDER: [ 153, 51, 51 ] +BLACK_CONCRETE_POWDER: [ 25, 25, 25 ] +TURTLE_EGG: [ 247, 233, 163 ] +DEAD_TUBE_CORAL_BLOCK: [ 76, 76, 76 ] +DEAD_BRAIN_CORAL_BLOCK: [ 76, 76, 76 ] +DEAD_BUBBLE_CORAL_BLOCK: [ 76, 76, 76 ] +DEAD_FIRE_CORAL_BLOCK: [ 76, 76, 76 ] +DEAD_HORN_CORAL_BLOCK: [ 76, 76, 76 ] +TUBE_CORAL_BLOCK: [ 51, 76, 178 ] +BRAIN_CORAL_BLOCK: [ 242, 127, 165 ] +BUBBLE_CORAL_BLOCK: [ 127, 63, 178 ] +FIRE_CORAL_BLOCK: [ 153, 51, 51 ] +HORN_CORAL_BLOCK: [ 229, 229, 51 ] +TUBE_CORAL: [ 51, 76, 178 ] +BRAIN_CORAL: [ 242, 127, 165 ] +BUBBLE_CORAL: [ 127, 63, 178 ] +FIRE_CORAL: [ 153, 51, 51 ] +HORN_CORAL: [ 229, 229, 51 ] +DEAD_BRAIN_CORAL: [ 76, 76, 76 ] +DEAD_BUBBLE_CORAL: [ 76, 76, 76 ] +DEAD_FIRE_CORAL: [ 76, 76, 76 ] +DEAD_HORN_CORAL: [ 76, 76, 76 ] +DEAD_TUBE_CORAL: [ 76, 76, 76 ] +TUBE_CORAL_FAN: [ 51, 76, 178 ] +BRAIN_CORAL_FAN: [ 242, 127, 165 ] +BUBBLE_CORAL_FAN: [ 127, 63, 178 ] +FIRE_CORAL_FAN: [ 153, 51, 51 ] +HORN_CORAL_FAN: [ 229, 229, 51 ] +DEAD_TUBE_CORAL_FAN: [ 76, 76, 76 ] +DEAD_BRAIN_CORAL_FAN: [ 76, 76, 76 ] +DEAD_BUBBLE_CORAL_FAN: [ 76, 76, 76 ] +DEAD_FIRE_CORAL_FAN: [ 76, 76, 76 ] +DEAD_HORN_CORAL_FAN: [ 76, 76, 76 ] +BLUE_ICE: [ 160, 160, 255 ] +CONDUIT: [ 92, 219, 213 ] +POLISHED_GRANITE_STAIRS: [ 151, 109, 77 ] +SMOOTH_RED_SANDSTONE_STAIRS: [ 216, 127, 51 ] +MOSSY_STONE_BRICK_STAIRS: [ 112, 112, 112 ] +POLISHED_DIORITE_STAIRS: [ 255, 252, 245 ] +MOSSY_COBBLESTONE_STAIRS: [ 112, 112, 112 ] +END_STONE_BRICK_STAIRS: [ 247, 233, 163 ] +STONE_STAIRS: [ 112, 112, 112 ] +SMOOTH_SANDSTONE_STAIRS: [ 247, 233, 163 ] +SMOOTH_QUARTZ_STAIRS: [ 255, 252, 245 ] +GRANITE_STAIRS: [ 151, 109, 77 ] +ANDESITE_STAIRS: [ 112, 112, 112 ] +RED_NETHER_BRICK_STAIRS: [ 112, 2, 0 ] +POLISHED_ANDESITE_STAIRS: [ 112, 112, 112 ] +DIORITE_STAIRS: [ 255, 252, 245 ] +COBBLED_DEEPSLATE_STAIRS: [ 100, 100, 100 ] +POLISHED_DEEPSLATE_STAIRS: [ 100, 100, 100 ] +DEEPSLATE_BRICK_STAIRS: [ 100, 100, 100 ] +DEEPSLATE_TILE_STAIRS: [ 100, 100, 100 ] +POLISHED_GRANITE_SLAB: [ 151, 109, 77 ] +SMOOTH_RED_SANDSTONE_SLAB: [ 216, 127, 51 ] +MOSSY_STONE_BRICK_SLAB: [ 112, 112, 112 ] +POLISHED_DIORITE_SLAB: [ 255, 252, 245 ] +MOSSY_COBBLESTONE_SLAB: [ 112, 112, 112 ] +END_STONE_BRICK_SLAB: [ 247, 233, 163 ] +SMOOTH_SANDSTONE_SLAB: [ 247, 233, 163 ] +SMOOTH_QUARTZ_SLAB: [ 255, 252, 245 ] +GRANITE_SLAB: [ 151, 109, 77 ] +ANDESITE_SLAB: [ 112, 112, 112 ] +RED_NETHER_BRICK_SLAB: [ 112, 2, 0 ] +POLISHED_ANDESITE_SLAB: [ 112, 112, 112 ] +DIORITE_SLAB: [ 255, 252, 245 ] +COBBLED_DEEPSLATE_SLAB: [ 100, 100, 100 ] +POLISHED_DEEPSLATE_SLAB: [ 100, 100, 100 ] +DEEPSLATE_BRICK_SLAB: [ 100, 100, 100 ] +DEEPSLATE_TILE_SLAB: [ 100, 100, 100 ] +SCAFFOLDING: [ 247, 233, 163 ] +REDSTONE_TORCH: [ 0, 0, 0 ] +REDSTONE_BLOCK: [ 255, 0, 0 ] +REPEATER: [ 0, 0, 0 ] +COMPARATOR: [ 0, 0, 0 ] +PISTON: [ 112, 112, 112 ] +STICKY_PISTON: [ 112, 112, 112 ] +SLIME_BLOCK: [ 127, 178, 56 ] +HONEY_BLOCK: [ 216, 127, 51 ] +OBSERVER: [ 112, 112, 112 ] +HOPPER: [ 112, 112, 112 ] +DISPENSER: [ 112, 112, 112 ] +DROPPER: [ 112, 112, 112 ] +LECTERN: [ 143, 119, 72 ] +TARGET: [ 255, 252, 245 ] +LEVER: [ 0, 0, 0 ] +LIGHTNING_ROD: [ 216, 127, 51 ] +DAYLIGHT_DETECTOR: [ 143, 119, 72 ] +SCULK_SENSOR: [ 76, 127, 153 ] +TRIPWIRE_HOOK: [ 0, 0, 0 ] +TRAPPED_CHEST: [ 143, 119, 72 ] +TNT: [ 255, 0, 0 ] +REDSTONE_LAMP: [ 0, 0, 0 ] +NOTE_BLOCK: [ 143, 119, 72 ] +STONE_BUTTON: [ 0, 0, 0 ] +POLISHED_BLACKSTONE_BUTTON: [ 0, 0, 0 ] +OAK_BUTTON: [ 0, 0, 0 ] +SPRUCE_BUTTON: [ 0, 0, 0 ] +BIRCH_BUTTON: [ 0, 0, 0 ] +JUNGLE_BUTTON: [ 0, 0, 0 ] +ACACIA_BUTTON: [ 0, 0, 0 ] +DARK_OAK_BUTTON: [ 0, 0, 0 ] +CRIMSON_BUTTON: [ 0, 0, 0 ] +WARPED_BUTTON: [ 0, 0, 0 ] +STONE_PRESSURE_PLATE: [ 112, 112, 112 ] +POLISHED_BLACKSTONE_PRESSURE_PLATE: [ 25, 25, 25 ] +LIGHT_WEIGHTED_PRESSURE_PLATE: [ 250, 238, 77 ] +HEAVY_WEIGHTED_PRESSURE_PLATE: [ 167, 167, 167 ] +OAK_PRESSURE_PLATE: [ 143, 119, 72 ] +SPRUCE_PRESSURE_PLATE: [ 129, 86, 49 ] +BIRCH_PRESSURE_PLATE: [ 247, 233, 163 ] +JUNGLE_PRESSURE_PLATE: [ 151, 109, 77 ] +ACACIA_PRESSURE_PLATE: [ 216, 127, 51 ] +DARK_OAK_PRESSURE_PLATE: [ 102, 76, 51 ] +CRIMSON_PRESSURE_PLATE: [ 148, 63, 97 ] +WARPED_PRESSURE_PLATE: [ 58, 142, 140 ] +IRON_DOOR: [ 167, 167, 167 ] +OAK_DOOR: [ 143, 119, 72 ] +SPRUCE_DOOR: [ 129, 86, 49 ] +BIRCH_DOOR: [ 247, 233, 163 ] +JUNGLE_DOOR: [ 151, 109, 77 ] +ACACIA_DOOR: [ 216, 127, 51 ] +DARK_OAK_DOOR: [ 102, 76, 51 ] +CRIMSON_DOOR: [ 148, 63, 97 ] +WARPED_DOOR: [ 58, 142, 140 ] +IRON_TRAPDOOR: [ 167, 167, 167 ] +OAK_TRAPDOOR: [ 143, 119, 72 ] +SPRUCE_TRAPDOOR: [ 129, 86, 49 ] +BIRCH_TRAPDOOR: [ 247, 233, 163 ] +JUNGLE_TRAPDOOR: [ 151, 109, 77 ] +ACACIA_TRAPDOOR: [ 216, 127, 51 ] +DARK_OAK_TRAPDOOR: [ 102, 76, 51 ] +CRIMSON_TRAPDOOR: [ 148, 63, 97 ] +WARPED_TRAPDOOR: [ 58, 142, 140 ] +OAK_FENCE_GATE: [ 143, 119, 72 ] +SPRUCE_FENCE_GATE: [ 129, 86, 49 ] +BIRCH_FENCE_GATE: [ 247, 233, 163 ] +JUNGLE_FENCE_GATE: [ 151, 109, 77 ] +ACACIA_FENCE_GATE: [ 216, 127, 51 ] +DARK_OAK_FENCE_GATE: [ 102, 76, 51 ] +CRIMSON_FENCE_GATE: [ 148, 63, 97 ] +WARPED_FENCE_GATE: [ 58, 142, 140 ] +POWERED_RAIL: [ 0, 0, 0 ] +DETECTOR_RAIL: [ 0, 0, 0 ] +RAIL: [ 0, 0, 0 ] +ACTIVATOR_RAIL: [ 0, 0, 0 ] +STRUCTURE_BLOCK: [ 153, 153, 153 ] +JIGSAW: [ 153, 153, 153 ] +WHEAT: [ 0, 124, 0 ] +OAK_SIGN: [ 143, 119, 72 ] +SPRUCE_SIGN: [ 129, 86, 49 ] +BIRCH_SIGN: [ 247, 233, 163 ] +JUNGLE_SIGN: [ 151, 109, 77 ] +ACACIA_SIGN: [ 216, 127, 51 ] +DARK_OAK_SIGN: [ 102, 76, 51 ] +CRIMSON_SIGN: [ 148, 63, 97 ] +WARPED_SIGN: [ 58, 142, 140 ] +DRIED_KELP_BLOCK: [ 102, 127, 51 ] +CAKE: [ 0, 0, 0 ] +WHITE_BED: [ 255, 255, 255 ] +ORANGE_BED: [ 216, 127, 51 ] +MAGENTA_BED: [ 178, 76, 216 ] +LIGHT_BLUE_BED: [ 102, 153, 216 ] +YELLOW_BED: [ 229, 229, 51 ] +LIME_BED: [ 127, 204, 25 ] +PINK_BED: [ 242, 127, 165 ] +GRAY_BED: [ 76, 76, 76 ] +LIGHT_GRAY_BED: [ 153, 153, 153 ] +CYAN_BED: [ 76, 127, 153 ] +PURPLE_BED: [ 127, 63, 178 ] +BLUE_BED: [ 51, 76, 178 ] +BROWN_BED: [ 102, 76, 51 ] +GREEN_BED: [ 102, 127, 51 ] +RED_BED: [ 153, 51, 51 ] +BLACK_BED: [ 25, 25, 25 ] +NETHER_WART: [ 153, 51, 51 ] +BREWING_STAND: [ 167, 167, 167 ] +CAULDRON: [ 112, 112, 112 ] +FLOWER_POT: [ 0, 0, 0 ] +SKELETON_SKULL: [ 0, 0, 0 ] +WITHER_SKELETON_SKULL: [ 0, 0, 0 ] +PLAYER_HEAD: [ 0, 0, 0 ] +ZOMBIE_HEAD: [ 0, 0, 0 ] +CREEPER_HEAD: [ 0, 0, 0 ] +DRAGON_HEAD: [ 0, 0, 0 ] +WHITE_BANNER: [ 143, 119, 72 ] +ORANGE_BANNER: [ 143, 119, 72 ] +MAGENTA_BANNER: [ 143, 119, 72 ] +LIGHT_BLUE_BANNER: [ 143, 119, 72 ] +YELLOW_BANNER: [ 143, 119, 72 ] +LIME_BANNER: [ 143, 119, 72 ] +PINK_BANNER: [ 143, 119, 72 ] +GRAY_BANNER: [ 143, 119, 72 ] +LIGHT_GRAY_BANNER: [ 143, 119, 72 ] +CYAN_BANNER: [ 143, 119, 72 ] +PURPLE_BANNER: [ 143, 119, 72 ] +BLUE_BANNER: [ 143, 119, 72 ] +BROWN_BANNER: [ 143, 119, 72 ] +GREEN_BANNER: [ 143, 119, 72 ] +RED_BANNER: [ 143, 119, 72 ] +BLACK_BANNER: [ 143, 119, 72 ] +LOOM: [ 143, 119, 72 ] +COMPOSTER: [ 143, 119, 72 ] +BARREL: [ 143, 119, 72 ] +SMOKER: [ 112, 112, 112 ] +BLAST_FURNACE: [ 112, 112, 112 ] +CARTOGRAPHY_TABLE: [ 143, 119, 72 ] +FLETCHING_TABLE: [ 143, 119, 72 ] +GRINDSTONE: [ 167, 167, 167 ] +SMITHING_TABLE: [ 143, 119, 72 ] +STONECUTTER: [ 112, 112, 112 ] +BELL: [ 250, 238, 77 ] +LANTERN: [ 167, 167, 167 ] +SOUL_LANTERN: [ 167, 167, 167 ] +CAMPFIRE: [ 129, 86, 49 ] +SOUL_CAMPFIRE: [ 129, 86, 49 ] +SHROOMLIGHT: [ 153, 51, 51 ] +BEE_NEST: [ 229, 229, 51 ] +BEEHIVE: [ 143, 119, 72 ] +HONEYCOMB_BLOCK: [ 216, 127, 51 ] +LODESTONE: [ 167, 167, 167 ] +CRYING_OBSIDIAN: [ 25, 25, 25 ] +BLACKSTONE: [ 25, 25, 25 ] +BLACKSTONE_SLAB: [ 25, 25, 25 ] +BLACKSTONE_STAIRS: [ 25, 25, 25 ] +GILDED_BLACKSTONE: [ 25, 25, 25 ] +POLISHED_BLACKSTONE: [ 25, 25, 25 ] +POLISHED_BLACKSTONE_SLAB: [ 25, 25, 25 ] +POLISHED_BLACKSTONE_STAIRS: [ 25, 25, 25 ] +CHISELED_POLISHED_BLACKSTONE: [ 25, 25, 25 ] +POLISHED_BLACKSTONE_BRICKS: [ 25, 25, 25 ] +POLISHED_BLACKSTONE_BRICK_SLAB: [ 25, 25, 25 ] +POLISHED_BLACKSTONE_BRICK_STAIRS: [ 25, 25, 25 ] +CRACKED_POLISHED_BLACKSTONE_BRICKS: [ 25, 25, 25 ] +RESPAWN_ANCHOR: [ 25, 25, 25 ] +CANDLE: [ 247, 233, 163 ] +WHITE_CANDLE: [ 199, 199, 199 ] +ORANGE_CANDLE: [ 216, 127, 51 ] +MAGENTA_CANDLE: [ 178, 76, 216 ] +LIGHT_BLUE_CANDLE: [ 102, 153, 216 ] +YELLOW_CANDLE: [ 229, 229, 51 ] +LIME_CANDLE: [ 127, 204, 25 ] +PINK_CANDLE: [ 242, 127, 165 ] +GRAY_CANDLE: [ 76, 76, 76 ] +LIGHT_GRAY_CANDLE: [ 153, 153, 153 ] +CYAN_CANDLE: [ 76, 127, 153 ] +PURPLE_CANDLE: [ 127, 63, 178 ] +BLUE_CANDLE: [ 51, 76, 178 ] +BROWN_CANDLE: [ 102, 76, 51 ] +GREEN_CANDLE: [ 102, 127, 51 ] +RED_CANDLE: [ 153, 51, 51 ] +BLACK_CANDLE: [ 25, 25, 25 ] +SMALL_AMETHYST_BUD: [ 127, 63, 178 ] +MEDIUM_AMETHYST_BUD: [ 127, 63, 178 ] +LARGE_AMETHYST_BUD: [ 127, 63, 178 ] +AMETHYST_CLUSTER: [ 127, 63, 178 ] +POINTED_DRIPSTONE: [ 76, 50, 35 ] +WATER: [ 64, 64, 255 ] +LAVA: [ 255, 0, 0 ] +TALL_SEAGRASS: [ 64, 64, 255 ] +PISTON_HEAD: [ 112, 112, 112 ] +MOVING_PISTON: [ 112, 112, 112 ] +WALL_TORCH: [ 0, 0, 0 ] +FIRE: [ 255, 0, 0 ] +SOUL_FIRE: [ 0, 0, 0 ] +REDSTONE_WIRE: [ 0, 0, 0 ] +OAK_WALL_SIGN: [ 143, 119, 72 ] +SPRUCE_WALL_SIGN: [ 129, 86, 49 ] +BIRCH_WALL_SIGN: [ 247, 233, 163 ] +ACACIA_WALL_SIGN: [ 216, 127, 51 ] +JUNGLE_WALL_SIGN: [ 151, 109, 77 ] +DARK_OAK_WALL_SIGN: [ 102, 76, 51 ] +REDSTONE_WALL_TORCH: [ 0, 0, 0 ] +SOUL_WALL_TORCH: [ 0, 0, 0 ] +NETHER_PORTAL: [ 0, 0, 0 ] +ATTACHED_PUMPKIN_STEM: [ 0, 124, 0 ] +ATTACHED_MELON_STEM: [ 0, 124, 0 ] +PUMPKIN_STEM: [ 0, 124, 0 ] +MELON_STEM: [ 0, 124, 0 ] +WATER_CAULDRON: [ 112, 112, 112 ] +LAVA_CAULDRON: [ 112, 112, 112 ] +POWDER_SNOW_CAULDRON: [ 112, 112, 112 ] +END_PORTAL: [ 25, 25, 25 ] +COCOA: [ 0, 124, 0 ] +TRIPWIRE: [ 0, 0, 0 ] +POTTED_OAK_SAPLING: [ 0, 0, 0 ] +POTTED_SPRUCE_SAPLING: [ 0, 0, 0 ] +POTTED_BIRCH_SAPLING: [ 0, 0, 0 ] +POTTED_JUNGLE_SAPLING: [ 0, 0, 0 ] +POTTED_ACACIA_SAPLING: [ 0, 0, 0 ] +POTTED_DARK_OAK_SAPLING: [ 0, 0, 0 ] +POTTED_FERN: [ 0, 0, 0 ] +POTTED_DANDELION: [ 0, 0, 0 ] +POTTED_POPPY: [ 0, 0, 0 ] +POTTED_BLUE_ORCHID: [ 0, 0, 0 ] +POTTED_ALLIUM: [ 0, 0, 0 ] +POTTED_AZURE_BLUET: [ 0, 0, 0 ] +POTTED_RED_TULIP: [ 0, 0, 0 ] +POTTED_ORANGE_TULIP: [ 0, 0, 0 ] +POTTED_WHITE_TULIP: [ 0, 0, 0 ] +POTTED_PINK_TULIP: [ 0, 0, 0 ] +POTTED_OXEYE_DAISY: [ 0, 0, 0 ] +POTTED_CORNFLOWER: [ 0, 0, 0 ] +POTTED_LILY_OF_THE_VALLEY: [ 0, 0, 0 ] +POTTED_WITHER_ROSE: [ 0, 0, 0 ] +POTTED_RED_MUSHROOM: [ 0, 0, 0 ] +POTTED_BROWN_MUSHROOM: [ 0, 0, 0 ] +POTTED_DEAD_BUSH: [ 0, 0, 0 ] +POTTED_CACTUS: [ 0, 0, 0 ] +CARROTS: [ 0, 124, 0 ] +POTATOES: [ 0, 124, 0 ] +SKELETON_WALL_SKULL: [ 0, 0, 0 ] +WITHER_SKELETON_WALL_SKULL: [ 0, 0, 0 ] +ZOMBIE_WALL_HEAD: [ 0, 0, 0 ] +PLAYER_WALL_HEAD: [ 0, 0, 0 ] +CREEPER_WALL_HEAD: [ 0, 0, 0 ] +DRAGON_WALL_HEAD: [ 0, 0, 0 ] +WHITE_WALL_BANNER: [ 143, 119, 72 ] +ORANGE_WALL_BANNER: [ 143, 119, 72 ] +MAGENTA_WALL_BANNER: [ 143, 119, 72 ] +LIGHT_BLUE_WALL_BANNER: [ 143, 119, 72 ] +YELLOW_WALL_BANNER: [ 143, 119, 72 ] +LIME_WALL_BANNER: [ 143, 119, 72 ] +PINK_WALL_BANNER: [ 143, 119, 72 ] +GRAY_WALL_BANNER: [ 143, 119, 72 ] +LIGHT_GRAY_WALL_BANNER: [ 143, 119, 72 ] +CYAN_WALL_BANNER: [ 143, 119, 72 ] +PURPLE_WALL_BANNER: [ 143, 119, 72 ] +BLUE_WALL_BANNER: [ 143, 119, 72 ] +BROWN_WALL_BANNER: [ 143, 119, 72 ] +GREEN_WALL_BANNER: [ 143, 119, 72 ] +RED_WALL_BANNER: [ 143, 119, 72 ] +BLACK_WALL_BANNER: [ 143, 119, 72 ] +BEETROOTS: [ 0, 124, 0 ] +END_GATEWAY: [ 25, 25, 25 ] +FROSTED_ICE: [ 160, 160, 255 ] +KELP_PLANT: [ 64, 64, 255 ] +DEAD_TUBE_CORAL_WALL_FAN: [ 76, 76, 76 ] +DEAD_BRAIN_CORAL_WALL_FAN: [ 76, 76, 76 ] +DEAD_BUBBLE_CORAL_WALL_FAN: [ 76, 76, 76 ] +DEAD_FIRE_CORAL_WALL_FAN: [ 76, 76, 76 ] +DEAD_HORN_CORAL_WALL_FAN: [ 76, 76, 76 ] +TUBE_CORAL_WALL_FAN: [ 51, 76, 178 ] +BRAIN_CORAL_WALL_FAN: [ 242, 127, 165 ] +BUBBLE_CORAL_WALL_FAN: [ 127, 63, 178 ] +FIRE_CORAL_WALL_FAN: [ 153, 51, 51 ] +HORN_CORAL_WALL_FAN: [ 229, 229, 51 ] +BAMBOO_SAPLING: [ 143, 119, 72 ] +POTTED_BAMBOO: [ 0, 0, 0 ] +VOID_AIR: [ 0, 0, 0 ] +CAVE_AIR: [ 0, 0, 0 ] +BUBBLE_COLUMN: [ 64, 64, 255 ] +SWEET_BERRY_BUSH: [ 0, 124, 0 ] +WEEPING_VINES_PLANT: [ 112, 2, 0 ] +TWISTING_VINES_PLANT: [ 76, 127, 153 ] +CRIMSON_WALL_SIGN: [ 148, 63, 97 ] +WARPED_WALL_SIGN: [ 58, 142, 140 ] +POTTED_CRIMSON_FUNGUS: [ 0, 0, 0 ] +POTTED_WARPED_FUNGUS: [ 0, 0, 0 ] +POTTED_CRIMSON_ROOTS: [ 0, 0, 0 ] +POTTED_WARPED_ROOTS: [ 0, 0, 0 ] +CANDLE_CAKE: [ 0, 0, 0 ] +WHITE_CANDLE_CAKE: [ 0, 0, 0 ] +ORANGE_CANDLE_CAKE: [ 0, 0, 0 ] +MAGENTA_CANDLE_CAKE: [ 0, 0, 0 ] +LIGHT_BLUE_CANDLE_CAKE: [ 0, 0, 0 ] +YELLOW_CANDLE_CAKE: [ 0, 0, 0 ] +LIME_CANDLE_CAKE: [ 0, 0, 0 ] +PINK_CANDLE_CAKE: [ 0, 0, 0 ] +GRAY_CANDLE_CAKE: [ 0, 0, 0 ] +LIGHT_GRAY_CANDLE_CAKE: [ 0, 0, 0 ] +CYAN_CANDLE_CAKE: [ 0, 0, 0 ] +PURPLE_CANDLE_CAKE: [ 0, 0, 0 ] +BLUE_CANDLE_CAKE: [ 0, 0, 0 ] +BROWN_CANDLE_CAKE: [ 0, 0, 0 ] +GREEN_CANDLE_CAKE: [ 0, 0, 0 ] +RED_CANDLE_CAKE: [ 0, 0, 0 ] +BLACK_CANDLE_CAKE: [ 0, 0, 0 ] +POWDER_SNOW: [ 255, 255, 255 ] +CAVE_VINES: [ 0, 124, 0 ] +CAVE_VINES_PLANT: [ 0, 124, 0 ] +BIG_DRIPLEAF_STEM: [ 0, 124, 0 ] +POTTED_AZALEA_BUSH: [ 0, 0, 0 ] +POTTED_FLOWERING_AZALEA_BUSH: [ 0, 0, 0 ] +======= AIR: [0, 0, 0] STONE: [112, 112, 112] GRANITE: [151, 109, 77] diff --git a/src/main/resources/spells.yml b/src/main/resources/spells.yml new file mode 100644 index 00000000..e69de29b