mirror of
https://github.com/Auxilor/EcoMobs.git
synced 2025-12-19 15:09:17 +00:00
Compare commits
435 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed0fd90df8 | ||
|
|
42af89c79a | ||
|
|
d453461eeb | ||
|
|
e4093a0fd5 | ||
|
|
7e950ea508 | ||
|
|
ac79baa2d3 | ||
|
|
50adfae567 | ||
|
|
153022c3bf | ||
|
|
8d37635381 | ||
|
|
299d3ee1d6 | ||
|
|
f0a2d32b95 | ||
|
|
4e86750c7d | ||
|
|
b3b7695218 | ||
|
|
1aa0a27c65 | ||
|
|
392a76bad8 | ||
|
|
95afe96860 | ||
|
|
21d24a5198 | ||
|
|
af9766a391 | ||
|
|
df70871bad | ||
|
|
b030af609a | ||
|
|
344e71cd9a | ||
|
|
7b7a16f9c6 | ||
|
|
ba1c348f8e | ||
|
|
c81f7174e2 | ||
|
|
53b037816d | ||
|
|
d7e07c1a62 | ||
|
|
d939296d96 | ||
|
|
2505ddd845 | ||
|
|
ea7371db9e | ||
|
|
b53ab306ed | ||
|
|
33f82117e4 | ||
|
|
a80e060a7e | ||
|
|
a915752922 | ||
|
|
06eb724bd8 | ||
|
|
18c66ef10c | ||
|
|
ae0c8531b0 | ||
|
|
705eafb9af | ||
|
|
e83ede56f0 | ||
|
|
6bddf72111 | ||
|
|
d32d07f4e2 | ||
|
|
8c40d9861d | ||
|
|
03272f794e | ||
|
|
8ff42da43c | ||
|
|
7f61f6a66a | ||
|
|
c1dde026b7 | ||
|
|
983246a7c4 | ||
|
|
ee32897b1c | ||
|
|
67b38896ca | ||
|
|
39b91bc828 | ||
|
|
e2e7b44a75 | ||
|
|
3c1e5ee192 | ||
|
|
56789f331b | ||
|
|
e99b96132f | ||
|
|
c0297cd3db | ||
|
|
3b798a8ed7 | ||
|
|
bc73201ec5 | ||
|
|
b1365855af | ||
|
|
1ce50cb0b9 | ||
|
|
2a50868624 | ||
|
|
0a0e7a9661 | ||
|
|
8cd4ccdbd7 | ||
|
|
429bc6a61f | ||
|
|
b92ea06667 | ||
|
|
1e332bf845 | ||
|
|
7cec9f3e30 | ||
|
|
7db3af5dca | ||
|
|
137f4e3732 | ||
|
|
7338a24b81 | ||
|
|
bde5de1d77 | ||
|
|
b48cc66383 | ||
|
|
bf59ba4d4a | ||
|
|
127a43e032 | ||
|
|
383893c8f6 | ||
|
|
37926bd016 | ||
|
|
6778058150 | ||
|
|
8addad09d2 | ||
|
|
7fe0eece16 | ||
|
|
eca8726323 | ||
|
|
16ba41f39a | ||
|
|
685f40a71b | ||
|
|
76c6d22a00 | ||
|
|
38629407bc | ||
|
|
1eee00b88e | ||
|
|
de47ccf159 | ||
|
|
b81e7af836 | ||
|
|
fcde21c21a | ||
|
|
405659f293 | ||
|
|
2d6154d11f | ||
|
|
9fad76ffad | ||
|
|
e4a40470b8 | ||
|
|
f966629e21 | ||
|
|
93d09c1f3d | ||
|
|
56763be02d | ||
|
|
bd05d4474f | ||
|
|
aa0f9c195d | ||
|
|
e9e0214d1e | ||
|
|
744e3a943d | ||
|
|
fcaea262e8 | ||
|
|
062d2eea77 | ||
|
|
25844170eb | ||
|
|
00cc509b40 | ||
|
|
77e46ffb55 | ||
|
|
1f72e3b9b3 | ||
|
|
a94a5cc04d | ||
|
|
2b8d8eb20a | ||
|
|
1b4851fb9c | ||
|
|
80181bb66e | ||
|
|
d2d6355003 | ||
|
|
b44016d4fe | ||
|
|
74f1953074 | ||
|
|
041e8e070e | ||
|
|
d69b205de5 | ||
|
|
ad827f2b65 | ||
|
|
e8b8dcd2c4 | ||
|
|
e54660cf5e | ||
|
|
7a21d1897d | ||
|
|
64726f665f | ||
|
|
e4fdaeec1d | ||
|
|
3c5fbd6151 | ||
|
|
4329431994 | ||
|
|
c55692e89f | ||
|
|
03466f7892 | ||
|
|
1a6ebd4455 | ||
|
|
486f071dea | ||
|
|
fb4eac5e5e | ||
|
|
49d1d3f054 | ||
|
|
6dc7426146 | ||
|
|
00c5ead347 | ||
|
|
9bd501dfbe | ||
|
|
67d55bbdc2 | ||
|
|
46aa086366 | ||
|
|
9f00334ea4 | ||
|
|
e6db159bfb | ||
|
|
3df7b75737 | ||
|
|
c243a425b3 | ||
|
|
e57fe61d22 | ||
|
|
9830aed484 | ||
|
|
999b89bcb0 | ||
|
|
e7f326efbb | ||
|
|
0cb5b0b7b7 | ||
|
|
8e2d901e9b | ||
|
|
724eede36e | ||
|
|
01a2cc7118 | ||
|
|
20aace3727 | ||
|
|
ec9d4c0dd6 | ||
|
|
b3a0c1fa67 | ||
|
|
88294a17cd | ||
|
|
1ac6a350ec | ||
|
|
a9333cb8b5 | ||
|
|
05cf399e77 | ||
|
|
de2b8f7526 | ||
|
|
23085e74e2 | ||
|
|
80f02a07a4 | ||
|
|
a63625593d | ||
|
|
1dfd7bac1f | ||
|
|
34b983b185 | ||
|
|
33b2fd9e13 | ||
|
|
85cfb542dc | ||
|
|
197f9e91aa | ||
|
|
9d4a91805a | ||
|
|
87b91c46d1 | ||
|
|
4a7e6e9ff1 | ||
|
|
b59e54be01 | ||
|
|
d26f0294cc | ||
|
|
150433d46b | ||
|
|
7de4d75c93 | ||
|
|
9790459a26 | ||
|
|
666a80b401 | ||
|
|
59810059aa | ||
|
|
7b604c7812 | ||
|
|
81eab18e42 | ||
|
|
fa54c7022b | ||
|
|
26f976a7ca | ||
|
|
4fa070dabe | ||
|
|
f73327b204 | ||
|
|
d9b702f2f1 | ||
|
|
7692e84a60 | ||
|
|
ffd6037e73 | ||
|
|
7c959d7221 | ||
|
|
91ad33334d | ||
|
|
c1b8ed5b48 | ||
|
|
2f3c5f60a4 | ||
|
|
f3387668e6 | ||
|
|
b62e79d904 | ||
|
|
d7afeecc27 | ||
|
|
72e61940c5 | ||
|
|
245445473b | ||
|
|
46772ac97a | ||
|
|
29a1e541a2 | ||
|
|
89a6bc97b7 | ||
|
|
c59707e6ac | ||
|
|
99bc2a04ab | ||
|
|
b4e90d9bda | ||
|
|
72c3722429 | ||
|
|
c14b2f0a80 | ||
|
|
0b6c7152e8 | ||
|
|
6e551eeaeb | ||
|
|
d5610ae804 | ||
|
|
79c8ed4992 | ||
|
|
947a0f3c6d | ||
|
|
ce8b0af155 | ||
|
|
a41e5b702d | ||
|
|
f04bf3aeea | ||
|
|
08941461c9 | ||
|
|
743dbac656 | ||
|
|
2e8d1ea4cc | ||
|
|
d31a98fd99 | ||
|
|
f7244a7d7f | ||
|
|
268ed76951 | ||
|
|
d0ccb78c17 | ||
|
|
34de040849 | ||
|
|
6b01f8e64a | ||
|
|
2a4d5a8fd2 | ||
|
|
f9d7315fd3 | ||
|
|
497f42ccc6 | ||
|
|
d149eb7907 | ||
|
|
47277d0dd8 | ||
|
|
f307f13d1e | ||
|
|
ac3370c0be | ||
|
|
4f616ac8c8 | ||
|
|
24256e9789 | ||
|
|
bbf20e77d0 | ||
|
|
8a506c015b | ||
|
|
744883630d | ||
|
|
8519f4fc23 | ||
|
|
d1cb11ef79 | ||
|
|
edcc185b58 | ||
|
|
ab6d297222 | ||
|
|
9626588c66 | ||
|
|
c4eda19d78 | ||
|
|
691326577a | ||
|
|
e2086387e7 | ||
|
|
13a72f849d | ||
|
|
6346975e77 | ||
|
|
0d846d9dff | ||
|
|
31610383c4 | ||
|
|
d7c16ad3cc | ||
|
|
afe9095276 | ||
|
|
31a782581f | ||
|
|
8aad221450 | ||
|
|
b0bff24263 | ||
|
|
04b00fa01b | ||
|
|
276ba4616a | ||
|
|
d8e5fb9cd0 | ||
|
|
9f05a6504a | ||
|
|
322a6bb41b | ||
|
|
4dbc8afdf4 | ||
|
|
7ffa6ff4f4 | ||
|
|
3769684bb0 | ||
|
|
7bb931e027 | ||
|
|
879d6dd72d | ||
|
|
0a4aff45ad | ||
|
|
5929da1f48 | ||
|
|
6db5de581b | ||
|
|
9ce1bb7ddf | ||
|
|
351d34de9f | ||
|
|
4d2b726aa0 | ||
|
|
ff20b70784 | ||
|
|
f31cd20200 | ||
|
|
0ad2d3cfc7 | ||
|
|
ccc7c5797a | ||
|
|
a218fa96c0 | ||
|
|
13c0a4d83a | ||
|
|
62e7177b1b | ||
|
|
752b30b4a2 | ||
|
|
be4d6156e3 | ||
|
|
fed6dcafd7 | ||
|
|
36f944c58c | ||
|
|
1bc35656fe | ||
|
|
1216e83a39 | ||
|
|
4723c7982c | ||
|
|
8ba3c7834c | ||
|
|
76530a1617 | ||
|
|
bf41554846 | ||
|
|
a741c78b6b | ||
|
|
0f8dce74da | ||
|
|
0d31556b84 | ||
|
|
f8544c284e | ||
|
|
512a477fc6 | ||
|
|
8a1b473837 | ||
|
|
7464133c74 | ||
|
|
1e00b28a8b | ||
|
|
b152313f87 | ||
|
|
ec6d7175b9 | ||
|
|
804a0e88b9 | ||
|
|
ff2de5aebe | ||
|
|
990ad363eb | ||
|
|
d958b94fb0 | ||
|
|
e4f2a91968 | ||
|
|
f1d50d6222 | ||
|
|
035550db06 | ||
|
|
f4bd64c192 | ||
|
|
4b8e1c0579 | ||
|
|
d8cf08eb25 | ||
|
|
a94c96e5d4 | ||
|
|
dddf2d8a20 | ||
|
|
7e67620c8c | ||
|
|
8c44303cdc | ||
|
|
97c1045243 | ||
|
|
c47019f3c5 | ||
|
|
1ffedfcb2e | ||
|
|
17705e9fdb | ||
|
|
7087feefbc | ||
|
|
31504975ce | ||
|
|
142894c0f4 | ||
|
|
1babbcb377 | ||
|
|
87ca7e3718 | ||
|
|
aee2b376c4 | ||
|
|
6ca3441f3b | ||
|
|
af1eb8d27c | ||
|
|
db3bc38e9c | ||
|
|
f7961ba7f3 | ||
|
|
4765b20d20 | ||
|
|
64b22a17d6 | ||
|
|
b1ad28eee4 | ||
|
|
f6f9fb3c1d | ||
|
|
4093fa92bd | ||
|
|
96a6c3d700 | ||
|
|
61de345aec | ||
|
|
68b5886505 | ||
|
|
f768890e46 | ||
|
|
8f12af5d49 | ||
|
|
28c0162a5e | ||
|
|
3360ceddca | ||
|
|
e575df9f37 | ||
|
|
474b9bcffd | ||
|
|
d583167dbb | ||
|
|
baa2b6718e | ||
|
|
03efa137f4 | ||
|
|
765b65343a | ||
|
|
172a345b87 | ||
|
|
b1a3c03181 | ||
|
|
e39c01a4a2 | ||
|
|
24e5b6d2f4 | ||
|
|
4ff099ab45 | ||
|
|
055d792168 | ||
|
|
a355b55ff2 | ||
|
|
6ac3001e52 | ||
|
|
0f04ca86d9 | ||
|
|
f7422b012d | ||
|
|
d95de6926e | ||
|
|
ab13053987 | ||
|
|
ab23e19804 | ||
|
|
c4a04ed048 | ||
|
|
b6941baa50 | ||
|
|
0a1cc72afc | ||
|
|
086f50b0b6 | ||
|
|
bd51eb9d7d | ||
|
|
95462086d2 | ||
|
|
39df2c9c6d | ||
|
|
a6713661a2 | ||
|
|
a995568485 | ||
|
|
470f39da09 | ||
|
|
b13bcdd14c | ||
|
|
97a07f31bf | ||
|
|
d4134b4443 | ||
|
|
770ee369e5 | ||
|
|
978022df6e | ||
|
|
58a05b41c6 | ||
|
|
ec2bed91c4 | ||
|
|
041ec1c79e | ||
|
|
f0b09c035e | ||
|
|
4c6ac852aa | ||
|
|
9772081d7b | ||
|
|
cea2d96819 | ||
|
|
9dbba3f751 | ||
|
|
9cecb33b04 | ||
|
|
7b60749b88 | ||
|
|
e0d03cc8ed | ||
|
|
80109fc061 | ||
|
|
c1fc918757 | ||
|
|
955a378b98 | ||
|
|
a1875933c8 | ||
|
|
cf3c302513 | ||
|
|
2acdc4a74e | ||
|
|
0e2cdb71cb | ||
|
|
f1c26763e0 | ||
|
|
b75b83aebf | ||
|
|
ea2b14fbec | ||
|
|
0747a0a3d4 | ||
|
|
260aec8ba4 | ||
|
|
77985e5a23 | ||
|
|
201ec4161b | ||
|
|
468b0b4292 | ||
|
|
203bec560e | ||
|
|
a2c8b73dbc | ||
|
|
31ccdf2589 | ||
|
|
7ea1f8938b | ||
|
|
436e833213 | ||
|
|
60b4c1c246 | ||
|
|
c5f5032e17 | ||
|
|
310ace62b3 | ||
|
|
0af79cfc27 | ||
|
|
a107d78937 | ||
|
|
d8c229d4fa | ||
|
|
406601a193 | ||
|
|
fb9fdacb9f | ||
|
|
45bbc668dc | ||
|
|
b5f222976b | ||
|
|
10d297e0da | ||
|
|
76df0fd2ef | ||
|
|
56b76f70c6 | ||
|
|
30e0ed02a4 | ||
|
|
2795fa8220 | ||
|
|
cbeff28dbf | ||
|
|
38dd7ea604 | ||
|
|
af72bfbbb6 | ||
|
|
de675b49be | ||
|
|
3df4cfaae7 | ||
|
|
32ac455720 | ||
|
|
89a7d37d37 | ||
|
|
04eff9d3f3 | ||
|
|
c3c96a6892 | ||
|
|
d135922dc1 | ||
|
|
1569d12b44 | ||
|
|
aea6e5c2f1 | ||
|
|
d837311ae2 | ||
|
|
c66b914104 | ||
|
|
1f73b9acf7 | ||
|
|
cafb41567f | ||
|
|
8f912abf31 | ||
|
|
2fe8c9197d | ||
|
|
46eccfc345 | ||
|
|
7804cebd53 | ||
|
|
1918a46678 | ||
|
|
99de824b04 | ||
|
|
b18eb3942a | ||
|
|
7434bbb38e | ||
|
|
7bf88ed09a | ||
|
|
d8f54cb9f6 | ||
|
|
3bc5ed6f6a | ||
|
|
ab759afe56 | ||
|
|
3ae961c9c5 | ||
|
|
b6754c6d5c | ||
|
|
846b03d8bc |
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Discord
|
||||||
|
url: https://discord.gg/ZcwpSsE/
|
||||||
|
about: Issues have moved to Discord, please join the server to get help!
|
||||||
11
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: Report a Bug
|
||||||
|
about: Report an issue with the plugin
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
# Please report bugs on the discord!
|
||||||
|
|
||||||
|
[Join by clicking here](https://discord.gg/ZcwpSsE/)
|
||||||
33
.github/workflows/publish-release.yml
vendored
Normal file
33
.github/workflows/publish-release.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Publish Packages
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
release:
|
||||||
|
types: [ created ]
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout latest code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Change wrapper permissions
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
|
||||||
|
- name: Publish package
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: publish
|
||||||
|
env:
|
||||||
|
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
|
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
17
README.md
17
README.md
@@ -1,14 +1,14 @@
|
|||||||
<h1 align="center">
|
<h1 align="center">
|
||||||
<br>
|
<br>
|
||||||
<img src="https://i.imgur.com/I74yjwu.png" alt="EcoBosses logo" width="256">
|
<img src="https://i.imgur.com/3n3ssb4.png" alt="EcoBosses logo" width="256">
|
||||||
<br>
|
<br>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<h4 align="center">Source code for EcoBosses, a premium spigot plugin.</h4>
|
<h4 align="center">Source code for EcoBosses, a premium spigot plugin.</h4>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://www.spigotmc.org/resources/ecobosses.79573/">
|
<a href="https://polymart.org/resource/1-16-1-17-ecobosses.525">
|
||||||
<img alt="spigot" src="https://img.shields.io/badge/spigot-ecobosses-blue?style=for-the-badge"/>
|
<img alt="spigot" src="https://img.shields.io/badge/polymart-ecobosses-blue?style=for-the-badge"/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://bstats.org/plugin/bukkit/EcoBosses" alt="bstats servers">
|
<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"/>
|
<img src="https://img.shields.io/bstats/servers/10635?color=blue&style=for-the-badge"/>
|
||||||
@@ -29,3 +29,14 @@
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
*Click here to read [the entire license](https://github.com/Auxilor/EcoBosses/blob/master/LICENSE.md).*
|
*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>
|
||||||
|
|||||||
98
build.gradle
98
build.gradle
@@ -1,98 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java-library'
|
|
||||||
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
|
||||||
id 'maven-publish'
|
|
||||||
id 'java'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(":eco-core").getSubprojects()
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
apply plugin: 'java'
|
|
||||||
apply plugin: 'maven-publish'
|
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
mavenLocal()
|
|
||||||
maven { url 'https://jitpack.io' }
|
|
||||||
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
|
|
||||||
maven { url 'https://repo.codemc.org/repository/nms/' }
|
|
||||||
maven { url 'https://repo.codemc.org/repository/maven-public' }
|
|
||||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
|
|
||||||
maven { url 'https://oss.sonatype.org/content/groups/public/' }
|
|
||||||
maven { url 'https://maven.enginehub.org/repo/' }
|
|
||||||
maven { url 'https://ci.ender.zone/plugin/repository/project/' }
|
|
||||||
maven { url 'https://ci.ender.zone/plugin/repository/everything/' }
|
|
||||||
maven { url 'https://repo.md-5.net/content/repositories/snapshots/' }
|
|
||||||
maven { url 'https://repo.dmulloy2.net/nexus/repository/public/' }
|
|
||||||
maven { url 'https://papermc.io/repo/repository/maven-public/' }
|
|
||||||
maven { url 'https://repo.maven.apache.org/maven2/' }
|
|
||||||
maven { url 'https://repo.dustplanet.de/artifactory/ext-release-local/' }
|
|
||||||
maven { url 'https://maven.seyfahni.de/repository/snapshots/' }
|
|
||||||
maven { url 'https://libraries.minecraft.net/' }
|
|
||||||
maven { url 'https://repo.spongepowered.org/maven/' }
|
|
||||||
maven { url 'https://org.kitteh.pastegg' }
|
|
||||||
maven { url 'https://repo.mikeprimm.com/' }
|
|
||||||
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/' }
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
onlyIf { !sourceSets.main.allSource.files.isEmpty() }
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly 'com.willfp:eco:6.0.0'
|
|
||||||
|
|
||||||
compileOnly 'org.jetbrains:annotations:19.0.0'
|
|
||||||
|
|
||||||
compileOnly 'org.projectlombok:lombok:1.18.20'
|
|
||||||
annotationProcessor 'org.projectlombok:lombok:1.18.20'
|
|
||||||
|
|
||||||
testCompileOnly 'org.projectlombok:lombok:1.18.20'
|
|
||||||
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.deprecation = true
|
|
||||||
options.encoding = 'UTF-8'
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
|
||||||
filesNotMatching(["**/*.png", "**/models/**", "**/textures/**"]) {
|
|
||||||
expand projectVersion: project.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compileJava.options.encoding = 'UTF-8'
|
|
||||||
compileJava.dependsOn clean
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(Jar) {
|
|
||||||
destinationDirectory = file("$rootDir/bin/")
|
|
||||||
}
|
|
||||||
|
|
||||||
clean.doLast {
|
|
||||||
file("${rootDir}/bin").deleteDir()
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowJar {
|
|
||||||
archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + ".jar"
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + " " + "unshaded" + ".jar"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.willfp'
|
|
||||||
archivesBaseName = project.name
|
|
||||||
version = findProperty("version")
|
|
||||||
java.sourceCompatibility = JavaVersion.VERSION_16
|
|
||||||
|
|
||||||
compileJava.options.encoding = 'UTF-8'
|
|
||||||
|
|
||||||
build.dependsOn shadowJar
|
|
||||||
83
build.gradle.kts
Normal file
83
build.gradle.kts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
plugins {
|
||||||
|
java
|
||||||
|
`java-library`
|
||||||
|
`maven-publish`
|
||||||
|
kotlin("jvm") version "1.7.10"
|
||||||
|
id("com.github.johnrengelman.shadow") version "8.0.0"
|
||||||
|
id("com.willfp.libreforge-gradle-plugin") version "1.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.willfp"
|
||||||
|
version = findProperty("version")!!
|
||||||
|
val libreforgeVersion = findProperty("libreforge-version")
|
||||||
|
|
||||||
|
base {
|
||||||
|
archivesName.set(project.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
project(":eco-core").dependencyProject.subprojects {
|
||||||
|
implementation(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply(plugin = "java")
|
||||||
|
apply(plugin = "kotlin")
|
||||||
|
apply(plugin = "maven-publish")
|
||||||
|
apply(plugin = "com.github.johnrengelman.shadow")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
|
||||||
|
maven("https://repo.papermc.io/repository/maven-public/")
|
||||||
|
maven("https://repo.auxilor.io/repository/maven-public/")
|
||||||
|
maven("https://jitpack.io")
|
||||||
|
maven("https://mvn.lumine.io/repository/maven-public/")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly("com.willfp:eco:6.53.0")
|
||||||
|
compileOnly("org.jetbrains:annotations:23.0.0")
|
||||||
|
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.7.10")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withSourcesJar()
|
||||||
|
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
shadowJar {
|
||||||
|
relocate("com.willfp.libreforge.loader", "com.willfp.ecobosses.libreforge.loader")
|
||||||
|
}
|
||||||
|
|
||||||
|
compileKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
options.isDeprecation = true
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
|
||||||
|
dependsOn(clean)
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
filesMatching(listOf("**plugin.yml", "**eco.yml")) {
|
||||||
|
expand(
|
||||||
|
"version" to project.version,
|
||||||
|
"libreforgeVersion" to libreforgeVersion,
|
||||||
|
"pluginName" to rootProject.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build {
|
||||||
|
dependsOn(shadowJar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
group 'com.willfp'
|
|
||||||
version rootProject.version
|
|
||||||
2
eco-core/build.gradle.kts
Normal file
2
eco-core/build.gradle.kts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
group = "com.willfp"
|
||||||
|
version = rootProject.version
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
group 'com.willfp'
|
|
||||||
version rootProject.version
|
|
||||||
|
|
||||||
subprojects {
|
|
||||||
dependencies {
|
|
||||||
compileOnly project(':eco-core:core-proxy')
|
|
||||||
compileOnly project(':eco-core:core-plugin')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
group 'com.willfp'
|
|
||||||
version rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly 'org.spigotmc:spigot:1.16.1-R0.1-SNAPSHOT'
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
group 'com.willfp'
|
|
||||||
version rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly 'org.spigotmc:spigot:1.16.3-R0.1-SNAPSHOT'
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
group 'com.willfp'
|
|
||||||
version rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly 'org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT'
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
group 'com.willfp'
|
|
||||||
version rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly 'org.spigotmc:spigot:1.17-R0.1-SNAPSHOT'
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package com.willfp.ecobosses.proxy.v1_17_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
package com.willfp.ecobosses.proxy.v1_17_R1;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.proxy.proxies.CustomIllusionerProxy;
|
|
||||||
import net.minecraft.world.entity.EntityInsentient;
|
|
||||||
import net.minecraft.world.entity.EntityTypes;
|
|
||||||
import net.minecraft.world.entity.ai.goal.PathfinderGoalBowShoot;
|
|
||||||
import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat;
|
|
||||||
import net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer;
|
|
||||||
import net.minecraft.world.entity.ai.goal.PathfinderGoalMeleeAttack;
|
|
||||||
import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStroll;
|
|
||||||
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalHurtByTarget;
|
|
||||||
import net.minecraft.world.entity.ai.goal.target.PathfinderGoalNearestAttackableTarget;
|
|
||||||
import net.minecraft.world.entity.animal.EntityIronGolem;
|
|
||||||
import net.minecraft.world.entity.monster.EntityIllagerIllusioner;
|
|
||||||
import net.minecraft.world.entity.monster.EntityIllagerWizard;
|
|
||||||
import net.minecraft.world.entity.npc.EntityVillagerAbstract;
|
|
||||||
import net.minecraft.world.entity.player.EntityHuman;
|
|
||||||
import net.minecraft.world.entity.raid.EntityRaider;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.craftbukkit.v1_17_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.O, ((CraftWorld) location.getWorld()).getHandle());
|
|
||||||
|
|
||||||
this.setPosition(location.getX(), location.getY(), location.getZ());
|
|
||||||
|
|
||||||
this.bO.a(0, new PathfinderGoalFloat(this));
|
|
||||||
this.bO.a(1, new EntityIllagerWizard.b());
|
|
||||||
this.bO.a(2, new PathfinderGoalMeleeAttack(this, 1.0D, false));
|
|
||||||
this.bO.a(2, new PathfinderGoalBowShoot<>(this, 1.0D, 20, 15.0F));
|
|
||||||
this.bO.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
|
|
||||||
this.bO.a(0, new PathfinderGoalFloat(this));
|
|
||||||
this.bO.a(6, new PathfinderGoalBowShoot<>(this, 0.5D, 20, 15.0F));
|
|
||||||
this.bO.a(8, new PathfinderGoalRandomStroll(this, 0.6D));
|
|
||||||
this.bO.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F));
|
|
||||||
this.bO.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F));
|
|
||||||
this.bP.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0]));
|
|
||||||
this.bP.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300));
|
|
||||||
this.bP.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300));
|
|
||||||
this.bP.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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
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 'commons-io:commons-io:2.8.0'
|
|
||||||
compileOnly 'com.destroystokyo.paper:paper-api:1.16.3-R0.1-SNAPSHOT'
|
|
||||||
}
|
|
||||||
34
eco-core/core-plugin/build.gradle.kts
Normal file
34
eco-core/core-plugin/build.gradle.kts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
group = "com.willfp"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly("io.papermc.paper:paper-api:1.19.3-R0.1-SNAPSHOT")
|
||||||
|
compileOnly("com.github.lokka30:LevelledMobs:3.1.4")
|
||||||
|
compileOnly("com.ticxo.modelengine:api:R3.1.6")
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
register("maven", MavenPublication::class) {
|
||||||
|
from(components["java"])
|
||||||
|
artifactId = rootProject.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "auxilor"
|
||||||
|
url = uri("https://repo.auxilor.io/repository/maven-releases/")
|
||||||
|
credentials {
|
||||||
|
username = System.getenv("MAVEN_USERNAME")
|
||||||
|
password = System.getenv("MAVEN_PASSWORD")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
build {
|
||||||
|
dependsOn(publishToMavenLocal)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package com.willfp.ecobosses;
|
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
|
||||||
import com.willfp.eco.core.command.impl.PluginCommand;
|
|
||||||
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 lombok.Getter;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class EcoBossesPlugin extends EcoPlugin {
|
|
||||||
/**
|
|
||||||
* Instance of the plugin.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private static EcoBossesPlugin instance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal constructor called by bukkit on plugin load.
|
|
||||||
*/
|
|
||||||
public EcoBossesPlugin() {
|
|
||||||
super(86576, 10635, "com.willfp.ecobosses.proxy", "&9");
|
|
||||||
instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleDisable() {
|
|
||||||
BossUtils.killAllBosses();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleReload() {
|
|
||||||
this.getScheduler().runTimer(new AutoSpawnTimer(), 5, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<PluginCommand> loadPluginCommands() {
|
|
||||||
return Arrays.asList(
|
|
||||||
new CommandEcobosses(this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Listener> loadListeners() {
|
|
||||||
return Arrays.asList(
|
|
||||||
new AttackListeners(this),
|
|
||||||
new DeathListeners(this),
|
|
||||||
new SpawnListeners(this),
|
|
||||||
new PassiveListeners(this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,539 +0,0 @@
|
|||||||
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.interfaces.Config;
|
|
||||||
import com.willfp.eco.core.tuples.Pair;
|
|
||||||
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.BossbarProperties;
|
|
||||||
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.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.boss.BarColor;
|
|
||||||
import org.bukkit.boss.BarStyle;
|
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class EcoBoss extends PluginDependent<EcoPlugin> {
|
|
||||||
/**
|
|
||||||
* The name of the boss.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The config of the set.
|
|
||||||
*/
|
|
||||||
@Getter(AccessLevel.PRIVATE)
|
|
||||||
private final Config config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The display name of the boss.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final String displayName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The base entity spawner.
|
|
||||||
*/
|
|
||||||
private final BossType bossType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the boss bar is enabled.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final boolean bossbarEnabled;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The BossBar properties.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final BossbarProperties bossbarProperties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If spawn totem is enabled.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final boolean spawnTotemEnabled;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The spawn totem.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final SpawnTotem spawnTotem;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disabled world names for spawn totem.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<String> spawnTotemDisabledWorldNames;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The max health.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final int maxHealth;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The attack damage.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final int attackDamage;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The follow range.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final double followRange;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The movement speed multiplier.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final double movementSpeedMultiplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The immunity options.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final ImmunityOptions immunityOptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The drops.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final Map<ItemStack, Double> drops;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The exp to drop.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final ExperienceOptions experienceOptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If attacks should be called on injury.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final boolean attackOnInjure;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sounds played on injure.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<OptionedSound> injureSounds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawn sounds.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<OptionedSound> spawnSounds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Death sounds.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<OptionedSound> deathSounds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Summon sounds.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<OptionedSound> summonSounds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawn messages.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<String> spawnMessages;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Death messages.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<String> deathMessages;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Nearby players radius.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final double nearbyRadius;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Nearby players commands.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final Map<String, Double> nearbyPlayersCommands;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Top damager commands.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final Map<Integer, List<Pair<Double, String>>> topDamagerCommands;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Incoming damage multipliers.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final Map<EntityDamageEvent.DamageCause, Double> incomingMultipliers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The currently living bosses of this type.
|
|
||||||
*/
|
|
||||||
private final Map<LivingEntity, LivingEcoBoss> livingBosses;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The effect names and arguments.
|
|
||||||
*/
|
|
||||||
private final Map<String, List<String>> effectNames;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The target distance.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final double targetDistance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The targeting mode.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final TargetMode targetMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the boss shouldn't get into boats and minecarts.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final boolean disableBoats;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The time between auto spawns.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final int autoSpawnInterval;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locations that the boss can auto spawn at.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<Location> autoSpawnLocations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Boss.
|
|
||||||
*
|
|
||||||
* @param name The name of the set.
|
|
||||||
* @param config The set's config.
|
|
||||||
* @param plugin Instance of EcoBosses.
|
|
||||||
*/
|
|
||||||
public EcoBoss(@NotNull final String name,
|
|
||||||
@NotNull final Config config,
|
|
||||||
@NotNull final EcoPlugin plugin) {
|
|
||||||
super(plugin);
|
|
||||||
this.config = config;
|
|
||||||
this.name = name;
|
|
||||||
this.livingBosses = new HashMap<>();
|
|
||||||
|
|
||||||
this.displayName = this.getConfig().getString("name");
|
|
||||||
|
|
||||||
// Boss Type
|
|
||||||
this.bossType = BossEntityUtils.getBossType(this.getConfig().getString("base-mob"));
|
|
||||||
|
|
||||||
// Boss Bar
|
|
||||||
this.bossbarEnabled = this.getConfig().getBool("bossbar.enabled");
|
|
||||||
this.bossbarProperties = new BossbarProperties(
|
|
||||||
BarColor.valueOf(this.getConfig().getString("bossbar.color").toUpperCase()),
|
|
||||||
BarStyle.valueOf(this.getConfig().getString("bossbar.style").toUpperCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Attributes
|
|
||||||
this.attackDamage = this.getConfig().getInt("attack-damage");
|
|
||||||
this.maxHealth = this.getConfig().getInt("max-health");
|
|
||||||
this.followRange = this.getConfig().getInt("follow-range");
|
|
||||||
this.movementSpeedMultiplier = this.getConfig().getInt("movement-speed");
|
|
||||||
|
|
||||||
// Spawn Totem
|
|
||||||
this.spawnTotemEnabled = this.getConfig().getBool("spawn-totem.enabled");
|
|
||||||
this.spawnTotem = new SpawnTotem(
|
|
||||||
Material.getMaterial(this.getConfig().getString("spawn-totem.bottom").toUpperCase()),
|
|
||||||
Material.getMaterial(this.getConfig().getString("spawn-totem.middle").toUpperCase()),
|
|
||||||
Material.getMaterial(this.getConfig().getString("spawn-totem.top").toUpperCase())
|
|
||||||
);
|
|
||||||
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.experienceOptions = new ExperienceOptions(
|
|
||||||
this.getConfig().getInt("rewards.xp.minimum"),
|
|
||||||
this.getConfig().getInt("rewards.xp.maximum")
|
|
||||||
);
|
|
||||||
|
|
||||||
// Immunities
|
|
||||||
this.immunityOptions = new ImmunityOptions(
|
|
||||||
this.getConfig().getBool("defence.immunities.fire"),
|
|
||||||
this.getConfig().getBool("defence.immunities.suffocation"),
|
|
||||||
this.getConfig().getBool("defence.immunities.drowning"),
|
|
||||||
this.getConfig().getBool("defence.immunities.projectiles"),
|
|
||||||
this.getConfig().getBool("defence.immunities.explosion")
|
|
||||||
);
|
|
||||||
|
|
||||||
// Multipliers
|
|
||||||
this.incomingMultipliers = new HashMap<>();
|
|
||||||
double melee = this.getConfig().getDouble("defence.incoming-multipliers.melee");
|
|
||||||
this.incomingMultipliers.put(EntityDamageEvent.DamageCause.ENTITY_ATTACK, melee);
|
|
||||||
this.incomingMultipliers.put(EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK, melee);
|
|
||||||
|
|
||||||
double projectile = this.getConfig().getDouble("defence.incoming-multipliers.projectile");
|
|
||||||
this.incomingMultipliers.put(EntityDamageEvent.DamageCause.PROJECTILE, projectile);
|
|
||||||
|
|
||||||
// Attack on injure
|
|
||||||
this.attackOnInjure = this.getConfig().getBool("attacks.on-injure");
|
|
||||||
|
|
||||||
// Sounds
|
|
||||||
this.injureSounds = new ArrayList<>();
|
|
||||||
for (String string : this.getConfig().getStrings("sounds.injure")) {
|
|
||||||
String[] split = string.split(":");
|
|
||||||
this.injureSounds.add(new OptionedSound(
|
|
||||||
Sound.valueOf(split[0].toUpperCase()),
|
|
||||||
Float.parseFloat(split[1]) / 16,
|
|
||||||
Float.parseFloat(split[2])
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deathSounds = new ArrayList<>();
|
|
||||||
for (String string : this.getConfig().getStrings("sounds.death")) {
|
|
||||||
String[] split = string.split(":");
|
|
||||||
this.deathSounds.add(new OptionedSound(
|
|
||||||
Sound.valueOf(split[0].toUpperCase()),
|
|
||||||
Float.parseFloat(split[1]) / 16,
|
|
||||||
Float.parseFloat(split[2])
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.summonSounds = new ArrayList<>();
|
|
||||||
for (String string : this.getConfig().getStrings("sounds.summon")) {
|
|
||||||
String[] split = string.split(":");
|
|
||||||
this.summonSounds.add(new OptionedSound(
|
|
||||||
Sound.valueOf(split[0].toUpperCase()),
|
|
||||||
Float.parseFloat(split[1]) / 16,
|
|
||||||
Float.parseFloat(split[2])
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.spawnSounds = new ArrayList<>();
|
|
||||||
for (String string : this.getConfig().getStrings("sounds.spawn")) {
|
|
||||||
String[] split = string.split(":");
|
|
||||||
this.spawnSounds.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.format(string));
|
|
||||||
}
|
|
||||||
this.deathMessages = new ArrayList<>();
|
|
||||||
for (String string : this.getConfig().getStrings("broadcast.death")) {
|
|
||||||
this.deathMessages.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, false)) {
|
|
||||||
double chance = 100;
|
|
||||||
if (string.contains("::")) {
|
|
||||||
String[] split = string.split("::");
|
|
||||||
chance = Double.parseDouble(split[0]);
|
|
||||||
string = split[1];
|
|
||||||
}
|
|
||||||
List<Pair<Double, String>> commands = this.topDamagerCommands.get(i) == null ? new ArrayList<>() : this.topDamagerCommands.get(i);
|
|
||||||
commands.add(new Pair<>(chance, string));
|
|
||||||
this.topDamagerCommands.put(i, commands);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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", false)) {
|
|
||||||
double chance = 100;
|
|
||||||
if (string.contains("::")) {
|
|
||||||
String[] split = string.split("::");
|
|
||||||
chance = Double.parseDouble(split[0]);
|
|
||||||
string = split[1];
|
|
||||||
}
|
|
||||||
this.nearbyPlayersCommands.put(string, chance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Effects
|
|
||||||
this.effectNames = new HashMap<>();
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Targeting
|
|
||||||
this.targetDistance = this.getConfig().getDouble("attacks.target.range");
|
|
||||||
this.targetMode = TargetMode.getByName(this.getConfig().getString("attacks.target.mode"));
|
|
||||||
|
|
||||||
// Boat + Minecarts
|
|
||||||
this.disableBoats = this.getConfig().getBool("defence.no-boats");
|
|
||||||
|
|
||||||
// Auto Spawn
|
|
||||||
this.autoSpawnInterval = this.getConfig().getInt("auto-spawn-interval");
|
|
||||||
this.autoSpawnLocations = new ArrayList<>();
|
|
||||||
for (String string : this.getConfig().getStrings("auto-spawn-locations")) {
|
|
||||||
String[] split = string.split(":");
|
|
||||||
World world = Bukkit.getWorld(split[0]);
|
|
||||||
double x = Double.parseDouble(split[1]);
|
|
||||||
double y = Double.parseDouble(split[2]);
|
|
||||||
double z = Double.parseDouble(split[3]);
|
|
||||||
autoSpawnLocations.add(new Location(world, x, y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getConfig().getBool("enabled")) {
|
|
||||||
EcoBosses.addBoss(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create effect tickers for Living Boss.
|
|
||||||
*
|
|
||||||
* @return The effects.
|
|
||||||
*/
|
|
||||||
public List<Effect> createEffects() {
|
|
||||||
List<Effect> effects = new ArrayList<>();
|
|
||||||
this.effectNames.forEach((string, args) -> {
|
|
||||||
effects.add(Effects.getEffect(string, args));
|
|
||||||
});
|
|
||||||
|
|
||||||
return effects;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spawn the boss.
|
|
||||||
*
|
|
||||||
* @param location The location.
|
|
||||||
*/
|
|
||||||
public void spawn(@NotNull final Location location) {
|
|
||||||
location.getChunk().load();
|
|
||||||
|
|
||||||
LivingEntity entity = bossType.spawnBossEntity(location);
|
|
||||||
this.livingBosses.put(entity, new LivingEcoBoss(
|
|
||||||
this.getPlugin(),
|
|
||||||
entity,
|
|
||||||
this
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get {@link LivingEcoBoss} from an entity.
|
|
||||||
*
|
|
||||||
* @param entity The entity.
|
|
||||||
* @return The living boss, or null if not a boss.
|
|
||||||
*/
|
|
||||||
public LivingEcoBoss getLivingBoss(@NotNull final LivingEntity entity) {
|
|
||||||
return this.livingBosses.get(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove living boss.
|
|
||||||
*
|
|
||||||
* @param entity The entity.
|
|
||||||
*/
|
|
||||||
public void removeLivingBoss(@Nullable final LivingEntity entity) {
|
|
||||||
this.livingBosses.remove(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all living bosses.
|
|
||||||
*
|
|
||||||
* @return The living bosses.
|
|
||||||
*/
|
|
||||||
public Map<LivingEntity, LivingEcoBoss> getLivingBosses() {
|
|
||||||
return ImmutableMap.copyOf(this.livingBosses);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(o instanceof EcoBoss boss)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getName().equals(boss.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(this.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "EcoBoss{"
|
|
||||||
+ this.getName()
|
|
||||||
+ "}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses;
|
|
||||||
|
|
||||||
import com.google.common.collect.BiMap;
|
|
||||||
import com.google.common.collect.HashBiMap;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.willfp.eco.core.config.updating.ConfigUpdater;
|
|
||||||
import com.willfp.ecobosses.EcoBossesPlugin;
|
|
||||||
import com.willfp.ecobosses.config.BaseBossConfig;
|
|
||||||
import com.willfp.ecobosses.config.CustomConfig;
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class EcoBosses {
|
|
||||||
/**
|
|
||||||
* Registered armor sets.
|
|
||||||
*/
|
|
||||||
private static final BiMap<String, EcoBoss> BY_NAME = HashBiMap.create();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets that exist by default.
|
|
||||||
*/
|
|
||||||
private static final List<String> DEFAULT_BOSSES = Arrays.asList(
|
|
||||||
"illusioner",
|
|
||||||
"tarantula",
|
|
||||||
"steel_golem",
|
|
||||||
"alpha_wolf"
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all registered {@link EcoBoss}es.
|
|
||||||
*
|
|
||||||
* @return A list of all {@link EcoBoss}es.
|
|
||||||
*/
|
|
||||||
public static List<EcoBoss> values() {
|
|
||||||
return ImmutableList.copyOf(BY_NAME.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get {@link EcoBoss} matching name.
|
|
||||||
*
|
|
||||||
* @param name The name to search for.
|
|
||||||
* @return The matching {@link EcoBoss}, or null if not found.
|
|
||||||
*/
|
|
||||||
public static EcoBoss getByName(@NotNull final String name) {
|
|
||||||
return BY_NAME.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update all {@link EcoBoss}s.
|
|
||||||
*/
|
|
||||||
@ConfigUpdater
|
|
||||||
public static void update() {
|
|
||||||
for (EcoBoss boss : values()) {
|
|
||||||
removeBoss(boss);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String defaultSetName : DEFAULT_BOSSES) {
|
|
||||||
new EcoBoss(defaultSetName, new BaseBossConfig(defaultSetName), EcoBossesPlugin.getInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Files.walk(Paths.get(new File(EcoBossesPlugin.getInstance().getDataFolder(), "bosses/").toURI()))
|
|
||||||
.filter(Files::isRegularFile)
|
|
||||||
.forEach(path -> {
|
|
||||||
String name = path.getFileName().toString().replace(".yml", "");
|
|
||||||
new EcoBoss(
|
|
||||||
name,
|
|
||||||
new CustomConfig(name, YamlConfiguration.loadConfiguration(path.toFile())),
|
|
||||||
EcoBossesPlugin.getInstance()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add new {@link EcoBoss} to EcoBosses.
|
|
||||||
*
|
|
||||||
* @param set The {@link EcoBoss} to add.
|
|
||||||
*/
|
|
||||||
public static void addBoss(@NotNull final EcoBoss set) {
|
|
||||||
BY_NAME.remove(set.getName());
|
|
||||||
BY_NAME.put(set.getName(), set);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove {@link EcoBoss} from EcoBosses.
|
|
||||||
*
|
|
||||||
* @param set The {@link EcoBoss} to remove.
|
|
||||||
*/
|
|
||||||
public static void removeBoss(@NotNull final EcoBoss set) {
|
|
||||||
BY_NAME.remove(set.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
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.TargetTicker;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
|
|
||||||
import lombok.Getter;
|
|
||||||
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.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
public class LivingEcoBoss extends PluginDependent<EcoPlugin> {
|
|
||||||
/**
|
|
||||||
* The entity.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private LivingEntity entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The boss.
|
|
||||||
*/
|
|
||||||
private final EcoBoss boss;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The boss tickers.
|
|
||||||
*/
|
|
||||||
private final List<BossTicker> tickers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The effects.
|
|
||||||
*/
|
|
||||||
private final List<Effect> effects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new living EcoBoss.
|
|
||||||
*
|
|
||||||
* @param plugin Instance of EcoBosses.
|
|
||||||
* @param entity The entity.
|
|
||||||
* @param boss The boss.
|
|
||||||
*/
|
|
||||||
public LivingEcoBoss(@NotNull final EcoPlugin plugin,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
@NotNull final EcoBoss boss) {
|
|
||||||
super(plugin);
|
|
||||||
this.entity = entity;
|
|
||||||
this.boss = boss;
|
|
||||||
|
|
||||||
this.onSpawn();
|
|
||||||
|
|
||||||
// Tickers
|
|
||||||
this.tickers = new ArrayList<>();
|
|
||||||
this.tickers.add(new HealthPlaceholderTicker());
|
|
||||||
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().color(),
|
|
||||||
boss.getBossbarProperties().style(),
|
|
||||||
(BarFlag) null
|
|
||||||
),
|
|
||||||
this.getPlugin().getConfigYml().getInt("bossbar-radius")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Effects
|
|
||||||
this.effects = new ArrayList<>();
|
|
||||||
this.effects.addAll(boss.createEffects());
|
|
||||||
|
|
||||||
AtomicLong currentTick = new AtomicLong(0);
|
|
||||||
this.getPlugin().getRunnableFactory().create(runnable -> this.tick(currentTick.getAndAdd(1), runnable)).runTaskTimer(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onSpawn() {
|
|
||||||
entity.getPersistentDataContainer().set(this.getPlugin().getNamespacedKeyFactory().create("boss"), PersistentDataType.STRING, boss.getName());
|
|
||||||
entity.setPersistent(true);
|
|
||||||
entity.setRemoveWhenFarAway(false);
|
|
||||||
|
|
||||||
entity.setCustomName(boss.getDisplayName());
|
|
||||||
entity.setCustomNameVisible(true);
|
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
AttributeInstance maxHealth = entity.getAttribute(Attribute.GENERIC_MAX_HEALTH);
|
|
||||||
assert maxHealth != null;
|
|
||||||
maxHealth.setBaseValue(boss.getMaxHealth());
|
|
||||||
|
|
||||||
entity.setHealth(maxHealth.getValue());
|
|
||||||
|
|
||||||
AttributeInstance followRange = entity.getAttribute(Attribute.GENERIC_FOLLOW_RANGE);
|
|
||||||
assert followRange != null;
|
|
||||||
followRange.setBaseValue(boss.getFollowRange());
|
|
||||||
|
|
||||||
AttributeInstance attackDamage = entity.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE);
|
|
||||||
assert attackDamage != null;
|
|
||||||
attackDamage.setBaseValue(boss.getAttackDamage());
|
|
||||||
|
|
||||||
for (OptionedSound sound : boss.getSpawnSounds()) {
|
|
||||||
entity.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String spawnMessage : boss.getSpawnMessages()) {
|
|
||||||
Bukkit.broadcastMessage(spawnMessage
|
|
||||||
.replace("%x%", StringUtils.internalToString(entity.getLocation().getBlockX()))
|
|
||||||
.replace("%y%", StringUtils.internalToString(entity.getLocation().getBlockY()))
|
|
||||||
.replace("%z%", StringUtils.internalToString(entity.getLocation().getBlockZ()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tick(final long tick,
|
|
||||||
@NotNull final RunnableTask runnable) {
|
|
||||||
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);
|
|
||||||
runnable.cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BossTicker ticker : tickers) {
|
|
||||||
ticker.tick(boss, entity, tick);
|
|
||||||
}
|
|
||||||
for (Effect effect : effects) {
|
|
||||||
effect.tick(boss, entity, tick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle an attack to the player.
|
|
||||||
*
|
|
||||||
* @param player The player.
|
|
||||||
*/
|
|
||||||
public void handleAttack(@NotNull final Player player) {
|
|
||||||
for (OptionedSound sound : boss.getInjureSounds()) {
|
|
||||||
player.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Effect effect : effects) {
|
|
||||||
effect.onAttack(boss, entity, player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.tick.BossTicker;
|
|
||||||
import lombok.Getter;
|
|
||||||
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 {
|
|
||||||
/**
|
|
||||||
* The effect args.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final List<String> args;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new effect.
|
|
||||||
*
|
|
||||||
* @param args The args.
|
|
||||||
*/
|
|
||||||
protected Effect(@NotNull final List<String> args) {
|
|
||||||
this.args = args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a config error.
|
|
||||||
*
|
|
||||||
* @param message The error message.
|
|
||||||
*/
|
|
||||||
public void showConfigError(@NotNull final String message) {
|
|
||||||
Bukkit.getLogger().warning("An effect is configured incorrectly!");
|
|
||||||
Bukkit.getLogger().warning(message);
|
|
||||||
Bukkit.getLogger().warning("Usage: " + getUsage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get effect usage.
|
|
||||||
*
|
|
||||||
* @return The usage.
|
|
||||||
*/
|
|
||||||
public abstract String getUsage();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the boss attacking a player.
|
|
||||||
*
|
|
||||||
* @param boss The boss.
|
|
||||||
* @param entity The boss entity.
|
|
||||||
* @param player The player.
|
|
||||||
*/
|
|
||||||
public void onAttack(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
@NotNull final Player player) {
|
|
||||||
// Override when needed.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tick the effect.
|
|
||||||
*
|
|
||||||
* @param boss The boss.
|
|
||||||
* @param entity The boss entity.
|
|
||||||
* @param tick The current tick: counts up from zero.
|
|
||||||
*/
|
|
||||||
public void tick(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
final long tick) {
|
|
||||||
// Override when needed.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On boss death.
|
|
||||||
*
|
|
||||||
* @param boss The boss.
|
|
||||||
* @param entity The boss entity.
|
|
||||||
* @param tick The current tick: counts up from zero.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onDeath(@NotNull final EcoBoss boss,
|
|
||||||
@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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.bosses.effects.effects.*;
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class Effects {
|
|
||||||
/**
|
|
||||||
* Registered effects.
|
|
||||||
*/
|
|
||||||
private static final Map<String, Function<List<String>, Effect>> EFFECTS = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
register("damage-nearby-players", EffectDamageNearbyPlayers::new);
|
|
||||||
register("lightning-nearby-entities", EffectLightningNearbyEntities::new);
|
|
||||||
register("summon", EffectSummon::new);
|
|
||||||
register("give-potion-effect", EffectGivePotionEffect::new);
|
|
||||||
register("shuffle-hotbar", EffectShuffleHotbar::new);
|
|
||||||
register("teleport", EffectTeleport::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register new effect.
|
|
||||||
*
|
|
||||||
* @param name The effect name.
|
|
||||||
* @param creator Function to create an instance of the effect given args.
|
|
||||||
*/
|
|
||||||
public void register(@NotNull final String name,
|
|
||||||
@NotNull final Function<List<String>, Effect> creator) {
|
|
||||||
EFFECTS.put(name, creator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get effect matching name.
|
|
||||||
*
|
|
||||||
* @param name The effect name.
|
|
||||||
* @param args The args.
|
|
||||||
* @return The found effect, or null.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Effect getEffect(@NotNull final String name,
|
|
||||||
@NotNull final List<String> args) {
|
|
||||||
Function<List<String>, Effect> found = EFFECTS.get(name.toLowerCase());
|
|
||||||
return found == null ? null : found.apply(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects.effects;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.effects.Effect;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class EffectDamageNearbyPlayers extends Effect {
|
|
||||||
private final int frequency;
|
|
||||||
private final double damage;
|
|
||||||
private final double radius;
|
|
||||||
|
|
||||||
public EffectDamageNearbyPlayers(@NotNull final List<String> args) {
|
|
||||||
super(args);
|
|
||||||
|
|
||||||
if (args.size() < 3) {
|
|
||||||
showConfigError("Incorrect amount of arguments!");
|
|
||||||
}
|
|
||||||
|
|
||||||
frequency = Integer.parseInt(args.get(0));
|
|
||||||
radius = Double.parseDouble(args.get(1));
|
|
||||||
damage = Double.parseDouble(args.get(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsage() {
|
|
||||||
return "damage-nearby-players:<frequency>:<damage>:<radius>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
final long tick) {
|
|
||||||
if (tick % frequency == 0) {
|
|
||||||
for (Entity nearbyEntity : entity.getNearbyEntities(radius, radius, radius)) {
|
|
||||||
if (nearbyEntity instanceof Player) {
|
|
||||||
((Player) nearbyEntity).damage(damage, entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects.effects;
|
|
||||||
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.effects.Effect;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.bukkit.potion.PotionEffectType;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class EffectGivePotionEffect extends Effect {
|
|
||||||
private final PotionEffectType type;
|
|
||||||
private final double chance;
|
|
||||||
private final int duration;
|
|
||||||
private final int strength;
|
|
||||||
|
|
||||||
public EffectGivePotionEffect(@NotNull final List<String> args) {
|
|
||||||
super(args);
|
|
||||||
|
|
||||||
if (args.size() < 4) {
|
|
||||||
showConfigError("Incorrect amount of arguments!");
|
|
||||||
}
|
|
||||||
|
|
||||||
type = PotionEffectType.getByName(args.get(0).toUpperCase());
|
|
||||||
chance = Double.parseDouble(args.get(1));
|
|
||||||
duration = Integer.parseInt(args.get(2));
|
|
||||||
strength = Integer.parseInt(args.get(3));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsage() {
|
|
||||||
return "give-potion-effect:<effect>:<chance>:<duration>:<strength>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttack(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
@NotNull final Player player) {
|
|
||||||
if (NumberUtils.randFloat(0, 100) > this.chance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.addPotionEffect(new PotionEffect(type, duration, strength - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects.effects;
|
|
||||||
|
|
||||||
import com.willfp.eco.util.LightningUtils;
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.effects.Effect;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class EffectLightningNearbyEntities extends Effect {
|
|
||||||
private final int frequency;
|
|
||||||
private final double chance;
|
|
||||||
private final double damage;
|
|
||||||
private final double radius;
|
|
||||||
|
|
||||||
public EffectLightningNearbyEntities(@NotNull final List<String> args) {
|
|
||||||
super(args);
|
|
||||||
|
|
||||||
if (args.size() < 4) {
|
|
||||||
showConfigError("Incorrect amount of arguments!");
|
|
||||||
}
|
|
||||||
|
|
||||||
frequency = Integer.parseInt(args.get(0));
|
|
||||||
chance = Double.parseDouble(args.get(1));
|
|
||||||
radius = Double.parseDouble(args.get(2));
|
|
||||||
damage = Double.parseDouble(args.get(3));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsage() {
|
|
||||||
return "lightning-nearby-entities:<frequency>:<chance>:<damage>:<radius>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
final long tick) {
|
|
||||||
if (tick % frequency == 0) {
|
|
||||||
for (Entity nearbyEntity : entity.getNearbyEntities(radius, radius, radius)) {
|
|
||||||
if (NumberUtils.randFloat(0, 100) < chance) {
|
|
||||||
if (nearbyEntity instanceof LivingEntity) {
|
|
||||||
LightningUtils.strike((LivingEntity) nearbyEntity, damage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects.effects;
|
|
||||||
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.effects.Effect;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class EffectShuffleHotbar extends Effect {
|
|
||||||
private final double chance;
|
|
||||||
|
|
||||||
public EffectShuffleHotbar(@NotNull final List<String> args) {
|
|
||||||
super(args);
|
|
||||||
|
|
||||||
if (args.size() < 1) {
|
|
||||||
showConfigError("Incorrect amount of arguments!");
|
|
||||||
}
|
|
||||||
|
|
||||||
chance = Double.parseDouble(args.get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsage() {
|
|
||||||
return "shuffle-hotbar:<chance>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttack(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
@NotNull final Player player) {
|
|
||||||
if (NumberUtils.randFloat(0, 100) > this.chance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ItemStack> hotbar = new ArrayList<>();
|
|
||||||
for (int i = 0; i < 9; i++) {
|
|
||||||
hotbar.add(player.getInventory().getItem(i));
|
|
||||||
}
|
|
||||||
Collections.shuffle(hotbar);
|
|
||||||
int i2 = 0;
|
|
||||||
for (ItemStack item : hotbar) {
|
|
||||||
player.getInventory().setItem(i2, item);
|
|
||||||
i2++;
|
|
||||||
}
|
|
||||||
player.playSound(player.getLocation(), Sound.ENTITY_ENDER_PEARL_THROW, 1, 0.5f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects.effects;
|
|
||||||
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.effects.Effect;
|
|
||||||
import com.willfp.ecobosses.bosses.util.bosstype.BossEntityUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.util.bosstype.BossType;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Mob;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class EffectSummon extends Effect {
|
|
||||||
private final BossType type;
|
|
||||||
private final double chance;
|
|
||||||
|
|
||||||
public EffectSummon(@NotNull final List<String> args) {
|
|
||||||
super(args);
|
|
||||||
|
|
||||||
if (args.size() < 2) {
|
|
||||||
showConfigError("Incorrect amount of arguments!");
|
|
||||||
}
|
|
||||||
|
|
||||||
type = BossEntityUtils.getBossType(args.get(0));
|
|
||||||
chance = Double.parseDouble(args.get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsage() {
|
|
||||||
return "summon:<entity>:<chance>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttack(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
@NotNull final Player player) {
|
|
||||||
if (NumberUtils.randFloat(0, 100) > this.chance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Location loc = player.getLocation().add(NumberUtils.randInt(2, 6), 0, NumberUtils.randInt(2, 6));
|
|
||||||
for (int i = 0; i < 15; i++) {
|
|
||||||
if (loc.getBlock().getType() == Material.AIR) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
loc.add(0, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity summonedEntity = type.spawnBossEntity(loc);
|
|
||||||
if (summonedEntity instanceof Mob) {
|
|
||||||
((Mob) summonedEntity).setTarget(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (OptionedSound sound : boss.getSummonSounds()) {
|
|
||||||
player.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.effects.effects;
|
|
||||||
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.effects.Effect;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class EffectTeleport extends Effect {
|
|
||||||
private final int range;
|
|
||||||
private final double chance;
|
|
||||||
|
|
||||||
public EffectTeleport(@NotNull final List<String> args) {
|
|
||||||
super(args);
|
|
||||||
|
|
||||||
if (args.size() < 2) {
|
|
||||||
showConfigError("Incorrect amount of arguments!");
|
|
||||||
}
|
|
||||||
|
|
||||||
range = Integer.parseInt(args.get(0));
|
|
||||||
chance = Double.parseDouble(args.get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsage() {
|
|
||||||
return "teleport:<range>:<chance>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttack(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
@NotNull final Player player) {
|
|
||||||
if (NumberUtils.randFloat(0, 100) > this.chance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Location> valid = new ArrayList<>();
|
|
||||||
for (int x = -range; x <= range; x++) {
|
|
||||||
for (int y = -range; y <= range; y++) {
|
|
||||||
for (int z = -range; z <= range; z++) {
|
|
||||||
Location location = entity.getLocation().clone();
|
|
||||||
location.setX(location.getX() + x);
|
|
||||||
location.setY(location.getY() + y);
|
|
||||||
location.setZ(location.getZ() + z);
|
|
||||||
|
|
||||||
Block block = location.getBlock();
|
|
||||||
|
|
||||||
if (block.getType() == Material.AIR
|
|
||||||
&& block.getRelative(BlockFace.UP).getType() == Material.AIR
|
|
||||||
&& !(block.getRelative(BlockFace.DOWN).isLiquid() || block.getRelative(BlockFace.DOWN).getType() == Material.AIR)) {
|
|
||||||
valid.add(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valid.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.shuffle(valid);
|
|
||||||
Location location = valid.get(0);
|
|
||||||
|
|
||||||
entity.teleport(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.listeners;
|
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
|
||||||
import com.willfp.eco.core.PluginDependent;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.LivingEcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.util.BossUtils;
|
|
||||||
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;
|
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class AttackListeners extends PluginDependent<EcoPlugin> implements Listener {
|
|
||||||
/**
|
|
||||||
* Create new attack listeners.
|
|
||||||
*
|
|
||||||
* @param plugin Instance of EcoBosses.
|
|
||||||
*/
|
|
||||||
public AttackListeners(@NotNull final EcoPlugin plugin) {
|
|
||||||
super(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a player attacks a boss.
|
|
||||||
*
|
|
||||||
* @param event The event to listen for.
|
|
||||||
*/
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
|
||||||
public void onAttackBoss(@NotNull final EntityDamageByEntityEvent event) {
|
|
||||||
if (!(event.getEntity() instanceof LivingEntity entity)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = BossUtils.getPlayerFromEntity(event.getDamager());
|
|
||||||
|
|
||||||
if (player == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EcoBoss boss = BossUtils.getBoss(entity);
|
|
||||||
|
|
||||||
if (boss == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LivingEcoBoss livingEcoBoss = boss.getLivingBoss(entity);
|
|
||||||
|
|
||||||
BossUtils.warnIfNull(livingEcoBoss);
|
|
||||||
|
|
||||||
if (boss.isAttackOnInjure()) {
|
|
||||||
livingEcoBoss.handleAttack(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Track top damage players.
|
|
||||||
*
|
|
||||||
* @param event The event to listen for.
|
|
||||||
*/
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
|
||||||
public void topDamageTracker(@NotNull final EntityDamageByEntityEvent event) {
|
|
||||||
if (!(event.getEntity() instanceof LivingEntity entity)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = BossUtils.getPlayerFromEntity(event.getDamager());
|
|
||||||
|
|
||||||
if (player == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EcoBoss boss = BossUtils.getBoss(entity);
|
|
||||||
|
|
||||||
if (boss == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DamagerProperty> topDamagers = BossUtils.getTopDamagers(entity);
|
|
||||||
|
|
||||||
double playerDamage;
|
|
||||||
|
|
||||||
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.playerUUID().equals(player.getUniqueId()));
|
|
||||||
topDamagers.add(new DamagerProperty(player.getUniqueId(), playerDamage));
|
|
||||||
|
|
||||||
entity.removeMetadata("ecobosses-top-damagers", this.getPlugin());
|
|
||||||
entity.setMetadata("ecobosses-top-damagers", this.getPlugin().getMetadataValueFactory().create(topDamagers));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a boss attacks a player.
|
|
||||||
*
|
|
||||||
* @param event The event to listen for.
|
|
||||||
*/
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
|
||||||
public void onAttackPlayer(@NotNull final EntityDamageByEntityEvent event) {
|
|
||||||
if (!(event.getEntity() instanceof Player player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(event.getDamager() instanceof LivingEntity entity)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EcoBoss boss = BossUtils.getBoss(entity);
|
|
||||||
|
|
||||||
if (boss == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LivingEcoBoss livingEcoBoss = boss.getLivingBoss(entity);
|
|
||||||
|
|
||||||
BossUtils.warnIfNull(livingEcoBoss);
|
|
||||||
|
|
||||||
livingEcoBoss.handleAttack(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a boss is damaged.
|
|
||||||
*
|
|
||||||
* @param event The event to listen for.
|
|
||||||
*/
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
|
|
||||||
public void defenceListener(@NotNull final EntityDamageEvent event) {
|
|
||||||
if (!(event.getEntity() instanceof LivingEntity entity)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EcoBoss boss = BossUtils.getBoss(entity);
|
|
||||||
|
|
||||||
if (boss == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmunityOptions immunities = boss.getImmunityOptions();
|
|
||||||
|
|
||||||
if (immunities.immuneToFire()
|
|
||||||
&& (event.getCause() == EntityDamageEvent.DamageCause.FIRE
|
|
||||||
|| event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK
|
|
||||||
|| event.getCause() == EntityDamageEvent.DamageCause.HOT_FLOOR)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
if (immunities.immuneToSuffocation()&& event.getCause() == EntityDamageEvent.DamageCause.SUFFOCATION) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
if (immunities.immuneToDrowning() && event.getCause() == EntityDamageEvent.DamageCause.DROWNING) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
if (immunities.immuneToExplosions() && (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_EXPLOSION || event.getCause() == EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
if (immunities.immuneToProjectiles() && (event.getCause() == EntityDamageEvent.DamageCause.PROJECTILE)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<EntityDamageEvent.DamageCause, Double> entry : boss.getIncomingMultipliers().entrySet()) {
|
|
||||||
if (event.getCause() == entry.getKey()) {
|
|
||||||
event.setDamage(event.getDamage() * entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
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.bosses.util.BossUtils;
|
|
||||||
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;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
tick++;
|
|
||||||
|
|
||||||
for (EcoBoss boss : EcoBosses.values()) {
|
|
||||||
if (boss.getAutoSpawnInterval() < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boss.getAutoSpawnLocations().isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<World> worlds = new HashSet<>();
|
|
||||||
|
|
||||||
for (Entity entity : boss.getLivingBosses().keySet()) {
|
|
||||||
BossUtils.warnIfNull(entity);
|
|
||||||
assert entity != null;
|
|
||||||
|
|
||||||
worlds.add(entity.getWorld());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Location> locations = new ArrayList<>(boss.getAutoSpawnLocations());
|
|
||||||
locations.removeIf(location -> worlds.contains(location.getWorld()));
|
|
||||||
|
|
||||||
if (locations.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tick % boss.getAutoSpawnInterval() == 0) {
|
|
||||||
Location location = locations.get(NumberUtils.randInt(0, locations.size() - 1));
|
|
||||||
boss.spawn(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.listeners;
|
|
||||||
|
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
|
||||||
import com.willfp.eco.core.PluginDependent;
|
|
||||||
import com.willfp.eco.core.events.EntityDeathByEntityEvent;
|
|
||||||
import com.willfp.eco.core.tuples.Pair;
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
import com.willfp.eco.util.StringUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.util.BossUtils;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.DamagerProperty;
|
|
||||||
import com.willfp.ecobosses.bosses.util.obj.OptionedSound;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.entity.EntityDeathEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class DeathListeners extends PluginDependent<EcoPlugin> implements Listener {
|
|
||||||
/**
|
|
||||||
* Create new death listeners.
|
|
||||||
*
|
|
||||||
* @param plugin Instance of EcoBosses.
|
|
||||||
*/
|
|
||||||
public DeathListeners(@NotNull final EcoPlugin plugin) {
|
|
||||||
super(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a boss dies.
|
|
||||||
*
|
|
||||||
* @param event The event to listen for.
|
|
||||||
*/
|
|
||||||
@EventHandler
|
|
||||||
public void onBossDeath(@NotNull final EntityDeathByEntityEvent event) {
|
|
||||||
LivingEntity entity = event.getVictim();
|
|
||||||
|
|
||||||
EcoBoss boss = BossUtils.getBoss(entity);
|
|
||||||
|
|
||||||
if (boss == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (OptionedSound sound : boss.getDeathSounds()) {
|
|
||||||
entity.getWorld().playSound(entity.getLocation(), sound.sound(), sound.volume(), sound.pitch());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle drops and experience.
|
|
||||||
*
|
|
||||||
* @param event The event.
|
|
||||||
*/
|
|
||||||
@EventHandler(priority = EventPriority.LOW)
|
|
||||||
public void onOtherDeath(@NotNull final EntityDeathEvent event) {
|
|
||||||
LivingEntity entity = event.getEntity();
|
|
||||||
|
|
||||||
EcoBoss boss = BossUtils.getBoss(entity);
|
|
||||||
|
|
||||||
if (boss == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DamagerProperty> topDamagers = BossUtils.getTopDamagers(entity);
|
|
||||||
|
|
||||||
DamagerProperty top = null;
|
|
||||||
DamagerProperty second = null;
|
|
||||||
DamagerProperty third = null;
|
|
||||||
|
|
||||||
if (topDamagers.size() >= 1) {
|
|
||||||
top = topDamagers.get(0);
|
|
||||||
}
|
|
||||||
if (topDamagers.size() >= 2) {
|
|
||||||
second = topDamagers.get(1);
|
|
||||||
}
|
|
||||||
if (topDamagers.size() >= 3) {
|
|
||||||
third = topDamagers.get(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
String na = this.getPlugin().getLangYml().getString("na");
|
|
||||||
|
|
||||||
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.playerUUID()).getDisplayName();
|
|
||||||
String secondDamage = second == null ? na : StringUtils.internalToString(second.damage());
|
|
||||||
|
|
||||||
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
|
|
||||||
.replace("%top%", topDamager)
|
|
||||||
.replace("%top_damage%", topDamage)
|
|
||||||
.replace("%second%", secondDamager)
|
|
||||||
.replace("%second_damage%", secondDamage)
|
|
||||||
.replace("%third%", thirdDamager)
|
|
||||||
.replace("%third_damage%", thirdDamage)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i <= 3; i++) {
|
|
||||||
List<Pair<Double, String>> topDamagerCommands = boss.getTopDamagerCommands().get(i);
|
|
||||||
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.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.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.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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Entity nearby : entity.getNearbyEntities(boss.getNearbyRadius(), boss.getNearbyRadius(), boss.getNearbyRadius())) {
|
|
||||||
if (nearby instanceof Player) {
|
|
||||||
String playerName = nearby.getName();
|
|
||||||
for (Map.Entry<String, Double> entry : boss.getNearbyPlayersCommands().entrySet()) {
|
|
||||||
if (NumberUtils.randFloat(0, 100) < entry.getValue()) {
|
|
||||||
Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), entry.getKey().replace("%player%", playerName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event.getDrops().addAll(drops);
|
|
||||||
event.setDroppedExp(boss.getExperienceOptions().generateXp());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.listeners;
|
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
|
||||||
import com.willfp.eco.core.PluginDependent;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.util.BossUtils;
|
|
||||||
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;
|
|
||||||
import org.spigotmc.event.entity.EntityMountEvent;
|
|
||||||
|
|
||||||
public class PassiveListeners extends PluginDependent<EcoPlugin> implements Listener {
|
|
||||||
/**
|
|
||||||
* Create new attack listeners.
|
|
||||||
*
|
|
||||||
* @param plugin Instance of EcoBosses.
|
|
||||||
*/
|
|
||||||
public PassiveListeners(@NotNull final EcoPlugin plugin) {
|
|
||||||
super(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a player attacks a boss.
|
|
||||||
*
|
|
||||||
* @param event The event to listen for.
|
|
||||||
*/
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
|
||||||
public void onAttackBoss(@NotNull final EntityMountEvent event) {
|
|
||||||
if (!(event.getEntity() instanceof LivingEntity entity)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(event.getMount() instanceof Boat || event.getMount() instanceof Minecart)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EcoBoss boss = BossUtils.getBoss(entity);
|
|
||||||
|
|
||||||
if (boss == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boss.isDisableBoats()) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.listeners;
|
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
|
||||||
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 org.bukkit.Material;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class SpawnListeners extends PluginDependent<EcoPlugin> implements Listener {
|
|
||||||
/**
|
|
||||||
* Create new spawn listeners and link them to a plugin.
|
|
||||||
*
|
|
||||||
* @param plugin The plugin to link to.
|
|
||||||
*/
|
|
||||||
public SpawnListeners(@NotNull final EcoPlugin plugin) {
|
|
||||||
super(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called on block place.
|
|
||||||
*
|
|
||||||
* @param event The event to listen for.
|
|
||||||
*/
|
|
||||||
@EventHandler
|
|
||||||
public void spawnTotem(@NotNull final BlockPlaceEvent event) {
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
Block block1;
|
|
||||||
Block block2;
|
|
||||||
Block block3;
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
block3 = event.getBlock();
|
|
||||||
block2 = event.getBlock().getRelative(0, -1, 0);
|
|
||||||
block1 = event.getBlock().getRelative(0, -2, 0);
|
|
||||||
} else if (i == 1) {
|
|
||||||
block1 = event.getBlock();
|
|
||||||
block2 = event.getBlock().getRelative(0, 1, 0);
|
|
||||||
block3 = event.getBlock().getRelative(0, 2, 0);
|
|
||||||
} else {
|
|
||||||
block2 = event.getBlock();
|
|
||||||
block1 = event.getBlock().getRelative(0, -1, 0);
|
|
||||||
block3 = event.getBlock().getRelative(0, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpawnTotem placedTotem = new SpawnTotem(block1.getType(), block2.getType(), block3.getType());
|
|
||||||
|
|
||||||
for (EcoBoss boss : EcoBosses.values()) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.tick;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public interface BossTicker {
|
|
||||||
/**
|
|
||||||
* Run on boss tick.
|
|
||||||
*
|
|
||||||
* @param boss The boss.
|
|
||||||
* @param entity The boss entity.
|
|
||||||
* @param tick The current tick: counts up from zero.
|
|
||||||
*/
|
|
||||||
void tick(@NotNull EcoBoss boss,
|
|
||||||
@NotNull LivingEntity entity,
|
|
||||||
long tick);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run on boss death.
|
|
||||||
*
|
|
||||||
* @param boss The boss.
|
|
||||||
* @param entity The boss entity.
|
|
||||||
* @param tick The current tick: counts up from zero.
|
|
||||||
*/
|
|
||||||
default void onDeath(@NotNull EcoBoss boss,
|
|
||||||
@Nullable LivingEntity entity,
|
|
||||||
long tick) {
|
|
||||||
// Can be overridden when needed.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.tick.tickers;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.tick.BossTicker;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.attribute.Attribute;
|
|
||||||
import org.bukkit.boss.BossBar;
|
|
||||||
import org.bukkit.boss.KeyedBossBar;
|
|
||||||
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 {
|
|
||||||
/**
|
|
||||||
* The boss bar.
|
|
||||||
*/
|
|
||||||
private final BossBar bossBar;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The radius that the boss bar should be visible in.
|
|
||||||
*/
|
|
||||||
private final double radius;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new boss bar ticker.
|
|
||||||
* @param bossBar The boss bar.
|
|
||||||
* @param radius The radius.
|
|
||||||
*/
|
|
||||||
public BossBarTicker(@NotNull final BossBar bossBar,
|
|
||||||
final double radius) {
|
|
||||||
this.bossBar = bossBar;
|
|
||||||
this.radius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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());
|
|
||||||
|
|
||||||
if (tick % 40 == 0) {
|
|
||||||
bossBar.removeAll();
|
|
||||||
entity.getNearbyEntities(radius, radius, radius).forEach(entity1 -> {
|
|
||||||
if (entity1 instanceof Player) {
|
|
||||||
bossBar.addPlayer((Player) entity1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeath(@NotNull final EcoBoss boss,
|
|
||||||
@Nullable final LivingEntity entity,
|
|
||||||
final long tick) {
|
|
||||||
bossBar.removeAll();
|
|
||||||
bossBar.setVisible(false);
|
|
||||||
Bukkit.removeBossBar(((KeyedBossBar) bossBar).getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
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.TargetMode;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Mob;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TargetTicker implements BossTicker {
|
|
||||||
/**
|
|
||||||
* The targeting mode.
|
|
||||||
*/
|
|
||||||
private final TargetMode mode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum range.
|
|
||||||
*/
|
|
||||||
private final double range;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new target ticker.
|
|
||||||
*
|
|
||||||
* @param mode The targeting mode.
|
|
||||||
* @param range The range.
|
|
||||||
*/
|
|
||||||
public TargetTicker(@NotNull final TargetMode mode,
|
|
||||||
final double range) {
|
|
||||||
this.mode = mode;
|
|
||||||
this.range = range;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick(@NotNull final EcoBoss boss,
|
|
||||||
@NotNull final LivingEntity entity,
|
|
||||||
final long tick) {
|
|
||||||
Mob mob = (Mob) entity;
|
|
||||||
if (tick % 10 == 0) {
|
|
||||||
List<Player> nearbyPlayers = new ArrayList<>();
|
|
||||||
for (Entity nearbyEntity : entity.getNearbyEntities(range, range, range)) {
|
|
||||||
if (nearbyEntity instanceof Player) {
|
|
||||||
nearbyPlayers.add((Player) nearbyEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nearbyPlayers.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mob.setTarget(mode.getTarget(nearbyPlayers, entity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.EcoBossesPlugin;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBoss;
|
|
||||||
import com.willfp.ecobosses.bosses.EcoBosses;
|
|
||||||
import com.willfp.ecobosses.bosses.LivingEcoBoss;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public class BossUtils {
|
|
||||||
/**
|
|
||||||
* Instance of EcoBosses.
|
|
||||||
*/
|
|
||||||
private static final EcoBossesPlugin PLUGIN = EcoBossesPlugin.getInstance();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get {@link EcoBoss} from an entity.
|
|
||||||
*
|
|
||||||
* @param entity The entity.
|
|
||||||
* @return The boss, or null if not a boss.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public EcoBoss getBoss(@NotNull final LivingEntity entity) {
|
|
||||||
if (!entity.getPersistentDataContainer().has(PLUGIN.getNamespacedKeyFactory().create("boss"), PersistentDataType.STRING)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String bossName = entity.getPersistentDataContainer().get(PLUGIN.getNamespacedKeyFactory().create("boss"), PersistentDataType.STRING);
|
|
||||||
|
|
||||||
if (bossName == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EcoBosses.getByName(bossName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get top damagers for a boss.
|
|
||||||
*
|
|
||||||
* @param entity The boss entity.
|
|
||||||
* @return A list of the top damagers, sorted.
|
|
||||||
*/
|
|
||||||
public List<DamagerProperty> getTopDamagers(@NotNull final LivingEntity entity) {
|
|
||||||
if (getBoss(entity) == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DamagerProperty> topDamagers;
|
|
||||||
if (entity.hasMetadata("ecobosses-top-damagers")) {
|
|
||||||
topDamagers = (List<DamagerProperty>) entity.getMetadata("ecobosses-top-damagers").get(0).value();
|
|
||||||
} else {
|
|
||||||
topDamagers = new ArrayList<>();
|
|
||||||
}
|
|
||||||
assert topDamagers != null;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Warn if a boss is null.
|
|
||||||
*
|
|
||||||
* @param boss The boss.
|
|
||||||
*/
|
|
||||||
public void warnIfNull(@Nullable final LivingEcoBoss boss) {
|
|
||||||
if (boss != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PLUGIN.getLogger().severe("Boss is null! Report this to Auxilor (https://discord.gg/ZcwpSsE)");
|
|
||||||
PLUGIN.getLogger().severe("Send this stack-trace in the relevant channel.");
|
|
||||||
throw new NullPointerException("Boss is null!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Warn if an entity is null.
|
|
||||||
*/
|
|
||||||
public void warnIfNull(@Nullable final Entity entity) {
|
|
||||||
if (entity != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PLUGIN.getLogger().severe("Entity is null! Report this to Auxilor (https://discord.gg/ZcwpSsE)");
|
|
||||||
PLUGIN.getLogger().severe("Send this stack-trace in the relevant channel.");
|
|
||||||
throw new NullPointerException("Entity is null!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.bosstype;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.proxy.util.CustomEntities;
|
|
||||||
import com.willfp.ecobosses.proxy.util.CustomEntity;
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public class BossEntityUtils {
|
|
||||||
/**
|
|
||||||
* Get boss type.
|
|
||||||
*
|
|
||||||
* @param id The name.
|
|
||||||
* @return The boss type.
|
|
||||||
*/
|
|
||||||
public static BossType getBossType(@NotNull final String id) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.bosstype;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public abstract class BossType {
|
|
||||||
/**
|
|
||||||
* Spawn boss entity.
|
|
||||||
*
|
|
||||||
* @param location The location.
|
|
||||||
* @return The entity.
|
|
||||||
*/
|
|
||||||
public abstract LivingEntity spawnBossEntity(@NotNull Location location);
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.bosstype;
|
|
||||||
|
|
||||||
import com.willfp.ecobosses.EcoBossesPlugin;
|
|
||||||
import com.willfp.ecobosses.proxy.proxies.CustomEntitySpawnerProxy;
|
|
||||||
import com.willfp.ecobosses.proxy.util.CustomEntity;
|
|
||||||
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 EcoBossesPlugin.getInstance().getProxy(CustomEntitySpawnerProxy.class).spawnCustomEntity(entityClass, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.bosstype;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
class VanillaBossType extends BossType {
|
|
||||||
/**
|
|
||||||
* The entity type.
|
|
||||||
*/
|
|
||||||
private final Class<? extends LivingEntity> entityClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new vanilla boss type.
|
|
||||||
*
|
|
||||||
* @param entityClass The entity class.
|
|
||||||
*/
|
|
||||||
VanillaBossType(@NotNull final Class<? extends LivingEntity> entityClass) {
|
|
||||||
this.entityClass = entityClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LivingEntity spawnBossEntity(@NotNull final Location location) {
|
|
||||||
return Objects.requireNonNull(location.getWorld()).spawn(location, entityClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.obj;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.bukkit.boss.BarColor;
|
|
||||||
import org.bukkit.boss.BarStyle;
|
|
||||||
|
|
||||||
public record BossbarProperties(BarColor color, BarStyle style) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.obj;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public record DamagerProperty(UUID playerUUID, double damage) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.obj;
|
|
||||||
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
|
|
||||||
public record ExperienceOptions(int minimum, int maximum) {
|
|
||||||
/**
|
|
||||||
* Generate an exp amount.
|
|
||||||
*
|
|
||||||
* @return The amount.
|
|
||||||
*/
|
|
||||||
public int generateXp() {
|
|
||||||
return NumberUtils.randInt(minimum, maximum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.obj;
|
|
||||||
|
|
||||||
public record ImmunityOptions(boolean immuneToFire,
|
|
||||||
boolean immuneToSuffocation,
|
|
||||||
boolean immuneToDrowning,
|
|
||||||
boolean immuneToProjectiles,
|
|
||||||
boolean immuneToExplosions) {
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.obj;
|
|
||||||
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
|
|
||||||
public record OptionedSound(Sound sound,
|
|
||||||
float volume,
|
|
||||||
float pitch) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.obj;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
|
|
||||||
public record SpawnTotem(Material bottom,
|
|
||||||
Material middle,
|
|
||||||
Material top) {
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package com.willfp.ecobosses.bosses.util.obj;
|
|
||||||
|
|
||||||
import com.willfp.eco.util.NumberUtils;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
public class TargetMode {
|
|
||||||
/**
|
|
||||||
* All registered target modes.
|
|
||||||
*/
|
|
||||||
private static final Map<String, TargetMode> VALUES = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Random nearby player.
|
|
||||||
*/
|
|
||||||
public static final TargetMode RANDOM = new TargetMode("random", (list, entity) -> {
|
|
||||||
return list.get(NumberUtils.randInt(0, list.size() - 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closest player.
|
|
||||||
*/
|
|
||||||
public static final TargetMode CLOSEST = new TargetMode("closest", (list, entity) -> {
|
|
||||||
Player player = null;
|
|
||||||
double nearestD2 = 10000;
|
|
||||||
for (Player nearbyPlayer : list) {
|
|
||||||
double d2 = nearbyPlayer.getLocation().distanceSquared(entity.getLocation());
|
|
||||||
if (d2 < nearestD2) {
|
|
||||||
player = nearbyPlayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return player;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Player with lowest health.
|
|
||||||
*/
|
|
||||||
public static final TargetMode LOWEST_HEALTH = new TargetMode("lowest-health", (list, entity) -> {
|
|
||||||
Player player = null;
|
|
||||||
double lowest = 100;
|
|
||||||
for (Player nearbyPlayer : list) {
|
|
||||||
double health = nearbyPlayer.getHealth();
|
|
||||||
if (health < lowest) {
|
|
||||||
player = nearbyPlayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return player;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Player with highest health.
|
|
||||||
*/
|
|
||||||
public static final TargetMode HIGHEST_HEALTH = new TargetMode("highest-health", (list, entity) -> {
|
|
||||||
Player player = null;
|
|
||||||
double highest = 0;
|
|
||||||
for (Player nearbyPlayer : list) {
|
|
||||||
double health = nearbyPlayer.getHealth();
|
|
||||||
if (health > highest) {
|
|
||||||
player = nearbyPlayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return player;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the target mode.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The function to find a player out of a list.
|
|
||||||
*/
|
|
||||||
private final BiFunction<List<Player>, LivingEntity, Player> function;
|
|
||||||
|
|
||||||
protected TargetMode(@NotNull final String name,
|
|
||||||
@NotNull final BiFunction<List<Player>, LivingEntity, Player> function) {
|
|
||||||
this.name = name;
|
|
||||||
this.function = function;
|
|
||||||
|
|
||||||
VALUES.put(name, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get target from list of players.
|
|
||||||
*
|
|
||||||
* @param list The list.
|
|
||||||
* @param entity The boss.
|
|
||||||
* @return The target.
|
|
||||||
*/
|
|
||||||
public Player getTarget(@NotNull final List<Player> list,
|
|
||||||
@NotNull final LivingEntity entity) {
|
|
||||||
return function.apply(list, entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get target mode by name.
|
|
||||||
*
|
|
||||||
* @param name The name.
|
|
||||||
* @return The target mode, or null if not found.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public static TargetMode getByName(@NotNull final String name) {
|
|
||||||
return VALUES.get(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
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.bukkit.Bukkit;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
public class CommandBase64 extends Subcommand {
|
|
||||||
/**
|
|
||||||
* Instantiate a new executor for /ebdrop.
|
|
||||||
*
|
|
||||||
* @param plugin The plugin to manage the execution for.
|
|
||||||
*/
|
|
||||||
public CommandBase64(@NotNull final EcoBossesPlugin plugin) {
|
|
||||||
super(plugin, "base64", "ecobosses.command.base64", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandHandler getHandler() {
|
|
||||||
return (sender, 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());
|
|
||||||
|
|
||||||
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"));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
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 CommandBase64(plugin));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandHandler getHandler() {
|
|
||||||
return (sender, args) -> {
|
|
||||||
sender.sendMessage(this.getPlugin().getLangYml().getMessage("invalid-command"));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
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))));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
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"));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
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);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.willfp.ecobosses.config;
|
|
||||||
|
|
||||||
import com.willfp.eco.core.config.yaml.YamlExtendableConfig;
|
|
||||||
import com.willfp.ecobosses.EcoBossesPlugin;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class BaseBossConfig extends YamlExtendableConfig {
|
|
||||||
/**
|
|
||||||
* Create new EcoBoss config.
|
|
||||||
*
|
|
||||||
* @param configName The name of the config.
|
|
||||||
*/
|
|
||||||
public BaseBossConfig(@NotNull final String configName) {
|
|
||||||
super(configName, true, EcoBossesPlugin.getInstance(), EcoBossesPlugin.class, "bosses/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.willfp.ecobosses.config;
|
|
||||||
|
|
||||||
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 YamlTransientConfig {
|
|
||||||
/**
|
|
||||||
* The name of the config.
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private final String configName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new custom config.
|
|
||||||
*
|
|
||||||
* @param configName The name of the config.
|
|
||||||
* @param config The config.
|
|
||||||
*/
|
|
||||||
public CustomConfig(@NotNull final String configName,
|
|
||||||
@NotNull final YamlConfiguration config) {
|
|
||||||
super(config);
|
|
||||||
this.configName = configName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.willfp.ecobosses
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import com.willfp.eco.core.display.DisplayModule
|
||||||
|
import com.willfp.eco.core.integrations.IntegrationLoader
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import com.willfp.ecobosses.bosses.EggDisplay
|
||||||
|
import com.willfp.ecobosses.bosses.bossHolders
|
||||||
|
import com.willfp.ecobosses.commands.CommandEcoBosses
|
||||||
|
import com.willfp.ecobosses.defence.DamageMultiplierHandler
|
||||||
|
import com.willfp.ecobosses.defence.ImmunitiesHandler
|
||||||
|
import com.willfp.ecobosses.defence.MountHandler
|
||||||
|
import com.willfp.ecobosses.defence.PickupHandler
|
||||||
|
import com.willfp.ecobosses.integrations.levelledmobs.IntegrationLevelledMobs
|
||||||
|
import com.willfp.ecobosses.libreforge.EffectBossDropChanceMultiplier
|
||||||
|
import com.willfp.ecobosses.libreforge.TriggerKillBoss
|
||||||
|
import com.willfp.ecobosses.libreforge.TriggerSpawnBoss
|
||||||
|
import com.willfp.ecobosses.lifecycle.CompatibilityListeners
|
||||||
|
import com.willfp.ecobosses.lifecycle.ConsoleLoggers
|
||||||
|
import com.willfp.ecobosses.lifecycle.DeathListeners
|
||||||
|
import com.willfp.ecobosses.lifecycle.LifecycleHandlers
|
||||||
|
import com.willfp.ecobosses.spawn.AutospawnHandler
|
||||||
|
import com.willfp.ecobosses.spawn.SpawnEggHandler
|
||||||
|
import com.willfp.ecobosses.spawn.SpawnTotemHandler
|
||||||
|
import com.willfp.ecobosses.util.DiscoverRecipeListener
|
||||||
|
import com.willfp.ecobosses.util.TopDamagerListener
|
||||||
|
import com.willfp.libreforge.effects.Effects
|
||||||
|
import com.willfp.libreforge.loader.LibreforgePlugin
|
||||||
|
import com.willfp.libreforge.loader.configs.ConfigCategory
|
||||||
|
import com.willfp.libreforge.registerHolderProvider
|
||||||
|
import com.willfp.libreforge.triggers.Triggers
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
|
||||||
|
class EcoBossesPlugin : LibreforgePlugin() {
|
||||||
|
init {
|
||||||
|
instance = this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadConfigCategories(): List<ConfigCategory> {
|
||||||
|
return listOf(
|
||||||
|
Bosses
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleEnable() {
|
||||||
|
Effects.register(EffectBossDropChanceMultiplier)
|
||||||
|
Triggers.register(TriggerKillBoss)
|
||||||
|
Triggers.register(TriggerSpawnBoss)
|
||||||
|
|
||||||
|
registerHolderProvider { it.bossHolders }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleReload() {
|
||||||
|
Bosses.getAllAlive().forEach { it.remove() }
|
||||||
|
|
||||||
|
AutospawnHandler.startSpawning(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleDisable() {
|
||||||
|
Bosses.getAllAlive().forEach { it.remove() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createDisplayModule(): DisplayModule {
|
||||||
|
return EggDisplay(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadPluginCommands(): List<PluginCommand> {
|
||||||
|
return listOf(
|
||||||
|
CommandEcoBosses(this)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadListeners(): List<Listener> {
|
||||||
|
return listOf(
|
||||||
|
DiscoverRecipeListener(this),
|
||||||
|
TopDamagerListener(),
|
||||||
|
LifecycleHandlers(),
|
||||||
|
SpawnEggHandler(this),
|
||||||
|
DamageMultiplierHandler(),
|
||||||
|
MountHandler(),
|
||||||
|
PickupHandler(),
|
||||||
|
ImmunitiesHandler(),
|
||||||
|
CompatibilityListeners(),
|
||||||
|
SpawnTotemHandler(),
|
||||||
|
DeathListeners(),
|
||||||
|
ConsoleLoggers(this)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadIntegrationLoaders(): List<IntegrationLoader> {
|
||||||
|
return listOf(
|
||||||
|
IntegrationLoader("LevelledMobs") { this.eventManager.registerListener(IntegrationLevelledMobs()) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
lateinit var instance: EcoBossesPlugin
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.willfp.ecobosses.bosses
|
||||||
|
|
||||||
|
import com.willfp.eco.core.fast.fast
|
||||||
|
import com.willfp.ecobosses.EcoBossesPlugin
|
||||||
|
import com.willfp.ecobosses.util.EntityProvidedHolder
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
val Player.bossHolders: Collection<EntityProvidedHolder>
|
||||||
|
get() {
|
||||||
|
val holders = mutableListOf<EntityProvidedHolder>()
|
||||||
|
|
||||||
|
for (boss in Bosses.values()) {
|
||||||
|
for (livingBoss in boss.getAllAlive()) {
|
||||||
|
val entity = livingBoss.entity
|
||||||
|
|
||||||
|
if (entity.world != this.world) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity.location.distanceSquared(this.location) <= boss.influence.pow(2)) {
|
||||||
|
holders.add(EntityProvidedHolder(boss, entity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return holders
|
||||||
|
}
|
||||||
|
|
||||||
|
private val spawnEggKey = EcoBossesPlugin.instance.namespacedKeyFactory.create("spawn_egg")
|
||||||
|
|
||||||
|
var ItemStack.bossEgg: EcoBoss?
|
||||||
|
set(value) {
|
||||||
|
val meta = this.itemMeta ?: return
|
||||||
|
val pdc = meta.persistentDataContainer
|
||||||
|
if (value == null) {
|
||||||
|
pdc.remove(spawnEggKey)
|
||||||
|
} else {
|
||||||
|
pdc.set(spawnEggKey, PersistentDataType.STRING, value.id.key)
|
||||||
|
}
|
||||||
|
this.itemMeta = meta
|
||||||
|
}
|
||||||
|
get() {
|
||||||
|
val pdc = this.fast().persistentDataContainer
|
||||||
|
val id = pdc.get(spawnEggKey, PersistentDataType.STRING) ?: return null
|
||||||
|
return Bosses.getByID(id)
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package com.willfp.ecobosses.bosses
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.willfp.eco.core.config.ConfigType
|
||||||
|
import com.willfp.eco.core.config.interfaces.Config
|
||||||
|
import com.willfp.eco.core.config.readConfig
|
||||||
|
import com.willfp.eco.core.config.updating.ConfigUpdater
|
||||||
|
import com.willfp.eco.core.registry.Registry
|
||||||
|
import com.willfp.ecobosses.EcoBossesPlugin
|
||||||
|
import com.willfp.libreforge.loader.LibreforgePlugin
|
||||||
|
import com.willfp.libreforge.loader.configs.ConfigCategory
|
||||||
|
import com.willfp.libreforge.loader.configs.LegacyLocation
|
||||||
|
import com.willfp.libreforge.separatorAmbivalent
|
||||||
|
import org.bukkit.entity.Entity
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import java.io.File
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
object Bosses : ConfigCategory("boss", "bosses") {
|
||||||
|
/** Registered bosses. */
|
||||||
|
private val registry = Registry<EcoBoss>()
|
||||||
|
|
||||||
|
override val legacyLocation = LegacyLocation(
|
||||||
|
"ecobosses.yml",
|
||||||
|
"bosses"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all registered [EcoBoss]s.
|
||||||
|
*
|
||||||
|
* @return A list of all [EcoBoss]s.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun values(): List<EcoBoss> {
|
||||||
|
return ImmutableList.copyOf(registry.values())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get [EcoBoss] matching ID.
|
||||||
|
*
|
||||||
|
* @param name The name to search for.
|
||||||
|
* @return The matching [EcoBoss], or null if not found.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getByID(name: String): EcoBoss? {
|
||||||
|
return registry[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear(plugin: LibreforgePlugin) {
|
||||||
|
registry.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun acceptConfig(plugin: LibreforgePlugin, id: String, config: Config) {
|
||||||
|
registry.register(EcoBoss(id, config, plugin as EcoBossesPlugin))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all currently alive [EcoBoss]es.
|
||||||
|
*
|
||||||
|
* @return All living bosses.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getAllAlive(): Set<LivingEcoBoss> {
|
||||||
|
val entities = mutableSetOf<LivingEcoBoss>()
|
||||||
|
|
||||||
|
for (boss in values()) {
|
||||||
|
entities.addAll(boss.getAllAlive())
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get [LivingEcoBoss].
|
||||||
|
*
|
||||||
|
* @return The boss, or null if not a boss.
|
||||||
|
*/
|
||||||
|
operator fun get(uuid: UUID): LivingEcoBoss? {
|
||||||
|
for (boss in values()) {
|
||||||
|
val found = boss[uuid]
|
||||||
|
|
||||||
|
if (found != null) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get [LivingEcoBoss].
|
||||||
|
*
|
||||||
|
* @return The boss, or null if not a boss.
|
||||||
|
*/
|
||||||
|
operator fun get(entity: LivingEntity): LivingEcoBoss? {
|
||||||
|
return get(entity.uniqueId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If an entity is a boss. */
|
||||||
|
val Entity?.isBoss: Boolean
|
||||||
|
get() {
|
||||||
|
if (this !is LivingEntity) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bosses[this] != null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.willfp.ecobosses.bosses
|
||||||
|
|
||||||
|
import com.willfp.eco.core.entities.ai.Goal
|
||||||
|
|
||||||
|
data class ConfiguredGoal<T : Goal<*>>(
|
||||||
|
val priority: Int,
|
||||||
|
val goal: T
|
||||||
|
)
|
||||||
@@ -0,0 +1,501 @@
|
|||||||
|
package com.willfp.ecobosses.bosses
|
||||||
|
|
||||||
|
import com.ticxo.modelengine.api.ModelEngineAPI
|
||||||
|
import com.willfp.eco.core.EcoPlugin
|
||||||
|
import com.willfp.eco.core.config.interfaces.Config
|
||||||
|
import com.willfp.eco.core.entities.CustomEntity
|
||||||
|
import com.willfp.eco.core.entities.Entities
|
||||||
|
import com.willfp.eco.core.entities.TestableEntity
|
||||||
|
import com.willfp.eco.core.entities.ai.EntityController
|
||||||
|
import com.willfp.eco.core.entities.ai.EntityGoal
|
||||||
|
import com.willfp.eco.core.entities.ai.EntityGoals
|
||||||
|
import com.willfp.eco.core.entities.ai.TargetGoal
|
||||||
|
import com.willfp.eco.core.entities.ai.TargetGoals
|
||||||
|
import com.willfp.eco.core.items.CustomItem
|
||||||
|
import com.willfp.eco.core.items.Items
|
||||||
|
import com.willfp.eco.core.items.builder.ItemStackBuilder
|
||||||
|
import com.willfp.eco.core.recipe.Recipes
|
||||||
|
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
|
||||||
|
import com.willfp.eco.core.recipe.recipes.CraftingRecipe
|
||||||
|
import com.willfp.eco.core.registry.Registrable
|
||||||
|
import com.willfp.eco.util.NamespacedKeyUtils
|
||||||
|
import com.willfp.eco.util.toComponent
|
||||||
|
import com.willfp.ecobosses.events.BossKillEvent
|
||||||
|
import com.willfp.ecobosses.lifecycle.BossLifecycle
|
||||||
|
import com.willfp.ecobosses.tick.BossBarTicker
|
||||||
|
import com.willfp.ecobosses.tick.BossTicker
|
||||||
|
import com.willfp.ecobosses.tick.ChunkTicker
|
||||||
|
import com.willfp.ecobosses.tick.DisplayNameTicker
|
||||||
|
import com.willfp.ecobosses.tick.LifespanTicker
|
||||||
|
import com.willfp.ecobosses.tick.TargetTicker
|
||||||
|
import com.willfp.ecobosses.tick.TeleportHandler
|
||||||
|
import com.willfp.ecobosses.util.BossDrop
|
||||||
|
import com.willfp.ecobosses.util.CommandReward
|
||||||
|
import com.willfp.ecobosses.util.ConfiguredSound
|
||||||
|
import com.willfp.ecobosses.util.LocalBroadcast
|
||||||
|
import com.willfp.ecobosses.util.LocalCommands
|
||||||
|
import com.willfp.ecobosses.util.PlayableSound
|
||||||
|
import com.willfp.ecobosses.util.SpawnTotem
|
||||||
|
import com.willfp.ecobosses.util.XpReward
|
||||||
|
import com.willfp.ecobosses.util.topDamagers
|
||||||
|
import com.willfp.libreforge.Holder
|
||||||
|
import com.willfp.libreforge.ViolationContext
|
||||||
|
import com.willfp.libreforge.conditions.Conditions
|
||||||
|
import com.willfp.libreforge.effects.Effects
|
||||||
|
import net.kyori.adventure.bossbar.BossBar
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.entity.Mob
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
import java.util.Objects
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class EcoBoss(
|
||||||
|
id: String,
|
||||||
|
val config: Config,
|
||||||
|
private val plugin: EcoPlugin
|
||||||
|
) : Holder, Registrable {
|
||||||
|
override val id = plugin.createNamespacedKey(id)
|
||||||
|
|
||||||
|
val displayName: String = config.getString("display-name")
|
||||||
|
|
||||||
|
val lifespan = config.getInt("lifespan")
|
||||||
|
|
||||||
|
val influence = config.getDouble("influence")
|
||||||
|
|
||||||
|
val targetRange = config.getDouble("target.range")
|
||||||
|
|
||||||
|
val targetMode = TargetMode.getByID(config.getString("target.mode"))!!
|
||||||
|
|
||||||
|
val isBossBarEnabled = config.getBool("boss-bar.enabled")
|
||||||
|
|
||||||
|
val bossBarRadius = config.getDouble("boss-bar.radius")
|
||||||
|
|
||||||
|
val isPreventingMounts = config.getBool("defence.prevent-mounts")
|
||||||
|
|
||||||
|
val isImmuneToExplosions = config.getBool("defence.explosion-immune")
|
||||||
|
|
||||||
|
val isImmuneToFire = config.getBool("defence.fire-immune")
|
||||||
|
|
||||||
|
val isImmuneToDrowning = config.getBool("defence.drowning-immune")
|
||||||
|
|
||||||
|
val isImmuneToSuffocation = config.getBool("defence.suffocation-immune")
|
||||||
|
|
||||||
|
val meleeDamageMultiplier = config.getDouble("defence.melee-damage-multiplier")
|
||||||
|
|
||||||
|
val projectileDamageMultiplier = config.getDouble("defence.projectile-damage-multiplier")
|
||||||
|
|
||||||
|
val canTeleport = config.getBool("defence.teleportation.enabled")
|
||||||
|
|
||||||
|
val teleportRange = config.getInt("defence.teleportation.range")
|
||||||
|
|
||||||
|
val teleportInterval = config.getInt("defence.teleportation.interval")
|
||||||
|
|
||||||
|
private val spawnEggBacker: ItemStack? = run {
|
||||||
|
val enabled = config.getBool("spawn.egg.enabled")
|
||||||
|
if (!enabled) {
|
||||||
|
return@run null
|
||||||
|
}
|
||||||
|
|
||||||
|
val lookup = Items.lookup(config.getString("spawn.egg.item"))
|
||||||
|
|
||||||
|
if (lookup is EmptyTestableItem) {
|
||||||
|
return@run null
|
||||||
|
}
|
||||||
|
|
||||||
|
val name = config.getFormattedStringOrNull("spawn.egg.name")
|
||||||
|
|
||||||
|
val item = ItemStackBuilder(lookup)
|
||||||
|
.addLoreLines(config.getFormattedStrings("spawn.egg.lore"))
|
||||||
|
.apply {
|
||||||
|
if (name != null) {
|
||||||
|
setDisplayName(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.build().apply { bossEgg = this@EcoBoss }
|
||||||
|
|
||||||
|
val key = plugin.namespacedKeyFactory.create("${this.id}_spawn_egg")
|
||||||
|
|
||||||
|
Items.registerCustomItem(
|
||||||
|
key,
|
||||||
|
CustomItem(
|
||||||
|
key,
|
||||||
|
{ it.bossEgg == this },
|
||||||
|
item
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
item
|
||||||
|
}
|
||||||
|
|
||||||
|
val spawnEgg: ItemStack?
|
||||||
|
get() = this.spawnEggBacker?.clone()
|
||||||
|
|
||||||
|
val recipe: CraftingRecipe? = run {
|
||||||
|
if (spawnEggBacker == null || !config.getBool("spawn.egg.craftable")) {
|
||||||
|
return@run null
|
||||||
|
}
|
||||||
|
|
||||||
|
val recipe = Recipes.createAndRegisterRecipe(
|
||||||
|
this@EcoBoss.plugin,
|
||||||
|
"${this.id.key}_spawn_egg",
|
||||||
|
spawnEggBacker,
|
||||||
|
config.getStrings("spawn.egg.recipe")
|
||||||
|
)
|
||||||
|
|
||||||
|
recipe
|
||||||
|
}
|
||||||
|
|
||||||
|
val totem: SpawnTotem? = run {
|
||||||
|
if (!config.getBool("spawn.totem.enabled")) {
|
||||||
|
return@run null
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnTotem(
|
||||||
|
Material.getMaterial(config.getString("spawn.totem.top").uppercase()) ?: return@run null,
|
||||||
|
Material.getMaterial(config.getString("spawn.totem.middle").uppercase()) ?: return@run null,
|
||||||
|
Material.getMaterial(config.getString("spawn.totem.bottom").uppercase()) ?: return@run null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val disabledTotemWorlds: List<String> = config.getStrings("spawn.totem.not-in-worlds")
|
||||||
|
|
||||||
|
val autoSpawnInterval = config.getInt("spawn.autospawn.interval")
|
||||||
|
|
||||||
|
val autoSpawnLocations: List<Location> = run {
|
||||||
|
val locations = mutableListOf<Location>()
|
||||||
|
|
||||||
|
for (config in config.getSubsections("spawn.autospawn.locations")) {
|
||||||
|
val world = Bukkit.getWorld(config.getString("world")) ?: continue
|
||||||
|
val x = config.getDouble("x")
|
||||||
|
val y = config.getDouble("y")
|
||||||
|
val z = config.getDouble("z")
|
||||||
|
locations.add(Location(world, x, y, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
locations
|
||||||
|
}
|
||||||
|
|
||||||
|
val hasCustomAI = config.getBool("custom-ai.enabled")
|
||||||
|
|
||||||
|
val targetGoals = config.getSubsections("custom-ai.target-goals").mapNotNull {
|
||||||
|
val key = NamespacedKeyUtils.fromStringOrNull(it.getString("key")) ?: return@mapNotNull null
|
||||||
|
val deserializer = TargetGoals.getByKey(key) ?: return@mapNotNull null
|
||||||
|
val goal = deserializer.deserialize(it.getSubsection("args")) ?: return@mapNotNull null
|
||||||
|
ConfiguredGoal(it.getInt("priority"), goal)
|
||||||
|
}
|
||||||
|
|
||||||
|
val entityGoals = config.getSubsections("custom-ai.ai-goals").mapNotNull {
|
||||||
|
val key = NamespacedKeyUtils.fromStringOrNull(it.getString("key")) ?: return@mapNotNull null
|
||||||
|
val deserializer = EntityGoals.getByKey(key) ?: return@mapNotNull null
|
||||||
|
val goal = deserializer.deserialize(it.getSubsection("args")) ?: return@mapNotNull null
|
||||||
|
ConfiguredGoal(it.getInt("priority"), goal)
|
||||||
|
}
|
||||||
|
|
||||||
|
val spawnConditions = Conditions.compile(
|
||||||
|
config.getSubsections("spawn.conditions"),
|
||||||
|
ViolationContext(plugin, "$id Spawn Conditions")
|
||||||
|
)
|
||||||
|
|
||||||
|
private val bossBarColor = BossBar.Color.valueOf(config.getString("boss-bar.color").uppercase())
|
||||||
|
|
||||||
|
private val bossBarStyle = BossBar.Overlay.valueOf(config.getString("boss-bar.style").uppercase())
|
||||||
|
|
||||||
|
private val sounds: Map<BossLifecycle, PlayableSound> = run {
|
||||||
|
val map = mutableMapOf<BossLifecycle, PlayableSound>()
|
||||||
|
|
||||||
|
for (value in BossLifecycle.values()) {
|
||||||
|
map[value] = PlayableSound(
|
||||||
|
config.getSubsections("sounds.${value.name.lowercase()}").map {
|
||||||
|
ConfiguredSound.fromConfig(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
private val messages: Map<BossLifecycle, Iterable<LocalBroadcast>> = run {
|
||||||
|
val map = mutableMapOf<BossLifecycle, Iterable<LocalBroadcast>>()
|
||||||
|
|
||||||
|
for (value in BossLifecycle.values()) {
|
||||||
|
map[value] = config.getSubsections("messages.${value.name.lowercase()}").map {
|
||||||
|
LocalBroadcast.fromConfig(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
private val commands: Map<BossLifecycle, LocalCommands> = run {
|
||||||
|
val map = mutableMapOf<BossLifecycle, LocalCommands>()
|
||||||
|
|
||||||
|
for (value in BossLifecycle.values()) {
|
||||||
|
map[value] = LocalCommands(config.getStrings("commands.${value.name.lowercase()}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
private val commandRewards: Map<Int, Iterable<CommandReward>> = run {
|
||||||
|
val map = mutableMapOf<Int, Iterable<CommandReward>>()
|
||||||
|
|
||||||
|
for (rank in config.getSubsection("rewards.top-damager-commands").getKeys(false)) {
|
||||||
|
val rankRewards = mutableListOf<CommandReward>()
|
||||||
|
|
||||||
|
for (config in config.getSubsections("rewards.top-damager-commands.$rank")) {
|
||||||
|
rankRewards.add(
|
||||||
|
CommandReward(
|
||||||
|
config.getDouble("chance"),
|
||||||
|
config.getStrings("commands")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
map[rank.toInt()] = rankRewards
|
||||||
|
}
|
||||||
|
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
private val nearbyCommandRewardRadius = config.getDouble("rewards.nearby-player-commands.radius")
|
||||||
|
|
||||||
|
private val nearbyCommands: Iterable<CommandReward> = run {
|
||||||
|
val list = mutableListOf<CommandReward>()
|
||||||
|
|
||||||
|
for (config in config.getSubsections("rewards.nearby-player-commands.commands")) {
|
||||||
|
list.add(
|
||||||
|
CommandReward(
|
||||||
|
config.getDouble("chance"),
|
||||||
|
config.getStrings("commands")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
||||||
|
private val xp = XpReward(
|
||||||
|
config.getInt("rewards.xp.minimum"),
|
||||||
|
config.getInt("rewards.xp.maximum")
|
||||||
|
)
|
||||||
|
|
||||||
|
private val drops: Iterable<BossDrop> = run {
|
||||||
|
val list = mutableListOf<BossDrop>()
|
||||||
|
|
||||||
|
for (config in config.getSubsections("rewards.drops")) {
|
||||||
|
list.add(
|
||||||
|
BossDrop(
|
||||||
|
config.getDouble("chance"),
|
||||||
|
config.getStrings("items")
|
||||||
|
.map { Items.lookup(it) }
|
||||||
|
.filter { it !is EmptyTestableItem }
|
||||||
|
.map { it.item }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mob: TestableEntity = Entities.lookup(config.getString("mob"))
|
||||||
|
|
||||||
|
private val modelEngineID = config.getStringOrNull("model-engine-id")
|
||||||
|
|
||||||
|
private val modelEngineAnimation = config.getStringOrNull("model-engine-animation")
|
||||||
|
|
||||||
|
private val currentlyAlive = mutableMapOf<UUID, LivingEcoBoss>()
|
||||||
|
|
||||||
|
override val conditions = Conditions.compile(
|
||||||
|
config.getSubsections("conditions"),
|
||||||
|
ViolationContext(plugin, "Boss ID $id")
|
||||||
|
)
|
||||||
|
|
||||||
|
override val effects = Effects.compile(
|
||||||
|
config.getSubsections("effects"),
|
||||||
|
ViolationContext(plugin, "Boss ID $id")
|
||||||
|
)
|
||||||
|
|
||||||
|
fun markDead(uuid: UUID) {
|
||||||
|
currentlyAlive.remove(uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(uuid: UUID): LivingEcoBoss? {
|
||||||
|
return currentlyAlive[uuid]
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(entity: LivingEntity): LivingEcoBoss? {
|
||||||
|
return currentlyAlive[entity.uniqueId]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllAlive(): Set<LivingEcoBoss> {
|
||||||
|
return currentlyAlive.values.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun spawn(location: Location): LivingEcoBoss {
|
||||||
|
val mob = mob.spawn(location) as Mob
|
||||||
|
mob.isPersistent = true
|
||||||
|
mob.isCustomNameVisible = true
|
||||||
|
mob.removeWhenFarAway = false
|
||||||
|
mob.persistentDataContainer.set(
|
||||||
|
plugin.namespacedKeyFactory.create("boss"),
|
||||||
|
PersistentDataType.STRING,
|
||||||
|
this.id.key
|
||||||
|
)
|
||||||
|
|
||||||
|
if (hasCustomAI) {
|
||||||
|
val controller = EntityController.getFor(mob).clearAllGoals()
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST") // What could go wrong?
|
||||||
|
targetGoals.forEach { controller.addTargetGoal(it.priority, it.goal as TargetGoal<in Mob>) }
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
entityGoals.forEach { controller.addEntityGoal(it.priority, it.goal as EntityGoal<in Mob>) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelEngineID != null && Bukkit.getPluginManager().isPluginEnabled("ModelEngine")) {
|
||||||
|
val model = ModelEngineAPI.createActiveModel(modelEngineID)
|
||||||
|
|
||||||
|
if (model == null) {
|
||||||
|
plugin.logger.warning("Invalid Model Engine ID for boss $id")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelEngineAnimation != null) {
|
||||||
|
val animationHandler = model.animationHandler
|
||||||
|
val animationProperty = animationHandler.getAnimation(modelEngineAnimation)
|
||||||
|
|
||||||
|
if (animationProperty != null) {
|
||||||
|
animationHandler.playAnimation(animationProperty, true)
|
||||||
|
} else {
|
||||||
|
plugin.logger.warning("Animation $modelEngineAnimation not found in model $modelEngineID, defaulting to walk!")
|
||||||
|
val animationPropertyWalk = animationHandler.getAnimation("walk")
|
||||||
|
if (animationPropertyWalk != null) {
|
||||||
|
animationHandler.playAnimation(animationPropertyWalk, true)
|
||||||
|
} else {
|
||||||
|
plugin.logger.warning("Walk animation not found in $modelEngineID!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val modelled = ModelEngineAPI.createModeledEntity(mob)
|
||||||
|
modelled.addModel(model, true)
|
||||||
|
modelled.isBaseEntityVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
val boss = LivingEcoBoss(
|
||||||
|
plugin,
|
||||||
|
mob,
|
||||||
|
this,
|
||||||
|
createTickers()
|
||||||
|
)
|
||||||
|
currentlyAlive[mob.uniqueId] = boss
|
||||||
|
return boss
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTickers(): Set<BossTicker> {
|
||||||
|
val tickers = mutableSetOf(
|
||||||
|
LifespanTicker(),
|
||||||
|
DisplayNameTicker(),
|
||||||
|
TargetTicker(),
|
||||||
|
TeleportHandler(),
|
||||||
|
ChunkTicker()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isBossBarEnabled) {
|
||||||
|
tickers.add(
|
||||||
|
BossBarTicker(
|
||||||
|
BossBar.bossBar(
|
||||||
|
this.displayName.toComponent(),
|
||||||
|
1.0f,
|
||||||
|
bossBarColor,
|
||||||
|
bossBarStyle
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tickers
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleLifecycle(lifecycle: BossLifecycle, location: Location, entity: LivingEntity?) {
|
||||||
|
sounds[lifecycle]?.play(location)
|
||||||
|
messages[lifecycle]?.forEach { it.broadcast(location, entity?.topDamagers ?: emptyList()) }
|
||||||
|
commands[lifecycle]?.dispatch(location, entity?.topDamagers ?: emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun processRewards(event: BossKillEvent) {
|
||||||
|
val entity = event.boss.entity
|
||||||
|
val location = entity.location
|
||||||
|
val player = event.killer
|
||||||
|
|
||||||
|
for (drop in drops) {
|
||||||
|
drop.drop(this, location, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
xp.modify(event.event)
|
||||||
|
|
||||||
|
for ((index, damager) in entity.topDamagers.withIndex()) {
|
||||||
|
val rewards = commandRewards[index + 1] ?: continue
|
||||||
|
val damagerPlayer = Bukkit.getPlayer(damager.uuid) ?: continue
|
||||||
|
for (reward in rewards) {
|
||||||
|
reward.reward(damagerPlayer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (nearbyPlayer in entity.getNearbyEntities(
|
||||||
|
nearbyCommandRewardRadius,
|
||||||
|
nearbyCommandRewardRadius,
|
||||||
|
nearbyCommandRewardRadius
|
||||||
|
).filterIsInstance<Player>()) {
|
||||||
|
for (command in nearbyCommands) {
|
||||||
|
command.reward(nearbyPlayer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
Entities.registerCustomEntity(
|
||||||
|
plugin.namespacedKeyFactory.create(id),
|
||||||
|
CustomEntity(
|
||||||
|
plugin.namespacedKeyFactory.create(id),
|
||||||
|
{
|
||||||
|
if (it !is LivingEntity) {
|
||||||
|
return@CustomEntity false
|
||||||
|
}
|
||||||
|
|
||||||
|
return@CustomEntity Bosses[it]?.boss == this
|
||||||
|
},
|
||||||
|
{
|
||||||
|
this.spawn(it).entity
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getID(): String {
|
||||||
|
return this.id.key
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is EcoBoss) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return id == other.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return Objects.hash(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return (
|
||||||
|
"EcoBoss{" +
|
||||||
|
id +
|
||||||
|
"}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.willfp.ecobosses.bosses
|
||||||
|
|
||||||
|
import com.willfp.eco.core.EcoPlugin
|
||||||
|
import com.willfp.eco.core.display.Display
|
||||||
|
import com.willfp.eco.core.display.DisplayModule
|
||||||
|
import com.willfp.eco.core.display.DisplayPriority
|
||||||
|
import com.willfp.eco.core.fast.fast
|
||||||
|
import com.willfp.libreforge.SimpleProvidedHolder
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
|
class EggDisplay(
|
||||||
|
plugin: EcoPlugin
|
||||||
|
) : DisplayModule(
|
||||||
|
plugin,
|
||||||
|
DisplayPriority.LOW
|
||||||
|
) {
|
||||||
|
override fun display(itemStack: ItemStack, player: Player?, vararg args: Any) {
|
||||||
|
if (player == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val fis = itemStack.fast()
|
||||||
|
|
||||||
|
val lore = fis.lore.toMutableList()
|
||||||
|
|
||||||
|
val egg = itemStack.bossEgg ?: return
|
||||||
|
|
||||||
|
val lines = egg.spawnConditions
|
||||||
|
.filterNot { it.isMet(player, SimpleProvidedHolder(egg)) }
|
||||||
|
.map { it.notMetLines.map { line -> Display.PREFIX + line } }
|
||||||
|
.flatten()
|
||||||
|
|
||||||
|
|
||||||
|
if (lines.isNotEmpty()) {
|
||||||
|
lore.add(Display.PREFIX)
|
||||||
|
lore.addAll(lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
fis.lore = lore
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.willfp.ecobosses.bosses
|
||||||
|
|
||||||
|
import com.willfp.eco.core.EcoPlugin
|
||||||
|
import com.willfp.ecobosses.tick.BossTicker
|
||||||
|
import org.bukkit.Chunk
|
||||||
|
import org.bukkit.entity.Mob
|
||||||
|
|
||||||
|
class LivingEcoBoss(
|
||||||
|
plugin: EcoPlugin,
|
||||||
|
val entity: Mob,
|
||||||
|
val boss: EcoBoss,
|
||||||
|
private val tickers: Set<BossTicker>
|
||||||
|
) {
|
||||||
|
private val ticker = plugin.runnableFactory.create {
|
||||||
|
if (tick()) {
|
||||||
|
it.cancel()
|
||||||
|
}
|
||||||
|
}.apply { runTaskTimer(1, 1) }
|
||||||
|
|
||||||
|
val chunk: Chunk
|
||||||
|
get() = entity.location.chunk
|
||||||
|
|
||||||
|
val forceLoadedChunks = mutableListOf<Chunk>()
|
||||||
|
|
||||||
|
val deathTime = System.currentTimeMillis() + (boss.lifespan * 1000)
|
||||||
|
|
||||||
|
private var currentTick = 1 // Start at 1 as 0 is divisible by everything
|
||||||
|
|
||||||
|
private fun tick(): Boolean {
|
||||||
|
if (entity.isDead) {
|
||||||
|
remove()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ticker in tickers) {
|
||||||
|
ticker.tick(this, currentTick)
|
||||||
|
}
|
||||||
|
currentTick++
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove() {
|
||||||
|
ticker.cancel()
|
||||||
|
entity.remove()
|
||||||
|
tickers.forEach { it.onDeath(this, currentTick) }
|
||||||
|
|
||||||
|
boss.markDead(entity.uniqueId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "LivingEcoBoss{boss=$boss, uuid=${entity.uniqueId}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.willfp.ecobosses.bosses
|
||||||
|
|
||||||
|
import com.google.common.collect.BiMap
|
||||||
|
import com.google.common.collect.HashBiMap
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import org.bukkit.GameMode
|
||||||
|
import org.bukkit.entity.Entity
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
|
class TargetMode(
|
||||||
|
val id: String,
|
||||||
|
private val function: (Collection<LivingEntity>, Entity) -> LivingEntity?
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
BY_ID[this.id] = this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTarget(boss: LivingEcoBoss): LivingEntity? {
|
||||||
|
val entity = boss.entity
|
||||||
|
|
||||||
|
return function(
|
||||||
|
entity.getNearbyEntities(
|
||||||
|
boss.boss.targetRange,
|
||||||
|
boss.boss.targetRange,
|
||||||
|
boss.boss.targetRange
|
||||||
|
).filterIsInstance<Player>()
|
||||||
|
.filter { listOf(GameMode.SURVIVAL, GameMode.ADVENTURE).contains(it.gameMode) }
|
||||||
|
.ifEmpty { return null },
|
||||||
|
entity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val BY_ID: BiMap<String, TargetMode> = HashBiMap.create()
|
||||||
|
|
||||||
|
val RANDOM = TargetMode("random") { entities, _ ->
|
||||||
|
entities.random()
|
||||||
|
}
|
||||||
|
|
||||||
|
val CLOSEST = TargetMode("closest") { entities, boss ->
|
||||||
|
entities.minByOrNull { it.location.distanceSquared(boss.location) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val LOWEST_HEALTH = TargetMode("lowest_health") { entities, _ ->
|
||||||
|
entities.minByOrNull { it.health }
|
||||||
|
}
|
||||||
|
|
||||||
|
val HIGHEST_HEALTH = TargetMode("highest_health") { entities, _ ->
|
||||||
|
entities.maxByOrNull { it.health }
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun values(): List<TargetMode> {
|
||||||
|
return ImmutableList.copyOf(BY_ID.values)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getByID(id: String): TargetMode? {
|
||||||
|
return BY_ID[id]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.willfp.ecobosses.commands
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import com.willfp.ecobosses.EcoBossesPlugin
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class CommandEcoBosses(plugin: EcoBossesPlugin) : PluginCommand(
|
||||||
|
plugin,
|
||||||
|
"ecobosses",
|
||||||
|
"ecobosses.command.ecobosses",
|
||||||
|
false
|
||||||
|
) {
|
||||||
|
override fun onExecute(
|
||||||
|
sender: CommandSender,
|
||||||
|
args: List<String>
|
||||||
|
) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("invalid-command"))
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
addSubcommand(CommandReload(plugin))
|
||||||
|
.addSubcommand(CommandKillall(plugin))
|
||||||
|
.addSubcommand(CommandSpawn(plugin))
|
||||||
|
.addSubcommand(CommandGive(plugin))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package com.willfp.ecobosses.commands
|
||||||
|
|
||||||
|
import com.willfp.eco.core.EcoPlugin
|
||||||
|
import com.willfp.eco.core.command.impl.Subcommand
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.util.StringUtil
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
|
class CommandGive(plugin: EcoPlugin) : Subcommand(
|
||||||
|
plugin,
|
||||||
|
"give",
|
||||||
|
"ecobosses.command.give",
|
||||||
|
false
|
||||||
|
) {
|
||||||
|
override fun onExecute(
|
||||||
|
sender: CommandSender,
|
||||||
|
args: List<String>
|
||||||
|
) {
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("needs-player"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (args.size == 1) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("needs-boss"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var amount = 1
|
||||||
|
if (args.size > 2) {
|
||||||
|
amount = args[2].toIntOrNull() ?: amount
|
||||||
|
}
|
||||||
|
|
||||||
|
val recieverName = args[0]
|
||||||
|
val reciever = Bukkit.getPlayer(recieverName)
|
||||||
|
if (reciever == null) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("invalid-player"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val key = args[1]
|
||||||
|
val boss = Bosses.getByID(key)
|
||||||
|
|
||||||
|
if (boss?.spawnEgg == null) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("invalid-boss"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var message = plugin.langYml.getMessage("give-success")
|
||||||
|
message = message.replace("%boss%", boss.id.key).replace("%recipient%", reciever.name)
|
||||||
|
sender.sendMessage(message)
|
||||||
|
|
||||||
|
val itemStack = boss.spawnEgg!!
|
||||||
|
|
||||||
|
itemStack.amount = amount
|
||||||
|
reciever.inventory.addItem(itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tabComplete(
|
||||||
|
sender: CommandSender,
|
||||||
|
args: List<String>
|
||||||
|
): List<String> {
|
||||||
|
val completions = mutableListOf<String>()
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
return BOSS_NAMES
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size == 1) {
|
||||||
|
StringUtil.copyPartialMatches(args[0], Bukkit.getOnlinePlayers().stream().map { obj: Player -> obj.name }
|
||||||
|
.collect(Collectors.toList()), completions)
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size == 2) {
|
||||||
|
StringUtil.copyPartialMatches(args[1], BOSS_NAMES, completions)
|
||||||
|
completions.sort()
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size == 3) {
|
||||||
|
StringUtil.copyPartialMatches(args[2], NUMBERS, completions)
|
||||||
|
completions.sortWith { s1: String, s2: String ->
|
||||||
|
val t1 = s1.toInt()
|
||||||
|
val t2 = s2.toInt()
|
||||||
|
t1 - t2
|
||||||
|
}
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
return ArrayList(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* The cached names.
|
||||||
|
*/
|
||||||
|
private val BOSS_NAMES: List<String>
|
||||||
|
get() = Bosses.values().map { it.id.key }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cached numbers.
|
||||||
|
*/
|
||||||
|
private val NUMBERS = listOf(
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"10",
|
||||||
|
"32",
|
||||||
|
"64"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.willfp.ecobosses.commands
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.Subcommand
|
||||||
|
import com.willfp.ecobosses.EcoBossesPlugin
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class CommandKillall(plugin: EcoBossesPlugin) : Subcommand(
|
||||||
|
plugin,
|
||||||
|
"killall",
|
||||||
|
"ecobosses.command.killall",
|
||||||
|
false
|
||||||
|
) {
|
||||||
|
override fun onExecute(
|
||||||
|
sender: CommandSender,
|
||||||
|
args: List<String>
|
||||||
|
) {
|
||||||
|
val alive = Bosses.getAllAlive()
|
||||||
|
|
||||||
|
for (boss in alive) {
|
||||||
|
boss.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(
|
||||||
|
plugin.langYml.getMessage("killall").replace("%amount%", alive.size.toString())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.willfp.ecobosses.commands
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.Subcommand
|
||||||
|
import com.willfp.ecobosses.EcoBossesPlugin
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class CommandReload(plugin: EcoBossesPlugin) : Subcommand(
|
||||||
|
plugin,
|
||||||
|
"reload",
|
||||||
|
"ecobosses.command.reload",
|
||||||
|
false
|
||||||
|
) {
|
||||||
|
override fun onExecute(
|
||||||
|
sender: CommandSender,
|
||||||
|
args: List<String>
|
||||||
|
) {
|
||||||
|
plugin.reload()
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("reloaded"))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
package com.willfp.ecobosses.commands
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.Subcommand
|
||||||
|
import com.willfp.ecobosses.EcoBossesPlugin
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import com.willfp.ecobosses.events.BossSpawnEvent
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.World
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.util.StringUtil
|
||||||
|
|
||||||
|
class CommandSpawn(plugin: EcoBossesPlugin) : Subcommand(
|
||||||
|
plugin,
|
||||||
|
"spawn",
|
||||||
|
"ecobosses.command.spawn",
|
||||||
|
false
|
||||||
|
) {
|
||||||
|
override fun onExecute(
|
||||||
|
sender: CommandSender,
|
||||||
|
args: List<String>
|
||||||
|
) {
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("specify-boss"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val bossName = args[0]
|
||||||
|
val boss = Bosses.getByID(bossName.lowercase())
|
||||||
|
if (boss == null) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("specify-boss"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var location: Location? = null
|
||||||
|
if (sender is Player) {
|
||||||
|
location = sender.location
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size >= 4) {
|
||||||
|
val xString = args[1]
|
||||||
|
val yString = args[2]
|
||||||
|
val zString = args[3]
|
||||||
|
val xPos: Double
|
||||||
|
val yPos: Double
|
||||||
|
val zPos: Double
|
||||||
|
if (xString.startsWith("~") && sender is Player) {
|
||||||
|
val xDiff = xString.replace("~", "")
|
||||||
|
val yDiff = yString.replace("~", "")
|
||||||
|
val zDiff = zString.replace("~", "")
|
||||||
|
xPos = if (xDiff.isEmpty()) {
|
||||||
|
sender.location.x
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
sender.location.x + xDiff.toDouble()
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
sender.location.x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yPos = if (yDiff.isEmpty()) {
|
||||||
|
sender.location.y
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
sender.location.y + yDiff.toDouble()
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
sender.location.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zPos = if (zDiff.isEmpty()) {
|
||||||
|
sender.location.z
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
sender.location.z + yDiff.toDouble()
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
sender.location.z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
xPos = xString.toDouble()
|
||||||
|
yPos = yString.toDouble()
|
||||||
|
zPos = zString.toDouble()
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("invalid-location"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
location = Location(null, xPos, yPos, zPos)
|
||||||
|
}
|
||||||
|
var world: World? = null
|
||||||
|
if (sender is Player) {
|
||||||
|
world = sender.world
|
||||||
|
}
|
||||||
|
if (args.size >= 5) {
|
||||||
|
world = Bukkit.getWorld(args[4])
|
||||||
|
}
|
||||||
|
if (location == null) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("invalid-location"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
location.world = world
|
||||||
|
|
||||||
|
if (world == null) {
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("invalid-world"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val event = BossSpawnEvent(
|
||||||
|
boss,
|
||||||
|
location,
|
||||||
|
BossSpawnEvent.SpawnReason.COMMAND,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().callEvent(event)
|
||||||
|
|
||||||
|
if (!event.isCancelled) {
|
||||||
|
boss.spawn(location)
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(plugin.langYml.getMessage("spawned"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tabComplete(
|
||||||
|
sender: CommandSender,
|
||||||
|
args: List<String>
|
||||||
|
): List<String> {
|
||||||
|
val completions = mutableListOf<String>()
|
||||||
|
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size == 1) {
|
||||||
|
StringUtil.copyPartialMatches(args[0], BOSS_NAMES, completions)
|
||||||
|
completions.sort()
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
if (args.size == 2) {
|
||||||
|
StringUtil.copyPartialMatches(args[1], TILDE, completions)
|
||||||
|
completions.sort()
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
if (args.size == 3) {
|
||||||
|
StringUtil.copyPartialMatches(args[2], TILDE, completions)
|
||||||
|
completions.sort()
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
if (args.size == 4) {
|
||||||
|
StringUtil.copyPartialMatches(args[3], TILDE, completions)
|
||||||
|
completions.sort()
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
if (args.size == 5) {
|
||||||
|
StringUtil.copyPartialMatches(args[4], Bukkit.getWorlds().map { it.name }, completions)
|
||||||
|
completions.sort()
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
return ArrayList(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* The cached names.
|
||||||
|
*/
|
||||||
|
private val BOSS_NAMES: List<String>
|
||||||
|
get() = Bosses.values().map { it.id.key }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cached numbers.
|
||||||
|
*/
|
||||||
|
private val TILDE = listOf(
|
||||||
|
"~"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.willfp.ecobosses.defence
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.entity.Projectile
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityDamageByEntityEvent
|
||||||
|
|
||||||
|
class DamageMultiplierHandler : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: EntityDamageByEntityEvent) {
|
||||||
|
val entity = event.entity as? LivingEntity ?: return
|
||||||
|
val boss = Bosses[entity]?.boss ?: return
|
||||||
|
|
||||||
|
if (event.damager is Player) {
|
||||||
|
event.damage *= boss.meleeDamageMultiplier
|
||||||
|
|
||||||
|
if (boss.meleeDamageMultiplier == 0.0) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.damager is Projectile) {
|
||||||
|
event.damage *= boss.projectileDamageMultiplier
|
||||||
|
|
||||||
|
if (boss.projectileDamageMultiplier == 0.0) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.willfp.ecobosses.defence
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent
|
||||||
|
|
||||||
|
class ImmunitiesHandler : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: EntityDamageEvent) {
|
||||||
|
val entity = event.entity as? LivingEntity ?: return
|
||||||
|
val boss = Bosses[entity]?.boss ?: return
|
||||||
|
|
||||||
|
when (event.cause) {
|
||||||
|
EntityDamageEvent.DamageCause.SUFFOCATION -> {
|
||||||
|
if (boss.isImmuneToSuffocation) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityDamageEvent.DamageCause.ENTITY_EXPLOSION, EntityDamageEvent.DamageCause.BLOCK_EXPLOSION -> {
|
||||||
|
if (boss.isImmuneToExplosions) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityDamageEvent.DamageCause.HOT_FLOOR, EntityDamageEvent.DamageCause.FIRE,
|
||||||
|
EntityDamageEvent.DamageCause.FIRE_TICK, EntityDamageEvent.DamageCause.LAVA -> {
|
||||||
|
if (boss.isImmuneToFire) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityDamageEvent.DamageCause.DROWNING -> {
|
||||||
|
if (boss.isImmuneToDrowning) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.willfp.ecobosses.defence
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.spigotmc.event.entity.EntityMountEvent
|
||||||
|
|
||||||
|
class MountHandler : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: EntityMountEvent) {
|
||||||
|
val entity = event.entity as? LivingEntity ?: return
|
||||||
|
val boss = Bosses[entity]?.boss ?: return
|
||||||
|
|
||||||
|
if (boss.isPreventingMounts) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.willfp.ecobosses.defence
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityPickupItemEvent
|
||||||
|
|
||||||
|
class PickupHandler : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: EntityPickupItemEvent) {
|
||||||
|
val entity = event.entity as? LivingEntity ?: return
|
||||||
|
Bosses[entity]?.boss ?: return
|
||||||
|
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.willfp.ecobosses.events
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.LivingEcoBoss
|
||||||
|
import org.bukkit.event.Event
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
|
||||||
|
abstract class BossDeathEvent(
|
||||||
|
val boss: LivingEcoBoss
|
||||||
|
) : Event() {
|
||||||
|
override fun getHandlers(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val HANDLERS = HandlerList()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getHandlerList(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.willfp.ecobosses.events
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.LivingEcoBoss
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
|
||||||
|
class BossDespawnEvent(
|
||||||
|
boss: LivingEcoBoss,
|
||||||
|
) : BossDeathEvent(boss) {
|
||||||
|
override fun getHandlers(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val HANDLERS = HandlerList()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getHandlerList(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.willfp.ecobosses.events
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.LivingEcoBoss
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.event.entity.EntityDeathEvent
|
||||||
|
|
||||||
|
class BossKillEvent(
|
||||||
|
boss: LivingEcoBoss,
|
||||||
|
val killer: Player?,
|
||||||
|
val event: EntityDeathEvent
|
||||||
|
) : BossDeathEvent(boss) {
|
||||||
|
override fun getHandlers(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val HANDLERS = HandlerList()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getHandlerList(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
class BossSpawnEvent(
|
||||||
|
val boss: EcoBoss,
|
||||||
|
val location: Location,
|
||||||
|
val reason: SpawnReason,
|
||||||
|
val spawner: Player?
|
||||||
|
) : Event(), Cancellable {
|
||||||
|
private var isCancelled: Boolean = false
|
||||||
|
|
||||||
|
override fun isCancelled(): Boolean {
|
||||||
|
return isCancelled
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setCancelled(cancelled: Boolean) {
|
||||||
|
isCancelled = cancelled
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getHandlers(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class SpawnReason {
|
||||||
|
TOTEM,
|
||||||
|
EGG,
|
||||||
|
COMMAND,
|
||||||
|
AUTOSPAWN,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val HANDLERS = HandlerList()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getHandlerList(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.willfp.ecobosses.events
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.EcoBoss
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.Event
|
||||||
|
import org.bukkit.event.HandlerList
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
|
class BossTryDropItemEvent(
|
||||||
|
val boss: EcoBoss,
|
||||||
|
val location: Location,
|
||||||
|
var items: MutableCollection<ItemStack>,
|
||||||
|
var chance: Double,
|
||||||
|
val player: Player?
|
||||||
|
) : Event() {
|
||||||
|
override fun getHandlers(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val HANDLERS = HandlerList()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getHandlerList(): HandlerList {
|
||||||
|
return HANDLERS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.willfp.ecobosses.integrations.levelledmobs
|
||||||
|
|
||||||
|
import com.willfp.eco.core.integrations.Integration
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import me.lokka30.levelledmobs.events.MobPreLevelEvent
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
|
||||||
|
class IntegrationLevelledMobs : Listener, Integration {
|
||||||
|
@EventHandler
|
||||||
|
fun handle(event: MobPreLevelEvent) {
|
||||||
|
if (Bosses[event.entity] != null) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPluginName(): String {
|
||||||
|
return "LevelledMobs"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.willfp.ecobosses.libreforge
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import com.willfp.ecobosses.bosses.EcoBoss
|
||||||
|
import com.willfp.ecobosses.events.BossTryDropItemEvent
|
||||||
|
import com.willfp.libreforge.effects.templates.MultiMultiplierEffect
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
|
||||||
|
object EffectBossDropChanceMultiplier : MultiMultiplierEffect<EcoBoss>("boss_drop_chance_multiplier") {
|
||||||
|
override val key = "bosses"
|
||||||
|
|
||||||
|
override fun getElement(key: String): EcoBoss? {
|
||||||
|
return Bosses.getByID(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAllElements(): Collection<EcoBoss> {
|
||||||
|
return Bosses.values()
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
fun handle(event: BossTryDropItemEvent) {
|
||||||
|
val player = event.player ?: return
|
||||||
|
|
||||||
|
val multiplier = getMultiplier(player, event.boss)
|
||||||
|
|
||||||
|
event.chance *= multiplier
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.willfp.ecobosses.libreforge
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.events.BossKillEvent
|
||||||
|
import com.willfp.libreforge.triggers.Trigger
|
||||||
|
import com.willfp.libreforge.triggers.TriggerData
|
||||||
|
import com.willfp.libreforge.triggers.TriggerParameter
|
||||||
|
import org.bukkit.attribute.Attribute
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
|
||||||
|
object TriggerKillBoss : Trigger("kill_boss") {
|
||||||
|
override val parameters = setOf(
|
||||||
|
TriggerParameter.PLAYER,
|
||||||
|
TriggerParameter.VICTIM,
|
||||||
|
TriggerParameter.LOCATION
|
||||||
|
)
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
fun handle(event: BossKillEvent) {
|
||||||
|
val killer = event.killer ?: return
|
||||||
|
val entity = event.boss.entity
|
||||||
|
|
||||||
|
this.dispatch(
|
||||||
|
killer,
|
||||||
|
TriggerData(
|
||||||
|
player = killer,
|
||||||
|
victim = entity,
|
||||||
|
location = entity.location,
|
||||||
|
value = entity.getAttribute(Attribute.GENERIC_MAX_HEALTH)!!.value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.willfp.ecobosses.libreforge
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.events.BossSpawnEvent
|
||||||
|
import com.willfp.libreforge.triggers.Trigger
|
||||||
|
import com.willfp.libreforge.triggers.TriggerData
|
||||||
|
import com.willfp.libreforge.triggers.TriggerParameter
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
|
||||||
|
object TriggerSpawnBoss : Trigger("spawn_boss") {
|
||||||
|
override val parameters = setOf(
|
||||||
|
TriggerParameter.PLAYER,
|
||||||
|
TriggerParameter.LOCATION
|
||||||
|
)
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
fun handle(event: BossSpawnEvent) {
|
||||||
|
val player = event.spawner ?: return
|
||||||
|
val location = event.location
|
||||||
|
|
||||||
|
this.dispatch(
|
||||||
|
player,
|
||||||
|
TriggerData(
|
||||||
|
player = player,
|
||||||
|
location = location
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.willfp.ecobosses.lifecycle
|
||||||
|
|
||||||
|
enum class BossLifecycle(
|
||||||
|
val isDeath: Boolean
|
||||||
|
) {
|
||||||
|
SPAWN(false),
|
||||||
|
KILL(true),
|
||||||
|
DESPAWN(true),
|
||||||
|
INJURE(false)
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.willfp.ecobosses.lifecycle
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses.isBoss
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityTransformEvent
|
||||||
|
import org.bukkit.event.entity.SlimeSplitEvent
|
||||||
|
|
||||||
|
class CompatibilityListeners : Listener {
|
||||||
|
@EventHandler
|
||||||
|
fun handle(event: SlimeSplitEvent) {
|
||||||
|
if (!event.entity.isBoss) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun handle(event: EntityTransformEvent) {
|
||||||
|
if (!event.entity.isBoss) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.willfp.ecobosses.lifecycle
|
||||||
|
|
||||||
|
import com.willfp.eco.core.EcoPlugin
|
||||||
|
import com.willfp.ecobosses.events.BossDespawnEvent
|
||||||
|
import com.willfp.ecobosses.events.BossKillEvent
|
||||||
|
import com.willfp.ecobosses.events.BossSpawnEvent
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.EventPriority
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
|
||||||
|
class ConsoleLoggers(
|
||||||
|
private val plugin: EcoPlugin
|
||||||
|
) : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.MONITOR
|
||||||
|
)
|
||||||
|
fun handle(event: BossSpawnEvent) {
|
||||||
|
if (!plugin.configYml.getBool("log-spawn-kill")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val location = "${event.location.world?.name}: ${event.location.x}, ${event.location.y}, ${event.location.z}"
|
||||||
|
|
||||||
|
plugin.logger.info("&a${event.boss.id}&r was spawned by &a${event.spawner?.name}&r at &a$location")
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.MONITOR
|
||||||
|
)
|
||||||
|
fun handle(event: BossKillEvent) {
|
||||||
|
if (!plugin.configYml.getBool("log-spawn-kill")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val loc = event.boss.entity.location
|
||||||
|
val location = "${loc.world?.name}: ${loc.x}, ${loc.y}, ${loc.z}"
|
||||||
|
|
||||||
|
plugin.logger.info("&a${event.boss.boss.id}&r was killed by &a${event.killer?.name}&r at &a$location")
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.MONITOR
|
||||||
|
)
|
||||||
|
fun handle(event: BossDespawnEvent) {
|
||||||
|
if (!plugin.configYml.getBool("log-spawn-kill")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val loc = event.boss.entity.location
|
||||||
|
val location = "${loc.world?.name}: ${loc.x}, ${loc.y}, ${loc.z}"
|
||||||
|
|
||||||
|
plugin.logger.info("&a${event.boss.boss.id}&r despawned at &a$location")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.willfp.ecobosses.lifecycle
|
||||||
|
|
||||||
|
import com.willfp.eco.core.events.EntityDeathByEntityEvent
|
||||||
|
import com.willfp.eco.util.tryAsPlayer
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import com.willfp.ecobosses.events.BossKillEvent
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.EventPriority
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityDeathEvent
|
||||||
|
|
||||||
|
class DeathListeners : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: EntityDeathByEntityEvent) {
|
||||||
|
val boss = Bosses[event.victim] ?: return
|
||||||
|
|
||||||
|
val deathEvent = BossKillEvent(boss, event.killer.tryAsPlayer(), event.deathEvent)
|
||||||
|
Bukkit.getPluginManager().callEvent(deathEvent)
|
||||||
|
|
||||||
|
boss.remove()
|
||||||
|
|
||||||
|
event.drops.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.HIGHEST
|
||||||
|
)
|
||||||
|
fun handle(event: EntityDeathEvent) {
|
||||||
|
val boss = Bosses[event.entity] ?: return
|
||||||
|
|
||||||
|
val deathEvent = BossKillEvent(boss, null, event)
|
||||||
|
Bukkit.getPluginManager().callEvent(deathEvent)
|
||||||
|
|
||||||
|
boss.remove()
|
||||||
|
|
||||||
|
event.drops.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: BossKillEvent) {
|
||||||
|
event.boss.boss.processRewards(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.willfp.ecobosses.lifecycle
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import com.willfp.ecobosses.events.BossDespawnEvent
|
||||||
|
import com.willfp.ecobosses.events.BossKillEvent
|
||||||
|
import com.willfp.ecobosses.events.BossSpawnEvent
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.EventPriority
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent
|
||||||
|
|
||||||
|
class LifecycleHandlers : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.MONITOR
|
||||||
|
)
|
||||||
|
fun handle(event: EntityDamageEvent) {
|
||||||
|
val entity = event.entity as? LivingEntity ?: return
|
||||||
|
val boss = Bosses[entity] ?: return
|
||||||
|
|
||||||
|
boss.boss.handleLifecycle(BossLifecycle.INJURE, entity.location, entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.MONITOR
|
||||||
|
)
|
||||||
|
fun handle(event: BossKillEvent) {
|
||||||
|
val entity = event.boss.entity
|
||||||
|
|
||||||
|
event.boss.boss.handleLifecycle(BossLifecycle.KILL, entity.location, entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.MONITOR
|
||||||
|
)
|
||||||
|
fun handle(event: BossDespawnEvent) {
|
||||||
|
val entity = event.boss.entity
|
||||||
|
|
||||||
|
event.boss.boss.handleLifecycle(BossLifecycle.DESPAWN, entity.location, entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true,
|
||||||
|
priority = EventPriority.MONITOR
|
||||||
|
)
|
||||||
|
fun handle(event: BossSpawnEvent) {
|
||||||
|
event.boss.handleLifecycle(BossLifecycle.SPAWN, event.location, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.willfp.ecobosses.spawn
|
||||||
|
|
||||||
|
import com.willfp.eco.core.EcoPlugin
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import com.willfp.ecobosses.events.BossSpawnEvent
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
|
||||||
|
object AutospawnHandler {
|
||||||
|
private var tick = 1
|
||||||
|
|
||||||
|
fun startSpawning(plugin: EcoPlugin) {
|
||||||
|
plugin.scheduler.runTimer(1, 1) {
|
||||||
|
for (boss in Bosses.values()) {
|
||||||
|
if (boss.autoSpawnInterval < 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tick % boss.autoSpawnInterval != 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val location = boss.autoSpawnLocations.randomOrNull() ?: continue
|
||||||
|
val world = location.world ?: continue
|
||||||
|
|
||||||
|
if (plugin.configYml.getBool("autospawn.one-boss-per-world")) {
|
||||||
|
if (Bosses.getAllAlive().map { it.entity }.any { it.world == world }) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val spawnEvent = BossSpawnEvent(boss, location, BossSpawnEvent.SpawnReason.AUTOSPAWN, null)
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().callEvent(spawnEvent)
|
||||||
|
|
||||||
|
if (!spawnEvent.isCancelled) {
|
||||||
|
boss.spawn(location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tick++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package com.willfp.ecobosses.spawn
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.EcoBossesPlugin
|
||||||
|
import com.willfp.ecobosses.bosses.bossEgg
|
||||||
|
import com.willfp.ecobosses.events.BossSpawnEvent
|
||||||
|
import com.willfp.libreforge.SimpleProvidedHolder
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.block.Container
|
||||||
|
import org.bukkit.block.data.Directional
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
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.BlockDispenseEvent
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent
|
||||||
|
import org.bukkit.inventory.EquipmentSlot
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
|
class SpawnEggHandler(
|
||||||
|
private val plugin: EcoBossesPlugin
|
||||||
|
) : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: PlayerInteractEvent) {
|
||||||
|
if (event.action != Action.RIGHT_CLICK_BLOCK) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.handleSpawnEgg(event.item, event.clickedBlock?.location?.add(0.0, 1.5, 0.0), event.player)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.isCancelled = true
|
||||||
|
event.setUseItemInHand(Event.Result.DENY)
|
||||||
|
|
||||||
|
if (event.hand == EquipmentSlot.HAND) {
|
||||||
|
val hand = event.player.inventory.itemInMainHand
|
||||||
|
hand.amount = hand.amount - 1
|
||||||
|
} else {
|
||||||
|
val hand = event.player.inventory.itemInOffHand
|
||||||
|
hand.amount = hand.amount - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: BlockDispenseEvent) {
|
||||||
|
val facing = (event.block.blockData as Directional).facing
|
||||||
|
val location = event.block.location.add(facing.direction.multiply(1.7))
|
||||||
|
|
||||||
|
if (!this.handleSpawnEgg(event.item, location, null)) return
|
||||||
|
|
||||||
|
event.isCancelled = true
|
||||||
|
|
||||||
|
val dispenser = event.block.state as? Container ?: return
|
||||||
|
|
||||||
|
// This is needed as the event must finish first,
|
||||||
|
// Otherwise the dispenser/dropper thinks the item is already removed from this event.
|
||||||
|
plugin.scheduler.run {
|
||||||
|
val item = dispenser.inventory.find { it?.isSimilar(event.item) == true } ?: return@run
|
||||||
|
item.amount--
|
||||||
|
dispenser.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSpawnEgg(
|
||||||
|
item: ItemStack?,
|
||||||
|
location: Location?,
|
||||||
|
player: Player?
|
||||||
|
): Boolean {
|
||||||
|
val boss = item?.bossEgg ?: return false
|
||||||
|
|
||||||
|
if (location == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player != null) {
|
||||||
|
if (!boss.spawnConditions.areMet(player, SimpleProvidedHolder(boss))) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val spawnEvent = BossSpawnEvent(boss, location, BossSpawnEvent.SpawnReason.EGG, player)
|
||||||
|
Bukkit.getPluginManager().callEvent(spawnEvent)
|
||||||
|
|
||||||
|
if (spawnEvent.isCancelled) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
boss.spawn(location)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.willfp.ecobosses.spawn
|
||||||
|
|
||||||
|
import com.willfp.eco.util.containsIgnoreCase
|
||||||
|
import com.willfp.ecobosses.bosses.Bosses
|
||||||
|
import com.willfp.ecobosses.events.BossSpawnEvent
|
||||||
|
import com.willfp.ecobosses.util.SpawnTotem
|
||||||
|
import com.willfp.libreforge.SimpleProvidedHolder
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.block.Block
|
||||||
|
import org.bukkit.event.EventHandler
|
||||||
|
import org.bukkit.event.Listener
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent
|
||||||
|
|
||||||
|
class SpawnTotemHandler : Listener {
|
||||||
|
@EventHandler(
|
||||||
|
ignoreCancelled = true
|
||||||
|
)
|
||||||
|
fun handle(event: BlockPlaceEvent) {
|
||||||
|
for (i in 0..2) {
|
||||||
|
lateinit var top: Block
|
||||||
|
lateinit var middle: Block
|
||||||
|
lateinit var bottom: Block
|
||||||
|
|
||||||
|
// I know this code sucks ass, but I can't be arsed to write it nicely
|
||||||
|
when (i) {
|
||||||
|
0 -> {
|
||||||
|
top = event.block
|
||||||
|
middle = event.block.getRelative(0, -1, 0)
|
||||||
|
bottom = event.block.getRelative(0, -2, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
top = event.block.getRelative(0, 2, 0)
|
||||||
|
middle = event.block.getRelative(0, 1, 0)
|
||||||
|
bottom = event.block
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
top = event.block.getRelative(0, 1, 0)
|
||||||
|
middle = event.block
|
||||||
|
bottom = event.block.getRelative(0, -1, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val placedTotem = SpawnTotem(top.type, middle.type, bottom.type)
|
||||||
|
for (boss in Bosses.values()) {
|
||||||
|
if (boss.totem == null || boss.disabledTotemWorlds.containsIgnoreCase(event.block.world.name)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boss.totem.matches(placedTotem)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val player = event.player
|
||||||
|
|
||||||
|
if (!boss.spawnConditions.areMet(player, SimpleProvidedHolder(boss))) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val spawnEvent = BossSpawnEvent(boss, event.block.location, BossSpawnEvent.SpawnReason.TOTEM, player)
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().callEvent(spawnEvent)
|
||||||
|
|
||||||
|
if (!spawnEvent.isCancelled) {
|
||||||
|
top.type = Material.AIR
|
||||||
|
middle.type = Material.AIR
|
||||||
|
bottom.type = Material.AIR
|
||||||
|
|
||||||
|
boss.spawn(event.block.location.add(0.0, 1.5, 0.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.willfp.ecobosses.tick
|
||||||
|
|
||||||
|
import com.willfp.eco.util.asAudience
|
||||||
|
import com.willfp.eco.util.toComponent
|
||||||
|
import com.willfp.ecobosses.bosses.LivingEcoBoss
|
||||||
|
import net.kyori.adventure.bossbar.BossBar
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.attribute.Attribute
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
|
class BossBarTicker(
|
||||||
|
private val bar: BossBar
|
||||||
|
) : BossTicker {
|
||||||
|
override fun tick(boss: LivingEcoBoss, tick: Int) {
|
||||||
|
val entity = boss.entity
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
bar.name(entity.customName!!.toComponent())
|
||||||
|
bar.progress((entity.health / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH)!!.value).toFloat())
|
||||||
|
|
||||||
|
if (tick % 40 == 0) {
|
||||||
|
for (player in Bukkit.getOnlinePlayers()) {
|
||||||
|
player.asAudience().hideBossBar(bar)
|
||||||
|
}
|
||||||
|
entity.getNearbyEntities(
|
||||||
|
boss.boss.bossBarRadius,
|
||||||
|
boss.boss.bossBarRadius,
|
||||||
|
boss.boss.bossBarRadius
|
||||||
|
).filterIsInstance<Player>()
|
||||||
|
.map { it.asAudience() }
|
||||||
|
.forEach { it.showBossBar(bar) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tick % 10 != 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.target = boss.boss.targetMode.getTarget(boss) ?: return
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDeath(boss: LivingEcoBoss, tick: Int) {
|
||||||
|
for (player in Bukkit.getOnlinePlayers()) {
|
||||||
|
player.asAudience().hideBossBar(bar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.willfp.ecobosses.tick
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.LivingEcoBoss
|
||||||
|
|
||||||
|
interface BossTicker {
|
||||||
|
fun tick(
|
||||||
|
boss: LivingEcoBoss,
|
||||||
|
tick: Int
|
||||||
|
) {
|
||||||
|
// Can be overridden when needed.
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDeath(
|
||||||
|
boss: LivingEcoBoss,
|
||||||
|
tick: Int
|
||||||
|
) {
|
||||||
|
// Can be overridden when needed.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.willfp.ecobosses.tick
|
||||||
|
|
||||||
|
import com.willfp.ecobosses.bosses.LivingEcoBoss
|
||||||
|
|
||||||
|
class ChunkTicker : BossTicker {
|
||||||
|
override fun tick(boss: LivingEcoBoss, tick: Int) {
|
||||||
|
val currentChunk = boss.chunk
|
||||||
|
|
||||||
|
if (tick % 10 != 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentChunk.isLoaded && currentChunk.isForceLoaded) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
currentChunk.load()
|
||||||
|
currentChunk.isForceLoaded = true
|
||||||
|
boss.forceLoadedChunks.add(currentChunk)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDeath(boss: LivingEcoBoss, tick: Int) {
|
||||||
|
boss.forceLoadedChunks.forEach { it.isForceLoaded = false }
|
||||||
|
boss.forceLoadedChunks.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user