9
0
mirror of https://github.com/Auxilor/EcoMobs.git synced 2025-12-21 16:09:24 +00:00

Began complete rewrite

This commit is contained in:
Auxilor
2022-02-05 18:20:16 +00:00
parent 765b65343a
commit 03efa137f4
37 changed files with 723 additions and 319 deletions

View File

@@ -1,3 +1,13 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
}
}
plugins { plugins {
id 'java-library' id 'java-library'
id 'com.github.johnrengelman.shadow' version '7.0.0' id 'com.github.johnrengelman.shadow' version '7.0.0'
@@ -6,11 +16,12 @@ plugins {
} }
dependencies { dependencies {
implementation project(":eco-core:core-plugin") implementation project(":eco-core").getSubprojects()
} }
allprojects { allprojects {
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'com.github.johnrengelman.shadow'
@@ -39,23 +50,23 @@ allprojects {
maven { url 'https://maven.sk89q.com/repo/' } maven { url 'https://maven.sk89q.com/repo/' }
maven { url 'https://github.com/factions-site/repo/raw/public/' } maven { url 'https://github.com/factions-site/repo/raw/public/' }
maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' } maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
maven { url 'https://mvn.lumine.io/repository/maven-public/' }
} }
jar { jar {
onlyIf { !sourceSets.main.allSource.files.isEmpty() } onlyIf { !sourceSets.main.allSource.files.isEmpty() }
} }
shadowJar {
relocate('com.willfp.libreforge', 'com.willfp.ecoarmor.libreforge')
}
dependencies { dependencies {
compileOnly 'com.willfp:eco:6.18.1' compileOnly 'com.willfp:eco:6.24.0'
implementation 'com.willfp:libreforge:3.15.0'
compileOnly 'org.jetbrains:annotations:19.0.0' compileOnly 'org.jetbrains:annotations:23.0.0'
compileOnly 'org.projectlombok:lombok:1.18.20' compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.6.0'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
} }
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
@@ -64,13 +75,24 @@ allprojects {
} }
processResources { processResources {
filesNotMatching(["**/*.png", "**/models/**", "**/textures/**"]) { filesNotMatching(["**/*.png", "**/models/**", "**/textures/**", "**lang.yml"]) {
expand projectVersion: project.version expand projectVersion: project.version
} }
} }
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
kotlinOptions {
jvmTarget = "17"
}
}
java.sourceCompatibility = JavaVersion.VERSION_17
java.targetCompatibility = JavaVersion.VERSION_17
compileJava.options.encoding = 'UTF-8' compileJava.options.encoding = 'UTF-8'
compileJava.dependsOn clean compileJava.dependsOn clean
build.dependsOn shadowJar
} }
tasks.withType(Jar) { tasks.withType(Jar) {
@@ -86,22 +108,14 @@ shadowJar {
} }
jar { jar {
archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + ".jar" archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + " " + "unshaded" + ".jar"
}
publishing {
publications {
maven(MavenPublication) {
from(components.java)
}
}
} }
group = 'com.willfp' group = 'com.willfp'
archivesBaseName = project.name archivesBaseName = project.name
version = findProperty("version") version = findProperty("version")
java.sourceCompatibility = JavaVersion.VERSION_17
compileJava.options.encoding = 'UTF-8' compileJava.options.encoding = 'UTF-8'
build.dependsOn shadowJar build.dependsOn shadowJar
build.dependsOn publishToMavenLocal

View File

@@ -3,8 +3,7 @@ version rootProject.version
dependencies { dependencies {
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT' compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'commons-io:commons-io:2.8.0'
compileOnly 'com.github.lokka30:LevelledMobs:3.1.4' compileOnly 'com.github.lokka30:LevelledMobs:3.1.4'
compileOnly 'io.lumine.xikage:MythicMobs:4.9.1' compileOnly 'io.lumine.xikage:MythicMobs:4.9.1'
compileOnly 'net.kyori:adventure-api:4.9.1' compileOnly 'net.kyori:adventure-api:4.9.3'
} }

View File

@@ -28,7 +28,6 @@ import com.willfp.ecobosses.bosses.util.obj.ExperienceOptions;
import com.willfp.ecobosses.bosses.util.obj.ImmunityOptions; import com.willfp.ecobosses.bosses.util.obj.ImmunityOptions;
import com.willfp.ecobosses.bosses.util.obj.OptionedSound; import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
import com.willfp.ecobosses.bosses.util.obj.SpawnTotem; import com.willfp.ecobosses.bosses.util.obj.SpawnTotem;
import com.willfp.ecobosses.bosses.util.obj.TargetMode;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -250,7 +249,7 @@ public class EcoBoss extends PluginDependent<EcoPlugin> {
/** /**
* The currently living bosses of this type. * The currently living bosses of this type.
*/ */
private final Map<LivingEntity, LivingEcoBoss> livingBosses; private final Map<LivingEntity, com.willfp.ecobosses.bosses.LivingEcoBoss> livingBosses;
/** /**
* The effect names and arguments. * The effect names and arguments.
@@ -743,7 +742,7 @@ public class EcoBoss extends PluginDependent<EcoPlugin> {
location.getChunk().load(); location.getChunk().load();
LivingEntity entity = (LivingEntity) bossType.spawn(location); LivingEntity entity = (LivingEntity) bossType.spawn(location);
this.livingBosses.put(entity, new LivingEcoBoss( this.livingBosses.put(entity, new com.willfp.ecobosses.bosses.LivingEcoBoss(
this.getPlugin(), this.getPlugin(),
entity, entity,
this this
@@ -753,12 +752,12 @@ public class EcoBoss extends PluginDependent<EcoPlugin> {
} }
/** /**
* Get {@link LivingEcoBoss} from an entity. * Get {@link com.willfp.ecobosses.bosses.LivingEcoBoss} from an entity.
* *
* @param entity The entity. * @param entity The entity.
* @return The living boss, or null if not a boss. * @return The living boss, or null if not a boss.
*/ */
public LivingEcoBoss getLivingBoss(@NotNull final LivingEntity entity) { public com.willfp.ecobosses.bosses.LivingEcoBoss getLivingBoss(@NotNull final LivingEntity entity) {
return this.livingBosses.get(entity); return this.livingBosses.get(entity);
} }
@@ -786,7 +785,7 @@ public class EcoBoss extends PluginDependent<EcoPlugin> {
return true; return true;
} }
if (!(o instanceof EcoBoss boss)) { if (!(o instanceof com.willfp.ecobosses.bosses.EcoBoss boss)) {
return false; return false;
} }

View File

@@ -23,7 +23,7 @@ public class EcoBosses {
/** /**
* Registered armor sets. * Registered armor sets.
*/ */
private static final BiMap<String, EcoBoss> BY_NAME = HashBiMap.create(); private static final BiMap<String, com.willfp.ecobosses.bosses.EcoBoss> BY_NAME = HashBiMap.create();
/** /**
* Sets that exist by default. * Sets that exist by default.
@@ -36,35 +36,35 @@ public class EcoBosses {
); );
/** /**
* Get all registered {@link EcoBoss}es. * Get all registered {@link com.willfp.ecobosses.bosses.EcoBoss}es.
* *
* @return A list of all {@link EcoBoss}es. * @return A list of all {@link com.willfp.ecobosses.bosses.EcoBoss}es.
*/ */
public static List<EcoBoss> values() { public static List<com.willfp.ecobosses.bosses.EcoBoss> values() {
return ImmutableList.copyOf(BY_NAME.values()); return ImmutableList.copyOf(BY_NAME.values());
} }
/** /**
* Get {@link EcoBoss} matching name. * Get {@link com.willfp.ecobosses.bosses.EcoBoss} matching name.
* *
* @param name The name to search for. * @param name The name to search for.
* @return The matching {@link EcoBoss}, or null if not found. * @return The matching {@link com.willfp.ecobosses.bosses.EcoBoss}, or null if not found.
*/ */
public static EcoBoss getByName(@NotNull final String name) { public static com.willfp.ecobosses.bosses.EcoBoss getByName(@NotNull final String name) {
return BY_NAME.get(name); return BY_NAME.get(name);
} }
/** /**
* Update all {@link EcoBoss}s. * Update all {@link com.willfp.ecobosses.bosses.EcoBoss}s.
*/ */
@ConfigUpdater @ConfigUpdater
public static void update() { public static void update() {
for (EcoBoss boss : values()) { for (com.willfp.ecobosses.bosses.EcoBoss boss : values()) {
removeBoss(boss); removeBoss(boss);
} }
for (String defaultSetName : DEFAULT_BOSSES) { for (String defaultSetName : DEFAULT_BOSSES) {
new EcoBoss(defaultSetName, new BaseBossConfig(defaultSetName), EcoBossesPlugin.getInstance()); new com.willfp.ecobosses.bosses.EcoBoss(defaultSetName, new BaseBossConfig(defaultSetName), EcoBossesPlugin.getInstance());
} }
try { try {
@@ -72,7 +72,7 @@ public class EcoBosses {
.filter(Files::isRegularFile) .filter(Files::isRegularFile)
.forEach(path -> { .forEach(path -> {
String name = path.getFileName().toString().replace(".yml", ""); String name = path.getFileName().toString().replace(".yml", "");
new EcoBoss( new com.willfp.ecobosses.bosses.EcoBoss(
name, name,
new CustomConfig(name, YamlConfiguration.loadConfiguration(path.toFile())), new CustomConfig(name, YamlConfiguration.loadConfiguration(path.toFile())),
EcoBossesPlugin.getInstance() EcoBossesPlugin.getInstance()
@@ -84,19 +84,19 @@ public class EcoBosses {
} }
/** /**
* Add new {@link EcoBoss} to EcoBosses. * Add new {@link com.willfp.ecobosses.bosses.EcoBoss} to EcoBosses.
* *
* @param set The {@link EcoBoss} to add. * @param set The {@link com.willfp.ecobosses.bosses.EcoBoss} to add.
*/ */
public static void addBoss(@NotNull final EcoBoss set) { public static void addBoss(@NotNull final com.willfp.ecobosses.bosses.EcoBoss set) {
BY_NAME.remove(set.getId()); BY_NAME.remove(set.getId());
BY_NAME.put(set.getId(), set); BY_NAME.put(set.getId(), set);
} }
/** /**
* Remove {@link EcoBoss} from EcoBosses. * Remove {@link com.willfp.ecobosses.bosses.EcoBoss} from EcoBosses.
* *
* @param set The {@link EcoBoss} to remove. * @param set The {@link com.willfp.ecobosses.bosses.EcoBoss} to remove.
*/ */
public static void removeBoss(@NotNull final EcoBoss set) { public static void removeBoss(@NotNull final EcoBoss set) {
BY_NAME.remove(set.getId()); BY_NAME.remove(set.getId());

View File

@@ -5,13 +5,13 @@ import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.scheduling.RunnableTask; import com.willfp.eco.core.scheduling.RunnableTask;
import com.willfp.eco.util.StringUtils; import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.effects.Effect; import com.willfp.ecobosses.bosses.effects.Effect;
import com.willfp.ecobosses.bosses.tick.BossTicker;
import com.willfp.ecobosses.bosses.tick.tickers.BossBarTicker; import com.willfp.ecobosses.bosses.tick.tickers.BossBarTicker;
import com.willfp.ecobosses.bosses.tick.tickers.DeathTimeTicker; import com.willfp.ecobosses.bosses.tick.tickers.DeathTimeTicker;
import com.willfp.ecobosses.bosses.tick.tickers.NamePlaceholderTicker; import com.willfp.ecobosses.bosses.tick.tickers.NamePlaceholderTicker;
import com.willfp.ecobosses.bosses.tick.tickers.TargetTicker; import com.willfp.ecobosses.bosses.tick.tickers.TargetTicker;
import com.willfp.ecobosses.bosses.util.obj.EquipmentPiece; import com.willfp.ecobosses.bosses.util.obj.EquipmentPiece;
import com.willfp.ecobosses.bosses.util.obj.OptionedSound; import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
import com.willfp.ecobosses.tick.BossTicker;
import lombok.Getter; import lombok.Getter;
import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -42,7 +42,7 @@ public class LivingEcoBoss extends PluginDependent<EcoPlugin> {
/** /**
* The boss. * The boss.
*/ */
private final EcoBoss boss; private final com.willfp.ecobosses.bosses.EcoBoss boss;
/** /**
* The boss tickers. * The boss tickers.

View File

@@ -1,7 +1,6 @@
package com.willfp.ecobosses.bosses.effects; package com.willfp.ecobosses.bosses.effects;
import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;

View File

@@ -23,10 +23,8 @@ import org.bukkit.event.entity.SlimeSplitEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
public class DeathListeners extends PluginDependent<EcoPlugin> implements Listener { public class DeathListeners extends PluginDependent<EcoPlugin> implements Listener {
/** /**

View File

@@ -1,32 +0,0 @@
package com.willfp.ecobosses.bosses.tick;
import com.willfp.ecobosses.bosses.EcoBoss;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface BossTicker {
/**
* Run on boss tick.
*
* @param boss The boss.
* @param entity The boss entity.
* @param tick The current tick: counts up from zero.
*/
void tick(@NotNull EcoBoss boss,
@NotNull LivingEntity entity,
long tick);
/**
* Run on boss death.
*
* @param boss The boss.
* @param entity The boss entity.
* @param tick The current tick: counts up from zero.
*/
default void onDeath(@NotNull EcoBoss boss,
@Nullable LivingEntity entity,
long tick) {
// Can be overridden when needed.
}
}

View File

@@ -3,7 +3,7 @@ package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.eco.util.PlayerUtils; import com.willfp.eco.util.PlayerUtils;
import com.willfp.eco.util.StringUtils; import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker; import com.willfp.ecobosses.tick.BossTicker;
import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;

View File

@@ -1,8 +1,8 @@
package com.willfp.ecobosses.bosses.tick.tickers; package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker;
import com.willfp.ecobosses.bosses.util.obj.OptionedSound; import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
import com.willfp.ecobosses.tick.BossTicker;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@@ -2,7 +2,7 @@ package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.eco.util.StringUtils; import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker; import com.willfp.ecobosses.tick.BossTicker;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@@ -1,8 +1,7 @@
package com.willfp.ecobosses.bosses.tick.tickers; package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker; import com.willfp.ecobosses.tick.BossTicker;
import com.willfp.ecobosses.bosses.util.obj.TargetMode;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob; import org.bukkit.entity.Mob;

View File

@@ -1,114 +0,0 @@
package com.willfp.ecobosses.bosses.util.obj;
import com.willfp.eco.util.NumberUtils;
import lombok.Getter;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
public class TargetMode {
/**
* All registered target modes.
*/
private static final Map<String, TargetMode> VALUES = new HashMap<>();
/**
* Random nearby player.
*/
public static final TargetMode RANDOM = new TargetMode("random", (list, entity) -> {
return list.get(NumberUtils.randInt(0, list.size() - 1));
});
/**
* Closest player.
*/
public static final TargetMode CLOSEST = new TargetMode("closest", (list, entity) -> {
Player player = null;
double nearestD2 = 10000;
for (Player nearbyPlayer : list) {
double d2 = nearbyPlayer.getLocation().distanceSquared(entity.getLocation());
if (d2 < nearestD2) {
player = nearbyPlayer;
}
}
return player;
});
/**
* Player with lowest health.
*/
public static final TargetMode LOWEST_HEALTH = new TargetMode("lowest-health", (list, entity) -> {
Player player = null;
double lowest = 100;
for (Player nearbyPlayer : list) {
double health = nearbyPlayer.getHealth();
if (health < lowest) {
player = nearbyPlayer;
}
}
return player;
});
/**
* Player with highest health.
*/
public static final TargetMode HIGHEST_HEALTH = new TargetMode("highest-health", (list, entity) -> {
Player player = null;
double highest = 0;
for (Player nearbyPlayer : list) {
double health = nearbyPlayer.getHealth();
if (health > highest) {
player = nearbyPlayer;
}
}
return player;
});
/**
* The name of the target mode.
*/
@Getter
private final String name;
/**
* The function to find a player out of a list.
*/
private final BiFunction<List<Player>, LivingEntity, Player> function;
protected TargetMode(@NotNull final String name,
@NotNull final BiFunction<List<Player>, LivingEntity, Player> function) {
this.name = name;
this.function = function;
VALUES.put(name, this);
}
/**
* Get target from list of players.
*
* @param list The list.
* @param entity The boss.
* @return The target.
*/
public Player getTarget(@NotNull final List<Player> list,
@NotNull final LivingEntity entity) {
return function.apply(list, entity);
}
/**
* Get target mode by name.
*
* @param name The name.
* @return The target mode, or null if not found.
*/
@Nullable
public static TargetMode getByName(@NotNull final String name) {
return VALUES.get(name);
}
}

View File

@@ -1,17 +0,0 @@
package com.willfp.ecobosses.config;
import com.willfp.eco.core.config.ConfigType;
import com.willfp.eco.core.config.ExtendableConfig;
import com.willfp.ecobosses.EcoBossesPlugin;
import org.jetbrains.annotations.NotNull;
public class BaseBossConfig extends ExtendableConfig {
/**
* Create new EcoBoss config.
*
* @param configName The name of the config.
*/
public BaseBossConfig(@NotNull final String configName) {
super(configName, true, EcoBossesPlugin.getInstance(), EcoBossesPlugin.class, "bosses/", ConfigType.YAML);
}
}

View File

@@ -1,26 +0,0 @@
package com.willfp.ecobosses.config;
import com.willfp.eco.core.config.TransientConfig;
import lombok.Getter;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
public class CustomConfig extends TransientConfig {
/**
* The name of the config.
*/
@Getter
private final String configName;
/**
* Create new custom config.
*
* @param configName The name of the config.
* @param config The config.
*/
public CustomConfig(@NotNull final String configName,
@NotNull final YamlConfiguration config) {
super(config);
this.configName = configName;
}
}

View File

@@ -1,24 +0,0 @@
package com.willfp.ecobosses.integrations.levelledmobs;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.util.BossUtils;
import me.lokka30.levelledmobs.events.MobPreLevelEvent;
import org.bukkit.entity.Boat;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Minecart;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
public class LevelledMobsListener implements Listener {
@EventHandler
public void onMobLevel(@NotNull final MobPreLevelEvent event) {
EcoBoss boss = BossUtils.getBoss(event.getEntity());
if (boss == null) {
return;
}
event.setCancelled(true);
}
}

View File

@@ -1,46 +0,0 @@
package com.willfp.ecobosses.util;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ShapedRecipe;
import org.jetbrains.annotations.NotNull;
public class DiscoverRecipeListener extends PluginDependent<EcoPlugin> implements Listener {
/**
* Register listener.
*
* @param plugin Talismans.
*/
public DiscoverRecipeListener(@NotNull final EcoPlugin plugin) {
super(plugin);
}
/**
* Unlock all recipes on player join.
*
* @param event The event to listen for.
*/
@EventHandler
public void onJoin(@NotNull final PlayerJoinEvent event) {
Player player = event.getPlayer();
if (this.getPlugin().getConfigYml().getBool("discover-recipes")) {
Bukkit.getServer().recipeIterator().forEachRemaining(recipe -> {
if (recipe instanceof ShapedRecipe) {
NamespacedKey key = ((ShapedRecipe) recipe).getKey();
if (key.getNamespace().equals("ecobosses")) {
if (!key.getKey().contains("displayed")) {
player.discoverRecipe(key);
}
}
}
});
}
}
}

View File

@@ -0,0 +1,45 @@
package com.willfp.ecobosses
import com.willfp.eco.core.command.impl.PluginCommand
import com.willfp.ecobosses.bosses.EcoBosses
import com.willfp.ecobosses.bosses.bossHolders
import com.willfp.ecobosses.commands.CommandEcobosses
import com.willfp.ecobosses.config.EcoBossesYml
import com.willfp.ecobosses.util.DiscoverRecipeListener
import com.willfp.libreforge.LibReforgePlugin
import org.bukkit.event.Listener
class EcoBossesPlugin : LibReforgePlugin(525, 10635, "&9") {
val ecoBossesYml: EcoBossesYml
init {
instance = this
ecoBossesYml = EcoBossesYml(this)
registerHolderProvider { it.bossHolders }
}
override fun handleReloadAdditional() {
logger.info(EcoBosses.values().size.toString() + " Bosses Loaded")
}
override fun loadPluginCommands(): List<PluginCommand> {
return listOf(
CommandEcobosses(this)
)
}
override fun loadListeners(): List<Listener> {
return listOf(
DiscoverRecipeListener(this)
)
}
override fun getMinimumEcoVersion(): String {
return "6.24.0"
}
companion object {
@JvmStatic
lateinit var instance: EcoBossesPlugin
}
}

View File

@@ -0,0 +1,8 @@
package com.willfp.ecobosses.bosses
enum class BossLifecycle {
SPAWN,
KILL,
DESPAWN
}

View File

@@ -0,0 +1,24 @@
package com.willfp.ecobosses.bosses
import com.willfp.libreforge.Holder
import org.bukkit.entity.Player
import kotlin.math.pow
val Player.bossHolders: Iterable<Holder>
get() {
val holders = mutableListOf<Holder>()
for (boss in Bosses.values()) {
for (entity in boss.getAllAlive()) {
if (entity.world != this.world) {
continue
}
if (entity.location.distanceSquared(this.location) <= boss.influenceRadius.pow(2)) {
holders.add(boss)
}
}
}
return holders
}

View File

@@ -0,0 +1,122 @@
package com.willfp.ecobosses.bosses
import com.google.common.collect.BiMap
import com.google.common.collect.HashBiMap
import com.google.common.collect.ImmutableList
import com.willfp.eco.core.config.updating.ConfigUpdater
import com.willfp.ecobosses.EcoBossesPlugin
import com.willfp.libreforge.chains.EffectChains
import org.bukkit.entity.LivingEntity
import java.util.UUID
object Bosses {
/**
* Registered bosses.
*/
private val BY_ID: BiMap<String, EcoBoss> = HashBiMap.create()
/**
* Get all registered [EcoBoss]s.
*
* @return A list of all [EcoBoss]s.
*/
@JvmStatic
fun values(): List<EcoBoss> {
return ImmutableList.copyOf(BY_ID.values)
}
/**
* Get [EcoBoss] matching ID.
*
* @param name The name to search for.
* @return The matching [EcoBoss], or null if not found.
*/
@JvmStatic
fun getByID(name: String): EcoBoss? {
return BY_ID[name]
}
/**
* Update all [EcoBoss]s.
*
* @param plugin Instance of EcoBosses.
*/
@ConfigUpdater
@JvmStatic
fun update(plugin: EcoBossesPlugin) {
plugin.ecoBossesYml.getSubsections("chains").mapNotNull {
EffectChains.compile(it, "Effect Chains")
}
for (boss in values()) {
removeBoss(boss)
}
for (bossConfig in plugin.ecoBossesYml.getSubsections("bosses")) {
EcoBoss(bossConfig, plugin)
}
}
/**
* Add new [EcoBoss] to EcoBosses.
*
* @param set The [EcoBoss] to add.
*/
@JvmStatic
fun addNewBoss(set: EcoBoss) {
BY_ID.remove(set.id)
BY_ID[set.id] = set
}
/**
* Remove [EcoBoss] from EcoBosses.
*
* @param set The [EcoBoss] to remove.
*/
@JvmStatic
fun removeBoss(set: EcoBoss) {
BY_ID.remove(set.id)
}
/**
* Get all currently alive [EcoBoss]es.
*
* @return All living bosses.
*/
@JvmStatic
fun getAllAlive(): Set<LivingEntity> {
val entities = mutableSetOf<LivingEntity>()
for (boss in values()) {
entities.addAll(boss.getAllAlive())
}
return entities
}
/**
* Get [LivingEcoBoss].
*
* @return The boss, or null if not a boss.
*/
operator fun get(uuid: UUID): LivingEcoBoss? {
for (boss in values()) {
val found = boss[uuid]
if (found != null) {
return found
}
}
return null
}
/**
* Get [LivingEcoBoss].
*
* @return The boss, or null if not a boss.
*/
operator fun get(entity: LivingEntity): LivingEcoBoss? {
return get(entity.uniqueId)
}
}

View File

@@ -0,0 +1,121 @@
package com.willfp.ecobosses.bosses
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.entities.Entities
import com.willfp.eco.core.entities.TestableEntity
import com.willfp.ecobosses.tick.BossTicker
import com.willfp.ecobosses.tick.DisplayNameTicker
import com.willfp.ecobosses.tick.LifespanTicker
import com.willfp.ecobosses.tick.TargetTicker
import com.willfp.ecobosses.util.ConfiguredSound
import com.willfp.ecobosses.util.PlayableSound
import com.willfp.libreforge.Holder
import com.willfp.libreforge.conditions.ConfiguredCondition
import com.willfp.libreforge.effects.ConfiguredEffect
import com.willfp.libreforge.effects.Effects
import org.bukkit.Location
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
import java.util.Objects
import java.util.UUID
class EcoBoss(
val config: Config,
private val plugin: EcoPlugin
) : Holder {
val id: String = config.getString("id")
val displayName: String = config.getString("displayName")
val lifespan = config.getInt("lifespan")
val influenceRadius = config.getDouble("influenceRadius")
val targetRange = config.getDouble("target.range")
val targetMode = TargetMode.getByID(config.getString("target.mode"))!!
private val sounds: Map<BossLifecycle, PlayableSound> = run {
val map = mutableMapOf<BossLifecycle, PlayableSound>()
for (value in BossLifecycle.values()) {
map[value] = PlayableSound(config.getSubsections("sounds.${value.name.lowercase()}").map {
ConfiguredSound.fromConfig(it)
})
}
map
}
private val mob: TestableEntity = Entities.lookup(config.getString("mob"))
private val currentlyAlive = mutableMapOf<UUID, LivingEcoBoss>()
override val conditions = emptySet<ConfiguredCondition>()
override val effects = config.getSubsections("effects").mapNotNull {
Effects.compile(it, "Boss ID $id")
}.toSet()
fun markDead(uuid: UUID) {
currentlyAlive.remove(uuid)
}
operator fun get(uuid: UUID): LivingEcoBoss? {
return currentlyAlive[uuid]
}
operator fun get(entity: LivingEntity): LivingEcoBoss? {
return currentlyAlive[entity.uniqueId]
}
fun getAllAlive(): Set<LivingEntity> {
return currentlyAlive.values.mapNotNull { it.entity }.toSet()
}
fun spawn(location: Location) {
val mob = mob.spawn(location) as LivingEntity
currentlyAlive[mob.uniqueId] = LivingEcoBoss(
plugin,
mob.uniqueId,
this,
createTickersFor(mob)
)
}
private fun createTickersFor(entity: LivingEntity): Set<BossTicker> {
return setOf(
LifespanTicker(),
DisplayNameTicker(),
TargetTicker()
)
}
fun handleLifecycle(player: Player, lifecycle: BossLifecycle) {
sounds[lifecycle]?.play(player)
}
override fun equals(other: Any?): Boolean {
if (other !is EcoBoss) {
return false
}
return id == other.id
}
override fun hashCode(): Int {
return Objects.hash(id)
}
override fun toString(): String {
return ("EcoBoss{"
+ id
+ "}")
}
}
class SimpleHolder(
override val conditions: Set<ConfiguredCondition>,
override val effects: Set<ConfiguredEffect>
) : Holder

View File

@@ -0,0 +1,55 @@
package com.willfp.ecobosses.bosses
import com.willfp.eco.core.EcoPlugin
import com.willfp.ecobosses.tick.BossTicker
import org.bukkit.Bukkit
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Mob
import java.util.UUID
class LivingEcoBoss(
plugin: EcoPlugin,
private val uuid: UUID,
val boss: EcoBoss,
val tickers: Set<BossTicker>
) {
init {
plugin.runnableFactory.create {
if (tick()) {
it.cancel()
}
}
}
val entity: Mob?
get() = Bukkit.getEntity(uuid) as? Mob
val deathTime = System.currentTimeMillis() + (boss.lifespan * 1000)
private var currentTick = 0
private fun tick(): Boolean {
if (entity == null || entity?.isDead == true) {
for (ticker in tickers) {
ticker.onDeath(this, currentTick)
}
boss.markDead(uuid)
return true
}
for (ticker in tickers) {
ticker.tick(this, currentTick)
}
currentTick++
return false
}
fun kill(reason: BossLifecycle) {
if (reason == BossLifecycle.SPAWN) {
throw IllegalArgumentException("Spawn is not a death lifecycle!")
}
entity?.remove()
boss.markDead(uuid)
}
}

View File

@@ -0,0 +1,60 @@
package com.willfp.ecobosses.bosses
import com.google.common.collect.BiMap
import com.google.common.collect.HashBiMap
import com.google.common.collect.ImmutableList
import org.bukkit.entity.Entity
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
class TargetMode(
val id: String,
private val function: (Collection<LivingEntity>, Entity) -> LivingEntity?
) {
init {
BY_ID[this.id] = this
}
fun getTarget(boss: LivingEcoBoss): LivingEntity? {
val entity = boss.entity ?: return null
return function(
entity.getNearbyEntities(
boss.boss.targetRange,
boss.boss.targetRange,
boss.boss.targetRange
).filterIsInstance<Player>(),
entity
)
}
companion object {
private val BY_ID: BiMap<String, TargetMode> = HashBiMap.create()
val RANDOM = TargetMode("random") { entities, _ ->
entities.random()
}
val CLOSEST = TargetMode("closest") { entities, boss ->
entities.minByOrNull { it.location.distanceSquared(boss.location) }
}
val LOWEST_HEALTH = TargetMode("lowest_health") { entities, _ ->
entities.minByOrNull { it.health }
}
val HIGHEST_HEALTH = TargetMode("highest_health") { entities, _ ->
entities.maxByOrNull { it.health }
}
@JvmStatic
fun values(): List<TargetMode> {
return ImmutableList.copyOf(BY_ID.values)
}
@JvmStatic
fun getByID(id: String): TargetMode? {
return BY_ID[id]
}
}
}

View File

@@ -0,0 +1,12 @@
package com.willfp.ecobosses.config
import com.willfp.eco.core.config.BaseConfig
import com.willfp.eco.core.config.ConfigType
import com.willfp.ecobosses.EcoBossesPlugin
class EcoBossesYml(plugin: EcoBossesPlugin) : BaseConfig(
"ecobosses",
plugin,
true,
ConfigType.YAML
)

View File

@@ -0,0 +1,20 @@
package com.willfp.ecobosses.integrations.levelledmobs
import com.willfp.eco.core.integrations.Integration
import com.willfp.ecobosses.bosses.Bosses
import me.lokka30.levelledmobs.events.MobPreLevelEvent
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
class IntegrationLevelledMobs : Listener, Integration {
@EventHandler
fun handle(event: MobPreLevelEvent) {
if (Bosses[event.entity] != null) {
event.isCancelled = true
}
}
override fun getPluginName(): String {
return "LevelledMobs"
}
}

View File

@@ -0,0 +1,19 @@
package com.willfp.ecobosses.tick
import com.willfp.ecobosses.bosses.LivingEcoBoss
interface BossTicker {
fun tick(
boss: LivingEcoBoss,
tick: Int
) {
// Can be overridden when needed.
}
fun onDeath(
boss: LivingEcoBoss,
tick: Int
) {
// Can be overridden when needed.
}
}

View File

@@ -0,0 +1,23 @@
package com.willfp.ecobosses.tick
import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.formatEco
import com.willfp.ecobosses.bosses.LivingEcoBoss
import kotlin.math.ceil
class DisplayNameTicker : BossTicker {
override fun tick(boss: LivingEcoBoss, tick: Int) {
val entity = boss.entity ?: return
val timeLeft = ceil(
(boss.deathTime - System.currentTimeMillis()) / 1000.0
).toInt()
val formattedTime = String.format("%d:%02d", timeLeft / 60, timeLeft % 60)
entity.customName = boss.boss.displayName
.replace("%health%", NumberUtils.format(entity.health))
.replace("%time%", formattedTime)
.formatEco()
}
}

View File

@@ -0,0 +1,14 @@
package com.willfp.ecobosses.tick
import com.willfp.ecobosses.bosses.BossLifecycle
import com.willfp.ecobosses.bosses.LivingEcoBoss
class LifespanTicker : BossTicker {
override fun tick(boss: LivingEcoBoss, tick: Int) {
val timeLeft = (boss.deathTime - System.currentTimeMillis()) / 1000.0
if (timeLeft <= 0) {
boss.kill(BossLifecycle.DESPAWN)
}
}
}

View File

@@ -0,0 +1,15 @@
package com.willfp.ecobosses.tick
import com.willfp.ecobosses.bosses.LivingEcoBoss
class TargetTicker : BossTicker {
override fun tick(boss: LivingEcoBoss, tick: Int) {
val entity = boss.entity ?: return
if (tick % 10 != 0) {
return
}
entity.target = boss.boss.targetMode.getTarget(boss) ?: return
}
}

View File

@@ -0,0 +1,24 @@
package com.willfp.ecobosses.util
import com.willfp.eco.core.EcoPlugin
import org.bukkit.Bukkit
import org.bukkit.Keyed
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.inventory.Recipe
class DiscoverRecipeListener(private val plugin: EcoPlugin) : Listener {
@EventHandler
fun onJoin(event: PlayerJoinEvent) {
if (!plugin.configYml.getBool("discover-recipes")) {
return
}
mutableListOf<Recipe>()
.apply { Bukkit.getServer().recipeIterator().forEachRemaining(this::add) }
.filterIsInstance<Keyed>().map { it.key }
.filter { it.namespace == plugin.name.lowercase() }
.filter { !it.key.contains("displayed") }
.forEach { event.player.discoverRecipe(it) }
}
}

View File

@@ -0,0 +1,35 @@
package com.willfp.ecobosses.util
import com.willfp.eco.core.config.interfaces.Config
import org.bukkit.Sound
import org.bukkit.entity.Player
data class ConfiguredSound(
private val sound: Sound,
private val pitch: Double,
private val volume: Double
) {
fun play(player: Player) {
player.playSound(player.location, sound, volume.toFloat(), pitch.toFloat())
}
companion object {
fun fromConfig(config: Config): ConfiguredSound {
return ConfiguredSound(
Sound.valueOf(config.getString("sound").uppercase()),
config.getDouble("pitch"),
config.getDouble("volume")
)
}
}
}
data class PlayableSound(
val sounds: Iterable<ConfiguredSound>
) {
fun play(player: Player) {
for (sound in sounds) {
sound.play(player)
}
}
}

View File

@@ -3,7 +3,32 @@
# by Auxilor # by Auxilor
# #
bossbar-radius: 50 # How far away players should be able to see the boss bar for bosses.
discover-recipes: true discover-recipes: true
# Read the wiki! https://plugins.auxilor.io/ecobosses/ cooldown:
in-actionbar: true
sound:
enabled: true
sound: "BLOCK_NOTE_BLOCK_PLING"
pitch: 0.5
cannot-afford:
in-actionbar: true
sound:
enabled: true
sound: "BLOCK_NOTE_BLOCK_PLING"
pitch: 0.5
cannot-afford-type:
in-actionbar: true
sound:
enabled: true
sound: "BLOCK_NOTE_BLOCK_PLING"
pitch: 0.5
point-names: # If you have point names that look ugly (eg g_souls) then you can map them to nice names to be shown to players.
example_point: "Nicely Formatted Point"
use-faster-move-trigger: true # Disable if you want move trigger to detect sub-1-block movements
raytrace-distance: 80 # The distance that alt_click should check for a location
block-item-drop-place-check: true # If the block_item_drop trigger should only fire on naturally placed blocks (prevents dupes)

View File

@@ -0,0 +1,25 @@
chains:
- id: example_chain
effects:
- id: teleport
- id: potion_effect
args:
effect: blindness
level: 3
duration: 30
apply_to_player: true
- id: send_message
args:
message: "&fYou have been teleported!"
action_bar: true
- id: play_sound
args:
sound: entity_dragon_fireball_explode
pitch: 1.5
volume: 4
bosses:
- id: steel_golem
mob: iron_golem
displayName: "&8Steel Golem &7| &c%health%♥ &7| &e%time%"
effects: [ ]

View File

@@ -15,5 +15,8 @@ messages:
invalid-stone: "&cInvalid boss!" invalid-stone: "&cInvalid boss!"
give-success: "Gave &a%boss%&r spawn egg to &a%recipient%" give-success: "Gave &a%boss%&r spawn egg to &a%recipient%"
requirements-not-met: "&cYou can't spawn this boss!" requirements-not-met: "&cYou can't spawn this boss!"
on-cooldown: "&cThis effect is on cooldown! &fTime left: &a%seconds% seconds"
cannot-afford: "&cYou can't afford to do this! &fCost: &a$$%cost%"
cannot-afford-type: "&cYou can't afford to do this! &fCost: &a%cost% %type%"
na: "N/A" na: "N/A"

View File

@@ -5,10 +5,15 @@ api-version: 1.16
authors: [Auxilor] authors: [Auxilor]
website: willfp.com website: willfp.com
load: STARTUP load: STARTUP
softdepend:
- LevelledMobs
depend: depend:
- eco - eco
softdepend:
- LevelledMobs
- EcoSkills
- AureliumSkills
- Jobs
- mcMMO
- Vault
commands: commands:
ecobosses: ecobosses:

View File

@@ -1,2 +1,2 @@
version = 7.0.1 version = 8.0.0
plugin-name = EcoBosses plugin-name = EcoBosses