9
0
mirror of https://github.com/Auxilor/EcoMobs.git synced 2025-12-19 23:19:17 +00:00

Compare commits

...

126 Commits
5.0.0 ... 6.8.0

Author SHA1 Message Date
Auxilor
041ec1c79e Updated to 6.8.0 2021-11-07 15:37:18 +00:00
Auxilor
f0b09c035e PR Codestyle 2021-11-07 15:37:07 +00:00
Will FP
4c6ac852aa Merge pull request #10
Implemented spawn events for all types of boss spawns (egg, totem, timer)
2021-11-07 15:36:00 +00:00
_OfTeN_
9772081d7b Implemented spawn events for all types of boss spawns (egg, totem, timer) 2021-11-07 14:06:20 +03:00
Will FP
cea2d96819 Update README.md 2021-10-12 20:12:46 +01:00
Auxilor
9dbba3f751 Fixed the fix 2021-10-01 19:05:08 +01:00
Auxilor
9cecb33b04 Updated to 6.7.1 2021-10-01 19:04:25 +01:00
Auxilor
7b60749b88 Fixed BarStyle 2021-10-01 19:04:15 +01:00
Auxilor
e0d03cc8ed Updated to 6.7.0 2021-10-01 18:22:35 +01:00
Auxilor
80109fc061 Added getMinimumEcoVersion 2021-10-01 18:21:53 +01:00
Auxilor
c1fc918757 Updated boss bar to use Adventure 2021-10-01 18:21:17 +01:00
Auxilor
955a378b98 Updated to 6.6.3 2021-09-26 13:57:37 +01:00
Auxilor
a1875933c8 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	gradle.properties
2021-09-26 13:57:30 +01:00
Auxilor
cf3c302513 Updated to 6.5.5 2021-09-26 13:57:21 +01:00
Will FP
2acdc4a74e Merge pull request #9
Fixed mythicmobs:mob_level not working in summon effect.
2021-09-26 13:57:06 +01:00
_OfTeN_
0e2cdb71cb Fixed mythicmobs:mob_level not working in summon effect. 2021-09-26 03:20:09 +03:00
Auxilor
f1c26763e0 Updated to 6.6.2 2021-09-21 08:44:47 +01:00
Auxilor
b75b83aebf Updated PR to use ChargedCreeperBossType 2021-09-21 08:44:37 +01:00
Will FP
ea2b14fbec Merge pull request #8
Charged creepers support
2021-09-21 08:42:07 +01:00
_OfTeN_
0747a0a3d4 Added ability to use "charged_creeper" as 'base-mob:' or in 'summon:' effect to spawn charged creepers 2021-09-20 22:00:01 +03:00
Auxilor
260aec8ba4 Updated to 6.6.1 2021-09-20 16:46:13 +01:00
Auxilor
77985e5a23 Improved mythicmobs pr 2021-09-20 16:46:07 +01:00
Will FP
201ec4161b Merge pull request #7
MythicMobs support
2021-09-20 16:43:40 +01:00
_OfTeN_
468b0b4292 Added 'baby: true/false' option for boss config to control the mob age. 2021-09-20 11:16:44 +03:00
_OfTeN_
203bec560e Updated how mythic mob fetcher works 2021-09-19 23:01:40 +03:00
_OfTeN_
a2c8b73dbc Added MythicMobs mobs support. Usage: 'base-mob: mythicmobs_<MythicMobName>_<level>' 2021-09-19 22:49:49 +03:00
Auxilor
31ccdf2589 Updated to 6.6.0 2021-09-19 13:33:32 +01:00
Auxilor
7ea1f8938b Added option to set boss gear (armor / weapon) 2021-09-19 13:33:23 +01:00
Auxilor
436e833213 Updated to 6.5.5 2021-09-19 11:31:03 +01:00
Auxilor
60b4c1c246 Updated to eco 6.8.1 polymart resource checker 2021-09-19 11:30:51 +01:00
Auxilor
c5f5032e17 Updated README.md 2021-09-19 11:30:25 +01:00
Auxilor
310ace62b3 Updated to eco 6.8.0 2021-09-17 20:07:49 +01:00
Auxilor
0af79cfc27 Updated to 6.5.4 2021-09-17 20:06:12 +01:00
Will FP
a107d78937 Merge pull request #6
Added glowing: true/false option for boss config
2021-09-17 20:05:44 +01:00
_OfTeN_
d8c229d4fa Added glowing: true/false option for boss config 2021-09-17 21:17:27 +03:00
Auxilor
406601a193 Merge remote-tracking branch 'origin/master' 2021-09-16 18:13:24 +01:00
Auxilor
fb9fdacb9f Updated to 6.5.3 2021-09-16 18:13:19 +01:00
Will FP
45bbc668dc Merge pull request #5
Added %ecobosses_timeunlilspawn_<boss>% placeholder
2021-09-16 18:13:07 +01:00
_OfTeN_
b5f222976b Added %ecobosses_timeunlilspawn_<boss>% placeholder 2021-09-14 15:34:15 +03:00
Auxilor
10d297e0da Updated to 6.5.2 2021-09-12 18:57:37 +01:00
Auxilor
76df0fd2ef Fixed spawn egg bug 2021-09-12 18:57:31 +01:00
Auxilor
56b76f70c6 Updated to 6.5.1 2021-09-12 16:57:22 +01:00
Auxilor
30e0ed02a4 Improved drops for multiple identical items 2021-09-12 16:57:14 +01:00
Auxilor
2795fa8220 Updated to 6.5.0 2021-09-12 16:31:50 +01:00
Auxilor
cbeff28dbf Added spawn requirements 2021-09-12 16:31:03 +01:00
Auxilor
38dd7ea604 Updated to 6.4.0 2021-09-02 10:24:48 +01:00
Auxilor
af72bfbbb6 Legacy base64 system has been removed in favour of the eco items system 2021-09-02 10:24:30 +01:00
Auxilor
de675b49be Updated to 6.3.4 2021-08-28 18:04:40 +01:00
Auxilor
3df4cfaae7 Added LevelledMobs integration 2021-08-28 18:04:30 +01:00
Auxilor
32ac455720 Merge remote-tracking branch 'origin/master' 2021-08-28 15:53:25 +01:00
Auxilor
89a7d37d37 Updated to 6.3.3 2021-08-28 15:53:19 +01:00
Auxilor
04eff9d3f3 Fixed 2 effects with same name not being registered 2021-08-28 15:53:10 +01:00
Will FP
c3c96a6892 Update README.md 2021-08-21 01:23:06 +01:00
Auxilor
d135922dc1 Updated to 6.3.2 2021-08-15 16:25:31 +01:00
Auxilor
1569d12b44 Added lava immunity to fire imunity 2021-08-15 16:25:17 +01:00
Auxilor
aea6e5c2f1 Updated to 6.3.1 2021-08-14 13:37:12 +01:00
Auxilor
d837311ae2 Added discover-recipes 2021-08-14 13:37:05 +01:00
Auxilor
c66b914104 Fixed spawn egg 2021-08-14 13:28:04 +01:00
Auxilor
1f73b9acf7 Fixed lang.yml 2021-08-14 13:24:33 +01:00
Auxilor
cafb41567f Added /ecobosses give 2021-08-14 13:19:28 +01:00
Auxilor
8f912abf31 Updated to 6.3.0 2021-08-14 13:13:32 +01:00
Auxilor
2fe8c9197d Added spawn eggs 2021-08-14 13:13:24 +01:00
Auxilor
46eccfc345 Updated to 6.2.0 2021-08-13 15:38:24 +01:00
Auxilor
7804cebd53 Removed NMS, replaced illusioner with Dark Guardian 2021-08-13 15:38:12 +01:00
Auxilor
1918a46678 Added despawn sounds and messages 2021-08-13 14:33:58 +01:00
Auxilor
99de824b04 Added death time ticker 2021-08-13 14:12:47 +01:00
Auxilor
b18eb3942a Updated to 6.1.0 2021-08-13 14:02:32 +01:00
Auxilor
7434bbb38e Updated to 6.0.4 2021-08-11 20:42:09 +01:00
Auxilor
7bf88ed09a Updated to 6.0.3 2021-08-09 17:45:44 +01:00
Auxilor
d8f54cb9f6 Prevented slime bosses from splitting 2021-08-09 17:45:35 +01:00
Auxilor
3bc5ed6f6a Fixed 1.17 illusioner 2021-08-09 17:43:42 +01:00
Auxilor
ab759afe56 Updated to 6.0.2 2021-08-07 13:59:37 +01:00
Auxilor
3ae961c9c5 Fixed bosses picking up items 2021-08-07 13:59:29 +01:00
Auxilor
b6754c6d5c Updated to 6.0.1 2021-07-27 16:22:40 +01:00
Auxilor
846b03d8bc Removed null traces 2021-07-27 16:22:32 +01:00
Auxilor
746ab5d2b5 jitpack.yml 2021-07-21 19:09:49 +01:00
Auxilor
3f6f13a61f Updated to eco 6 2021-07-21 18:49:15 +01:00
Auxilor
fd82811d2c Updated to eco 6 2021-07-21 18:29:15 +01:00
Auxilor
950bfab5f3 Updated to eco 6 2021-07-21 18:28:42 +01:00
Auxilor
3e4d3af215 Updated to eco 6 2021-07-21 18:28:17 +01:00
Auxilor
9486903895 Updated to 5.3.0 2021-07-20 15:27:57 +01:00
Auxilor
da7ee14787 Removed legacy code 2021-07-20 15:25:49 +01:00
Auxilor
36fa2e5138 Removed UUID tracking 2021-07-20 15:22:53 +01:00
Auxilor
31e3cb993e Removed 10tick delay on timer 2021-07-20 14:43:01 +01:00
Auxilor
c7ea383115 Updated to 5.2.1 2021-07-15 23:31:12 +02:00
Auxilor
1d800a52de Fixed /ecobosses only being able to be ran as a player 2021-07-15 23:31:04 +02:00
Auxilor
1a78db6b07 Fixed permissions 2021-07-12 14:00:57 +02:00
Auxilor
9ab765edb6 Fixed type paramets 2021-07-12 13:57:34 +02:00
Auxilor
c8054c209a Updated to new eco command system and 5.2.0 2021-07-12 13:57:07 +02:00
Auxilor
8db8cca1c9 Updated to 5.1.4 2021-07-09 22:38:32 +02:00
Auxilor
413d86c2d3 Updated to eco 5.7.1x 2021-07-09 22:38:24 +02:00
Auxilor
a335b5b52e Fixed %player% bug 2021-07-09 22:37:28 +02:00
Auxilor
d5dced49b3 Updated to 5.1.3 2021-06-30 19:43:05 +01:00
Auxilor
4ac870f5c3 Chunks with bosses in them should not unload 2021-06-30 19:42:31 +01:00
Auxilor
1a364615a3 Updated to 5.1.2 2021-06-29 18:29:18 +01:00
Auxilor
890b034d4a Bosses should now load the chunk they're in on autospawn 2021-06-29 18:29:08 +01:00
Auxilor
22f59c7c5c Fixed record migration 2021-06-24 08:58:24 +01:00
Auxilor
8bc296f2f8 Updated to 5.1.1 2021-06-24 08:57:19 +01:00
Auxilor
5fe7eb1318 Java 16 migration, more null checks, record conversion 2021-06-24 08:57:11 +01:00
Auxilor
36a3c7f70d Updated to 5.1.0 2021-06-11 12:29:46 +01:00
Auxilor
6b3ff0c88d Updated to 1.17 and Java 16 2021-06-11 12:29:35 +01:00
Auxilor
3e384dbeea Updated to 5.0.7 2021-06-10 11:05:18 +01:00
Auxilor
b16444799a Updated to 5.0.8 2021-06-10 11:04:41 +01:00
Auxilor
98faf823ba Fixed 2 NPE errors 2021-06-10 11:04:28 +01:00
Auxilor
87095166d0 Updated to 5.0.7 2021-05-20 11:40:40 +01:00
Auxilor
b4510233aa Fixed potential NPE 2021-05-20 11:40:08 +01:00
Auxilor
a31b0210ab Updated to use UUID's on backend and update entity object on tick 2021-05-20 11:39:35 +01:00
Auxilor
3a480da078 Updated to 5.0.6 2021-05-20 09:02:15 +01:00
Auxilor
efc56e1763 Fixed several bugs 2021-05-20 09:02:06 +01:00
Auxilor
64f35b6338 Updated to 5.0.5 2021-05-19 11:31:48 +01:00
Auxilor
ab6e990f0b More fixes 2021-05-19 11:31:03 +01:00
Auxilor
fa8c5da31a Fixed 2 effects of the same type not working 2021-05-19 11:30:03 +01:00
Auxilor
730c259d19 Moved autospawn checks to by world 2021-05-02 10:29:04 +01:00
Auxilor
7fbc39d4d1 Updated to 5.0.4 2021-05-02 10:24:46 +01:00
Auxilor
5d69d0faee Added check for living bosses 2021-05-02 10:24:33 +01:00
Auxilor
21ed4b09fd Added extra check to boss bars 2021-04-24 17:55:57 +01:00
Auxilor
9eb3619c35 Fixed lingering boss bars 2021-04-24 17:54:40 +01:00
Auxilor
9abbfbf363 Updated to 5.0.3 2021-04-24 17:49:46 +01:00
Auxilor
12abdcbf5e Fixed Autospawn 2021-04-24 17:49:35 +01:00
Auxilor
11d8d8d13f Updated to 5.0.2 2021-04-18 21:06:43 +01:00
Auxilor
0932e68461 Merge remote-tracking branch 'origin/master' 2021-04-18 21:06:31 +01:00
Auxilor
6975daaeaf Fixed potential issues in boss ticking 2021-04-18 21:06:19 +01:00
Auxilor
663104bda0 Cleaned up /killall leaving lingering boss bars 2021-04-18 21:05:51 +01:00
Auxilor
83805215e9 Updated to 5.0.1 2021-04-17 15:12:24 +01:00
Auxilor
0b1f4d4f6d Removed unused 1.15 code 2021-04-17 15:12:09 +01:00
Auxilor
86e414e108 Updated to eco 5.2.0 2021-04-17 15:11:53 +01:00
84 changed files with 2079 additions and 1367 deletions

View File

@@ -1,14 +1,14 @@
<h1 align="center">
<br>
<img src="https://i.imgur.com/I74yjwu.png" alt="EcoBosses logo" width="256">
<img src="https://i.imgur.com/A2qieC3.png" alt="EcoBosses logo" width="256">
<br>
</h1>
<h4 align="center">Source code for EcoBosses, a premium spigot plugin.</h4>
<p align="center">
<a href="https://www.spigotmc.org/resources/ecobosses.79573/">
<img alt="spigot" src="https://img.shields.io/badge/spigot-ecobosses-blue?style=for-the-badge"/>
<a href="https://polymart.org/resource/1-16-1-17-ecobosses.525">
<img alt="spigot" src="https://img.shields.io/badge/polymart-ecobosses-blue?style=for-the-badge"/>
</a>
<a href="https://bstats.org/plugin/bukkit/EcoBosses" alt="bstats servers">
<img src="https://img.shields.io/bstats/servers/10635?color=blue&style=for-the-badge"/>
@@ -29,3 +29,14 @@
## License
*Click here to read [the entire license](https://github.com/Auxilor/EcoBosses/blob/master/LICENSE.md).*
<h1 align="center">
<br>
<a href="http://gamersupps.gg/discount/Auxilor?afmc=Auxilor" target="_blank">
<img src="https://i.imgur.com/uFDpBAC.png" alt="supps banner">
</a>
<a href="https://dedimc.promo/Auxilor" target="_blank">
<img src="https://i.imgur.com/zdDLhFA.png" alt="dedimc banner">
</a>
<br>
</h1>

View File

@@ -1,12 +1,12 @@
plugins {
id 'java-library'
id 'com.github.johnrengelman.shadow' version '5.2.0'
id 'com.github.johnrengelman.shadow' version '7.0.0'
id 'maven-publish'
id 'java'
}
dependencies {
implementation project(":eco-core").getSubprojects()
implementation project(":eco-core:core-plugin")
}
allprojects {
@@ -16,7 +16,6 @@ allprojects {
repositories {
mavenCentral()
jcenter()
mavenLocal()
maven { url 'https://jitpack.io' }
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
@@ -40,6 +39,7 @@ allprojects {
maven { url 'https://maven.sk89q.com/repo/' }
maven { url 'https://github.com/factions-site/repo/raw/public/' }
maven { url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
maven { url 'https://mvn.lumine.io/repository/maven-public/' }
}
jar {
@@ -47,15 +47,15 @@ allprojects {
}
dependencies {
compileOnly 'com.willfp:eco:5.0.0'
compileOnly 'com.willfp:eco:6.9.0'
compileOnly 'org.jetbrains:annotations:19.0.0'
compileOnly 'org.projectlombok:lombok:1.18.16'
annotationProcessor 'org.projectlombok:lombok:1.18.16'
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.16'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.16'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
}
tasks.withType(JavaCompile) {
@@ -86,22 +86,22 @@ shadowJar {
}
jar {
archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + " " + "unshaded" + ".jar"
archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + ".jar"
}
group = 'com.willfp'
archivesBaseName = project.name
version = findProperty("version")
java.sourceCompatibility = JavaVersion.VERSION_1_8
compileJava.options.encoding = 'UTF-8'
build.dependsOn shadowJar
publishing {
publications {
maven(MavenPublication) {
from(components.java)
}
}
}
}
group = 'com.willfp'
archivesBaseName = project.name
version = findProperty("version")
java.sourceCompatibility = JavaVersion.VERSION_16
compileJava.options.encoding = 'UTF-8'
build.dependsOn shadowJar

View File

@@ -1,9 +0,0 @@
group 'com.willfp'
version rootProject.version
subprojects {
dependencies {
compileOnly project(':eco-core:core-proxy')
compileOnly project(':eco-core:core-plugin')
}
}

View File

@@ -1,6 +0,0 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.16.1-R0.1-SNAPSHOT'
}

View File

@@ -1,22 +0,0 @@
package com.willfp.ecobosses.proxy.v1_16_R1;
import com.willfp.ecobosses.proxy.proxies.CustomEntitySpawnerProxy;
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
import com.willfp.ecobosses.proxy.util.CustomEntity;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("unchecked")
public class CustomEntitySpawner implements CustomEntitySpawnerProxy {
@Override
public <T extends LivingEntity> @Nullable T spawnCustomEntity(final Class<? extends CustomEntity<? extends LivingEntity>> entityClass,
@NotNull final Location location) {
if (entityClass.equals(CustomIllusionerProxy.class)) {
return (T) CustomIllusioner.spawn(location);
}
return null;
}
}

View File

@@ -1,62 +0,0 @@
package com.willfp.ecobosses.proxy.v1_16_R1;
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
import net.minecraft.server.v1_16_R1.EntityHuman;
import net.minecraft.server.v1_16_R1.EntityIllagerIllusioner;
import net.minecraft.server.v1_16_R1.EntityIllagerWizard;
import net.minecraft.server.v1_16_R1.EntityInsentient;
import net.minecraft.server.v1_16_R1.EntityIronGolem;
import net.minecraft.server.v1_16_R1.EntityRaider;
import net.minecraft.server.v1_16_R1.EntityTypes;
import net.minecraft.server.v1_16_R1.EntityVillagerAbstract;
import net.minecraft.server.v1_16_R1.PathfinderGoalBowShoot;
import net.minecraft.server.v1_16_R1.PathfinderGoalFloat;
import net.minecraft.server.v1_16_R1.PathfinderGoalHurtByTarget;
import net.minecraft.server.v1_16_R1.PathfinderGoalLookAtPlayer;
import net.minecraft.server.v1_16_R1.PathfinderGoalMeleeAttack;
import net.minecraft.server.v1_16_R1.PathfinderGoalNearestAttackableTarget;
import net.minecraft.server.v1_16_R1.PathfinderGoalRandomStroll;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_16_R1.CraftWorld;
import org.bukkit.entity.Illusioner;
import org.jetbrains.annotations.NotNull;
public class CustomIllusioner extends EntityIllagerIllusioner implements CustomIllusionerProxy {
/**
* Instantiate a new custom illusioner entity.
*
* @param location The location to spawn it at.
*/
public CustomIllusioner(@NotNull final Location location) {
super(EntityTypes.ILLUSIONER, ((CraftWorld) location.getWorld()).getHandle());
this.setPosition(location.getX(), location.getY(), location.getZ());
this.goalSelector.a(0, new PathfinderGoalFloat(this));
this.goalSelector.a(1, new EntityIllagerWizard.b());
this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false));
this.goalSelector.a(2, new PathfinderGoalBowShoot<>(this, 1.0D, 20, 15.0F));
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(0, new PathfinderGoalFloat(this));
this.goalSelector.a(6, new PathfinderGoalBowShoot<>(this, 0.5D, 20, 15.0F));
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0]));
this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, false)).a(300));
}
/**
* Spawn illusioner.
*
* @param location The location.
* @return The illusioner.
*/
public static Illusioner spawn(@NotNull final Location location) {
CustomIllusioner illusioner = new CustomIllusioner(location);
((CraftWorld) location.getWorld()).getHandle().addEntity(illusioner);
return (Illusioner) illusioner.getBukkitEntity();
}
}

View File

@@ -1,6 +0,0 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.16.3-R0.1-SNAPSHOT'
}

View File

@@ -1,22 +0,0 @@
package com.willfp.ecobosses.proxy.v1_16_R2;
import com.willfp.ecobosses.proxy.proxies.CustomEntitySpawnerProxy;
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
import com.willfp.ecobosses.proxy.util.CustomEntity;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("unchecked")
public class CustomEntitySpawner implements CustomEntitySpawnerProxy {
@Override
public <T extends LivingEntity> @Nullable T spawnCustomEntity(final Class<? extends CustomEntity<? extends LivingEntity>> entityClass,
@NotNull final Location location) {
if (entityClass.equals(CustomIllusionerProxy.class)) {
return (T) CustomIllusioner.spawn(location);
}
return null;
}
}

View File

@@ -1,62 +0,0 @@
package com.willfp.ecobosses.proxy.v1_16_R2;
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
import net.minecraft.server.v1_16_R2.EntityHuman;
import net.minecraft.server.v1_16_R2.EntityIllagerIllusioner;
import net.minecraft.server.v1_16_R2.EntityIllagerWizard;
import net.minecraft.server.v1_16_R2.EntityInsentient;
import net.minecraft.server.v1_16_R2.EntityIronGolem;
import net.minecraft.server.v1_16_R2.EntityRaider;
import net.minecraft.server.v1_16_R2.EntityTypes;
import net.minecraft.server.v1_16_R2.EntityVillagerAbstract;
import net.minecraft.server.v1_16_R2.PathfinderGoalBowShoot;
import net.minecraft.server.v1_16_R2.PathfinderGoalFloat;
import net.minecraft.server.v1_16_R2.PathfinderGoalHurtByTarget;
import net.minecraft.server.v1_16_R2.PathfinderGoalLookAtPlayer;
import net.minecraft.server.v1_16_R2.PathfinderGoalMeleeAttack;
import net.minecraft.server.v1_16_R2.PathfinderGoalNearestAttackableTarget;
import net.minecraft.server.v1_16_R2.PathfinderGoalRandomStroll;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_16_R2.CraftWorld;
import org.bukkit.entity.Illusioner;
import org.jetbrains.annotations.NotNull;
public class CustomIllusioner extends EntityIllagerIllusioner implements CustomIllusionerProxy {
/**
* Instantiate a new custom illusioner entity.
*
* @param location The location to spawn it at.
*/
public CustomIllusioner(@NotNull final Location location) {
super(EntityTypes.ILLUSIONER, ((CraftWorld) location.getWorld()).getHandle());
this.setPosition(location.getX(), location.getY(), location.getZ());
this.goalSelector.a(0, new PathfinderGoalFloat(this));
this.goalSelector.a(1, new EntityIllagerWizard.b());
this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false));
this.goalSelector.a(2, new PathfinderGoalBowShoot<>(this, 1.0D, 20, 15.0F));
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(0, new PathfinderGoalFloat(this));
this.goalSelector.a(6, new PathfinderGoalBowShoot<>(this, 0.5D, 20, 15.0F));
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0]));
this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, false)).a(300));
}
/**
* Spawn illusioner.
*
* @param location The location.
* @return The illusioner.
*/
public static Illusioner spawn(@NotNull final Location location) {
CustomIllusioner illusioner = new CustomIllusioner(location);
((CraftWorld) location.getWorld()).getHandle().addEntity(illusioner);
return (Illusioner) illusioner.getBukkitEntity();
}
}

View File

@@ -1,6 +0,0 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT'
}

View File

@@ -1,22 +0,0 @@
package com.willfp.ecobosses.proxy.v1_16_R3;
import com.willfp.ecobosses.proxy.proxies.CustomEntitySpawnerProxy;
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
import com.willfp.ecobosses.proxy.util.CustomEntity;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("unchecked")
public class CustomEntitySpawner implements CustomEntitySpawnerProxy {
@Override
public <T extends LivingEntity> @Nullable T spawnCustomEntity(final Class<? extends CustomEntity<? extends LivingEntity>> entityClass,
@NotNull final Location location) {
if (entityClass.equals(CustomIllusionerProxy.class)) {
return (T) CustomIllusioner.spawn(location);
}
return null;
}
}

View File

@@ -1,62 +0,0 @@
package com.willfp.ecobosses.proxy.v1_16_R3;
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
import net.minecraft.server.v1_16_R3.EntityHuman;
import net.minecraft.server.v1_16_R3.EntityIllagerIllusioner;
import net.minecraft.server.v1_16_R3.EntityIllagerWizard;
import net.minecraft.server.v1_16_R3.EntityInsentient;
import net.minecraft.server.v1_16_R3.EntityIronGolem;
import net.minecraft.server.v1_16_R3.EntityRaider;
import net.minecraft.server.v1_16_R3.EntityTypes;
import net.minecraft.server.v1_16_R3.EntityVillagerAbstract;
import net.minecraft.server.v1_16_R3.PathfinderGoalBowShoot;
import net.minecraft.server.v1_16_R3.PathfinderGoalFloat;
import net.minecraft.server.v1_16_R3.PathfinderGoalHurtByTarget;
import net.minecraft.server.v1_16_R3.PathfinderGoalLookAtPlayer;
import net.minecraft.server.v1_16_R3.PathfinderGoalMeleeAttack;
import net.minecraft.server.v1_16_R3.PathfinderGoalNearestAttackableTarget;
import net.minecraft.server.v1_16_R3.PathfinderGoalRandomStroll;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
import org.bukkit.entity.Illusioner;
import org.jetbrains.annotations.NotNull;
public class CustomIllusioner extends EntityIllagerIllusioner implements CustomIllusionerProxy {
/**
* Instantiate a new custom illusioner entity.
*
* @param location The location to spawn it at.
*/
public CustomIllusioner(@NotNull final Location location) {
super(EntityTypes.ILLUSIONER, ((CraftWorld) location.getWorld()).getHandle());
this.setPosition(location.getX(), location.getY(), location.getZ());
this.goalSelector.a(0, new PathfinderGoalFloat(this));
this.goalSelector.a(1, new EntityIllagerWizard.b());
this.goalSelector.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false));
this.goalSelector.a(2, new PathfinderGoalBowShoot<>(this, 1.0D, 20, 15.0F));
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(0, new PathfinderGoalFloat(this));
this.goalSelector.a(6, new PathfinderGoalBowShoot<>(this, 0.5D, 20, 15.0F));
this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F));
this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0]));
this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300));
this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, false)).a(300));
}
/**
* Spawn illusioner.
*
* @param location The location.
* @return The illusioner.
*/
public static Illusioner spawn(@NotNull final Location location) {
CustomIllusioner illusioner = new CustomIllusioner(location);
((CraftWorld) location.getWorld()).getHandle().addEntity(illusioner);
return (Illusioner) illusioner.getBukkitEntity();
}
}

View File

@@ -2,8 +2,9 @@ group 'com.willfp'
version rootProject.version
dependencies {
compileOnly project(":eco-core:core-proxy")
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'commons-io:commons-io:2.8.0'
compileOnly 'com.destroystokyo.paper:paper-api:1.16.3-R0.1-SNAPSHOT'
compileOnly 'com.github.lokka30:LevelledMobs:3.1.4'
compileOnly 'io.lumine.xikage:MythicMobs:4.9.1'
compileOnly 'net.kyori:adventure-api:4.9.1'
}

View File

@@ -1,26 +1,22 @@
package com.willfp.ecobosses;
import com.willfp.eco.core.AbstractPacketAdapter;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.command.AbstractCommand;
import com.willfp.eco.core.command.impl.PluginCommand;
import com.willfp.eco.core.integrations.IntegrationLoader;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import com.willfp.ecobosses.bosses.listeners.*;
import com.willfp.ecobosses.commands.CommandEbdrop;
import com.willfp.ecobosses.commands.CommandEbkillall;
import com.willfp.ecobosses.commands.CommandEbreload;
import com.willfp.ecobosses.commands.CommandEbspawn;
import com.willfp.ecobosses.commands.TabCompleterEbspawn;
import com.willfp.ecobosses.bosses.listeners.AttackListeners;
import com.willfp.ecobosses.bosses.listeners.AutoSpawnTimer;
import com.willfp.ecobosses.bosses.listeners.DeathListeners;
import com.willfp.ecobosses.bosses.listeners.PassiveListeners;
import com.willfp.ecobosses.bosses.listeners.SpawnListeners;
import com.willfp.ecobosses.bosses.util.BossUtils;
import com.willfp.ecobosses.commands.CommandEcobosses;
import com.willfp.ecobosses.integrations.levelledmobs.LevelledMobsListener;
import com.willfp.ecobosses.util.DiscoverRecipeListener;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Listener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
@SuppressWarnings("unused")
public class EcoBossesPlugin extends EcoPlugin {
@@ -34,122 +30,47 @@ public class EcoBossesPlugin extends EcoPlugin {
* Internal constructor called by bukkit on plugin load.
*/
public EcoBossesPlugin() {
super("EcoBosses", 86576, 10635, "com.willfp.ecobosses.proxy", "&9");
super(525, 10635, "com.willfp.ecobosses.proxy", "&9");
instance = this;
}
/**
* Code executed on plugin enable.
*/
@Override
public void enable() {
this.getExtensionLoader().loadExtensions();
public String getMinimumEcoVersion() {
return "6.9.0";
}
if (this.getExtensionLoader().getLoadedExtensions().isEmpty()) {
this.getLogger().info("&cNo extensions found");
} else {
this.getLogger().info("Extensions Loaded:");
this.getExtensionLoader().getLoadedExtensions().forEach(extension -> this.getLogger().info("- " + extension.getName() + " v" + extension.getVersion()));
}
@Override
protected void handleDisable() {
BossUtils.killAllBosses();
}
@Override
protected void handleReload() {
this.getScheduler().runTimer(new AutoSpawnTimer(), 5, 1);
}
/**
* Code executed on plugin disable.
*/
@Override
public void disable() {
this.getExtensionLoader().unloadExtensions();
for (EcoBoss boss : EcoBosses.values()) {
for (UUID uuid : boss.getLivingBosses().keySet()) {
LivingEntity entity = (LivingEntity) Bukkit.getEntity(uuid);
assert entity != null;
entity.damage(10000000);
}
}
}
/**
* Nothing is called on plugin load.
*/
@Override
public void load() {
// Nothing needs to be called on load
}
/**
* Code executed on reload.
*/
@Override
public void onReload() {
}
/**
* Code executed after server is up.
*/
@Override
public void postLoad() {
// Nothing is executed post-load.
}
/**
* EcoEnchants-specific integrations.
*
* @return A list of all integrations.
*/
@Override
public List<IntegrationLoader> getIntegrationLoaders() {
return new ArrayList<>();
}
/**
* EcoEnchants-specific commands.
*
* @return A list of all commands.
*/
@Override
public List<AbstractCommand> getCommands() {
return Arrays.asList(
new CommandEbreload(this),
new CommandEbdrop(this),
new CommandEbspawn(this),
new CommandEbkillall(this)
protected List<PluginCommand> loadPluginCommands() {
return List.of(
new CommandEcobosses(this)
);
}
/**
* Packet Adapters for enchant display.
*
* @return A list of packet adapters.
*/
@Override
public List<AbstractPacketAdapter> getPacketAdapters() {
return new ArrayList<>();
protected List<IntegrationLoader> loadIntegrationLoaders() {
return Arrays.asList(
new IntegrationLoader("LevelledMobs", () -> this.getEventManager().registerListener(new LevelledMobsListener()))
);
}
/**
* EcoEnchants-specific listeners.
*
* @return A list of all listeners.
*/
@Override
public List<Listener> getListeners() {
protected List<Listener> loadListeners() {
return Arrays.asList(
new AttackListeners(this),
new DeathListeners(this),
new SpawnListeners(this),
new DiscoverRecipeListener(this),
new PassiveListeners(this)
);
}
@Override
public List<Class<?>> getUpdatableClasses() {
return Arrays.asList(
EcoBosses.class,
TabCompleterEbspawn.class
);
}
}

View File

@@ -3,30 +3,61 @@ package com.willfp.ecobosses.bosses;
import com.google.common.collect.ImmutableMap;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.config.Config;
import com.willfp.eco.core.config.interfaces.Config;
import com.willfp.eco.core.integrations.placeholder.PlaceholderEntry;
import com.willfp.eco.core.items.Items;
import com.willfp.eco.core.items.builder.ItemBuilder;
import com.willfp.eco.core.items.builder.ItemStackBuilder;
import com.willfp.eco.core.recipe.Recipes;
import com.willfp.eco.core.requirement.Requirement;
import com.willfp.eco.core.requirement.Requirements;
import com.willfp.eco.core.tuples.Pair;
import com.willfp.eco.util.NumberUtils;
import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.effects.Effect;
import com.willfp.ecobosses.bosses.effects.Effects;
import com.willfp.ecobosses.bosses.util.bosstype.BossEntityUtils;
import com.willfp.ecobosses.bosses.util.bosstype.BossType;
import com.willfp.ecobosses.bosses.util.obj.*;
import com.willfp.ecobosses.bosses.util.obj.ArgumentedEffectName;
import com.willfp.ecobosses.bosses.util.obj.BossbarProperties;
import com.willfp.ecobosses.bosses.util.obj.EquipmentPiece;
import com.willfp.ecobosses.bosses.util.obj.ExperienceOptions;
import com.willfp.ecobosses.bosses.util.obj.ImmunityOptions;
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
import com.willfp.ecobosses.bosses.util.obj.SpawnTotem;
import com.willfp.ecobosses.bosses.util.obj.TargetMode;
import lombok.AccessLevel;
import lombok.Getter;
import org.bukkit.*;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import lombok.Setter;
import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
public class EcoBoss extends PluginDependent {
public class EcoBoss extends PluginDependent<EcoPlugin> {
/**
* The name of the boss.
*/
@@ -92,6 +123,11 @@ public class EcoBoss extends PluginDependent {
@Getter
private final int attackDamage;
/**
* Age state.
*/
@Getter
private final boolean baby;
/**
* The follow range.
@@ -114,8 +150,7 @@ public class EcoBoss extends PluginDependent {
/**
* The drops.
*/
@Getter
private final Map<ItemStack, Double> drops;
private final List<String> drops;
/**
* The exp to drop.
@@ -153,6 +188,12 @@ public class EcoBoss extends PluginDependent {
@Getter
private final List<OptionedSound> summonSounds;
/**
* Despawn sounds.
*/
@Getter
private final List<OptionedSound> despawnSounds;
/**
* Spawn messages.
*/
@@ -165,6 +206,12 @@ public class EcoBoss extends PluginDependent {
@Getter
private final List<String> deathMessages;
/**
* Despawn messages.
*/
@Getter
private final List<String> despawnMessages;
/**
* Nearby players radius.
*/
@@ -189,15 +236,21 @@ public class EcoBoss extends PluginDependent {
@Getter
private final Map<EntityDamageEvent.DamageCause, Double> incomingMultipliers;
/**
* Boss glowing effect.
*/
@Getter
private final boolean isGlowing;
/**
* The currently living bosses of this type.
*/
private final Map<UUID, LivingEcoBoss> livingBosses;
private final Map<LivingEntity, LivingEcoBoss> livingBosses;
/**
* The effect names and arguments.
*/
private final Map<String, List<String>> effectNames;
private final List<ArgumentedEffectName> effectNames;
/**
* The target distance.
@@ -223,12 +276,44 @@ public class EcoBoss extends PluginDependent {
@Getter
private final int autoSpawnInterval;
@Getter
@Setter
private int timeUntilSpawn;
/**
* The time to live.
*/
@Getter
private final int timeToLive;
/**
* Locations that the boss can auto spawn at.
*/
@Getter
private final List<Location> autoSpawnLocations;
/**
* The boss spawn egg.
*/
@Getter
private final ItemStack spawnEgg;
/**
* All the requirements needed in order to spawn the boss.
*/
private final Map<Requirement, List<String>> requirements = new HashMap<>();
/**
* Cached players to see if they meet requirements.
*/
private final Map<UUID, Boolean> cachedRequirements = new HashMap<>();
/**
* The equipment for the boss.
*/
@Getter
private final Map<EquipmentSlot, EquipmentPiece> equipment = new HashMap<>();
/**
* Create a new Boss.
*
@@ -243,6 +328,8 @@ public class EcoBoss extends PluginDependent {
this.config = config;
this.name = name;
this.livingBosses = new HashMap<>();
this.isGlowing = this.getConfig().getBool("glowing");
this.baby = this.getConfig().getBool("baby");
this.displayName = this.getConfig().getString("name");
@@ -251,9 +338,13 @@ public class EcoBoss extends PluginDependent {
// Boss Bar
this.bossbarEnabled = this.getConfig().getBool("bossbar.enabled");
String barStyle = this.getConfig().getString("bossbar.style").toUpperCase();
if (barStyle.equalsIgnoreCase("solid")) {
barStyle = "PROGRESS";
}
this.bossbarProperties = new BossbarProperties(
BarColor.valueOf(this.getConfig().getString("bossbar.color").toUpperCase()),
BarStyle.valueOf(this.getConfig().getString("bossbar.style").toUpperCase())
BossBar.Color.valueOf(this.getConfig().getString("bossbar.color").toUpperCase()),
BossBar.Overlay.valueOf(barStyle)
);
// Attributes
@@ -261,6 +352,61 @@ public class EcoBoss extends PluginDependent {
this.maxHealth = this.getConfig().getInt("max-health");
this.followRange = this.getConfig().getInt("follow-range");
this.movementSpeedMultiplier = this.getConfig().getInt("movement-speed");
this.timeToLive = this.getConfig().getInt("time-to-live", -1);
// Equipment
ItemStack helmet = Items.lookup(this.getConfig().getString("gear.helmet.item")).getItem();
ItemStack chestplate = Items.lookup(this.getConfig().getString("gear.chestplate.item")).getItem();
ItemStack leggings = Items.lookup(this.getConfig().getString("gear.leggings.item")).getItem();
ItemStack boots = Items.lookup(this.getConfig().getString("gear.boots.item")).getItem();
ItemStack hand = Items.lookup(this.getConfig().getString("gear.hand.item")).getItem();
if (helmet.getType() != Material.AIR) {
this.equipment.put(
EquipmentSlot.HEAD,
new EquipmentPiece(
helmet,
this.getConfig().getDouble("gear.helmet.chance")
)
);
}
if (chestplate.getType() != Material.AIR) {
this.equipment.put(
EquipmentSlot.CHEST,
new EquipmentPiece(
chestplate,
this.getConfig().getDouble("gear.chestplate.chance")
)
);
}
if (leggings.getType() != Material.AIR) {
this.equipment.put(
EquipmentSlot.LEGS,
new EquipmentPiece(
leggings,
this.getConfig().getDouble("gear.leggings.chance")
)
);
}
if (boots.getType() != Material.AIR) {
this.equipment.put(
EquipmentSlot.FEET,
new EquipmentPiece(
boots,
this.getConfig().getDouble("gear.boots.chance")
)
);
}
if (hand.getType() != Material.AIR) {
this.equipment.put(
EquipmentSlot.HAND,
new EquipmentPiece(
hand,
this.getConfig().getDouble("gear.hand.chance")
)
);
}
// Spawn Totem
this.spawnTotemEnabled = this.getConfig().getBool("spawn-totem.enabled");
@@ -272,24 +418,8 @@ public class EcoBoss extends PluginDependent {
this.spawnTotemDisabledWorldNames = this.getConfig().getStrings("spawn-totem.world-blacklist").stream().map(String::toLowerCase).collect(Collectors.toList());
// Rewards
this.drops = new HashMap<>();
for (String string : this.getConfig().getStrings("rewards.drops")) {
YamlConfiguration tempConfig = new YamlConfiguration();
double chance = 100;
if (string.contains("::")) {
String[] split = string.split("::");
chance = Double.parseDouble(split[0]);
string = split[1];
}
String tempConfigString = new String(Base64.getDecoder().decode(string));
try {
tempConfig.loadFromString(tempConfigString);
} catch (InvalidConfigurationException e) {
e.printStackTrace();
}
ItemStack itemStack = tempConfig.getItemStack("drop-key");
this.drops.put(itemStack, chance);
}
this.drops = new ArrayList<>();
drops.addAll(this.getConfig().getStrings("rewards.drops", false));
this.experienceOptions = new ExperienceOptions(
this.getConfig().getInt("rewards.xp.minimum"),
@@ -358,21 +488,35 @@ public class EcoBoss extends PluginDependent {
));
}
this.despawnSounds = new ArrayList<>();
for (String string : this.getConfig().getStrings("sounds.despawn")) {
String[] split = string.split(":");
this.despawnSounds.add(new OptionedSound(
Sound.valueOf(split[0].toUpperCase()),
Float.parseFloat(split[1]) / 16,
Float.parseFloat(split[2])
));
}
// Messages
this.spawnMessages = new ArrayList<>();
for (String string : this.getConfig().getStrings("broadcast.spawn")) {
this.spawnMessages.add(StringUtils.translate(string));
this.spawnMessages.add(StringUtils.format(string));
}
this.deathMessages = new ArrayList<>();
for (String string : this.getConfig().getStrings("broadcast.death")) {
this.deathMessages.add(StringUtils.translate(string));
this.deathMessages.add(StringUtils.format(string));
}
this.despawnMessages = new ArrayList<>();
for (String string : this.getConfig().getStrings("broadcast.despawn")) {
this.despawnMessages.add(StringUtils.format(string));
}
// Top Damager Commands
this.topDamagerCommands = new HashMap<>();
for (int i = 1; i <= 3; i++) {
this.topDamagerCommands.put(i, new ArrayList<>());
for (String string : this.getConfig().getStrings("rewards.top-damager-commands." + i)) {
for (String string : this.getConfig().getStrings("rewards.top-damager-commands." + i, false)) {
double chance = 100;
if (string.contains("::")) {
String[] split = string.split("::");
@@ -388,7 +532,7 @@ public class EcoBoss extends PluginDependent {
// Nearby Rewards
this.nearbyRadius = this.getConfig().getDouble("rewards.nearby-player-commands.radius");
this.nearbyPlayersCommands = new HashMap<>();
for (String string : this.getConfig().getStrings("rewards.nearby-player-commands.commands")) {
for (String string : this.getConfig().getStrings("rewards.nearby-player-commands.commands", false)) {
double chance = 100;
if (string.contains("::")) {
String[] split = string.split("::");
@@ -399,19 +543,24 @@ public class EcoBoss extends PluginDependent {
}
// Effects
this.effectNames = new HashMap<>();
this.effectNames = new ArrayList<>();
for (String string : this.getConfig().getStrings("effects")) {
String effectName = string.split(":")[0];
List<String> args = Arrays.asList(string.replace(effectName + ":", "").split(":"));
this.effectNames.put(effectName, args);
List<String> args = new ArrayList<>(Arrays.asList(string.replace(effectName + ":", "").split(":")));
if (args.contains("mythicmobs")) {
String newArg = "mythicmobs:" + args.get(args.indexOf("mythicmobs")+1);
args.set(args.indexOf("mythicmobs"), newArg);
args.remove(args.get(args.indexOf(newArg)+1));
}
this.effectNames.add(new ArgumentedEffectName(effectName, args));
}
new HashMap<>(this.effectNames).forEach((string, args) -> {
if (Effects.getEffect(string, args) == null) {
this.effectNames.remove(string);
Bukkit.getLogger().warning("Invalid effect specified in " + this.name);
for (ArgumentedEffectName effectName : new ArrayList<>(this.effectNames)) {
if (Effects.getEffect(effectName.name(), effectName.args()) == null) {
this.effectNames.remove(effectName);
Bukkit.getLogger().warning("Invalid effect " + effectName.name() + " specified in " + this.name);
}
});
}
// Targeting
this.targetDistance = this.getConfig().getDouble("attacks.target.range");
@@ -422,6 +571,7 @@ public class EcoBoss extends PluginDependent {
// Auto Spawn
this.autoSpawnInterval = this.getConfig().getInt("auto-spawn-interval");
this.timeUntilSpawn = this.autoSpawnInterval;
this.autoSpawnLocations = new ArrayList<>();
for (String string : this.getConfig().getStrings("auto-spawn-locations")) {
String[] split = string.split(":");
@@ -432,21 +582,122 @@ public class EcoBoss extends PluginDependent {
autoSpawnLocations.add(new Location(world, x, y, z));
}
new PlaceholderEntry(
"timeuntilspawn_"+this.name,
(player) -> new BigDecimal(this.timeUntilSpawn/20).setScale(1, RoundingMode.HALF_UP).toString(),
false
).register();
for (String req : config.getStrings("spawn-requirements", false)) {
List<String> split = Arrays.asList(req.split(":"));
if (split.size() < 2) {
continue;
}
Requirement requirement = Requirements.getByID(split.get(0).toLowerCase());
this.requirements.put(requirement, split.subList(1, split.size()));
}
this.clearCachedRequirements();
// Spawn egg
if (this.getConfig().getBool("spawn-egg.enabled")) {
Material material = Material.getMaterial(this.getConfig().getString("spawn-egg.material").toUpperCase());
assert material != null;
ItemBuilder builder = new ItemStackBuilder(material)
.setDisplayName(this.getConfig().getString("spawn-egg.name"))
.addLoreLines(this.getConfig().getStrings("spawn-egg.lore"))
.writeMetaKey(this.getPlugin().getNamespacedKeyFactory().create("spawn_egg"), PersistentDataType.STRING, this.getName());
if (this.getConfig().getBool("spawn-egg.glow")) {
builder.addEnchantment(Enchantment.DURABILITY, 1)
.addItemFlag(ItemFlag.HIDE_ENCHANTS);
}
this.spawnEgg = builder.build();
if (this.getConfig().getBool("spawn-egg.craftable")) {
Recipes.createAndRegisterRecipe(
this.getPlugin(),
"spawn_egg_" + this.getName(),
this.getSpawnEgg(),
this.getConfig().getStrings("spawn-egg.recipe", false)
);
}
} else {
this.spawnEgg = null;
}
if (this.getConfig().getBool("enabled")) {
EcoBosses.addBoss(this);
}
}
/**
* Clear requirements cache.
*/
public void clearCachedRequirements() {
this.cachedRequirements.clear();
}
/**
* Does the player meet the requirements to use this enchantment.
*
* @param player The player.
* @return If the requirements are met.
*/
public boolean areRequirementsMet(@NotNull final Player player) {
if (cachedRequirements.containsKey(player.getUniqueId())) {
return cachedRequirements.get(player.getUniqueId());
}
for (Map.Entry<Requirement, List<String>> entry : requirements.entrySet()) {
if (!entry.getKey().doesPlayerMeet(player, entry.getValue())) {
cachedRequirements.put(player.getUniqueId(), false);
return false;
}
}
cachedRequirements.put(player.getUniqueId(), true);
return true;
}
public List<ItemStack> generateDrops() {
List<ItemStack> drops = new ArrayList<>();
for (String dropName : this.drops) {
double chance = 100;
if (dropName.contains("::")) {
String[] split = dropName.split("::");
chance = Double.parseDouble(split[0]);
dropName = split[1];
}
ItemStack itemStack = Items.lookup(dropName).getItem();
if (itemStack.getType() == Material.AIR) {
Bukkit.getLogger().warning(this.getName() + " has an invalid drop configured! (" + dropName + ")");
continue;
}
if (NumberUtils.randFloat(0, 100) <= chance) {
drops.add(itemStack);
}
}
return drops;
}
/**
* Create effect tickers for Living Boss.
*
* @return The effects.
*/
public Set<Effect> createEffects() {
Set<Effect> effects = new HashSet<>();
this.effectNames.forEach((string, args) -> {
effects.add(Effects.getEffect(string, args));
});
public List<Effect> createEffects() {
List<Effect> effects = new ArrayList<>();
for (ArgumentedEffectName effectName : this.effectNames) {
effects.add(Effects.getEffect(effectName.name(), effectName.args()));
}
return effects;
}
@@ -457,8 +708,10 @@ public class EcoBoss extends PluginDependent {
* @param location The location.
*/
public void spawn(@NotNull final Location location) {
location.getChunk().load();
LivingEntity entity = bossType.spawnBossEntity(location);
this.livingBosses.put(entity.getUniqueId(), new LivingEcoBoss(
this.livingBosses.put(entity, new LivingEcoBoss(
this.getPlugin(),
entity,
this
@@ -473,16 +726,16 @@ public class EcoBoss extends PluginDependent {
* @return The living boss, or null if not a boss.
*/
public LivingEcoBoss getLivingBoss(@NotNull final LivingEntity entity) {
return this.livingBosses.get(entity.getUniqueId());
return this.livingBosses.get(entity);
}
/**
* Remove living boss.
*
* @param uuid The entity UUID.
* @param entity The entity.
*/
public void removeLivingBoss(@NotNull final UUID uuid) {
this.livingBosses.remove(uuid);
public void removeLivingBoss(@Nullable final LivingEntity entity) {
this.livingBosses.remove(entity);
}
/**
@@ -490,7 +743,7 @@ public class EcoBoss extends PluginDependent {
*
* @return The living bosses.
*/
public Map<UUID, LivingEcoBoss> getLivingBosses() {
public Map<LivingEntity, LivingEcoBoss> getLivingBosses() {
return ImmutableMap.copyOf(this.livingBosses);
}
@@ -500,11 +753,10 @@ public class EcoBoss extends PluginDependent {
return true;
}
if (!(o instanceof EcoBoss)) {
if (!(o instanceof EcoBoss boss)) {
return false;
}
EcoBoss boss = (EcoBoss) o;
return this.getName().equals(boss.getName());
}

View File

@@ -3,7 +3,7 @@ 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.ConfigUpdater;
import com.willfp.eco.core.config.updating.ConfigUpdater;
import com.willfp.ecobosses.EcoBossesPlugin;
import com.willfp.ecobosses.config.BaseBossConfig;
import com.willfp.ecobosses.config.CustomConfig;
@@ -29,7 +29,7 @@ public class EcoBosses {
* Sets that exist by default.
*/
private static final List<String> DEFAULT_BOSSES = Arrays.asList(
"illusioner",
"dark_guardian",
"tarantula",
"steel_golem",
"alpha_wolf"

View File

@@ -3,33 +3,41 @@ package com.willfp.ecobosses.bosses;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.scheduling.RunnableTask;
import com.willfp.eco.util.NumberUtils;
import com.willfp.eco.util.StringUtils;
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.HealthPlaceholderTicker;
import com.willfp.ecobosses.bosses.tick.tickers.DeathTimeTicker;
import com.willfp.ecobosses.bosses.tick.tickers.NamePlaceholderTicker;
import com.willfp.ecobosses.bosses.tick.tickers.TargetTicker;
import com.willfp.ecobosses.bosses.util.obj.EquipmentPiece;
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
import lombok.Getter;
import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.Bukkit;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.boss.BarFlag;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
public class LivingEcoBoss extends PluginDependent {
public class LivingEcoBoss extends PluginDependent<EcoPlugin> {
/**
* The entity.
*/
private final LivingEntity entity;
@Getter
private LivingEntity entity;
/**
* The boss.
@@ -39,12 +47,12 @@ public class LivingEcoBoss extends PluginDependent {
/**
* The boss tickers.
*/
private final Set<BossTicker> tickers;
private final List<BossTicker> tickers;
/**
* The effects.
*/
private final Set<Effect> effects;
private final List<Effect> effects;
/**
* Create new living EcoBoss.
@@ -63,18 +71,18 @@ public class LivingEcoBoss extends PluginDependent {
this.onSpawn();
// Tickers
this.tickers = new HashSet<>();
this.tickers.add(new HealthPlaceholderTicker());
this.tickers = new ArrayList<>();
this.tickers.add(new NamePlaceholderTicker());
this.tickers.add(new DeathTimeTicker());
this.tickers.add(new TargetTicker(boss.getTargetMode(), boss.getTargetDistance()));
if (boss.isBossbarEnabled()) {
this.tickers.add(
new BossBarTicker(
Bukkit.getServer().createBossBar(
plugin.getNamespacedKeyFactory().create("boss_" + NumberUtils.randInt(0, 1000000)),
entity.getCustomName(),
boss.getBossbarProperties().getColor(),
boss.getBossbarProperties().getStyle(),
(BarFlag) null
BossBar.bossBar(
StringUtils.toComponent(entity.getCustomName()),
1,
boss.getBossbarProperties().color(),
boss.getBossbarProperties().style()
),
this.getPlugin().getConfigYml().getInt("bossbar-radius")
)
@@ -82,7 +90,7 @@ public class LivingEcoBoss extends PluginDependent {
}
// Effects
this.effects = new HashSet<>();
this.effects = new ArrayList<>();
this.effects.addAll(boss.createEffects());
AtomicLong currentTick = new AtomicLong(0);
@@ -92,10 +100,51 @@ public class LivingEcoBoss extends PluginDependent {
private void onSpawn() {
entity.getPersistentDataContainer().set(this.getPlugin().getNamespacedKeyFactory().create("boss"), PersistentDataType.STRING, boss.getName());
entity.setPersistent(true);
entity.setRemoveWhenFarAway(false);
if (boss.isGlowing()) entity.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, Integer.MAX_VALUE, 1, false, false, false));
if (entity instanceof Ageable ageable) {
if (boss.isBaby()) ageable.setBaby();
else ageable.setAdult();
}
if (boss.getTimeToLive() > 0) {
entity.setMetadata("death-time", this.getPlugin().getMetadataValueFactory().create(System.currentTimeMillis() + (boss.getTimeToLive() * 1000L)));
}
entity.setCustomName(boss.getDisplayName());
entity.setCustomNameVisible(true);
EntityEquipment equipment = entity.getEquipment();
if (equipment != null) {
EquipmentPiece head = boss.getEquipment().get(EquipmentSlot.HEAD);
EquipmentPiece chest = boss.getEquipment().get(EquipmentSlot.CHEST);
EquipmentPiece legs = boss.getEquipment().get(EquipmentSlot.LEGS);
EquipmentPiece boots = boss.getEquipment().get(EquipmentSlot.FEET);
EquipmentPiece hand = boss.getEquipment().get(EquipmentSlot.HAND);
if (head != null) {
equipment.setHelmet(head.itemStack(), true);
equipment.setHelmetDropChance((float) head.chance());
}
if (chest != null) {
equipment.setChestplate(chest.itemStack(), true);
equipment.setChestplateDropChance((float) chest.chance());
}
if (legs != null) {
equipment.setLeggings(legs.itemStack(), true);
equipment.setLeggingsDropChance((float) legs.chance());
}
if (boots != null) {
equipment.setBoots(boots.itemStack(), true);
equipment.setBootsDropChance((float) boots.chance());
}
if (hand != null) {
equipment.setItemInMainHand(hand.itemStack(), true);
equipment.setItemInMainHandDropChance((float) hand.chance());
}
}
AttributeInstance movementSpeed = entity.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
assert movementSpeed != null;
movementSpeed.addModifier(new AttributeModifier(entity.getUniqueId(), "ecobosses-movement-multiplier", boss.getMovementSpeedMultiplier() - 1, AttributeModifier.Operation.MULTIPLY_SCALAR_1));
@@ -115,7 +164,7 @@ public class LivingEcoBoss extends PluginDependent {
attackDamage.setBaseValue(boss.getAttackDamage());
for (OptionedSound sound : boss.getSpawnSounds()) {
entity.getWorld().playSound(entity.getLocation(), sound.getSound(), sound.getVolume(), sound.getPitch());
entity.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
}
for (String spawnMessage : boss.getSpawnMessages()) {
@@ -129,21 +178,23 @@ public class LivingEcoBoss extends PluginDependent {
private void tick(final long tick,
@NotNull final RunnableTask runnable) {
for (BossTicker ticker : tickers) {
ticker.tick(boss, entity, tick);
}
for (Effect effect : effects) {
effect.tick(boss, entity, tick);
}
if (entity.isDead()) {
if (entity == null || entity.isDead()) {
for (BossTicker ticker : tickers) {
ticker.onDeath(boss, entity, tick);
}
for (Effect effect : effects) {
effect.onDeath(boss, entity, tick);
}
boss.removeLivingBoss(entity.getUniqueId());
boss.removeLivingBoss(entity);
runnable.cancel();
return;
}
for (BossTicker ticker : tickers) {
ticker.tick(boss, entity, tick);
}
for (Effect effect : effects) {
effect.tick(boss, entity, tick);
}
}
@@ -154,7 +205,7 @@ public class LivingEcoBoss extends PluginDependent {
*/
public void handleAttack(@NotNull final Player player) {
for (OptionedSound sound : boss.getInjureSounds()) {
player.getWorld().playSound(entity.getLocation(), sound.getSound(), sound.getVolume(), sound.getPitch());
player.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
}
for (Effect effect : effects) {

View File

@@ -7,8 +7,10 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
public abstract class Effect implements BossTicker {
/**
@@ -79,8 +81,24 @@ public abstract class Effect implements BossTicker {
*/
@Override
public void onDeath(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
@Nullable final LivingEntity entity,
final long tick) {
// Override when needed.
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Effect effect)) {
return false;
}
return Objects.equals(getArgs(), effect.getArgs());
}
@Override
public int hashCode() {
return Objects.hash(getArgs());
}
}

View File

@@ -59,7 +59,7 @@ public class EffectSummon extends Effect {
}
for (OptionedSound sound : boss.getSummonSounds()) {
player.getWorld().playSound(entity.getLocation(), sound.getSound(), sound.getVolume(), sound.getPitch());
player.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
}
}
}

View File

@@ -9,7 +9,6 @@ import com.willfp.ecobosses.bosses.util.obj.DamagerProperty;
import com.willfp.ecobosses.bosses.util.obj.ImmunityOptions;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@@ -21,7 +20,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
public class AttackListeners extends PluginDependent implements Listener {
public class AttackListeners extends PluginDependent<EcoPlugin> implements Listener {
/**
* Create new attack listeners.
*
@@ -38,21 +37,11 @@ public class AttackListeners extends PluginDependent implements Listener {
*/
@EventHandler(ignoreCancelled = true)
public void onAttackBoss(@NotNull final EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
if (!(event.getEntity() instanceof LivingEntity entity)) {
return;
}
LivingEntity entity = (LivingEntity) event.getEntity();
Player player = null;
if (event.getDamager() instanceof Player) {
player = (Player) event.getDamager();
} else if (event.getDamager() instanceof Projectile) {
if (((Projectile) event.getDamager()).getShooter() instanceof Player) {
player = (Player) ((Projectile) event.getDamager()).getShooter();
}
}
Player player = BossUtils.getPlayerFromEntity(event.getDamager());
if (player == null) {
return;
@@ -66,6 +55,10 @@ public class AttackListeners extends PluginDependent implements Listener {
LivingEcoBoss livingEcoBoss = boss.getLivingBoss(entity);
if (livingEcoBoss == null) {
return;
}
if (boss.isAttackOnInjure()) {
livingEcoBoss.handleAttack(player);
}
@@ -78,28 +71,16 @@ public class AttackListeners extends PluginDependent implements Listener {
*/
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void topDamageTracker(@NotNull final EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
if (!(event.getEntity() instanceof LivingEntity entity)) {
return;
}
LivingEntity entity = (LivingEntity) event.getEntity();
Player player = BossUtils.getPlayerFromEntity(event.getDamager());
Player temp = null;
if (event.getDamager() instanceof Player) {
temp = (Player) event.getDamager();
} else if (event.getDamager() instanceof Projectile) {
if (((Projectile) event.getDamager()).getShooter() instanceof Player) {
temp = (Player) ((Projectile) event.getDamager()).getShooter();
}
}
if (temp == null) {
if (player == null) {
return;
}
Player player = temp;
EcoBoss boss = BossUtils.getBoss(entity);
if (boss == null) {
@@ -110,11 +91,11 @@ public class AttackListeners extends PluginDependent implements Listener {
double playerDamage;
Optional<DamagerProperty> damager = topDamagers.stream().filter(damagerProperty -> damagerProperty.getPlayerUUID().equals(player.getUniqueId())).findFirst();
playerDamage = damager.map(DamagerProperty::getDamage).orElse(0.0);
Optional<DamagerProperty> damager = topDamagers.stream().filter(damagerProperty -> damagerProperty.playerUUID().equals(player.getUniqueId())).findFirst();
playerDamage = damager.map(DamagerProperty::damage).orElse(0.0);
playerDamage += event.getFinalDamage();
topDamagers.removeIf(damagerProperty -> damagerProperty.getPlayerUUID().equals(player.getUniqueId()));
topDamagers.removeIf(damagerProperty -> damagerProperty.playerUUID().equals(player.getUniqueId()));
topDamagers.add(new DamagerProperty(player.getUniqueId(), playerDamage));
entity.removeMetadata("ecobosses-top-damagers", this.getPlugin());
@@ -128,18 +109,14 @@ public class AttackListeners extends PluginDependent implements Listener {
*/
@EventHandler(ignoreCancelled = true)
public void onAttackPlayer(@NotNull final EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof Player)) {
if (!(event.getEntity() instanceof Player player)) {
return;
}
if (!(event.getDamager() instanceof LivingEntity)) {
if (!(event.getDamager() instanceof LivingEntity entity)) {
return;
}
LivingEntity entity = (LivingEntity) event.getDamager();
Player player = (Player) event.getEntity();
EcoBoss boss = BossUtils.getBoss(entity);
if (boss == null) {
@@ -148,6 +125,10 @@ public class AttackListeners extends PluginDependent implements Listener {
LivingEcoBoss livingEcoBoss = boss.getLivingBoss(entity);
if (livingEcoBoss == null) {
return;
}
livingEcoBoss.handleAttack(player);
}
@@ -158,12 +139,10 @@ public class AttackListeners extends PluginDependent implements Listener {
*/
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
public void defenceListener(@NotNull final EntityDamageEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
if (!(event.getEntity() instanceof LivingEntity entity)) {
return;
}
LivingEntity entity = (LivingEntity) event.getEntity();
EcoBoss boss = BossUtils.getBoss(entity);
if (boss == null) {
@@ -172,22 +151,23 @@ public class AttackListeners extends PluginDependent implements Listener {
ImmunityOptions immunities = boss.getImmunityOptions();
if (immunities.isImmuneToFire()
if (immunities.immuneToFire()
&& (event.getCause() == EntityDamageEvent.DamageCause.FIRE
|| event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK
|| event.getCause() == EntityDamageEvent.DamageCause.LAVA
|| event.getCause() == EntityDamageEvent.DamageCause.HOT_FLOOR)) {
event.setCancelled(true);
}
if (immunities.isImmuneToSuffocation()&& event.getCause() == EntityDamageEvent.DamageCause.SUFFOCATION) {
if (immunities.immuneToSuffocation()&& event.getCause() == EntityDamageEvent.DamageCause.SUFFOCATION) {
event.setCancelled(true);
}
if (immunities.isImmuneToDrowning() && event.getCause() == EntityDamageEvent.DamageCause.DROWNING) {
if (immunities.immuneToDrowning() && event.getCause() == EntityDamageEvent.DamageCause.DROWNING) {
event.setCancelled(true);
}
if (immunities.isImmuneToExplosions() && (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_EXPLOSION || event.getCause() == EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)) {
if (immunities.immuneToExplosions() && (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_EXPLOSION || event.getCause() == EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)) {
event.setCancelled(true);
}
if (immunities.isImmuneToProjectiles() && (event.getCause() == EntityDamageEvent.DamageCause.PROJECTILE)) {
if (immunities.immuneToProjectiles() && (event.getCause() == EntityDamageEvent.DamageCause.PROJECTILE)) {
event.setCancelled(true);
}

View File

@@ -3,7 +3,16 @@ package com.willfp.ecobosses.bosses.listeners;
import com.willfp.eco.util.NumberUtils;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import com.willfp.ecobosses.events.EcoBossSpawnTimerEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class AutoSpawnTimer implements Runnable {
private int tick = 0;
@@ -21,9 +30,33 @@ public class AutoSpawnTimer implements Runnable {
continue;
}
Set<World> worlds = new HashSet<>();
for (Entity entity : boss.getLivingBosses().keySet()) {
if (entity == null) {
continue;
}
worlds.add(entity.getWorld());
}
List<Location> locations = new ArrayList<>(boss.getAutoSpawnLocations());
locations.removeIf(location -> worlds.contains(location.getWorld()));
if (locations.isEmpty()) {
continue;
}
boss.setTimeUntilSpawn(boss.getTimeUntilSpawn()-1);
if (tick % boss.getAutoSpawnInterval() == 0) {
Location location = boss.getAutoSpawnLocations().get(NumberUtils.randInt(0, boss.getAutoSpawnLocations().size() - 1));
boss.spawn(location);
Location location = locations.get(NumberUtils.randInt(0, locations.size() - 1));
EcoBossSpawnTimerEvent event = new EcoBossSpawnTimerEvent(boss, location);
Bukkit.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
boss.spawn(location);
boss.setTimeUntilSpawn(boss.getAutoSpawnInterval());
}
}
}
}

View File

@@ -19,6 +19,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.SlimeSplitEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -26,7 +27,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class DeathListeners extends PluginDependent implements Listener {
public class DeathListeners extends PluginDependent<EcoPlugin> implements Listener {
/**
* Create new death listeners.
*
@@ -52,7 +53,7 @@ public class DeathListeners extends PluginDependent implements Listener {
}
for (OptionedSound sound : boss.getDeathSounds()) {
entity.getWorld().playSound(entity.getLocation(), sound.getSound(), sound.getVolume(), sound.getPitch());
entity.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
}
}
@@ -89,14 +90,14 @@ public class DeathListeners extends PluginDependent implements Listener {
String na = this.getPlugin().getLangYml().getString("na");
String topDamager = top == null ? na : Bukkit.getPlayer(top.getPlayerUUID()).getDisplayName();
String topDamage = top == null ? na : StringUtils.internalToString(top.getDamage());
String topDamager = top == null ? na : Bukkit.getPlayer(top.playerUUID()).getDisplayName();
String topDamage = top == null ? na : StringUtils.internalToString(top.damage());
String secondDamager = second == null ? na : Bukkit.getPlayer(second.getPlayerUUID()).getDisplayName();
String secondDamage = second == null ? na : StringUtils.internalToString(second.getDamage());
String secondDamager = second == null ? na : Bukkit.getPlayer(second.playerUUID()).getDisplayName();
String secondDamage = second == null ? na : StringUtils.internalToString(second.damage());
String thirdDamager = third == null ? na : Bukkit.getPlayer(third.getPlayerUUID()).getDisplayName();
String thirdDamage = third == null ? na : StringUtils.internalToString(third.getDamage());
String thirdDamager = third == null ? na : Bukkit.getPlayer(third.playerUUID()).getDisplayName();
String thirdDamage = third == null ? na : StringUtils.internalToString(third.damage());
for (String spawnMessage : boss.getDeathMessages()) {
Bukkit.broadcastMessage(spawnMessage
@@ -114,28 +115,23 @@ public class DeathListeners extends PluginDependent implements Listener {
for (Pair<Double, String> pair : topDamagerCommands) {
if (top != null && i == 1) {
if (NumberUtils.randFloat(0, 100) < pair.getFirst()) {
Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), pair.getSecond().replace("%player%", Bukkit.getOfflinePlayer(top.getPlayerUUID()).getName()));
Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), pair.getSecond().replace("%player%", Bukkit.getOfflinePlayer(top.playerUUID()).getName()));
}
}
if (second != null && i == 2) {
if (NumberUtils.randFloat(0, 100) < pair.getFirst()) {
Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), pair.getSecond().replace("%player%", Bukkit.getOfflinePlayer(second.getPlayerUUID()).getName()));
Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), pair.getSecond().replace("%player%", Bukkit.getOfflinePlayer(second.playerUUID()).getName()));
}
}
if (third != null && i == 3) {
if (NumberUtils.randFloat(0, 100) < pair.getFirst()) {
Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), pair.getSecond().replace("%player%", Bukkit.getOfflinePlayer(third.getPlayerUUID()).getName()));
Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), pair.getSecond().replace("%player%", Bukkit.getOfflinePlayer(third.playerUUID()).getName()));
}
}
}
}
List<ItemStack> drops = new ArrayList<>();
for (Map.Entry<ItemStack, Double> entry : boss.getDrops().entrySet()) {
if (NumberUtils.randFloat(0, 100) < entry.getValue()) {
drops.add(entry.getKey().clone());
}
}
List<ItemStack> drops = boss.generateDrops();
for (Entity nearby : entity.getNearbyEntities(boss.getNearbyRadius(), boss.getNearbyRadius(), boss.getNearbyRadius())) {
if (nearby instanceof Player) {
@@ -151,4 +147,17 @@ public class DeathListeners extends PluginDependent implements Listener {
event.getDrops().addAll(drops);
event.setDroppedExp(boss.getExperienceOptions().generateXp());
}
@EventHandler
public void preventSplit(@NotNull final SlimeSplitEvent event) {
LivingEntity entity = event.getEntity();
EcoBoss boss = BossUtils.getBoss(entity);
if (boss == null) {
return;
}
event.setCancelled(true);
}
}

View File

@@ -9,10 +9,11 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Minecart;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.jetbrains.annotations.NotNull;
import org.spigotmc.event.entity.EntityMountEvent;
public class PassiveListeners extends PluginDependent implements Listener {
public class PassiveListeners extends PluginDependent<EcoPlugin> implements Listener {
/**
* Create new attack listeners.
*
@@ -28,8 +29,8 @@ public class PassiveListeners extends PluginDependent implements Listener {
* @param event The event to listen for.
*/
@EventHandler(ignoreCancelled = true)
public void onAttackBoss(@NotNull final EntityMountEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
public void onMount(@NotNull final EntityMountEvent event) {
if (!(event.getEntity() instanceof LivingEntity entity)) {
return;
}
@@ -37,8 +38,6 @@ public class PassiveListeners extends PluginDependent implements Listener {
return;
}
LivingEntity entity = (LivingEntity) event.getEntity();
EcoBoss boss = BossUtils.getBoss(entity);
if (boss == null) {
@@ -49,4 +48,15 @@ public class PassiveListeners extends PluginDependent implements Listener {
event.setCancelled(true);
}
}
@EventHandler
public void onPickup(@NotNull final EntityPickupItemEvent event) {
EcoBoss boss = BossUtils.getBoss(event.getEntity());
if (boss == null) {
return;
}
event.setCancelled(true);
}
}

View File

@@ -5,14 +5,24 @@ import com.willfp.eco.core.PluginDependent;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import com.willfp.ecobosses.bosses.util.obj.SpawnTotem;
import com.willfp.ecobosses.events.EcoBossSpawnEggEvent;
import com.willfp.ecobosses.events.EcoBossSpawnTotemEvent;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
public class SpawnListeners extends PluginDependent implements Listener {
public class SpawnListeners extends PluginDependent<EcoPlugin> implements Listener {
/**
* Create new spawn listeners and link them to a plugin.
*
@@ -54,15 +64,91 @@ public class SpawnListeners extends PluginDependent implements Listener {
if (boss.isSpawnTotemEnabled()) {
if (!boss.getSpawnTotemDisabledWorldNames().contains(event.getBlock().getWorld().getName().toLowerCase())) {
if (boss.getSpawnTotem().equals(placedTotem)) {
block1.setType(Material.AIR);
block2.setType(Material.AIR);
block3.setType(Material.AIR);
boss.spawn(event.getBlock().getLocation());
if (!boss.areRequirementsMet(event.getPlayer())) {
event.getPlayer().sendMessage(this.getPlugin().getLangYml().getMessage("requirements-not-met"));
return;
}
EcoBossSpawnTotemEvent eggEvent = new EcoBossSpawnTotemEvent(boss, event.getPlayer(), event.getBlock().getLocation(), placedTotem);
this.getPlugin().getServer().getPluginManager().callEvent(eggEvent);
if (!eggEvent.isCancelled()) {
block1.setType(Material.AIR);
block2.setType(Material.AIR);
block3.setType(Material.AIR);
boss.spawn(event.getBlock().getLocation());
}
}
}
}
}
}
}
@EventHandler
public void spawnEgg(@NotNull final PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
ItemStack item = event.getItem();
if (item == null) {
return;
}
ItemMeta meta = item.getItemMeta();
if (meta == null) {
return;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
if (!container.has(this.getPlugin().getNamespacedKeyFactory().create("spawn_egg"), PersistentDataType.STRING)) {
return;
}
String id = container.get(this.getPlugin().getNamespacedKeyFactory().create("spawn_egg"), PersistentDataType.STRING);
if (id == null) {
return;
}
EcoBoss boss = EcoBosses.getByName(id);
if (boss == null) {
return;
}
event.setCancelled(true);
event.setUseItemInHand(Event.Result.DENY);
if (!boss.areRequirementsMet(event.getPlayer())) {
event.getPlayer().sendMessage(this.getPlugin().getLangYml().getMessage("requirements-not-met"));
return;
}
EcoBossSpawnEggEvent eggEvent = new EcoBossSpawnEggEvent(boss, event.getPlayer(), event.getClickedBlock().getLocation(), item);
this.getPlugin().getServer().getPluginManager().callEvent(eggEvent);
if (eggEvent.isCancelled()) {
return;
}
item.setAmount(item.getAmount() - 1);
if (event.getHand() == EquipmentSlot.HAND) {
ItemStack hand = event.getPlayer().getInventory().getItemInMainHand();
hand.setAmount(hand.getAmount() - 1);
} else {
ItemStack hand = event.getPlayer().getInventory().getItemInOffHand();
hand.setAmount(hand.getAmount() - 1);
}
Block block = event.getClickedBlock();
if (block == null) {
return;
}
boss.spawn(block.getLocation().add(0, 1.5, 0));
}
}

View File

@@ -3,6 +3,7 @@ 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 {
/**
@@ -24,7 +25,7 @@ public interface BossTicker {
* @param tick The current tick: counts up from zero.
*/
default void onDeath(@NotNull EcoBoss boss,
@NotNull LivingEntity entity,
@Nullable LivingEntity entity,
long tick) {
// Can be overridden when needed.
}

View File

@@ -1,12 +1,16 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.eco.util.PlayerUtils;
import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker;
import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.Bukkit;
import org.bukkit.attribute.Attribute;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class BossBarTicker implements BossTicker {
/**
@@ -34,14 +38,16 @@ public class BossBarTicker implements BossTicker {
public void tick(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
final long tick) {
bossBar.setTitle(entity.getCustomName());
bossBar.setProgress(entity.getHealth() / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
bossBar.name(StringUtils.toComponent(entity.getCustomName()));
bossBar.progress((float) (entity.getHealth() / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()));
if (tick % 40 == 0) {
bossBar.getPlayers().forEach(bossBar::removePlayer);
for (Player player : Bukkit.getOnlinePlayers()) {
PlayerUtils.getAudience(player).hideBossBar(bossBar);
}
entity.getNearbyEntities(radius, radius, radius).forEach(entity1 -> {
if (entity1 instanceof Player) {
bossBar.addPlayer((Player) entity1);
PlayerUtils.getAudience((Player) entity1).showBossBar(bossBar);
}
});
}
@@ -49,9 +55,10 @@ public class BossBarTicker implements BossTicker {
@Override
public void onDeath(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
@Nullable final LivingEntity entity,
final long tick) {
bossBar.getPlayers().forEach(bossBar::removePlayer);
bossBar.setVisible(false);
for (Player player : Bukkit.getOnlinePlayers()) {
PlayerUtils.getAudience(player).hideBossBar(bossBar);
}
}
}

View File

@@ -0,0 +1,35 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker;
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class DeathTimeTicker implements BossTicker {
@Override
public void tick(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
final long tick) {
if (boss.getTimeToLive() < 0) {
return;
}
int timeLeft;
timeLeft = (int) (entity.getMetadata("death-time").get(0).asLong() - System.currentTimeMillis());
timeLeft = (int) Math.ceil(timeLeft / 1000D);
if (timeLeft <= 0) {
entity.remove();
boss.removeLivingBoss(entity);
for (String despawnMessage : boss.getDespawnMessages()) {
Bukkit.broadcastMessage(despawnMessage);
}
for (OptionedSound sound : boss.getDespawnSounds()) {
entity.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
}
}
}
}

View File

@@ -1,16 +0,0 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class HealthPlaceholderTicker implements BossTicker {
@Override
public void tick(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
final long tick) {
entity.setCustomName(boss.getDisplayName().replace("%health%", StringUtils.internalToString(entity.getHealth())));
}
}

View File

@@ -0,0 +1,30 @@
package com.willfp.ecobosses.bosses.tick.tickers;
import com.willfp.eco.util.StringUtils;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.tick.BossTicker;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class NamePlaceholderTicker implements BossTicker {
@Override
public void tick(@NotNull final EcoBoss boss,
@NotNull final LivingEntity entity,
final long tick) {
int timeLeft = -1;
if (boss.getTimeToLive() > 0) {
timeLeft = (int) (entity.getMetadata("death-time").get(0).asLong() - System.currentTimeMillis());
timeLeft = (int) Math.ceil(timeLeft / 1000D);
}
String time = "";
if (timeLeft > 0) {
time = String.format("%d:%02d", timeLeft/60, timeLeft%60);
}
entity.setCustomName(
boss.getDisplayName()
.replace("%health%", StringUtils.internalToString(entity.getHealth()))
.replace("%time%", time)
);
}
}

View File

@@ -5,7 +5,14 @@ import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import com.willfp.ecobosses.bosses.util.obj.DamagerProperty;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.boss.BossBar;
import org.bukkit.boss.KeyedBossBar;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -63,9 +70,86 @@ public class BossUtils {
}
assert topDamagers != null;
topDamagers.sort(Comparator.comparingDouble(DamagerProperty::getDamage));
topDamagers.sort(Comparator.comparingDouble(DamagerProperty::damage));
Collections.reverse(topDamagers);
return topDamagers;
}
/**
* Kill all bosses.
*
* @return The amount of bosses killed.
*/
public int killAllBosses() {
return killAllBosses(false);
}
/**
* Kill all bosses.
*
* @param force If all entities should be checked for being bosses.
* @return The amount of bosses killed.
*/
public int killAllBosses(final boolean force) {
int amount = 0;
for (EcoBoss boss : EcoBosses.values()) {
for (LivingEntity entity : boss.getLivingBosses().keySet()) {
assert entity != null;
entity.damage(10000000);
amount++;
}
}
if (force) {
for (World world : Bukkit.getWorlds()) {
for (Entity entity : world.getEntities()) {
if (!(entity instanceof LivingEntity)) {
continue;
}
if (BossUtils.getBoss((LivingEntity) entity) == null) {
continue;
}
entity.remove();
}
}
}
List<KeyedBossBar> bars = new ArrayList<>();
Bukkit.getBossBars().forEachRemaining(bars::add);
for (KeyedBossBar bar : bars) {
if (bar.getKey().toString().startsWith("ecobosses:boss")) {
BossBar bossBar = Bukkit.getBossBar(bar.getKey());
assert bossBar != null;
bossBar.removeAll();
bossBar.setVisible(false);
Bukkit.removeBossBar(bar.getKey());
}
}
return amount;
}
/**
* Get player from entity if player or projectile.
*
* @param entity The entity.
* @return The player, or null if not a player.
*/
@Nullable
public Player getPlayerFromEntity(@NotNull final Entity entity) {
Player player = null;
if (entity instanceof Player) {
player = (Player) entity;
} else if (entity instanceof Projectile) {
if (((Projectile) entity).getShooter() instanceof Player) {
player = (Player) ((Projectile) entity).getShooter();
}
}
return player;
}
}

View File

@@ -1,12 +1,18 @@
package com.willfp.ecobosses.bosses.util.bosstype;
import com.willfp.ecobosses.proxy.util.CustomEntities;
import com.willfp.ecobosses.proxy.util.CustomEntity;
import io.lumine.xikage.mythicmobs.MythicMobs;
import io.lumine.xikage.mythicmobs.mobs.MythicMob;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Zombie;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@UtilityClass
@SuppressWarnings("unchecked")
public class BossEntityUtils {
@@ -16,18 +22,36 @@ public class BossEntityUtils {
* @param id The name.
* @return The boss type.
*/
public static BossType getBossType(@NotNull final String id) {
public static BossType getBossType(@NotNull String id) {
if (id.startsWith("mythicmobs:")) {
int level;
try {
level = Integer.parseInt(Arrays.stream(id.split("_")).toList().get(id.split("_").length - 1));
} catch (NumberFormatException exception) {
level = 1;
}
MythicMob mob = MythicMobs.inst().getMobManager().getMythicMob(id.replace("mythicmobs:", "")
.replace("_" + level, ""));
if (mob != null) {
return new MythicMobsBossType(mob, level);
}
}
if (id.equalsIgnoreCase("charged_creeper")) {
return new ChargedCreeperBossType();
}
try {
Class<? extends LivingEntity> type = (Class<? extends LivingEntity>) EntityType.valueOf(id.toUpperCase()).getEntityClass();
assert type != null;
return new VanillaBossType(type);
} catch (IllegalArgumentException e) {
Class<? extends CustomEntity<? extends LivingEntity>> proxy = CustomEntities.getEntityClass(id.toLowerCase());
if (proxy != null) {
return new CustomBossType(proxy);
}
} catch (IllegalArgumentException ignored) {
}
return null;
return new VanillaBossType(Zombie.class);
}
}

View File

@@ -0,0 +1,30 @@
package com.willfp.ecobosses.bosses.util.bosstype;
import org.bukkit.Location;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
class ChargedCreeperBossType extends VanillaBossType {
/**
* Create new Charged Creeper boss type.
*/
ChargedCreeperBossType() {
super(Creeper.class);
}
/**
* Spawn a charged creeper.
*
* @param location The location.
* @return The entity.
*/
@Override
public LivingEntity spawnBossEntity(@NotNull final Location location) {
Creeper creeper = Objects.requireNonNull(location.getWorld()).spawn(location, Creeper.class);
creeper.setPowered(true);
return creeper;
}
}

View File

@@ -1,29 +0,0 @@
package com.willfp.ecobosses.bosses.util.bosstype;
import com.willfp.ecobosses.proxy.proxies.CustomEntitySpawnerProxy;
import com.willfp.ecobosses.proxy.util.CustomEntity;
import com.willfp.ecobosses.util.ProxyUtils;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
class CustomBossType extends BossType {
/**
* The entity type.
*/
private final Class<? extends CustomEntity<? extends LivingEntity>> entityClass;
/**
* Create new vanilla boss type.
*
* @param entityClass The entity class.
*/
CustomBossType(@NotNull final Class<? extends CustomEntity<? extends LivingEntity>> entityClass) {
this.entityClass = entityClass;
}
@Override
public LivingEntity spawnBossEntity(@NotNull final Location location) {
return ProxyUtils.getProxy(CustomEntitySpawnerProxy.class).spawnCustomEntity(entityClass, location);
}
}

View File

@@ -0,0 +1,46 @@
package com.willfp.ecobosses.bosses.util.bosstype;
import io.lumine.xikage.mythicmobs.MythicMobs;
import io.lumine.xikage.mythicmobs.adapters.AbstractLocation;
import io.lumine.xikage.mythicmobs.adapters.AbstractWorld;
import io.lumine.xikage.mythicmobs.api.exceptions.InvalidMobTypeException;
import io.lumine.xikage.mythicmobs.mobs.MythicMob;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class MythicMobsBossType extends BossType {
/**
* The entity type.
*/
private final MythicMob boss;
/**
* Level of MythicMobs mob
*/
private final int level;
/**
* Create new vanilla boss type.
*
* @param boss The MythicMob.
*/
public MythicMobsBossType(MythicMob boss, int level) {
this.boss = boss;
this.level = level;
}
@Override
public LivingEntity spawnBossEntity(@NotNull Location location) {
try {
return (LivingEntity) MythicMobs.inst().getAPIHelper().spawnMythicMob(boss, location, level);
} catch (InvalidMobTypeException e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -1,6 +1,7 @@
package com.willfp.ecobosses.bosses.util.bosstype;
import org.bukkit.Location;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
@@ -23,6 +24,7 @@ class VanillaBossType extends BossType {
@Override
public LivingEntity spawnBossEntity(@NotNull final Location location) {
return Objects.requireNonNull(location.getWorld()).spawn(location, entityClass);
LivingEntity result = Objects.requireNonNull(location.getWorld()).spawn(location, entityClass);
return result;
}
}

View File

@@ -0,0 +1,8 @@
package com.willfp.ecobosses.bosses.util.obj;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public record ArgumentedEffectName(@NotNull String name, @NotNull List<String> args) {
}

View File

@@ -1,18 +1,7 @@
package com.willfp.ecobosses.bosses.util.obj;
import lombok.Data;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import net.kyori.adventure.bossbar.BossBar;
@Data
public class BossbarProperties {
/**
* The BossBar color.
*/
private final BarColor color;
public record BossbarProperties(BossBar.Color color, BossBar.Overlay style) {
/**
* The BossBar style.
*/
private final BarStyle style;
}

View File

@@ -1,18 +1,7 @@
package com.willfp.ecobosses.bosses.util.obj;
import lombok.Data;
import java.util.UUID;
@Data
public class DamagerProperty {
/**
* The player.
*/
private final UUID playerUUID;
public record DamagerProperty(UUID playerUUID, double damage) {
/**
* The damage.
*/
private final double damage;
}

View File

@@ -0,0 +1,8 @@
package com.willfp.ecobosses.bosses.util.obj;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public record EquipmentPiece(@NotNull ItemStack itemStack,
double chance) {
}

View File

@@ -2,29 +2,7 @@ package com.willfp.ecobosses.bosses.util.obj;
import com.willfp.eco.util.NumberUtils;
public class ExperienceOptions {
/**
* The minimum xp to drop.
*/
private final int minimum;
/**
* The maximum xp to drop.
*/
private final int maximum;
/**
* Create new experience options.
*
* @param minimum Minimum xp.
* @param maximum Maximum xp.
*/
public ExperienceOptions(final int minimum,
final int maximum) {
this.minimum = minimum;
this.maximum = maximum;
}
public record ExperienceOptions(int minimum, int maximum) {
/**
* Generate an exp amount.
*

View File

@@ -1,31 +1,8 @@
package com.willfp.ecobosses.bosses.util.obj;
import lombok.Data;
@Data
public class ImmunityOptions {
/**
* If is immune to fire.
*/
private final boolean immuneToFire;
/**
* If is immune to suffocation.
*/
private final boolean immuneToSuffocation;
/**
* If is immune to drowning.
*/
private final boolean immuneToDrowning;
/**
* If is immune to projectiles.
*/
private final boolean immuneToProjectiles;
/**
* If is immune to explosions.
*/
private final boolean immuneToExplosions;
public record ImmunityOptions(boolean immuneToFire,
boolean immuneToSuffocation,
boolean immuneToDrowning,
boolean immuneToProjectiles,
boolean immuneToExplosions) {
}

View File

@@ -1,40 +1,9 @@
package com.willfp.ecobosses.bosses.util.obj;
import lombok.Getter;
import org.bukkit.Sound;
import org.jetbrains.annotations.NotNull;
public class OptionedSound {
/**
* The sound.
*/
@Getter
private final Sound sound;
public record OptionedSound(Sound sound,
float volume,
float pitch) {
/**
* The volume.
*/
@Getter
private final float volume;
/**
* The pitch, from 0.5 to 2.
*/
@Getter
private final float pitch;
/**
* Create a new optioned sound.
*
* @param sound The sound.
* @param volume The volume.
* @param pitch The pitch, from 0.5 to 2.
*/
public OptionedSound(@NotNull final Sound sound,
final float volume,
final float pitch) {
this.sound = sound;
this.volume = volume;
this.pitch = pitch;
}
}

View File

@@ -3,20 +3,7 @@ package com.willfp.ecobosses.bosses.util.obj;
import lombok.Data;
import org.bukkit.Material;
@Data
public class SpawnTotem {
/**
* The bottom block.
*/
private final Material bottom;
/**
* The middle block.
*/
private final Material middle;
/**
* The top block.
*/
private final Material top;
public record SpawnTotem(Material bottom,
Material middle,
Material top) {
}

View File

@@ -1,42 +0,0 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.AbstractCommand;
import com.willfp.ecobosses.EcoBossesPlugin;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
public class CommandEbdrop extends AbstractCommand {
/**
* Instantiate a new executor for /ebdrop.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandEbdrop(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "ebdrop", "ecobosses.ebdrop", true);
}
@Override
public void onExecute(@NotNull final CommandSender sender,
@NotNull final List<String> args) {
Player player = (Player) sender;
ItemStack itemStack = player.getInventory().getItemInMainHand();
String key = "drop-key";
YamlConfiguration jank = new YamlConfiguration();
jank.set(key, itemStack);
String configString = jank.saveToString();
String dropString = Base64.getEncoder().encodeToString(configString.getBytes(StandardCharsets.UTF_8));
Bukkit.getLogger().info("Copy this into the drops section of your boss yml!");
Bukkit.getLogger().info("\n" + dropString);
player.sendMessage(this.getPlugin().getLangYml().getMessage("sent-drop"));
}
}

View File

@@ -1,40 +0,0 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.AbstractCommand;
import com.willfp.ecobosses.EcoBossesPlugin;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.UUID;
public class CommandEbkillall extends AbstractCommand {
/**
* Instantiate a new executor for /ebspawn.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandEbkillall(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "ebkillall", "ecobosses.killall", false);
}
@Override
public void onExecute(@NotNull final CommandSender sender,
@NotNull final List<String> args) {
int amount = 0;
for (EcoBoss boss : EcoBosses.values()) {
for (UUID uuid : boss.getLivingBosses().keySet()) {
LivingEntity entity = (LivingEntity) Bukkit.getEntity(uuid);
assert entity != null;
entity.damage(10000000);
amount++;
}
}
sender.sendMessage(this.getPlugin().getLangYml().getMessage("killall").replace("%amount%", String.valueOf(amount)));
}
}

View File

@@ -1,27 +0,0 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.AbstractCommand;
import com.willfp.ecobosses.EcoBossesPlugin;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class CommandEbreload extends AbstractCommand {
/**
* Instantiate a new executor for /ebreload.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandEbreload(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "ebreload", "ecobosses.reload", false);
}
@Override
public void onExecute(@NotNull final CommandSender sender,
@NotNull final List<String> args) {
this.getPlugin().reload();
this.getPlugin().reload();
sender.sendMessage(this.getPlugin().getLangYml().getMessage("reloaded"));
}
}

View File

@@ -1,138 +0,0 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.AbstractCommand;
import com.willfp.eco.core.command.AbstractTabCompleter;
import com.willfp.ecobosses.EcoBossesPlugin;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class CommandEbspawn extends AbstractCommand {
/**
* Instantiate a new executor for /ebspawn.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandEbspawn(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "ebspawn", "ecobosses.ebspawn", false);
}
@Override
@Nullable
public AbstractTabCompleter getTab() {
return new TabCompleterEbspawn(this);
}
@Override
public void onExecute(@NotNull final CommandSender sender,
@NotNull final List<String> args) {
if (args.isEmpty()) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("specify-boss"));
return;
}
String bossName = args.get(0);
EcoBoss boss = EcoBosses.getByName(bossName.toLowerCase());
if (boss == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("specify-boss"));
return;
}
Location location = null;
if (sender instanceof Player) {
location = ((Player) sender).getLocation();
}
if (args.size() >= 4) {
String xString = args.get(1);
String yString = args.get(2);
String zString = args.get(3);
double xPos;
double yPos;
double zPos;
if (xString.startsWith("~") && sender instanceof Player) {
String xDiff = xString.replace("~", "");
String yDiff = yString.replace("~", "");
String zDiff = zString.replace("~", "");
if (xDiff.isEmpty()) {
xPos = ((Player) sender).getLocation().getX();
} else {
try {
xPos = ((Player) sender).getLocation().getX() + Double.parseDouble(xDiff);
} catch (NumberFormatException e) {
xPos = ((Player) sender).getLocation().getX();
}
}
if (yDiff.isEmpty()) {
yPos = ((Player) sender).getLocation().getY();
} else {
try {
yPos = ((Player) sender).getLocation().getY() + Double.parseDouble(yDiff);
} catch (NumberFormatException e) {
yPos = ((Player) sender).getLocation().getY();
}
}
if (zDiff.isEmpty()) {
zPos = ((Player) sender).getLocation().getZ();
} else {
try {
zPos = ((Player) sender).getLocation().getZ() + Double.parseDouble(yDiff);
} catch (NumberFormatException e) {
zPos = ((Player) sender).getLocation().getZ();
}
}
} else {
try {
xPos = Double.parseDouble(xString);
yPos = Double.parseDouble(yString);
zPos = Double.parseDouble(zString);
} catch (NumberFormatException e) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-location"));
return;
}
}
location = new Location(null, xPos, yPos, zPos);
}
World world = null;
if (sender instanceof Player) {
world = ((Player) sender).getWorld();
}
if (args.size() >= 5) {
world = Bukkit.getWorld(args.get(4));
}
if (location == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-location"));
return;
}
location.setWorld(world);
if (world == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-world"));
return;
}
boss.spawn(location);
sender.sendMessage(this.getPlugin().getLangYml().getMessage("spawned"));
}
}

View File

@@ -0,0 +1,28 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.impl.PluginCommand;
import com.willfp.ecobosses.EcoBossesPlugin;
import org.jetbrains.annotations.NotNull;
public class CommandEcobosses extends PluginCommand {
/**
* Instantiate a new executor for /ebdrop.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandEcobosses(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "ecobosses", "ecobosses.command.ecobosses", false);
this.addSubcommand(new CommandReload(plugin))
.addSubcommand(new CommandKillall(plugin))
.addSubcommand(new CommandSpawn(plugin))
.addSubcommand(new CommandGive(plugin));
}
@Override
public CommandHandler getHandler() {
return (sender, args) -> {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-command"));
};
}
}

View File

@@ -0,0 +1,151 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.TabCompleteHandler;
import com.willfp.eco.core.command.impl.Subcommand;
import com.willfp.eco.core.config.updating.ConfigUpdater;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class CommandGive extends Subcommand {
/**
* The cached names.
*/
private static final List<String> BOSS_NAMES = new ArrayList<>();
/**
* The cached numbers.
*/
private static final List<String> NUMBERS = Arrays.asList(
"1",
"2",
"3",
"4",
"5",
"10",
"32",
"64"
);
/**
* Instantiate a new command handler.
*
* @param plugin The plugin for the commands to listen for.
*/
public CommandGive(@NotNull final EcoPlugin plugin) {
super(plugin, "give", "ecobosses.command.give", false);
}
/**
* Called on reload.
*/
@ConfigUpdater
public static void reload() {
BOSS_NAMES.clear();
BOSS_NAMES.addAll(EcoBosses.values().stream()
.filter(boss -> boss.getSpawnEgg() != null)
.map(EcoBoss::getName)
.collect(Collectors.toList()));
}
@Override
public CommandHandler getHandler() {
return (sender, args) -> {
if (args.isEmpty()) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("needs-player"));
return;
}
if (args.size() == 1) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("needs-boss"));
return;
}
int amount = 1;
if (args.size() > 2) {
try {
amount = Integer.parseInt(args.get(2));
} catch (NumberFormatException ignored) {
// do nothing
}
}
String recieverName = args.get(0);
Player reciever = Bukkit.getPlayer(recieverName);
if (reciever == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-player"));
return;
}
String key = args.get(1);
EcoBoss boss = EcoBosses.getByName(key);
if (boss == null || boss.getSpawnEgg() == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-boss"));
return;
}
String message = this.getPlugin().getLangYml().getMessage("give-success");
message = message.replace("%boss%", boss.getName()).replace("%recipient%", reciever.getName());
sender.sendMessage(message);
ItemStack itemStack = boss.getSpawnEgg();
itemStack.setAmount(amount);
reciever.getInventory().addItem(itemStack);
};
}
@Override
public TabCompleteHandler getTabCompleter() {
return (sender, args) -> {
List<String> completions = new ArrayList<>();
if (args.isEmpty()) {
// Currently, this case is not ever reached
return BOSS_NAMES;
}
if (args.size() == 1) {
StringUtil.copyPartialMatches(args.get(0), Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()), completions);
return completions;
}
if (args.size() == 2) {
StringUtil.copyPartialMatches(args.get(1), BOSS_NAMES, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 3) {
StringUtil.copyPartialMatches(args.get(2), NUMBERS, completions);
completions.sort((s1, s2) -> {
int t1 = Integer.parseInt(s1);
int t2 = Integer.parseInt(s2);
return t1 - t2;
});
return completions;
}
return new ArrayList<>(0);
};
}
}

View File

@@ -0,0 +1,30 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.impl.Subcommand;
import com.willfp.ecobosses.EcoBossesPlugin;
import com.willfp.ecobosses.bosses.util.BossUtils;
import org.jetbrains.annotations.NotNull;
public class CommandKillall extends Subcommand {
/**
* Instantiate a new executor for /ebspawn.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandKillall(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "killall", "ecobosses.command.killall", false);
}
@Override
public CommandHandler getHandler() {
return (sender, args) -> {
boolean force = false;
if (args.size() == 1) {
force = args.get(0).equalsIgnoreCase("force");
}
sender.sendMessage(this.getPlugin().getLangYml().getMessage("killall").replace("%amount%", String.valueOf(BossUtils.killAllBosses(force))));
};
}
}

View File

@@ -0,0 +1,26 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.impl.Subcommand;
import com.willfp.ecobosses.EcoBossesPlugin;
import org.jetbrains.annotations.NotNull;
public class CommandReload extends Subcommand {
/**
* Instantiate a new executor for /ebreload.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandReload(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "reload", "ecobosses.command.reload", false);
}
@Override
public CommandHandler getHandler() {
return (sender, args) -> {
this.getPlugin().reload();
this.getPlugin().reload();
sender.sendMessage(this.getPlugin().getLangYml().getMessage("reloaded"));
};
}
}

View File

@@ -0,0 +1,210 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.CommandHandler;
import com.willfp.eco.core.command.TabCompleteHandler;
import com.willfp.eco.core.command.impl.Subcommand;
import com.willfp.eco.core.config.updating.ConfigUpdater;
import com.willfp.ecobosses.EcoBossesPlugin;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class CommandSpawn extends Subcommand {
/**
* The cached names.
*/
private static final List<String> BOSS_NAMES = new ArrayList<>();
/**
* The cached numbers.
*/
private static final List<String> TILDE = Arrays.asList(
"~"
);
/**
* Instantiate a new executor for /ebspawn.
*
* @param plugin The plugin to manage the execution for.
*/
public CommandSpawn(@NotNull final EcoBossesPlugin plugin) {
super(plugin, "spawn", "ecobosses.command.spawn", false);
reload();
}
/**
* Called on reload.
*/
@ConfigUpdater
public static void reload() {
BOSS_NAMES.clear();
BOSS_NAMES.addAll(EcoBosses.values().stream().map(EcoBoss::getName).collect(Collectors.toList()));
}
@Override
public CommandHandler getHandler() {
return (sender, args) -> {
if (args.isEmpty()) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("specify-boss"));
return;
}
String bossName = args.get(0);
EcoBoss boss = EcoBosses.getByName(bossName.toLowerCase());
if (boss == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("specify-boss"));
return;
}
Location location = null;
if (sender instanceof Player) {
location = ((Player) sender).getLocation();
}
if (args.size() >= 4) {
String xString = args.get(1);
String yString = args.get(2);
String zString = args.get(3);
double xPos;
double yPos;
double zPos;
if (xString.startsWith("~") && sender instanceof Player) {
String xDiff = xString.replace("~", "");
String yDiff = yString.replace("~", "");
String zDiff = zString.replace("~", "");
if (xDiff.isEmpty()) {
xPos = ((Player) sender).getLocation().getX();
} else {
try {
xPos = ((Player) sender).getLocation().getX() + Double.parseDouble(xDiff);
} catch (NumberFormatException e) {
xPos = ((Player) sender).getLocation().getX();
}
}
if (yDiff.isEmpty()) {
yPos = ((Player) sender).getLocation().getY();
} else {
try {
yPos = ((Player) sender).getLocation().getY() + Double.parseDouble(yDiff);
} catch (NumberFormatException e) {
yPos = ((Player) sender).getLocation().getY();
}
}
if (zDiff.isEmpty()) {
zPos = ((Player) sender).getLocation().getZ();
} else {
try {
zPos = ((Player) sender).getLocation().getZ() + Double.parseDouble(yDiff);
} catch (NumberFormatException e) {
zPos = ((Player) sender).getLocation().getZ();
}
}
} else {
try {
xPos = Double.parseDouble(xString);
yPos = Double.parseDouble(yString);
zPos = Double.parseDouble(zString);
} catch (NumberFormatException e) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-location"));
return;
}
}
location = new Location(null, xPos, yPos, zPos);
}
World world = null;
if (sender instanceof Player) {
world = ((Player) sender).getWorld();
}
if (args.size() >= 5) {
world = Bukkit.getWorld(args.get(4));
}
if (location == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-location"));
return;
}
location.setWorld(world);
if (world == null) {
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-world"));
return;
}
boss.spawn(location);
sender.sendMessage(this.getPlugin().getLangYml().getMessage("spawned"));
};
}
@Override
public TabCompleteHandler getTabCompleter() {
return (sender, args) -> {
List<String> completions = new ArrayList<>();
if (args.isEmpty()) {
// Currently, this case is not ever reached
return new ArrayList<>();
}
if (args.size() == 1) {
StringUtil.copyPartialMatches(args.get(0), BOSS_NAMES, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 2) {
StringUtil.copyPartialMatches(args.get(1), TILDE, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 3) {
StringUtil.copyPartialMatches(args.get(2), TILDE, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 4) {
StringUtil.copyPartialMatches(args.get(3), TILDE, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 5) {
StringUtil.copyPartialMatches(args.get(4), Bukkit.getWorlds().stream().map(World::getName).collect(Collectors.toList()), completions);
Collections.sort(completions);
return completions;
}
return new ArrayList<>(0);
};
}
}

View File

@@ -1,105 +0,0 @@
package com.willfp.ecobosses.commands;
import com.willfp.eco.core.command.AbstractTabCompleter;
import com.willfp.eco.core.config.ConfigUpdater;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.EcoBosses;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class TabCompleterEbspawn extends AbstractTabCompleter {
/**
* The cached names.
*/
private static final List<String> BOSS_NAMES = new ArrayList<>();
/**
* The cached numbers.
*/
private static final List<String> TILDE = Arrays.asList(
"~"
);
/**
* Instantiate a new tab-completer for /ebspawn.
*
* @param command Instance of /ebspawn.
*/
public TabCompleterEbspawn(@NotNull final CommandEbspawn command) {
super(command);
reload();
}
/**
* Called on reload.
*/
@ConfigUpdater
public static void reload() {
BOSS_NAMES.clear();
BOSS_NAMES.addAll(EcoBosses.values().stream().map(EcoBoss::getName).collect(Collectors.toList()));
}
/**
* The execution of the tabcompleter.
*
* @param sender The sender of the command.
* @param args The arguments of the command.
* @return A list of tab-completions.
*/
@Override
public List<String> onTab(@NotNull final CommandSender sender,
@NotNull final List<String> args) {
List<String> completions = new ArrayList<>();
if (args.isEmpty()) {
// Currently, this case is not ever reached
return new ArrayList<>();
}
if (args.size() == 1) {
StringUtil.copyPartialMatches(args.get(0), BOSS_NAMES, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 2) {
StringUtil.copyPartialMatches(args.get(1), TILDE, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 3) {
StringUtil.copyPartialMatches(args.get(2), TILDE, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 4) {
StringUtil.copyPartialMatches(args.get(3), TILDE, completions);
Collections.sort(completions);
return completions;
}
if (args.size() == 5) {
StringUtil.copyPartialMatches(args.get(4), Bukkit.getWorlds().stream().map(World::getName).collect(Collectors.toList()), completions);
Collections.sort(completions);
return completions;
}
return new ArrayList<>(0);
}
}

View File

@@ -1,10 +1,10 @@
package com.willfp.ecobosses.config;
import com.willfp.eco.core.config.ExtendableConfig;
import com.willfp.eco.core.config.yaml.YamlExtendableConfig;
import com.willfp.ecobosses.EcoBossesPlugin;
import org.jetbrains.annotations.NotNull;
public class BaseBossConfig extends ExtendableConfig {
public class BaseBossConfig extends YamlExtendableConfig {
/**
* Create new EcoBoss config.
*

View File

@@ -1,11 +1,11 @@
package com.willfp.ecobosses.config;
import com.willfp.eco.core.config.YamlConfig;
import com.willfp.eco.core.config.yaml.YamlTransientConfig;
import lombok.Getter;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
public class CustomConfig extends YamlConfig {
public class CustomConfig extends YamlTransientConfig {
/**
* The name of the config.
*/

View File

@@ -0,0 +1,59 @@
package com.willfp.ecobosses.events;
import com.willfp.ecobosses.bosses.EcoBoss;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class EcoBossSpawnEggEvent extends EcoBossSpawnEvent {
/**
* The egg item.
*/
@NotNull
private final ItemStack egg;
/**
* Bukkit parity.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* Default constructor
*
* @param boss - The boss to be spawned.
* @param player - The player that spawned this boss (can be null)
* @param location - The location that boss will spawn at.
* @param egg - ItemStack that represents the egg.
*/
public EcoBossSpawnEggEvent(@NotNull EcoBoss boss, @Nullable Player player, @NotNull Location location, @NotNull ItemStack egg) {
super(boss, player, location);
this.egg = egg;
}
@NotNull
public final ItemStack getEgg() {
return this.egg;
}
/**
* Bukkit parity.
*
* @return The handlers.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
/**
* Bukkit parity.
*
* @return The handler list.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -0,0 +1,141 @@
package com.willfp.ecobosses.events;
import com.willfp.ecobosses.bosses.EcoBoss;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* This class represents all boss spawn events fired by EcoBosses.
*/
public class EcoBossSpawnEvent extends Event implements Cancellable {
/**
* Event cancellation state.
*/
private boolean cancelled;
/**
* The boss to be spawned.
*/
private final EcoBoss boss;
/**
* Location that boss will be spawned at.
*/
private final Location location;
/**
* Player that spawned this boss.
* (Will be null if EcoBossSpawnTimerEvent is fired)
*/
@Nullable
private final Player player;
/**
* Bukkit parity.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
*
* Default constructor
*
* @param boss - The boss to be spawned.
* @param player - The player that spawned this boss (can be null)
* @param location - The location that boss will spawn at.
*/
public EcoBossSpawnEvent(@NotNull final EcoBoss boss, @Nullable final Player player, @NotNull final Location location) {
this.cancelled = false;
this.boss = boss;
this.location = location;
this.player = player;
}
/**
*
* Get the EcoBoss.
*
* @return - EcoBoss to be spawned.
*/
@NotNull
public EcoBoss getBoss() {
return this.boss;
}
/**
*
* Get the location.
*
* @return - Location.
*/
@NotNull
public Location getLocation() {
return this.location;
}
/**
*
* Get the player if present.
*
* @return - The player.
*/
@Nullable
public Player getPlayer() {
return this.player;
}
/**
*
* Check if this event has any player presented.
*
* @return - If any player is presented in this event.
*/
public boolean hasPlayer() {
return this.player != null;
}
/**
* Bukkit parity.
*
* @return The handlers.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
/**
*
* Get if event is cancelled.
*
* @return Event cancellation state.
*/
@Override
public boolean isCancelled() {
return this.cancelled;
}
/**
*
* Set event cancellation state.
*
* @param b - The state to set.
*/
@Override
public void setCancelled(boolean b) {
this.cancelled = b;
}
/**
* Bukkit parity.
*
* @return The handler list.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -0,0 +1,42 @@
package com.willfp.ecobosses.events;
import com.willfp.ecobosses.bosses.EcoBoss;
import org.bukkit.Location;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class EcoBossSpawnTimerEvent extends EcoBossSpawnEvent {
/**
* Bukkit parity.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* Default constructor
*
* @param boss - The boss to be spawned.
* @param location - The location that boss will spawn at.
*/
public EcoBossSpawnTimerEvent(@NotNull EcoBoss boss, @NotNull Location location) {
super(boss, null, location);
}
/**
* Bukkit parity.
*
* @return The handlers.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
/**
* Bukkit parity.
*
* @return The handler list.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -0,0 +1,59 @@
package com.willfp.ecobosses.events;
import com.willfp.ecobosses.bosses.EcoBoss;
import com.willfp.ecobosses.bosses.util.obj.SpawnTotem;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class EcoBossSpawnTotemEvent extends EcoBossSpawnEvent {
/**
* The totem.
*/
@NotNull
private final SpawnTotem totem;
/**
* Bukkit parity.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* Default constructor
*
* @param boss - The boss to be spawned.
* @param player - The player that spawned this boss (can be null)
* @param location - The location that boss will spawn at.
* @param totem - The totem.
*/
public EcoBossSpawnTotemEvent(@NotNull final EcoBoss boss, @Nullable final Player player, @NotNull final Location location, @NotNull final SpawnTotem totem) {
super(boss, player, location);
this.totem = totem;
}
@NotNull
public SpawnTotem getTotem() {
return this.totem;
}
/**
* Bukkit parity.
*
* @return The handlers.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
/**
* Bukkit parity.
*
* @return The handler list.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -0,0 +1,24 @@
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

@@ -0,0 +1,46 @@
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

@@ -1,21 +0,0 @@
package com.willfp.ecobosses.util;
import com.willfp.eco.core.proxy.AbstractProxy;
import com.willfp.ecobosses.EcoBossesPlugin;
import com.willfp.ecobosses.proxy.util.ProxyFactory;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class ProxyUtils {
/**
* Get the implementation of a specified proxy.
*
* @param proxyClass The proxy interface.
* @param <T> The type of the proxy.
* @return The proxy implementation.
*/
public @NotNull <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxyClass) {
return new ProxyFactory<>(EcoBossesPlugin.getInstance(), proxyClass).getProxy();
}
}

View File

@@ -1,7 +1,8 @@
enabled: true
name: "&fAlpha Wolf &7| &c%health%♥" # Display name
base-mob: wolf # Any existing mob - custom_illusioner is also accepted (like in the old Illusioner plugin)
name: "&fAlpha Wolf &7| &c%health%♥ &7| &e%time%" # Display name
base-mob: wolf
baby: false # If set to true: will make the boss mob baby (if possible)
bossbar:
enabled: true
@@ -12,12 +13,37 @@ max-health: 600
attack-damage: 50
movement-speed: 2
follow-range: 15
time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to disable.
glowing: false # Should this boss have glowing effect
auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable.
auto-spawn-locations: [ ] # Formatted as world:x:y:z - for example world_nether:100:10:100
spawn-totem:
spawn-requirements: []
spawn-egg:
enabled: true
material: wolf_spawn_egg
name: "&fAlpha Wolf Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&osummon an &fAlpha Wolf"
glow: true
craftable: true
recipe:
- bone_block
- netherite_block
- bone_block
- bone
- ecoitems:boss_core ? nether_star
- bone
- bone_block
- netherite_block
- bone_block
spawn-totem:
enabled: false
top: beacon
middle: bone_block
bottom: bone_block
@@ -38,8 +64,7 @@ rewards:
# Use %player% as the placeholder for the player name
commands: []
# Get items to add here by copying the console output for /ebdrop
# To set the chance for a drop, put <chance>::<base64>
# To set the chance for a drop, put <chance>::item
drops: []
broadcast:
@@ -56,6 +81,10 @@ broadcast:
- "&f - %second%&f (%second_damage% Damage)"
- "&f - %third%&f (%third_damage% Damage)"
- ""
despawn:
- ""
- "&fYou ran out of time to kill the &lAlpha Wolf&r&f!"
- ""
# Effects can be found on the wiki! https://ecobosses.willfp.com/
effects:
@@ -63,6 +92,23 @@ effects:
- "give-potion-effect:wither:4:200:10"
- "give-potion-effect:hunger:10:600:10"
gear:
helmet:
item: ""
chance: 100
chestplate:
item: ""
chance: 100
leggings:
item: ""
chance: 100
boots:
item: ""
chance: 100
hand:
item: ""
chance: 100
defence:
immunities:
explosion: false
@@ -104,6 +150,10 @@ sounds:
- "entity_wolf_death:50:0.7"
- "entity_wolf_growl:50:0.8"
despawn:
- "entity_ender_dragon_ambient:50:0.5"
- "entity_enderman_death:50:0.5"
summon: # On summon enemy
- "entity_wolf_pant:10:0.8"

View File

@@ -1,7 +1,8 @@
enabled: true
name: "&9Illusioner &7| &c%health%♥" # Display name
base-mob: custom_illusioner # Any existing mob - custom_illusioner is also accepted (like in the old Illusioner plugin)
name: "&9Dark Guardian &7| &c%health%♥ &7| &e%time%" # Display name
base-mob: ravager
baby: false # If set to true: will make the boss mob baby (if possible)
bossbar:
enabled: true
@@ -12,12 +13,37 @@ max-health: 300
attack-damage: 30
movement-speed: 1.2
follow-range: 20
time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to disable.
glowing: false # Should this boss have glowing effect
auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable.
auto-spawn-locations: [ ] # Formatted as world:x:y:z - for example world_nether:100:10:100
spawn-totem:
spawn-requirements: []
spawn-egg:
enabled: true
material: ravager_spawn_egg
name: "&9Dark Guardian&f Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&osummon a &9Dark Guardian"
glow: true
craftable: true
recipe:
- emerald
- netherite_block
- emerald
- air
- ecoitems:boss_core ? nether_star
- air
- emerald
- netherite_block
- emerald
spawn-totem:
enabled: false
top: carved_pumpkin
middle: beacon
bottom: diamond_block
@@ -38,34 +64,54 @@ rewards:
# Use %player% as the placeholder for the player name
commands: []
# Get items to add here by copying the console output for /ebdrop
# To set the chance for a drop, put <chance>::<base64>
# To set the chance for a drop, put <chance>::item
drops: []
broadcast:
spawn:
- ""
- "&fAn &9&lIllusioner&r&f has been spawned!"
- "&fA &9&lDark Guardian&r&f has been spawned!"
- "&fCome fight it at &9%x%&f, &9%y%&f, &9%z%&f!"
- ""
death:
- ""
- "&fThe &9&lIllusioner&r&f has been killed!"
- "&fThe &9&lDark Guardian&r&f has been killed!"
- "&fMost Damage:"
- "&f - &9%top%&f (%top_damage% Damage)"
- "&f - &9%second%&f (%second_damage% Damage)"
- "&f - &9%third%&f (%third_damage% Damage)"
- ""
despawn:
- ""
- "&fYou ran out of time to kill the &9&lDark Guardian&r&f!"
- ""
# Effects can be found on the wiki! https://ecobosses.willfp.com/
effects:
- "summon:evoker:10"
- "summon:vindicator:10"
- "summon:enderman:10"
- "shuffle-hotbar:10"
- "give-potion-effect:confusion:10:200:10"
- "give-potion-effect:blindness:1:40:20"
- "teleport:7:15"
gear:
helmet:
item: ""
chance: 100
chestplate:
item: ""
chance: 100
leggings:
item: ""
chance: 100
boots:
item: ""
chance: 100
hand:
item: ""
chance: 100
defence:
immunities:
explosion: true
@@ -102,11 +148,17 @@ sounds:
spawn: # On spawn
- "entity_illusioner_mirror_move:100:0.5"
- "entity_wither_spawn:100:2"
- "entity_enderman_death:50:2"
death: # On death
- "entity_evoker_prepare_wololo:50:0.8"
- "entity_illusioner_prepare_blindness:50:1"
- "entity_wither_death:50:2"
- "entity_enderman_death:50:0.5"
despawn:
- "entity_ender_dragon_ambient:50:0.5"
- "entity_enderman_death:50:0.5"
summon: # On summon enemy
- "entity_evoker_prepare_attack:10:2"

View File

@@ -1,7 +1,8 @@
enabled: true
name: "&8Steel Golem &7| &c%health%♥" # Display name
base-mob: iron_golem # Any existing mob - custom_illusioner is also accepted (like in the old Illusioner plugin)
name: "&8Steel Golem &7| &c%health%♥ &7| &e%time%" # Display name
base-mob: iron_golem
baby: false # If set to true: will make the boss mob baby (if possible)
bossbar:
enabled: true
@@ -12,12 +13,37 @@ max-health: 1200
attack-damage: 90
movement-speed: 1.5
follow-range: 16
time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to disable.
glowing: false # Should this boss have glowing effect
auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable.
auto-spawn-locations: [] # Formatted as world:x:y:z - for example world_nether:100:10:100
spawn-totem:
spawn-requirements: []
spawn-egg:
enabled: true
material: evoker_spawn_egg
name: "&8Steel Golem&f Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&osummon a &8Steel Golem"
glow: true
craftable: true
recipe:
- iron_block
- netherite_block
- iron_block
- air
- ecoitems:boss_core ? nether_star
- air
- iron_block
- netherite_block
- iron_block
spawn-totem:
enabled: false
top: netherite_block
middle: iron_block
bottom: magma_block
@@ -38,8 +64,7 @@ rewards:
# Use %player% as the placeholder for the player name
commands: []
# Get items to add here by copying the console output for /ebdrop
# To set the chance for a drop, put <chance>::<base64>
# To set the chance for a drop, put <chance>::item
drops: []
broadcast:
@@ -56,6 +81,10 @@ broadcast:
- "&f - &8%second%&f (%second_damage% Damage)"
- "&f - &8%third%&f (%third_damage% Damage)"
- ""
despawn:
- ""
- "&fYou ran out of time to kill the &8&lSteel Golem&r&f!"
- ""
# Effects can be found on the wiki! https://ecobosses.willfp.com/
effects:
@@ -67,6 +96,23 @@ effects:
- "give-potion-effect:slow:5:100:20"
- "give-potion-effect:levitation:3:50:10"
gear:
helmet:
item: ""
chance: 100
chestplate:
item: ""
chance: 100
leggings:
item: ""
chance: 100
boots:
item: ""
chance: 100
hand:
item: ""
chance: 100
defence:
immunities:
explosion: true
@@ -109,6 +155,10 @@ sounds:
- "entity_ender_dragon_death:50:1.8"
- "entity_wither_death:50:1.2"
despawn:
- "entity_ender_dragon_ambient:50:0.5"
- "entity_enderman_death:50:0.5"
summon: # On summon enemy
- "entity_iron_golem_step:10:1.2"

View File

@@ -1,7 +1,8 @@
enabled: true
name: "&4Tarantula &7| &c%health%♥" # Display name
base-mob: cave_spider # Any existing mob - custom_illusioner is also accepted (like in the old Illusioner plugin)
name: "&4Tarantula &7| &c%health%♥ &7| &e%time%" # Display name
base-mob: cave_spider
baby: false # If set to true: will make the boss mob baby (if possible)
bossbar:
enabled: true
@@ -12,12 +13,37 @@ max-health: 900
attack-damage: 70
movement-speed: 1.3
follow-range: 15
time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to disable.
glowing: false # Should this boss have glowing effect
auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable.
auto-spawn-locations: [ ] # Formatted as world:x:y:z - for example world_nether:100:10:100
spawn-totem:
spawn-requirements: []
spawn-egg:
enabled: true
material: cave_spider_spawn_egg
name: "&4Tarantula&f Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&osummon a &4Tarantula"
glow: true
craftable: true
recipe:
- string
- netherite_block
- string
- air
- ecoitems:boss_core ? nether_star
- air
- string
- netherite_block
- string
spawn-totem:
enabled: false
top: netherite_block
middle: red_wool
bottom: white_wool
@@ -38,8 +64,7 @@ rewards:
# Use %player% as the placeholder for the player name
commands: []
# Get items to add here by copying the console output for /ebdrop
# To set the chance for a drop, put <chance>::<base64>
# To set the chance for a drop, put <chance>::item
drops: []
broadcast:
@@ -56,6 +81,10 @@ broadcast:
- "&f - &4%second%&f (%second_damage% Damage)"
- "&f - &4%third%&f (%third_damage% Damage)"
- ""
despawn:
- ""
- "&fYou ran out of time to kill the &4&lTarantula&r&f!"
- ""
# Effects can be found on the wiki! https://ecobosses.willfp.com/
effects:
@@ -67,6 +96,23 @@ effects:
- "give-potion-effect:hunger:5:400:10"
- "give-potion-effect:slow_digging:3:40:10"
gear:
helmet:
item: ""
chance: 100
chestplate:
item: ""
chance: 100
leggings:
item: ""
chance: 100
boots:
item: ""
chance: 100
hand:
item: ""
chance: 100
defence:
immunities:
explosion: false
@@ -108,6 +154,10 @@ sounds:
- "entity_spider_death:50:0.7"
- "entity_wither_death:50:0.5"
despawn:
- "entity_ender_dragon_ambient:50:0.5"
- "entity_enderman_death:50:0.5"
summon: # On summon enemy
- "entity_spider_step:10:1.2"

View File

@@ -4,5 +4,6 @@
#
bossbar-radius: 50 # How far away players should be able to see the boss bar for bosses.
discover-recipes: true
# Read the wiki! https://ecobosses.willfp.com/

View File

@@ -1,6 +1,7 @@
messages:
prefix: "&9&lEcoBosses &f» "
no-permission: "&cYou don't have permission to do this!"
invalid-command: "&cUnknown subcommand!"
not-player: "&cThis command must be run by a player"
reloaded: "Reloaded!"
sent-drop: "Check console for the drop!"
@@ -8,5 +9,11 @@ messages:
invalid-location: "&cInvalid location!"
spawned: "Spawned a boss!"
killall: "Killed &a%amount%&f bosses!"
needs-player: "&cYou must specify a player"
invalid-player: "&cInvalid player!"
needs-stone: "&cYou must specify a boss"
invalid-stone: "&cInvalid boss!"
give-success: "Gave &a%boss%&r spawn egg to &a%recipient%"
requirements-not-met: "&cYou can't spawn this boss!"
na: "N/A"

View File

@@ -5,45 +5,48 @@ api-version: 1.16
authors: [Auxilor]
website: willfp.com
load: STARTUP
softdepend:
- MythicMobs
- LevelledMobs
depend:
- eco
commands:
ebreload:
description: Reloads config
permission: ecobosses.reload
ebdrop:
description: Sends the held item to console to be added as a drop
permission: ecobosses.ebdrop
ebspawn:
description: Spawns a boss
permission: ecobosses.ebspawn
ebkillall:
description: Kill all bosses
permission: ecobosses.killall
ecobosses:
description: Base command
permission: ecobosses.command.ecobosses
permissions:
ecobosses.*:
description: All ecobosses permissions
default: op
children:
ecobosses.reload: true
ecobosses.ebdrop: true
ecobosses.ebspawn: true
ecobosses.killall: true
ecobosses.command.*: true
ecobosses.command.*:
description: All ecobosses commands
default: op
children:
ecobosses.command.ecobosses: true
ecobosses.command.reload: true
ecobosses.command.spawn: true
ecobosses.command.give: true
ecobosses.reload:
description: Allows reloading the config
ecobosses.command.ecobosses:
description: Allows the use of /ecobosses
default: true
ecobosses.command.give:
description: Allows the use of /ecobosses give
default: op
ecobosses.ebdrop:
description: Allows the use of /ebdrop
ecobosses.command.spawn:
description: Allows the use of /ecobosses spawn
default: op
ecobosses.ebspawn:
description: Allows the use of /ebspawn
ecobosses.command.killall:
description: Allows the use of /ecobosses killall
default: op
ecobosses.killall:
description: Allows the use of /ebkillall
ecobosses.command.reload:
description: Allows the use of /ecobosses reload
default: op

View File

@@ -1,6 +0,0 @@
group 'com.willfp'
version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
}

View File

@@ -1,21 +0,0 @@
package com.willfp.ecobosses.proxy.proxies;
import com.willfp.eco.core.proxy.AbstractProxy;
import com.willfp.ecobosses.proxy.util.CustomEntity;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface CustomEntitySpawnerProxy extends AbstractProxy {
/**
* Spawn custom entity.
*
* @param <T> The class.
* @param entityClass The custom entity proxy class.
* @param location The location.
* @return The bukkit entity, or null if invalid class.
*/
@Nullable <T extends LivingEntity> T spawnCustomEntity(Class<? extends CustomEntity<? extends LivingEntity>> entityClass,
@NotNull Location location);
}

View File

@@ -1,9 +0,0 @@
package com.willfp.ecobosses.proxy.proxies;
import com.willfp.eco.core.proxy.AbstractProxy;
import com.willfp.ecobosses.proxy.util.CustomEntity;
import org.bukkit.entity.Illusioner;
public interface CustomIllusionerProxy extends AbstractProxy, CustomEntity<Illusioner> {
}

View File

@@ -1,30 +0,0 @@
package com.willfp.ecobosses.proxy.util;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@UtilityClass
public class CustomEntities {
/**
* Registered custom entities.
*/
private static final BiMap<String, Class<? extends CustomEntity<? extends LivingEntity>>> REGISTRY = new ImmutableBiMap.Builder<String, Class<? extends CustomEntity<? extends LivingEntity>>>()
.put("custom_illusioner", CustomIllusionerProxy.class)
.build();
/**
* Get entity class.
*
* @param id The entity id.
* @return The class.
*/
@Nullable
public Class<? extends CustomEntity<? extends LivingEntity>> getEntityClass(@NotNull final String id) {
return REGISTRY.get(id);
}
}

View File

@@ -1,7 +0,0 @@
package com.willfp.ecobosses.proxy.util;
import org.bukkit.entity.LivingEntity;
public interface CustomEntity<T extends LivingEntity> {
}

View File

@@ -1,75 +0,0 @@
package com.willfp.ecobosses.proxy.util;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.PluginDependent;
import com.willfp.eco.core.proxy.AbstractProxy;
import com.willfp.eco.core.proxy.ProxyConstants;
import com.willfp.eco.core.proxy.UnsupportedVersionException;
import org.jetbrains.annotations.NotNull;
import java.util.IdentityHashMap;
import java.util.Map;
public class ProxyFactory<T extends AbstractProxy> extends PluginDependent {
/**
* Cached proxy implementations in order to not perform expensive reflective class-finding.
*/
private static final Map<Class<? extends AbstractProxy>, AbstractProxy> CACHE = new IdentityHashMap<>();
/**
* The class of the proxy interface.
*/
private final Class<T> proxyClass;
/**
* Create a new Proxy Factory for a specific type.
*
* @param plugin The plugin to create proxies for.
* @param proxyClass The class of the proxy interface.
*/
public ProxyFactory(@NotNull final EcoPlugin plugin,
@NotNull final Class<T> proxyClass) {
super(plugin);
this.proxyClass = proxyClass;
}
/**
* Get the implementation of a proxy.
*
* @return The proxy implementation.
*/
public @NotNull T getProxy() {
try {
T cachedProxy = attemptCache();
if (cachedProxy != null) {
return cachedProxy;
}
String className = this.getPlugin().getProxyPackage() + "." + ProxyConstants.NMS_VERSION + "." + proxyClass.getSimpleName().replace("Proxy", "");
final Class<?> class2 = Class.forName(className);
Object instance = class2.getConstructor().newInstance();
if (proxyClass.isAssignableFrom(class2) && proxyClass.isInstance(instance)) {
T proxy = proxyClass.cast(instance);
CACHE.put(proxyClass, proxy);
return proxy;
}
} catch (Exception e) {
// If not returned, then throw error
}
throw new UnsupportedVersionException("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION);
}
private T attemptCache() {
Object proxy = CACHE.get(proxyClass);
if (proxy == null) {
return null;
}
if (proxyClass.isInstance(proxy)) {
return proxyClass.cast(proxy);
}
return null;
}
}

View File

@@ -1,2 +1,2 @@
version = 5.0.0
version = 6.8.0
plugin-name = EcoBosses

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

2
gradlew vendored Normal file → Executable file
View File

@@ -130,7 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath

21
gradlew.bat vendored
View File

@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -64,21 +64,6 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
@@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

6
jitpack.yml Normal file
View File

@@ -0,0 +1,6 @@
jdk: openjdk16
before_install:
- source "$HOME/.sdkman/bin/sdkman-init.sh"
- sdk update
- sdk install java 16.0.1-open
- sdk use java 16.0.1-open

Binary file not shown.

Binary file not shown.

View File

@@ -1,11 +1,12 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url "https://repo.jpenilla.xyz/snapshots/" }
}
}
rootProject.name = 'EcoBosses'
// Core
include ':eco-core'
include ':eco-core:core-nms'
include ':eco-core:core-nms:v1_15_R1'
include ':eco-core:core-nms:v1_16_R1'
include ':eco-core:core-nms:v1_16_R2'
include ':eco-core:core-nms:v1_16_R3'
include ':eco-core:core-proxy'
include ':eco-core:core-plugin'