Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85a2070f4a
|
||
|
|
ab1365b738
|
||
|
|
d5a72a1900 | ||
|
|
0a02f9b5d3 | ||
|
|
aa9dd8a4e3 | ||
|
|
209d53e975 | ||
|
|
e2f5d5692c | ||
|
|
5337604dc0 | ||
|
|
3aae78c79e | ||
|
|
76555666ac | ||
|
|
5e6aac6d7a | ||
|
|
96ec8d8c87 | ||
|
|
47ff48a36c | ||
|
|
f7ded69884 | ||
|
|
f3379ba4ea | ||
|
|
f4f234eb30 | ||
|
|
b90cf924a9 | ||
|
|
75f6f9d07f | ||
|
|
ec7f5c5815 | ||
|
|
d3d3d06352 | ||
|
|
11453cd62b | ||
|
|
66b020845a | ||
|
|
bf67b284d8 | ||
|
|
b99e5f4063 | ||
|
|
82cbc90a57 | ||
|
|
32038c9aca | ||
|
|
3a74171832 | ||
|
|
3c2a2d4ef5 | ||
|
|
b8478678f7 | ||
|
|
712fada0fc | ||
|
|
9d1e0bacdb | ||
|
|
e3256c8a21 | ||
|
|
13f50670f0 | ||
|
|
ab8bd597e9 | ||
|
|
caf338c633 | ||
|
|
21bd46ca7c | ||
|
|
a593c4fd11 | ||
|
|
b0d5464774 | ||
|
|
ed5fb3b8df | ||
|
|
42c289381e | ||
|
|
540ec2a108 | ||
|
|
7b944d51c3 | ||
|
|
7d0aa23dd9 | ||
|
|
475fd103fe | ||
|
|
e8094e2159 | ||
|
|
a5f3d36f7e | ||
|
|
b0698a8ecd | ||
|
|
89f2362866 | ||
|
|
6e4d814ee0 | ||
|
|
a98b957bd2 | ||
|
|
c6ebd8aeb7 | ||
|
|
c299b057ed | ||
|
|
7fe023e5bf | ||
|
|
7dcdf9549f | ||
|
|
b6a4f9d2a3 | ||
|
|
886853f7fe | ||
|
|
b1c4a575bc | ||
|
|
2c35837fe0 | ||
|
|
e9783243e3 | ||
|
|
3d5d52c2f3 | ||
|
|
d238286567 | ||
|
|
258ca56b3f | ||
|
|
214ab35c5c | ||
|
|
8428319e14 | ||
|
|
33d07dd90d | ||
|
|
31f1543302 | ||
|
|
0694a02f04 | ||
|
|
1e5544515a | ||
|
|
a1e6fae656 | ||
|
|
71d4b78407 | ||
|
|
d1497d10f6 | ||
|
|
6f30519a1f | ||
|
|
9a9350a290 | ||
|
|
32b5013e3f | ||
|
|
a102719a59 | ||
|
|
195e02ccd8 | ||
|
|
22a200cbff | ||
|
|
734eab394e | ||
|
|
09d44ab150 | ||
|
|
5991f6f98e | ||
|
|
1d949ce64c | ||
|
|
30999d858c | ||
|
|
8b395aa6dc | ||
|
|
9355d185cd | ||
|
|
5ae26a7d46 | ||
|
|
325deb19c5 | ||
|
|
89cc4e5699 | ||
|
|
a85d8f5e58 | ||
|
|
ef182d2fec | ||
|
|
2bd7e3df86 | ||
|
|
b2f6a5b5e6 | ||
|
|
3edf7c279b | ||
|
|
80b2183028 | ||
|
|
cf5d86707b | ||
|
|
4db912d0d3 | ||
|
|
fbf742f91f | ||
|
|
79463bdea0 | ||
|
|
c60bb73ffa | ||
|
|
d96af5d3eb | ||
|
|
8e64cbb72e | ||
|
|
131871e999 | ||
|
|
615c4f72b1 | ||
|
|
d8f0bf99d7 | ||
|
|
3ac2950323 | ||
|
|
49cdc6b5bb | ||
|
|
3491084415 | ||
|
|
6f9c9817e1 | ||
|
|
5705798e62 | ||
|
|
eefb1649c0 | ||
|
|
b9276f4415 | ||
|
|
b8f56e1434 | ||
|
|
b8f55ea78e | ||
|
|
453573a7f9 | ||
|
|
a0f8d49aaf | ||
|
|
dd055b01d0 | ||
|
|
f5e1f1a0a1 | ||
|
|
32b10c844d | ||
|
|
ba429c74dd | ||
|
|
fab55fe945 | ||
|
|
7266fba207 | ||
|
|
b813c7c758 | ||
|
|
0623062dde | ||
|
|
49b640b173 | ||
|
|
e2830733c8 | ||
|
|
472e491abe | ||
|
|
4e2de05cf8 | ||
|
|
ed80532a2c | ||
|
|
6a7e3c3c91 | ||
|
|
7327e00b38 | ||
|
|
5d19ad5ea8 | ||
|
|
ee0355f6f2 | ||
|
|
45c1889bb9 | ||
|
|
e0b751f40f | ||
|
|
fc0cffbb33 | ||
|
|
5fc0dbbc55 | ||
|
|
e0eee7066a | ||
|
|
3a4060c39a | ||
|
|
1edd6770dd | ||
|
|
cfae81fc25 |
No files matched your search
@@ -0,0 +1 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -11,6 +11,11 @@ out/
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Eclipse files
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
@@ -111,3 +116,7 @@ buildNumber.properties
|
||||
|
||||
# Common working directory
|
||||
run/
|
||||
|
||||
# Gradle
|
||||
.gradle/
|
||||
build/
|
||||
@@ -0,0 +1,25 @@
|
||||
## PurpurExtras-OG
|
||||
|
||||
PurpurExtras-OG is a soft fork of [PurpurExtras](https://github.com/PurpurMC/PurpurExtras) maintained for 1.19.4 by [TrueOG Network](https://trueog.net).
|
||||
|
||||
PurpurExtras is a plugin designed to add all [Purpur](https://github.com/PurpurMC/Purpur) suggestions that should be in a plugin. Adding configurability, new fun and exciting gameplay features. All features can be found on the [Purpur wiki](https://purpurmc.org/docs/purpurextras/).
|
||||
|
||||
## Changes from PurpurExtras
|
||||
|
||||
- Backported API logic to 1.19.4.
|
||||
|
||||
- Lobotomized CreateSusBlockModule.
|
||||
|
||||
- Removed OpenIronDoorsWithHandModule (also applies to trapdoors).
|
||||
|
||||
- Added more error handling.
|
||||
|
||||
## Contact
|
||||
|
||||
Join us on [Discord](https://discord.gg/ma9pMYpBU6)
|
||||
|
||||
## License
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
All code is licensed under the GPL-2.0 license, unless otherwise noted.
|
||||
@@ -0,0 +1,163 @@
|
||||
import java.net.URL
|
||||
import java.nio.file.Files
|
||||
|
||||
/* ------------------------------ Plugins ------------------------------ */
|
||||
plugins {
|
||||
id("java") // Import Java plugin.
|
||||
id("java-library") // Import Java Library plugin.
|
||||
id("com.diffplug.spotless") version "7.0.4" // Import Spotless plugin.
|
||||
id("com.gradleup.shadow") version "8.3.6" // Import Shadow plugin.
|
||||
id("checkstyle") // Import Checkstyle plugin.
|
||||
eclipse // Import Eclipse plugin.
|
||||
kotlin("jvm") version "2.1.21" // Import Kotlin JVM plugin.
|
||||
}
|
||||
|
||||
/* --------------------------- JDK / Kotlin ---------------------------- */
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
|
||||
toolchain { // Select Java toolchain.
|
||||
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
|
||||
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
|
||||
}
|
||||
}
|
||||
|
||||
kotlin { jvmToolchain(17) }
|
||||
|
||||
/* ----------------------------- Metadata ------------------------------ */
|
||||
group = "org.purpurmc.purpurextras"
|
||||
|
||||
version = "1.33.0"
|
||||
|
||||
val apiVersion = "1.19" // Declare minecraft server target version.
|
||||
|
||||
val pluginName = "PurpurExtras-OG"
|
||||
|
||||
description = "\"This should be a plugin\" features from Purpur"
|
||||
|
||||
/* ----------------------------- Resources ----------------------------- */
|
||||
tasks.named<ProcessResources>("processResources") {
|
||||
val props =
|
||||
mapOf(
|
||||
"name" to project.name,
|
||||
"version" to project.version.toString(),
|
||||
"apiVersion" to apiVersion,
|
||||
"description" to project.description.orEmpty().replace("\"", "\\\""),
|
||||
"pluginName" to pluginName,
|
||||
)
|
||||
inputs.properties(props) // Indicates to rerun if version changes.
|
||||
filesMatching("plugin.yml") { expand(props) }
|
||||
from("LICENSE") { into("/") } // Bundle licenses into jarfiles.
|
||||
}
|
||||
|
||||
/* ---------------------------- Repos ---------------------------------- */
|
||||
repositories {
|
||||
mavenCentral() // Import the Maven Central Maven Repository.
|
||||
gradlePluginPortal() // Import the Gradle Plugin Portal Maven Repository.
|
||||
maven("https://oss.sonatype.org/content/groups/public/") // Import the OSS Sonatype Repository.
|
||||
maven("https://jitpack.io") // Import the Jitpack Maven Repository.
|
||||
maven { url = uri("https://repo.purpurmc.org/snapshots") } // Import the PurpurMC Maven Repository.
|
||||
maven("https://papermc.io/repo/repository/maven-public/") // Import the PaperMC Maven Repository.
|
||||
maven("https://libraries.minecraft.net") // Import the Mojang Maven Repository.
|
||||
}
|
||||
|
||||
/* ---------------------- Java project deps ---------------------------- */
|
||||
dependencies {
|
||||
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare Purpur API version to be packaged.
|
||||
api("com.github.YouHaveTrouble:Entiddy:v2.0.1") // Import Entiddy API.
|
||||
api("org.reflections:reflections:0.10.2") // Import Reflections API.
|
||||
}
|
||||
|
||||
val serverDir: File = projectDir.resolve("run")
|
||||
val pluginDir: File = serverDir.resolve("plugins")
|
||||
|
||||
/* ---------------------- Reproducible jars ---------------------------- */
|
||||
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
|
||||
isPreserveFileTimestamps = false
|
||||
isReproducibleFileOrder = true
|
||||
}
|
||||
|
||||
/* ----------------------------- Shadow -------------------------------- */
|
||||
tasks.shadowJar {
|
||||
exclude("io.github.miniplaceholders.*") // Exclude the MiniPlaceholders package from being shadowed.
|
||||
archiveClassifier.set("") // Use empty string instead of null.
|
||||
archiveFileName.set("PurpurExtras-OG-${project.version}.jar")
|
||||
relocate("org.reflections", "org.purpurmc.purpurextras.reflections")
|
||||
relocate("me.youhavetrouble.entiddy", "org.purpurmc.purpurextras.entiddy")
|
||||
minimize()
|
||||
}
|
||||
|
||||
tasks.clean { doLast { serverDir.deleteRecursively() } }
|
||||
|
||||
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
|
||||
|
||||
tasks.build { dependsOn(tasks.spotlessApply, tasks.shadowJar) } // Build depends on spotless and shadow.
|
||||
|
||||
/* ----------------------------- Server -------------------------------- */
|
||||
tasks.register("downloadServer") {
|
||||
group = "purpur"
|
||||
|
||||
doFirst {
|
||||
serverDir.mkdirs()
|
||||
pluginDir.mkdirs()
|
||||
URL("https://api.purpurmc.org/v2/purpur/1.21/latest/download").openStream().use {
|
||||
Files.copy(it, serverDir.resolve("server.jar").toPath())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<JavaExec>("runServer") {
|
||||
group = "purpur"
|
||||
dependsOn(tasks.named("spotlessApply"))
|
||||
dependsOn(tasks.named("shadowJar"))
|
||||
if (!serverDir.resolve("server.jar").exists()) dependsOn("downloadServer")
|
||||
|
||||
doFirst {
|
||||
pluginDir.resolve("PurpurExtras.jar").delete()
|
||||
Files.copy(
|
||||
layout.buildDirectory.file("libs/PurpurExtras-${project.version}.jar").get().asFile.toPath(),
|
||||
pluginDir.resolve("PurpurExtras.jar").toPath(),
|
||||
)
|
||||
}
|
||||
|
||||
classpath = files(serverDir.resolve("server.jar"))
|
||||
workingDir = serverDir
|
||||
jvmArgs = listOf("-Dcom.mojang.eula.agree=true")
|
||||
args = listOf("--nogui")
|
||||
standardInput = System.`in`
|
||||
}
|
||||
|
||||
/* --------------------------- Javac opts ------------------------------- */
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.compilerArgs.add("-parameters") // Enable reflection for java code.
|
||||
options.isFork = true // Run javac in its own process.
|
||||
options.compilerArgs.add("-Xlint:deprecation") // Trigger deprecation warning messages.
|
||||
options.encoding = "UTF-8" // Use UTF-8 file encoding.
|
||||
}
|
||||
|
||||
/* ----------------------------- Auto Formatting ------------------------ */
|
||||
spotless {
|
||||
java {
|
||||
eclipse().configFile("config/formatter/eclipse-java-formatter.xml") // Eclipse java formatting.
|
||||
leadingTabsToSpaces() // Convert leftover leading tabs to spaces.
|
||||
removeUnusedImports() // Remove imports that aren't being called.
|
||||
}
|
||||
kotlinGradle {
|
||||
ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } // JetBrains Kotlin formatting.
|
||||
target("build.gradle.kts", "settings.gradle.kts") // Gradle files to format.
|
||||
}
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "10.18.1" // Declare checkstyle version to use.
|
||||
configFile = file("config/checkstyle/checkstyle.xml") // Point checkstyle to config file.
|
||||
isIgnoreFailures = true // Don't fail the build if checkstyle does not pass.
|
||||
isShowViolations = true // Show the violations in any IDE with the checkstyle plugin.
|
||||
}
|
||||
|
||||
tasks.named("compileJava") {
|
||||
dependsOn("spotlessApply") // Run spotless before compiling with the JDK.
|
||||
}
|
||||
|
||||
tasks.named("spotlessCheck") {
|
||||
dependsOn("spotlessApply") // Run spotless before checking if spotless ran.
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
<module name="Checker">
|
||||
|
||||
<module name="FileTabCharacter">
|
||||
<property name="eachLine" value="true"/>
|
||||
<property name="severity" value="error"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<module name="FinalLocalVariable"/>
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="Indentation">
|
||||
<property name="severity" value="ignore"/>
|
||||
</module>
|
||||
</module>
|
||||
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="\borg\.junit\.jupiter\.api\.Assertions\.fail\s*\(\s*"Not yet implemented"\s*\)\s*;"/>
|
||||
<property name="message" value="Remove placeholder fail() and implement the test."/>
|
||||
<property name="ignoreCase" value="true"/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="(?<!\w)fail\s*\(\s*"Not yet implemented"\s*\)\s*;"/>
|
||||
<property name="message" value="Remove placeholder fail() and implement the test."/>
|
||||
<property name="severity" value="warning"/>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="23">
|
||||
<profile kind="CodeFormatterProfile" name="TrueOG Network Formatting" version="23">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case_after_arrow" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="20"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line_on_wrap"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
Vendored
BIN
Binary file not shown.
+7
@@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+94
@@ -0,0 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,99 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>me.youhavetrouble</groupId>
|
||||
<artifactId>PurpurExtras</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>PurpurExtras</name>
|
||||
|
||||
<description>"This should be a plugin" features from Purpur</description>
|
||||
<properties>
|
||||
<java.version>16</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>purpur</id>
|
||||
<url>https://repo.purpurmc.org/snapshots</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>minecraft-libraries</id>
|
||||
<name>Minecraft Libraries</name>
|
||||
<url>https://libraries.minecraft.net</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.purpurmc.purpur</groupId>
|
||||
<artifactId>purpur-api</artifactId>
|
||||
<version>1.18.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-mojangapi</artifactId>
|
||||
<version>1.18.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.YouHaveTrouble</groupId>
|
||||
<artifactId>Entiddy</artifactId>
|
||||
<version>v2.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1 @@
|
||||
rootProject.name = "PurpurExtras-OG"
|
||||
@@ -1,81 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras;
|
||||
|
||||
import me.youhavetrouble.purpurextras.command.FancyCommand;
|
||||
import me.youhavetrouble.purpurextras.config.PurpurConfig;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.kyori.adventure.text.minimessage.tag.standard.StandardTags;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public final class PurpurExtras extends JavaPlugin {
|
||||
|
||||
private static PurpurConfig config;
|
||||
private static PurpurExtras instance;
|
||||
|
||||
public final MiniMessage miniMessage = MiniMessage.builder().tags(
|
||||
TagResolver.builder()
|
||||
.resolver(StandardTags.color())
|
||||
.resolver(StandardTags.decorations())
|
||||
.resolver(StandardTags.gradient())
|
||||
.resolver(StandardTags.font())
|
||||
.resolver(StandardTags.reset())
|
||||
.resolver(StandardTags.rainbow())
|
||||
.resolver(StandardTags.translatable())
|
||||
.build()
|
||||
).build();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
try {
|
||||
Class.forName("org.purpurmc.purpur.PurpurConfig");
|
||||
} catch (ClassNotFoundException e) {
|
||||
getLogger().warning(ChatColor.translateAlternateColorCodes('&', "&x&8&0&5&2&8&0PurpurExtras was created to compliment Purpur, and it appears you're not using it!"));
|
||||
getLogger().warning(ChatColor.translateAlternateColorCodes('&', "&x&8&0&5&2&8&0Purpur is a drop-in replacement for " + getServer().getName() + "."));
|
||||
getLogger().warning(ChatColor.translateAlternateColorCodes('&', "&x&8&0&5&2&8&0You can get Purpur on https://purpurmc.org/downloads"));
|
||||
this.getPluginLoader().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
instance = this;
|
||||
config = new PurpurConfig();
|
||||
PluginCommand command = getCommand("purpurextras");
|
||||
if (command != null) {
|
||||
command.setExecutor(new PurpurExtrasCommand());
|
||||
getServer().getPluginManager().registerEvents(new FancyCommand(), this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static PurpurConfig getPurpurConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public static PurpurExtras getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected void reloadPurpurExtrasConfig(CommandSender commandSender) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
||||
config = new PurpurConfig();
|
||||
commandSender.sendMessage(Component.text("PurpurExtras configuration reloaded!"));
|
||||
});
|
||||
}
|
||||
|
||||
public void registerListener(Class<?> clazz) {
|
||||
try {
|
||||
Listener listener = (org.bukkit.event.Listener) clazz.getConstructor().newInstance();
|
||||
getServer().getPluginManager().registerEvents(listener, this);
|
||||
} catch (InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.command;
|
||||
|
||||
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
|
||||
import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class FancyCommand implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onCommandRegister(final CommandRegisteredEvent<BukkitBrigadierCommandSource> event) {
|
||||
if (event.getCommand().getName().equalsIgnoreCase("purpurextras")) {
|
||||
event.setLiteral(
|
||||
LiteralArgumentBuilder.<BukkitBrigadierCommandSource>literal(event.getCommandLabel())
|
||||
.then(LiteralArgumentBuilder.literal("reload"))
|
||||
.then(LiteralArgumentBuilder.literal("version"))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.config;
|
||||
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import me.youhavetrouble.purpurextras.listeners.*;
|
||||
import me.youhavetrouble.purpurextras.recipes.ToolUpgradesRecipes;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PurpurConfig {
|
||||
|
||||
Logger logger;
|
||||
FileConfiguration config;
|
||||
File configPath;
|
||||
|
||||
private final PurpurExtras plugin = PurpurExtras.getInstance();
|
||||
public boolean dispenserBreakBlockPickaxe, dispenserBreakBlockShovel, dispenserBreakBlockHoe,
|
||||
dispenserBreakBlockShears, dispenserBreakBlockAxe, dispenserShearPumpkin, dispenserActivatesJukebox;
|
||||
public final boolean upgradeWoodToStoneTools;
|
||||
public final boolean upgradeStoneToIronTools;
|
||||
public final boolean upgradeIronToDiamondTools;
|
||||
public final String beeHiveLoreBees, beeHiveLoreHoney;
|
||||
public final HashMap<Material, Material> anvilCrushBlocksIndex = new HashMap<>();
|
||||
public final HashSet<EntityType> stonecutterDamageBlacklist = new HashSet<>();
|
||||
public final HashMap<String, String> lightningTransformEntities = new HashMap<>();
|
||||
public final double furnaceBurnTimeMultiplier;
|
||||
|
||||
public PurpurConfig() {
|
||||
plugin.reloadConfig();
|
||||
logger = plugin.getLogger();
|
||||
config = plugin.getConfig();
|
||||
configPath = new File(plugin.getDataFolder(), "config.yml");
|
||||
|
||||
// Make sure that no listeners are registered from the plugin
|
||||
HandlerList.unregisterAll(plugin);
|
||||
|
||||
enableFeature(BeehiveLoreListener.class, getBoolean("settings.items.beehive-lore.enabled", false));
|
||||
|
||||
this.beeHiveLoreBees = getString("settings.items.beehive-lore.bees", "<reset><gray>Bees: <bees>/<maxbees>");
|
||||
this.beeHiveLoreHoney = getString("settings.items.beehive-lore.honey", "<reset><gray>Honey level: <honey>/<maxhoney>");
|
||||
|
||||
enableFeature(RespawnAnchorNeedsChargeListener.class, !getBoolean("settings.gameplay-settings.respawn-anchor-needs-charges", true));
|
||||
|
||||
enableFeature(EscapeCommandSlashListener.class, getBoolean("settings.chat.escape-commands", false));
|
||||
|
||||
getAnvilCrushIndex();
|
||||
enableFeature(AnvilMakesSandListener.class, getBoolean("settings.anvil-crushes-blocks.enabled", false));
|
||||
|
||||
enableFeature(GrindstoneEnchantsBooksListener.class, getBoolean("settings.grindstone.gives-enchants-back", false));
|
||||
|
||||
enableFeature(ForceNametaggedForRidingListener.class, getBoolean("settings.rideables.mob-needs-to-be-nametagged-to-ride", false));
|
||||
|
||||
enableFeature(MobNoTargetListener.class, getBoolean("settings.use-notarget-permissions", false));
|
||||
|
||||
|
||||
boolean lightningTransformEntities = getBoolean("settings.lightning-transforms-entities.enabled", false);
|
||||
handleLightningTransformedEntities(lightningTransformEntities);
|
||||
|
||||
handleBetterDispenser();
|
||||
|
||||
this.upgradeWoodToStoneTools = getBoolean("settings.smithing-table.tools.wood-to-stone", false);
|
||||
this.upgradeStoneToIronTools = getBoolean("settings.smithing-table.tools.stone-to-iron", false);
|
||||
this.upgradeIronToDiamondTools = getBoolean("settings.smithing-table.tools.iron-to-diamond", false);
|
||||
|
||||
ToolUpgradesRecipes.addUpgradeRecipes(
|
||||
upgradeWoodToStoneTools,
|
||||
upgradeStoneToIronTools,
|
||||
upgradeIronToDiamondTools
|
||||
);
|
||||
|
||||
List<String> stonecutterDamageblacklist = getList("settings.stonecutter-damage-filter.blacklist", List.of("player"));
|
||||
if (getBoolean("settings.stonecutter-damage-filter.enabled", false)) {
|
||||
handleStonecutterDamageBlacklist(stonecutterDamageblacklist, plugin);
|
||||
}
|
||||
|
||||
enableFeature(FurnaceBurnTimeListener.class, getBoolean("settings.furnace.burn-time.enabled", false));
|
||||
this.furnaceBurnTimeMultiplier = getDouble("settings.furnace.burn-time.multiplier", 1.0);
|
||||
|
||||
enableFeature(VoidTotemListener.class, getBoolean("settings.totem.work-on-void-death", false));
|
||||
|
||||
enableFeature(SkeletonWitherRoseListener.class, getBoolean("settings.mobs.skeleton.give-wither-rose-for-wither-skeleton", false));
|
||||
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
try {
|
||||
config.save(configPath);
|
||||
} catch (IOException e) {
|
||||
logger.severe("Failed to save configuration file! - " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getBoolean(String path, boolean def) {
|
||||
if (config.isSet(path))
|
||||
return config.getBoolean(path, def);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
}
|
||||
|
||||
private String getString(String path, String def) {
|
||||
if (config.isSet(path))
|
||||
return config.getString(path, def);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
}
|
||||
|
||||
private double getDouble(String path, double def) {
|
||||
if (config.isSet(path))
|
||||
return config.getDouble(path, def);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defKV Default key-value map
|
||||
*/
|
||||
private ConfigurationSection getConfigSection(String path, Map<String, Object> defKV) {
|
||||
if (config.isConfigurationSection(path))
|
||||
return config.getConfigurationSection(path);
|
||||
return config.createSection(path, defKV);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of strings or empty list if list doesn't exist in configuration file
|
||||
*/
|
||||
private List<String> getList(String path, List<String> def) {
|
||||
if (config.isSet(path))
|
||||
return config.getStringList(path);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
}
|
||||
|
||||
private void handleLightningTransformedEntities(boolean enable) {
|
||||
Map<String, Object> defaults = new HashMap<>();
|
||||
defaults.put("villager", "witch");
|
||||
defaults.put("pig", "zombie_piglin");
|
||||
ConfigurationSection section = getConfigSection("settings.lightning-transforms-entities.entities", defaults);
|
||||
if (!enable) return;
|
||||
for (String key : section.getKeys(false)) {
|
||||
String value = section.getString(key);
|
||||
lightningTransformEntities.put(key, value);
|
||||
}
|
||||
if (lightningTransformEntities.isEmpty()) return;
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(new LightningTransformsMobsListener(lightningTransformEntities), plugin);
|
||||
}
|
||||
|
||||
private void getAnvilCrushIndex() {
|
||||
Map<String, Object> defaults = new HashMap<>();
|
||||
defaults.put("cobblestone", "sand");
|
||||
ConfigurationSection section = getConfigSection("settings.anvil-crushes-blocks.blocks", defaults);
|
||||
for (String key : section.getKeys(false)) {
|
||||
String matString = section.getString(key);
|
||||
if (matString == null) continue;
|
||||
Material materialFrom = Material.getMaterial(key.toUpperCase());
|
||||
if (materialFrom == null || !materialFrom.isBlock()) {
|
||||
logger.warning(key + " is not valid block material.");
|
||||
continue;
|
||||
}
|
||||
Material materialTo = Material.getMaterial(matString.toUpperCase());
|
||||
if (materialTo == null || !materialTo.isBlock()) {
|
||||
logger.warning(matString + " is not valid block material.");
|
||||
continue;
|
||||
}
|
||||
anvilCrushBlocksIndex.put(materialFrom, materialTo);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStonecutterDamageBlacklist(List<String> blacklist, PurpurExtras plugin) {
|
||||
if (blacklist.isEmpty()) return;
|
||||
for (EntityType entityType : EntityType.values()) {
|
||||
if (!entityType.isAlive()) continue;
|
||||
for (String str : blacklist) {
|
||||
if (entityType.getKey().getKey().equals(str.toLowerCase(Locale.ROOT)))
|
||||
stonecutterDamageBlacklist.add(entityType);
|
||||
}
|
||||
}
|
||||
if (stonecutterDamageBlacklist.isEmpty()) return;
|
||||
plugin.registerListener(StonecutterDamageListener.class);
|
||||
}
|
||||
|
||||
private void handleBetterDispenser() {
|
||||
this.dispenserBreakBlockPickaxe = getBoolean("settings.dispenser.break-blocks.pickaxe", false);
|
||||
this.dispenserBreakBlockShovel = getBoolean("settings.dispenser.break-blocks.shovel", false);
|
||||
this.dispenserBreakBlockHoe = getBoolean("settings.dispenser.break-blocks.hoe", false);
|
||||
this.dispenserBreakBlockAxe = getBoolean("settings.dispenser.break-blocks.axe", false);
|
||||
this.dispenserBreakBlockShears = getBoolean("settings.dispenser.break-blocks.shears", false);
|
||||
|
||||
this.dispenserShearPumpkin = getBoolean("settings.dispenser.shears-shear-pumpkin", false);
|
||||
this.dispenserActivatesJukebox = getBoolean("settings.dispenser.puts-discs-in-jukebox", false);
|
||||
|
||||
if (dispenserBreakBlockPickaxe
|
||||
|| dispenserBreakBlockAxe
|
||||
|| dispenserBreakBlockShovel
|
||||
|| dispenserBreakBlockHoe
|
||||
|| dispenserBreakBlockShears
|
||||
|| dispenserShearPumpkin
|
||||
|| dispenserActivatesJukebox
|
||||
) {
|
||||
plugin.registerListener(DispenserListener.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableFeature(Class<?> listenerClass, boolean enable) {
|
||||
if (enable)
|
||||
plugin.registerListener(listenerClass);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class AnvilMakesSandListener implements Listener {
|
||||
|
||||
private final HashSet<Material> anvils = new HashSet<>();
|
||||
|
||||
public AnvilMakesSandListener() {
|
||||
anvils.add(Material.ANVIL);
|
||||
anvils.add(Material.CHIPPED_ANVIL);
|
||||
anvils.add(Material.DAMAGED_ANVIL);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onAnvilDrop(EntityChangeBlockEvent event) {
|
||||
|
||||
if (!anvils.contains(event.getTo())) return;
|
||||
|
||||
Location belowAnvil = event.getBlock().getLocation().clone().subtract(0, 1, 0);
|
||||
Block blockBelowAnvil = belowAnvil.getBlock();
|
||||
|
||||
if (!PurpurExtras.getPurpurConfig().anvilCrushBlocksIndex.containsKey(blockBelowAnvil.getType())) return;
|
||||
|
||||
blockBelowAnvil.setType(PurpurExtras.getPurpurConfig().anvilCrushBlocksIndex.get(blockBelowAnvil.getType()), true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import com.destroystokyo.paper.MaterialTags;
|
||||
import io.papermc.paper.event.block.BlockPreDispenseEvent;
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Jukebox;
|
||||
import org.bukkit.block.data.type.Dispenser;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class DispenserListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPreDispense(BlockPreDispenseEvent event) {
|
||||
if (!event.getBlock().getType().equals(Material.DISPENSER)) return;
|
||||
Dispenser dispenser = (Dispenser) event.getBlock().getBlockData();
|
||||
Block block = event.getBlock().getRelative(dispenser.getFacing());
|
||||
org.bukkit.block.Dispenser blockDispenser = (org.bukkit.block.Dispenser) event.getBlock().getState(false);
|
||||
ItemStack item = event.getItemStack();
|
||||
|
||||
// Block breaking
|
||||
|
||||
// if block is broken, stop processing
|
||||
if (handleBlockBreaking(event, item, blockDispenser, block)) return;
|
||||
|
||||
// shears do not drop as an item from dispenser by default, so no need to cancel event
|
||||
if (PurpurExtras.getPurpurConfig().dispenserBreakBlockShears && item.getType().equals(Material.SHEARS)) {
|
||||
// if block was broken, don't process more
|
||||
if (tryBreakBlock(item, blockDispenser, block)) return;
|
||||
}
|
||||
|
||||
// Interactions
|
||||
|
||||
// Shear pumpkin
|
||||
if (PurpurExtras.getPurpurConfig().dispenserShearPumpkin
|
||||
&& item.getType().equals(Material.SHEARS)
|
||||
&& block.getType().equals(Material.PUMPKIN)
|
||||
) {
|
||||
Inventory inventory = blockDispenser.getInventory();
|
||||
damageItem(item, inventory);
|
||||
event.setCancelled(true);
|
||||
block.setType(Material.CARVED_PUMPKIN);
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap records in jukebox
|
||||
if (PurpurExtras.getPurpurConfig().dispenserActivatesJukebox
|
||||
&& MaterialTags.MUSIC_DISCS.isTagged(item)
|
||||
&& block.getType().equals(Material.JUKEBOX)
|
||||
) {
|
||||
event.setCancelled(true);
|
||||
Jukebox jukebox = (Jukebox) block.getState(false);
|
||||
jukebox.eject();
|
||||
ItemStack record = consumeItem(item);
|
||||
jukebox.setRecord(record);
|
||||
jukebox.update();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean handleBlockBreaking(
|
||||
BlockPreDispenseEvent event,
|
||||
ItemStack item,
|
||||
org.bukkit.block.Dispenser blockDispenser,
|
||||
Block block
|
||||
) {
|
||||
if (PurpurExtras.getPurpurConfig().dispenserBreakBlockPickaxe && MaterialTags.PICKAXES.isTagged(item)) {
|
||||
event.setCancelled(true);
|
||||
tryBreakBlock(item, blockDispenser, block);
|
||||
return true;
|
||||
}
|
||||
if (PurpurExtras.getPurpurConfig().dispenserBreakBlockAxe && MaterialTags.AXES.isTagged(item)) {
|
||||
event.setCancelled(true);
|
||||
tryBreakBlock(item, blockDispenser, block);
|
||||
return true;
|
||||
}
|
||||
if (PurpurExtras.getPurpurConfig().dispenserBreakBlockShovel && MaterialTags.SHOVELS.isTagged(item)) {
|
||||
event.setCancelled(true);
|
||||
tryBreakBlock(item, blockDispenser, block);
|
||||
return true;
|
||||
}
|
||||
if (PurpurExtras.getPurpurConfig().dispenserBreakBlockHoe && MaterialTags.HOES.isTagged(item)) {
|
||||
event.setCancelled(true);
|
||||
tryBreakBlock(item, blockDispenser, block);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void damageItem(ItemStack itemStack, Inventory inventory) {
|
||||
int slot = inventory.first(itemStack);
|
||||
if (slot == -1) return;
|
||||
ItemStack item = inventory.getItem(slot);
|
||||
if (item == null) return;
|
||||
item.damage(1);
|
||||
}
|
||||
|
||||
private ItemStack consumeItem(ItemStack itemStack) {
|
||||
ItemStack consumed = itemStack.clone();
|
||||
consumed.setAmount(1);
|
||||
itemStack.setAmount(itemStack.getAmount()-1);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
private boolean tryBreakBlock(ItemStack itemStack, org.bukkit.block.Dispenser dispenser, Block block) {
|
||||
if (block.getDestroySpeed(itemStack, false) <= 1.0f) return false;
|
||||
Inventory inventory = dispenser.getInventory();
|
||||
damageItem(itemStack, inventory);
|
||||
return block.breakNaturally(itemStack, true);
|
||||
}
|
||||
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class EscapeCommandSlashListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onCommandEscape(AsyncChatEvent event) {
|
||||
|
||||
String message = PlainTextComponentSerializer.plainText().serialize(event.message());
|
||||
String[] messageSplit = message.split(" ");
|
||||
String command = messageSplit[0].substring(1);
|
||||
Component component = event.message().replaceText(
|
||||
TextReplacementConfig.builder()
|
||||
.match("(\\\\/\\S*)")
|
||||
.replacement(command)
|
||||
.once()
|
||||
.build());
|
||||
event.message(component);
|
||||
}
|
||||
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import io.papermc.paper.event.entity.EntityMoveEvent;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.spigotmc.event.entity.EntityMountEvent;
|
||||
|
||||
public class ForceNametaggedForRidingListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onMount(EntityMountEvent event) {
|
||||
Entity entity = event.getMount();
|
||||
|
||||
// if pig or strider with a saddle, ignore
|
||||
if (entity instanceof Steerable steerable && steerable.hasSaddle()) return;
|
||||
|
||||
// if mountable in vanilla, ignore
|
||||
if (entity instanceof Vehicle && (!(entity instanceof Steerable))) return;
|
||||
|
||||
// if player, ignore
|
||||
if (entity.getType().equals(EntityType.PLAYER)) return;
|
||||
|
||||
// if has nametag, ignore
|
||||
if (entity.getCustomName() != null) return;
|
||||
|
||||
// otherwise don't allow mounting
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onMountMove(EntityMoveEvent event) {
|
||||
if (!(event.getEntity() instanceof Vehicle vehicle)) return;
|
||||
if (vehicle.getPassengers().isEmpty()) return;
|
||||
Entity passenger = vehicle.getPassengers().get(0);
|
||||
if (!(passenger instanceof Player player)) return;
|
||||
if (vehicle.getCustomName() != null && player.hasPermission("allow.ride."+vehicle.getType().getKey().getKey())) return;
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.FurnaceBurnEvent;
|
||||
|
||||
public class FurnaceBurnTimeListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onFurnaceBurn(FurnaceBurnEvent event) {
|
||||
int burnTime = event.getBurnTime();
|
||||
event.setBurnTime((int) (burnTime * PurpurExtras.getPurpurConfig().furnaceBurnTimeMultiplier));
|
||||
}
|
||||
}
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityZapEvent;
|
||||
import me.youhavetrouble.entiddy.Entiddy;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
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.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class LightningTransformsMobsListener implements Listener {
|
||||
|
||||
private static final HashMap<String, Object> entities = new HashMap<>();
|
||||
|
||||
public LightningTransformsMobsListener(Map<String, String> lightningTransformEntities) {
|
||||
for (Map.Entry<String, String> entry : lightningTransformEntities.entrySet()) {
|
||||
getEntityTypeOrSpecial(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onLightningStrike(EntityDamageByEntityEvent event) {
|
||||
if (!event.getDamager().getType().equals(EntityType.LIGHTNING)) return;
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof LivingEntity livingEntity)) return;
|
||||
if (entity.getEntitySpawnReason().equals(CreatureSpawnEvent.SpawnReason.LIGHTNING)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
};
|
||||
Location location = entity.getLocation();
|
||||
Entiddy specialEntity = Entiddy.fromEntity(livingEntity);
|
||||
if (specialEntity != null) {
|
||||
event.setCancelled(true);
|
||||
entity.remove();
|
||||
String specialEntityKey = specialEntity.entiddy().toString().toLowerCase(Locale.ROOT);
|
||||
Object targetEntity = entities.get(specialEntityKey);
|
||||
spawnEntity(targetEntity, location);
|
||||
return;
|
||||
}
|
||||
Object targetEntity = entities.get(entity.getType().getKey().getKey());
|
||||
if (targetEntity == null) return;
|
||||
event.setCancelled(true);
|
||||
entity.remove();
|
||||
spawnEntity(targetEntity, location);
|
||||
}
|
||||
|
||||
private void spawnEntity(Object entity, Location location) {
|
||||
if (entity instanceof EntityType entityType) {
|
||||
location.getWorld().spawnEntity(location, entityType, CreatureSpawnEvent.SpawnReason.LIGHTNING);
|
||||
} else if (entity instanceof Entiddy entiddy) {
|
||||
entiddy.entiddy().spawn(location, CreatureSpawnEvent.SpawnReason.LIGHTNING);
|
||||
}
|
||||
}
|
||||
|
||||
private void getEntityTypeOrSpecial(String key, String value) {
|
||||
String sourceKey = null;
|
||||
Object goal = null;
|
||||
for (EntityType entityType : EntityType.values()) {
|
||||
if (!entityType.isSpawnable()) continue;
|
||||
String entityKey = entityType.getKey().getKey();
|
||||
if (entityKey.equals(key.toLowerCase(Locale.ROOT))) {
|
||||
sourceKey = key;
|
||||
}
|
||||
if (entityKey.equals(value.toLowerCase(Locale.ROOT))) {
|
||||
goal = entityType;
|
||||
}
|
||||
}
|
||||
if (sourceKey == null) {
|
||||
try {
|
||||
Entiddy entiddy = Entiddy.valueOf(key.toUpperCase(Locale.ROOT));
|
||||
sourceKey = key;
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
if (goal == null) {
|
||||
try {
|
||||
goal = Entiddy.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
entities.put(sourceKey, goal);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onLightningStrike(EntityZapEvent event) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
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.EntityTargetEvent;
|
||||
|
||||
public class MobNoTargetListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onMobTarget(EntityTargetEvent event) {
|
||||
if (!(event.getTarget() instanceof Player player)) return;
|
||||
if (!player.hasPermission("target.bypass." + event.getEntityType().getKey().getKey())) return;
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Skeleton;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
|
||||
public class SkeletonWitherRoseListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onRightClick(PlayerInteractEntityEvent event) {
|
||||
Entity entity = event.getRightClicked();
|
||||
if (!(entity instanceof Skeleton)) return;
|
||||
Location location = entity.getLocation();
|
||||
Player player = event.getPlayer();
|
||||
if (!player.getInventory().getItemInMainHand().getType().equals(Material.WITHER_ROSE)) return;
|
||||
player.swingMainHand();
|
||||
entity.remove();
|
||||
location.getWorld().spawnEntity(location, EntityType.WITHER_SKELETON, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class StonecutterDamageListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onStonecutterDamage(EntityDamageEvent event) {
|
||||
|
||||
if (!event.getCause().equals(EntityDamageEvent.DamageCause.CONTACT)) return;
|
||||
if (!event.getEntity().isOnGround()) return;
|
||||
|
||||
HashSet<EntityType> damageBlacklist = PurpurExtras.getPurpurConfig().stonecutterDamageBlacklist;
|
||||
|
||||
if (damageBlacklist.contains(event.getEntity().getType()))
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package me.youhavetrouble.purpurextras.recipes;
|
||||
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.RecipeChoice;
|
||||
import org.bukkit.inventory.SmithingRecipe;
|
||||
|
||||
public class ToolUpgradesRecipes {
|
||||
|
||||
|
||||
public static void addUpgradeRecipes(boolean woodToStone, boolean stoneToIron, boolean ironToDiamond) {
|
||||
|
||||
SmithingRecipe recipe;
|
||||
|
||||
if (woodToStone) {
|
||||
recipe = new SmithingRecipe(
|
||||
key("pick_wood_to_stone"),
|
||||
new ItemStack(Material.STONE_PICKAXE),
|
||||
new RecipeChoice.MaterialChoice(Material.WOODEN_PICKAXE),
|
||||
new RecipeChoice.MaterialChoice(Material.COBBLESTONE, Material.BLACKSTONE), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("axe_wood_to_stone"),
|
||||
new ItemStack(Material.STONE_AXE),
|
||||
new RecipeChoice.MaterialChoice(Material.WOODEN_AXE),
|
||||
new RecipeChoice.MaterialChoice(Material.COBBLESTONE, Material.BLACKSTONE), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("shovel_wood_to_stone"),
|
||||
new ItemStack(Material.STONE_SHOVEL),
|
||||
new RecipeChoice.MaterialChoice(Material.WOODEN_SHOVEL),
|
||||
new RecipeChoice.MaterialChoice(Material.COBBLESTONE, Material.BLACKSTONE), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("hoe_wood_to_stone"),
|
||||
new ItemStack(Material.STONE_HOE),
|
||||
new RecipeChoice.MaterialChoice(Material.WOODEN_HOE),
|
||||
new RecipeChoice.MaterialChoice(Material.COBBLESTONE, Material.BLACKSTONE), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("sword_wood_to_stone"),
|
||||
new ItemStack(Material.STONE_SWORD),
|
||||
new RecipeChoice.MaterialChoice(Material.WOODEN_SWORD),
|
||||
new RecipeChoice.MaterialChoice(Material.COBBLESTONE, Material.BLACKSTONE), true);
|
||||
addRecipe(recipe);
|
||||
} else {
|
||||
removeRecipe("sword_wood_to_stone");
|
||||
removeRecipe("pick_wood_to_stone");
|
||||
removeRecipe("axe_wood_to_stone");
|
||||
removeRecipe("shovel_wood_to_stone");
|
||||
removeRecipe("hoe_wood_to_stone");
|
||||
}
|
||||
|
||||
if (stoneToIron) {
|
||||
recipe = new SmithingRecipe(
|
||||
key("pick_stone_to_iron"),
|
||||
new ItemStack(Material.IRON_PICKAXE),
|
||||
new RecipeChoice.MaterialChoice(Material.STONE_PICKAXE),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_INGOT), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("axe_stone_to_iron"),
|
||||
new ItemStack(Material.IRON_AXE),
|
||||
new RecipeChoice.MaterialChoice(Material.STONE_AXE),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_INGOT), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("shovel_stone_to_iron"),
|
||||
new ItemStack(Material.IRON_SHOVEL),
|
||||
new RecipeChoice.MaterialChoice(Material.STONE_SHOVEL),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_INGOT), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("hoe_stone_to_iron"),
|
||||
new ItemStack(Material.IRON_HOE),
|
||||
new RecipeChoice.MaterialChoice(Material.STONE_HOE),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_INGOT), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("sword_stone_to_iron"),
|
||||
new ItemStack(Material.IRON_SWORD),
|
||||
new RecipeChoice.MaterialChoice(Material.STONE_SWORD),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_INGOT), true);
|
||||
addRecipe(recipe);
|
||||
} else {
|
||||
removeRecipe("sword_stone_to_iron");
|
||||
removeRecipe("pick_stone_to_iron");
|
||||
removeRecipe("axe_stone_to_iron");
|
||||
removeRecipe("shovel_stone_to_iron");
|
||||
removeRecipe("hoe_stone_to_iron");
|
||||
}
|
||||
|
||||
if (ironToDiamond) {
|
||||
recipe = new SmithingRecipe(
|
||||
key("pick_iron_to_diamond"),
|
||||
new ItemStack(Material.DIAMOND_PICKAXE),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_PICKAXE),
|
||||
new RecipeChoice.MaterialChoice(Material.DIAMOND), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("axe_iron_to_diamond"),
|
||||
new ItemStack(Material.DIAMOND_AXE),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_AXE),
|
||||
new RecipeChoice.MaterialChoice(Material.DIAMOND), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("shovel_iron_to_diamond"),
|
||||
new ItemStack(Material.DIAMOND_SHOVEL),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_SHOVEL),
|
||||
new RecipeChoice.MaterialChoice(Material.DIAMOND), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("hoe_iron_to_diamond"),
|
||||
new ItemStack(Material.DIAMOND_HOE),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_HOE),
|
||||
new RecipeChoice.MaterialChoice(Material.DIAMOND), true);
|
||||
addRecipe(recipe);
|
||||
recipe = new SmithingRecipe(
|
||||
key("sword_iron_to_diamond"),
|
||||
new ItemStack(Material.DIAMOND_SWORD),
|
||||
new RecipeChoice.MaterialChoice(Material.IRON_SWORD),
|
||||
new RecipeChoice.MaterialChoice(Material.DIAMOND), true);
|
||||
addRecipe(recipe);
|
||||
} else {
|
||||
removeRecipe("sword_iron_to_diamond");
|
||||
removeRecipe("pick_iron_to_diamond");
|
||||
removeRecipe("axe_iron_to_diamond");
|
||||
removeRecipe("shovel_iron_to_diamond");
|
||||
removeRecipe("hoe_iron_to_diamond");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static NamespacedKey key(String string) {
|
||||
return new NamespacedKey(PurpurExtras.getInstance(), string);
|
||||
}
|
||||
|
||||
private static void addRecipe(SmithingRecipe recipe) {
|
||||
if (Bukkit.getRecipe(recipe.getKey()) != null) return;
|
||||
Bukkit.getScheduler().runTask(PurpurExtras.getInstance(), () -> Bukkit.addRecipe(recipe));
|
||||
}
|
||||
|
||||
private static void removeRecipe(String key) {
|
||||
Bukkit.getScheduler().runTask(PurpurExtras.getInstance(), () -> Bukkit.removeRecipe(new NamespacedKey(PurpurExtras.getInstance(), key)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.purpurmc.purpurextras;
|
||||
|
||||
import java.util.*;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class PurpurConfig {
|
||||
|
||||
private FileConfiguration config;
|
||||
|
||||
protected PurpurConfig() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.saveDefaultConfig();
|
||||
plugin.reloadConfig();
|
||||
config = plugin.getConfig();
|
||||
|
||||
}
|
||||
|
||||
public boolean getBoolean(String path, boolean def) {
|
||||
|
||||
if (config.isSet(path))
|
||||
return config.getBoolean(path, def);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
|
||||
}
|
||||
|
||||
public String getString(String path, String def) {
|
||||
|
||||
if (config.isSet(path))
|
||||
return config.getString(path, def);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
|
||||
}
|
||||
|
||||
public double getDouble(String path, double def) {
|
||||
|
||||
if (config.isSet(path))
|
||||
return config.getDouble(path, def);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
|
||||
}
|
||||
|
||||
public int getInt(String path, int def) {
|
||||
|
||||
if (config.isSet(path))
|
||||
return config.getInt(path, def);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defKV Default key-value map
|
||||
*/
|
||||
public ConfigurationSection getConfigSection(String path, Map<String, Object> defKV) {
|
||||
|
||||
if (config.isConfigurationSection(path))
|
||||
return config.getConfigurationSection(path);
|
||||
return config.createSection(path, defKV);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of strings or empty list if list doesn't exist in configuration
|
||||
* file
|
||||
*/
|
||||
public List<String> getList(String path, List<String> def) {
|
||||
|
||||
if (config.isSet(path))
|
||||
return config.getStringList(path);
|
||||
config.set(path, def);
|
||||
return def;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+44
-10
@@ -1,38 +1,72 @@
|
||||
package me.youhavetrouble.purpurextras;
|
||||
package org.purpurmc.purpurextras;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PurpurExtrasCommand implements TabExecutor {
|
||||
|
||||
public class PurpurExtrasCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] strings)
|
||||
{
|
||||
|
||||
if (strings.length == 0) {
|
||||
commandSender.sendMessage(
|
||||
Component.text("PurpurExtras", NamedTextColor.DARK_PURPLE, TextDecoration.BOLD)
|
||||
.append(Component.text(" by YouHaveTrouble"))
|
||||
);
|
||||
|
||||
commandSender.sendMessage(Component.text("PurpurExtras", NamedTextColor.DARK_PURPLE, TextDecoration.BOLD)
|
||||
.append(Component.text(" by YouHaveTrouble")));
|
||||
|
||||
}
|
||||
|
||||
if (strings.length == 1 && strings[0].equalsIgnoreCase("reload")) {
|
||||
|
||||
if (!commandSender.hasPermission("purpurextras.reload")) {
|
||||
|
||||
commandSender.sendMessage(Component.text("You don't have permission to do that.", NamedTextColor.RED));
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
commandSender.sendMessage(Component.text("Reloading PurpurExtras config..."));
|
||||
PurpurExtras.getInstance().reloadPurpurExtrasConfig(commandSender);
|
||||
PurpurExtrasOG.getInstance().reloadPurpurExtrasConfig(commandSender);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if (strings.length == 1 && strings[0].equalsIgnoreCase("version")) {
|
||||
commandSender.sendMessage(Component.text("PurpurExtras version "+PurpurExtras.getInstance().getDescription().getVersion()));
|
||||
|
||||
commandSender.sendMessage(Component
|
||||
.text("PurpurExtras version " + PurpurExtrasOG.getInstance().getPluginMeta().getVersion()));
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd,
|
||||
@NotNull String label, @NotNull String[] args)
|
||||
{
|
||||
|
||||
List<String> cmds = List.of("reload", "version");
|
||||
if (args.length == 1) {
|
||||
|
||||
return cmds.stream().filter(s -> s.toLowerCase().startsWith(args[0])).toList();
|
||||
|
||||
} else {
|
||||
|
||||
return Collections.emptyList();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.purpurmc.purpurextras;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.purpurmc.purpurextras.modules.PurpurExtrasModule;
|
||||
|
||||
public final class PurpurExtrasOG extends JavaPlugin {
|
||||
|
||||
private static PurpurConfig config;
|
||||
private static PurpurExtrasOG instance;
|
||||
public final MiniMessage miniMessage = MiniMessage.miniMessage();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
try {
|
||||
|
||||
Class.forName("org.purpurmc.purpur.PurpurConfig");
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
||||
getLogger().warning("---------------------------------------------");
|
||||
getLogger().warning("Some features may not work without Purpur!");
|
||||
getLogger().warning("PurpurExtras was created to compliment Purpur, and it appears you're not using it!");
|
||||
getLogger().warning("Purpur is a drop-in replacement for " + getServer().getName() + ".");
|
||||
getLogger().warning("You can get Purpur on https://purpurmc.org/downloads");
|
||||
getLogger().warning("---------------------------------------------");
|
||||
|
||||
}
|
||||
|
||||
instance = this;
|
||||
config = new PurpurConfig();
|
||||
|
||||
PluginCommand command = getCommand("purpurextras");
|
||||
if (command != null) {
|
||||
|
||||
PurpurExtrasCommand cmd = new PurpurExtrasCommand();
|
||||
command.setExecutor(cmd);
|
||||
command.setTabCompleter(cmd);
|
||||
|
||||
}
|
||||
|
||||
PurpurExtrasModule.reloadModules();
|
||||
|
||||
}
|
||||
|
||||
public static PurpurConfig getPurpurConfig() {
|
||||
|
||||
return config;
|
||||
|
||||
}
|
||||
|
||||
public static PurpurExtrasOG getInstance() {
|
||||
|
||||
return instance;
|
||||
|
||||
}
|
||||
|
||||
void reloadPurpurExtrasConfig(CommandSender commandSender) {
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
||||
|
||||
config = new PurpurConfig();
|
||||
PurpurExtrasModule.reloadModules();
|
||||
commandSender.sendMessage(Component.text("PurpurExtras configuration reloaded!"));
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static NamespacedKey key(String string) {
|
||||
|
||||
return new NamespacedKey(PurpurExtrasOG.getInstance(), string);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, block list will be used. Key is the block material that will be
|
||||
* converted from and value is block material that will be converted to. In
|
||||
* default config if anvil falls on a cobblestone block, that cobblestone will
|
||||
* be converted to sand.
|
||||
*/
|
||||
public class AnvilChangesBlocksModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final HashSet<Material> anvils = new HashSet<>();
|
||||
private final HashMap<Material, Material> anvilCrushBlocksIndex = new HashMap<>();
|
||||
|
||||
protected AnvilChangesBlocksModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
Map<String, Object> defaults = new HashMap<>();
|
||||
|
||||
anvils.add(Material.ANVIL);
|
||||
anvils.add(Material.CHIPPED_ANVIL);
|
||||
anvils.add(Material.DAMAGED_ANVIL);
|
||||
|
||||
defaults.put("cobblestone", "sand");
|
||||
ConfigurationSection section = config.getConfigSection("settings.anvil-crushes-blocks.blocks", defaults);
|
||||
Logger logger = PurpurExtrasOG.getInstance().getLogger();
|
||||
for (String key : section.getKeys(false)) {
|
||||
|
||||
String matString = section.getString(key);
|
||||
if (matString == null)
|
||||
continue;
|
||||
Material materialFrom = Material.getMaterial(key.toUpperCase(Locale.ENGLISH));
|
||||
|
||||
if (materialFrom == null || !materialFrom.isBlock()) {
|
||||
|
||||
logger.warning(key + " is not valid block material.");
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
Material materialTo = Material.getMaterial(matString.toUpperCase());
|
||||
if (materialTo == null || !materialTo.isBlock()) {
|
||||
|
||||
logger.warning(matString + " is not valid block material.");
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
anvilCrushBlocksIndex.put(materialFrom, materialTo);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.anvil-crushes-blocks.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onAnvilDrop(EntityChangeBlockEvent event) {
|
||||
|
||||
if (!anvils.contains(event.getTo()))
|
||||
return;
|
||||
|
||||
Location belowAnvil = event.getBlock().getLocation().clone().subtract(0, 1, 0);
|
||||
Block blockBelowAnvil = belowAnvil.getBlock();
|
||||
|
||||
if (!anvilCrushBlocksIndex.containsKey(blockBelowAnvil.getType()))
|
||||
return;
|
||||
|
||||
blockBelowAnvil.setType(anvilCrushBlocksIndex.get(blockBelowAnvil.getType()), true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import com.destroystokyo.paper.MaterialSetTag;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, dropping an anvil from significant height onto minecart with
|
||||
* content (chest minecart, furnace minecart, etc.) in its item form, it will
|
||||
* not destroy the item, but split the minecart and the content and drop them
|
||||
* both. Does the same to chest boats
|
||||
*/
|
||||
public class AnvilSplitsMinecartsAndBoatsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final boolean splitBoats, splitMinecarts;
|
||||
|
||||
protected AnvilSplitsMinecartsAndBoatsModule() {
|
||||
|
||||
this.splitMinecarts = PurpurExtrasOG.getPurpurConfig().getBoolean("settings.anvil-splits-minecarts", false);
|
||||
this.splitBoats = PurpurExtrasOG.getPurpurConfig().getBoolean("settings.anvil-splits-boats", false);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.anvil-splits-minecarts", false)
|
||||
|| PurpurExtrasOG.getPurpurConfig().getBoolean("settings.anvil-splits-boats", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onAnvilDrop(EntityDamageByEntityEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Item item))
|
||||
return;
|
||||
if (!(event.getDamager() instanceof FallingBlock fallingBlock))
|
||||
return;
|
||||
|
||||
if (!MaterialSetTag.ANVIL.isTagged(fallingBlock.getBlockData().getMaterial()))
|
||||
return;
|
||||
|
||||
Material itemMaterial = item.getItemStack().getType();
|
||||
Location location = event.getEntity().getLocation();
|
||||
|
||||
if (splitBoats && MaterialSetTag.ITEMS_CHEST_BOATS.isTagged(itemMaterial)) {
|
||||
|
||||
String boatMaterialString = item.getItemStack().getType().toString().replace("_CHEST", "");
|
||||
Material boatMaterial = Material.matchMaterial(boatMaterialString);
|
||||
if (boatMaterial == null)
|
||||
return;
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.CHEST));
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(boatMaterial));
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (!splitMinecarts)
|
||||
return;
|
||||
|
||||
switch (itemMaterial) {
|
||||
|
||||
case CHEST_MINECART -> {
|
||||
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.CHEST));
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.MINECART));
|
||||
|
||||
}
|
||||
case FURNACE_MINECART -> {
|
||||
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.FURNACE));
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.MINECART));
|
||||
|
||||
}
|
||||
case TNT_MINECART -> {
|
||||
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.TNT));
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.MINECART));
|
||||
|
||||
}
|
||||
case HOPPER_MINECART -> {
|
||||
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.HOPPER));
|
||||
location.getWorld().dropItemNaturally(location, new ItemStack(Material.MINECART));
|
||||
|
||||
}
|
||||
default -> throw new IllegalArgumentException(
|
||||
"Unexpected item in AnvilSplitsMinecartsAndBoatsModule: " + itemMaterial);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+52
-11
@@ -1,6 +1,6 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.Material;
|
||||
@@ -13,19 +13,48 @@ import org.bukkit.event.block.BlockDropItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryCreativeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import java.util.List;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
public class BeehiveLoreListener implements Listener {
|
||||
/**
|
||||
* If true, will add lore with amount of bees and honey to the picked up hives.
|
||||
*/
|
||||
public class BeeHiveLoreModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final MiniMessage miniMessage = PurpurExtras.getInstance().miniMessage;
|
||||
private final String beeHiveLoreBees, beeHiveLoreHoney;
|
||||
private final MiniMessage miniMessage = PurpurExtrasOG.getInstance().miniMessage;
|
||||
|
||||
protected BeeHiveLoreModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
this.beeHiveLoreBees = config.getString("settings.items.beehive-lore.bees",
|
||||
"<reset><gray>Bees: <bees>/<maxbees>");
|
||||
this.beeHiveLoreHoney = config.getString("settings.items.beehive-lore.honey",
|
||||
"<reset><gray>Honey level: <honey>/<maxhoney>");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.items.beehive-lore.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onBeehiveDrop(BlockDropItemEvent event) {
|
||||
|
||||
BlockState blockState = event.getBlockState();
|
||||
|
||||
if (!blockState.getType().equals(Material.BEE_NEST)
|
||||
&& !blockState.getType().equals(Material.BEEHIVE))
|
||||
if (!blockState.getType().equals(Material.BEE_NEST) && !blockState.getType().equals(Material.BEEHIVE))
|
||||
return;
|
||||
|
||||
org.bukkit.block.Beehive beehive = (org.bukkit.block.Beehive) blockState;
|
||||
@@ -34,46 +63,58 @@ public class BeehiveLoreListener implements Listener {
|
||||
List<Item> itemDrops = event.getItems();
|
||||
|
||||
for (Item itemDrop : itemDrops) {
|
||||
|
||||
ItemStack item = itemDrop.getItemStack();
|
||||
if (item.getType().equals(Material.BEE_NEST) || item.getType().equals(Material.BEEHIVE)) {
|
||||
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
Component beeCountComponent = getBeesComponent(beehive.getEntityCount(), beehive.getMaxEntities());
|
||||
Component honeyLevelComponent = getHoneyComponent(beehiveData.getHoneyLevel(), beehiveData.getMaximumHoneyLevel());
|
||||
Component honeyLevelComponent = getHoneyComponent(beehiveData.getHoneyLevel(),
|
||||
beehiveData.getMaximumHoneyLevel());
|
||||
List<Component> lore = List.of(beeCountComponent, honeyLevelComponent);
|
||||
meta.lore(lore);
|
||||
item.setItemMeta(meta);
|
||||
itemDrop.setItemStack(item);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onBeehiveCreativePick(InventoryCreativeEvent event) {
|
||||
|
||||
if (!event.getCursor().getType().equals(Material.BEE_NEST)
|
||||
&& !event.getCursor().getType().equals(Material.BEEHIVE))
|
||||
return;
|
||||
ItemStack item = event.getCursor();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
//TODO find a way to read bee data from ItemStack
|
||||
// TODO find a way to read bee data from ItemStack
|
||||
Component beeCountComponent = getBeesComponent(0, 3);
|
||||
Component honeyLevelComponent = getHoneyComponent(0, 5);
|
||||
List<Component> lore = List.of(beeCountComponent, honeyLevelComponent);
|
||||
meta.lore(lore);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
}
|
||||
|
||||
private Component getBeesComponent(int bees, int maxBees) {
|
||||
String beeHiveLoreBeesString = PurpurExtras.getPurpurConfig().beeHiveLoreBees;
|
||||
|
||||
String beeHiveLoreBeesString = beeHiveLoreBees;
|
||||
beeHiveLoreBeesString = beeHiveLoreBeesString.replaceAll("<bees>", String.valueOf(bees));
|
||||
beeHiveLoreBeesString = beeHiveLoreBeesString.replaceAll("<maxbees>", String.valueOf(maxBees));
|
||||
return miniMessage.deserializeOrNull(beeHiveLoreBeesString);
|
||||
|
||||
}
|
||||
|
||||
private Component getHoneyComponent(int honey, int maxHoney) {
|
||||
String beeHiveLoreHoneyString = PurpurExtras.getPurpurConfig().beeHiveLoreHoney;
|
||||
|
||||
String beeHiveLoreHoneyString = beeHiveLoreHoney;
|
||||
beeHiveLoreHoneyString = beeHiveLoreHoneyString.replaceAll("<honey>", String.valueOf(honey));
|
||||
beeHiveLoreHoneyString = beeHiveLoreHoneyString.replaceAll("<maxhoney>", String.valueOf(maxHoney));
|
||||
return miniMessage.deserializeOrNull(beeHiveLoreHoneyString);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, pet owners will not be able to harm their own pets.
|
||||
*/
|
||||
public class CancelPetDamageFromOwnerModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected CancelPetDamageFromOwnerModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.gameplay-settings.cancel-damage-from-pet-owner",
|
||||
false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPetDamage(EntityDamageByEntityEvent damageEvent) {
|
||||
|
||||
Entity damager = damageEvent.getDamager();
|
||||
if (!(damageEvent.getEntity() instanceof Tameable pet))
|
||||
return;
|
||||
if (!pet.isTamed())
|
||||
return;
|
||||
if (!(pet.getOwner() instanceof OfflinePlayer owner))
|
||||
return;
|
||||
if (damager instanceof Projectile projectile) {
|
||||
|
||||
ProjectileSource shooter = projectile.getShooter();
|
||||
if (!(shooter instanceof OfflinePlayer playerShooter))
|
||||
return;
|
||||
if (playerShooter != owner)
|
||||
return;
|
||||
damageEvent.setCancelled(true);
|
||||
if ((projectile instanceof AbstractArrow && !projectile.getType().equals(EntityType.TRIDENT))) {
|
||||
|
||||
projectile.remove();
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (!(damager instanceof OfflinePlayer damagingPlayer))
|
||||
return;
|
||||
if (damagingPlayer.getUniqueId() != owner.getUniqueId())
|
||||
return;
|
||||
damageEvent.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import com.destroystokyo.paper.event.block.BlockDestroyEvent;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Makes it so chorus flowers always drop, no matter if they were destroyed
|
||||
* directly or not.
|
||||
*/
|
||||
public class ChorusFlowerAlwaysDropsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected ChorusFlowerAlwaysDropsModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.blocks.chorus-flowers-always-drop", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void entityHitChorusFlower(ProjectileHitEvent event) {
|
||||
|
||||
if (event.getHitBlock() == null)
|
||||
return;
|
||||
if (event.getHitBlock().getType().equals(Material.CHORUS_FLOWER)) {
|
||||
|
||||
Block chorusFlower = event.getHitBlock();
|
||||
event.setCancelled(true);
|
||||
chorusFlower.breakNaturally();
|
||||
chorusFlower.getWorld().dropItem(chorusFlower.getLocation(), new ItemStack(Material.CHORUS_FLOWER));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void chorusFlowerBreak(BlockDestroyEvent event) {
|
||||
|
||||
Block block = event.getBlock();
|
||||
if (!(block.getType().equals(Material.CHORUS_FLOWER)))
|
||||
return;
|
||||
Location flowerLocation = block.getLocation();
|
||||
Material blockMaterial = block.getType();
|
||||
flowerLocation.getWorld().dropItem(flowerLocation, new ItemStack(blockMaterial));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.entity.Boss;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, allows players to dye boss health bars by right-clicking the boss
|
||||
* with a dye item.
|
||||
*/
|
||||
public class ColoredBossBarsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final NamespacedKey dyeColor = PurpurExtrasOG.key("dyedColor");
|
||||
|
||||
protected ColoredBossBarsModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.dye-boss-bars", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onBossBarDye(PlayerInteractEntityEvent event) {
|
||||
|
||||
if (event.getHand().equals(EquipmentSlot.OFF_HAND))
|
||||
return;
|
||||
if (!(event.getRightClicked() instanceof Boss bossClicked))
|
||||
return;
|
||||
Player player = event.getPlayer();
|
||||
String materialName = player.getInventory().getItemInMainHand().getType().toString();
|
||||
if (!materialName.contains("_DYE"))
|
||||
return;
|
||||
int index = materialName.indexOf("_DYE");
|
||||
String bossBarColor = materialName.substring(0, index);
|
||||
try {
|
||||
|
||||
BarColor.valueOf(bossBarColor);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
bossClicked.getBossBar().setColor(BarColor.valueOf(bossBarColor));
|
||||
PersistentDataContainer pdc = bossClicked.getPersistentDataContainer();
|
||||
pdc.set(dyeColor, PersistentDataType.STRING, bossBarColor);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onBossBarDyeOnLoad(EntityAddToWorldEvent event) {
|
||||
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof Boss boss))
|
||||
return;
|
||||
PersistentDataContainer pdc = boss.getPersistentDataContainer();
|
||||
if (!pdc.has(dyeColor, PersistentDataType.STRING))
|
||||
return;
|
||||
String color = pdc.get(dyeColor, PersistentDataType.STRING);
|
||||
boss.getBossBar().setColor(BarColor.valueOf(color));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.event.Listener;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, players will be able to shift-right click on sand and gravel with
|
||||
* items in their hands to create suspicious blocks and put held item inside.
|
||||
* Held item will disappear from player's hand and will be added as loot inside
|
||||
* the suspicious block. Only one item can be added per block.
|
||||
*/
|
||||
public class CreateSusBlocksModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected CreateSusBlocksModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
// return
|
||||
// PurpurExtrasOG.getPurpurConfig().getBoolean("settings.create-suspicious-blocks",
|
||||
// false);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public
|
||||
* void onInteractWithSusBlock(PlayerInteractEvent event) { if
|
||||
* (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; Player player =
|
||||
* event.getPlayer(); if (!player.isSneaking()) return; Block block =
|
||||
* event.getClickedBlock(); if (block == null) return; if (block.getType() !=
|
||||
* Material.SAND && block.getType() != Material.GRAVEL) return; ItemStack
|
||||
* itemStack = event.getItem(); if (itemStack == null) return;
|
||||
*
|
||||
* switch (block.getType()) { case SAND ->
|
||||
* block.setType(Material.SUSPICIOUS_SAND); case GRAVEL ->
|
||||
* block.setType(Material.SUSPICIOUS_GRAVEL); default -> { return; } }
|
||||
*
|
||||
* BlockState blockState = block.getState(); if (!(blockState instanceof
|
||||
* BrushableBlock brushableBlock)) return;
|
||||
* brushableBlock.setItem(itemStack.asOne());
|
||||
* event.getItem().setAmount(itemStack.getAmount() - 1);
|
||||
* brushableBlock.update(); event.setUseInteractedBlock(Event.Result.DENY);
|
||||
* event.setUseItemInHand(Event.Result.DENY);
|
||||
*
|
||||
* EquipmentSlot hand = event.getHand(); if (hand == null) return;
|
||||
* player.swingHand(hand); }
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import com.destroystokyo.paper.entity.ai.Goal;
|
||||
import com.destroystokyo.paper.entity.ai.GoalKey;
|
||||
import com.destroystokyo.paper.entity.ai.GoalType;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.function.Predicate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Squid;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
||||
import org.bukkit.event.entity.ExplosionPrimeEvent;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Allows squids to act as Creepers - they will explode if within
|
||||
* {@link #maxDistance} after a fuse of {@link #maxSwell} ticks, as well as
|
||||
* moving towards you at a velocity of {@link #velocity} Explosion power /
|
||||
* radius is also configurable through {@link #explosionPower}
|
||||
*/
|
||||
public class CreeperSquidsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private int maxSwell;
|
||||
private int maxDistance;
|
||||
private int explosionPower;
|
||||
private double velocity;
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
Bukkit.getServer().getPluginManager().registerEvents(this, PurpurExtrasOG.getInstance());
|
||||
maxSwell = PurpurExtrasOG.getPurpurConfig().getInt("settings.creeper-squid.fuse-ticks", 30);
|
||||
maxDistance = (int) Math.pow(PurpurExtrasOG.getPurpurConfig().getInt("settings.creeper-squid.agro-distance", 7),
|
||||
2);
|
||||
explosionPower = PurpurExtrasOG.getPurpurConfig().getInt("settings.creeper-squid.explosion-radius", 3);
|
||||
velocity = PurpurExtrasOG.getPurpurConfig().getDouble("settings.creeper-squid.velocity", 0.5);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.creeper-squid.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
|
||||
public void onSquidSpawn(EntitySpawnEvent event) {
|
||||
|
||||
if (event.getEntityType() != EntityType.SQUID)
|
||||
return;
|
||||
Squid squid = (Squid) event.getEntity();
|
||||
Bukkit.getMobGoals().removeAllGoals(squid, GoalType.TARGET);
|
||||
Bukkit.getMobGoals().addGoal(squid, 3, new SquidGoal(squid));
|
||||
|
||||
}
|
||||
|
||||
// good chunk of this logic pulled directly from nms
|
||||
private final class SquidGoal implements Goal<Squid> {
|
||||
|
||||
private static final GoalKey<Squid> goalKey = GoalKey.of(Squid.class, PurpurExtrasOG.key("squidgoal"));
|
||||
private static final Predicate<Player> playerPredicate = player -> !player
|
||||
.hasPotionEffect(PotionEffectType.INVISIBILITY) && !player.isInvisible() && player.isValid()
|
||||
&& (player.getGameMode() == GameMode.SURVIVAL || player.getGameMode() == GameMode.ADVENTURE);
|
||||
private final Squid squid;
|
||||
private int currentSwell = 0;
|
||||
private int swellDir = -1;
|
||||
private Player currentTarget;
|
||||
|
||||
public SquidGoal(Squid squid) {
|
||||
|
||||
this.squid = squid;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldActivate() {
|
||||
|
||||
if (!squid.isValid())
|
||||
return false;
|
||||
if (currentTarget != null) {
|
||||
|
||||
if (currentTarget.getLocation().distanceSquared(squid.getLocation()) <= maxDistance) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
currentTarget = getClosestPlayer();
|
||||
if (currentTarget == null) {
|
||||
|
||||
swellDir = -1;
|
||||
if (currentSwell > 0)
|
||||
currentSwell += swellDir;
|
||||
squid.setGlowing(false);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
squid.setTarget(null);
|
||||
squid.setVelocity(Vector.getRandom());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
|
||||
squid.setGlowing(!squid.isGlowing());
|
||||
if (currentTarget != null) {
|
||||
|
||||
if (swellDir == -1)
|
||||
squid.getWorld().playSound(squid.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1F, 0.5F);
|
||||
swellDir = 1;
|
||||
squid.setVelocity(squid.getLocation().toVector().subtract(currentTarget.getLocation().toVector())
|
||||
.normalize().multiply(-1 * velocity));
|
||||
squid.lookAt(currentTarget.getEyeLocation());
|
||||
|
||||
}
|
||||
|
||||
this.currentSwell += swellDir;
|
||||
if (this.currentSwell >= maxSwell) {
|
||||
|
||||
explode();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull GoalKey<Squid> getKey() {
|
||||
|
||||
return goalKey;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EnumSet<GoalType> getTypes() {
|
||||
|
||||
return EnumSet.of(GoalType.MOVE, GoalType.LOOK);
|
||||
|
||||
}
|
||||
|
||||
private void explode() {
|
||||
|
||||
ExplosionPrimeEvent event = new ExplosionPrimeEvent(squid, 3, true);
|
||||
event.callEvent();
|
||||
if (!event.isCancelled()) {
|
||||
|
||||
squid.remove();
|
||||
squid.getWorld().createExplosion(squid, squid.getLocation(), explosionPower);
|
||||
Bukkit.getScheduler().runTaskLater(PurpurExtrasOG.getInstance(),
|
||||
() -> squid.getWorld().playSound(squid.getLocation(), Sound.ENTITY_CREEPER_DEATH, 1f, 0.5f), 1);
|
||||
|
||||
} else {
|
||||
|
||||
this.currentSwell = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Player getClosestPlayer() {
|
||||
|
||||
Collection<Player> players = squid.getWorld().getNearbyEntitiesByType(Player.class, squid.getLocation(),
|
||||
maxDistance, playerPredicate);
|
||||
double playerDistance = -1;
|
||||
Player closestPlayer = null;
|
||||
for (Player player : players) {
|
||||
|
||||
if (closestPlayer == null) {
|
||||
|
||||
closestPlayer = player;
|
||||
playerDistance = player.getLocation().distanceSquared(squid.getLocation());
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
double dist = player.getLocation().distanceSquared(squid.getLocation());
|
||||
if (dist < playerDistance) {
|
||||
|
||||
closestPlayer = player;
|
||||
playerDistance = player.getLocation().distanceSquared(squid.getLocation());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return closestPlayer;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import com.destroystokyo.paper.MaterialSetTag;
|
||||
import com.destroystokyo.paper.MaterialTags;
|
||||
import io.papermc.paper.event.block.BlockPreDispenseEvent;
|
||||
import java.util.Map;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Jukebox;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Levelled;
|
||||
import org.bukkit.block.data.type.Dispenser;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
import org.purpurmc.purpurextras.util.ItemStackUtil;
|
||||
|
||||
/**
|
||||
* Dispenser modifications
|
||||
*
|
||||
* **break-blocks** If a tool category is enabled, that tool dispensed from
|
||||
* dispenser will destroy the block in front of it. It will only destroy blocks
|
||||
* that tool can destroy and it will destroy them like that tool was used on it,
|
||||
* so wooden pickaxe will destroy diamond ore, but will not drop any items.
|
||||
*
|
||||
* **shears-shear-pumpkin** If enabled, when shears are dispensed and there's a
|
||||
* pumpkin in front of a dispenser, shears will be used, making carved pumpkin.
|
||||
*
|
||||
* **interact-with-cauldron** If enabled, will allow dispensers fill and empty
|
||||
* cauldrons.
|
||||
*
|
||||
* **put-discs-in-jukebox** If enabled, dispensers will be able to insert into
|
||||
* or swap music discs in jukeboxes.
|
||||
*/
|
||||
public class DispenserBlocksModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private static final MaterialSetTag CAULDRON_BUCKETS = new MaterialSetTag(
|
||||
new NamespacedKey(PurpurExtrasOG.getInstance(), "cauldron_buckets")).add(Material.BUCKET)
|
||||
.add(Material.WATER_BUCKET).add(Material.LAVA_BUCKET).add(Material.POWDER_SNOW_BUCKET);
|
||||
|
||||
BlockData waterCauldron = Bukkit.createBlockData(Material.WATER_CAULDRON, blockData -> {
|
||||
|
||||
Levelled cauldron = (Levelled) blockData;
|
||||
cauldron.setLevel(3);
|
||||
|
||||
});
|
||||
BlockData powderSnowCauldron = Bukkit.createBlockData(Material.POWDER_SNOW_CAULDRON, blockData -> {
|
||||
|
||||
Levelled cauldron = (Levelled) blockData;
|
||||
cauldron.setLevel(3);
|
||||
|
||||
});
|
||||
BlockData lavaCauldron = Bukkit.createBlockData(Material.LAVA_CAULDRON);
|
||||
|
||||
private final boolean breakBlockPickaxe, breakBlockShovel, breakBlockHoe, breakBlockAxe, breakBlockShears,
|
||||
shearPumpkin, activateJukebox, interactWithCauldron;
|
||||
|
||||
protected DispenserBlocksModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
breakBlockPickaxe = config.getBoolean("settings.dispenser.break-blocks.pickaxe", false);
|
||||
breakBlockShovel = config.getBoolean("settings.dispenser.break-blocks.shovel", false);
|
||||
breakBlockHoe = config.getBoolean("settings.dispenser.break-blocks.hoe", false);
|
||||
breakBlockAxe = config.getBoolean("settings.dispenser.break-blocks.axe", false);
|
||||
breakBlockShears = config.getBoolean("settings.dispenser.break-blocks.shears", false);
|
||||
shearPumpkin = config.getBoolean("settings.dispenser.shears-shear-pumpkin", false);
|
||||
activateJukebox = config.getBoolean("settings.dispenser.puts-discs-in-jukebox", false);
|
||||
interactWithCauldron = config.getBoolean("settings.dispenser.interact-with-cauldron", false);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return anyTrue(breakBlockAxe, breakBlockHoe, breakBlockPickaxe, breakBlockShovel, breakBlockShears,
|
||||
shearPumpkin, activateJukebox, interactWithCauldron);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPreDispense(BlockPreDispenseEvent event) {
|
||||
|
||||
if (!event.getBlock().getType().equals(Material.DISPENSER))
|
||||
return;
|
||||
Dispenser dispenser = (Dispenser) event.getBlock().getBlockData();
|
||||
Block block = event.getBlock().getRelative(dispenser.getFacing());
|
||||
org.bukkit.block.Dispenser blockDispenser = (org.bukkit.block.Dispenser) event.getBlock().getState(false);
|
||||
ItemStack item = event.getItemStack();
|
||||
|
||||
if (breakBlockPickaxe && MaterialTags.PICKAXES.isTagged(item)) {
|
||||
|
||||
event.setCancelled(true);
|
||||
if (tryBreakBlock(item, blockDispenser, block))
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (breakBlockAxe && MaterialTags.AXES.isTagged(item)) {
|
||||
|
||||
event.setCancelled(true);
|
||||
if (tryBreakBlock(item, blockDispenser, block))
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (breakBlockShovel && MaterialTags.SHOVELS.isTagged(item)) {
|
||||
|
||||
event.setCancelled(true);
|
||||
if (tryBreakBlock(item, blockDispenser, block))
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (breakBlockHoe && MaterialTags.HOES.isTagged(item)) {
|
||||
|
||||
event.setCancelled(true);
|
||||
if (tryBreakBlock(item, blockDispenser, block))
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Shear pumpkin
|
||||
if (shearPumpkin && item.getType().equals(Material.SHEARS) && block.getType().equals(Material.PUMPKIN)) {
|
||||
|
||||
Inventory inventory = blockDispenser.getInventory();
|
||||
damageItem(item, inventory);
|
||||
event.setCancelled(true);
|
||||
block.setType(Material.CARVED_PUMPKIN);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Swap records in jukebox
|
||||
if (activateJukebox && MaterialTags.MUSIC_DISCS.isTagged(item) && block.getType().equals(Material.JUKEBOX)) {
|
||||
|
||||
event.setCancelled(true);
|
||||
Jukebox jukebox = (Jukebox) block.getState(false);
|
||||
jukebox.eject();
|
||||
ItemStack record = consumeItem(item);
|
||||
jukebox.setRecord(record);
|
||||
jukebox.update();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Dispense liquid in and from cauldrons
|
||||
if (interactWithCauldron && Tag.CAULDRONS.isTagged(block.getType()) && CAULDRON_BUCKETS.isTagged(item)) {
|
||||
|
||||
Material dispensedItemType = item.getType();
|
||||
Levelled cauldronLevel;
|
||||
if (block.getType().equals(Material.CAULDRON)) {
|
||||
|
||||
switch (dispensedItemType) {
|
||||
|
||||
case BUCKET -> {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
case LAVA_BUCKET -> {
|
||||
|
||||
emptyCauldronHandler(block, lavaCauldron, item, blockDispenser.getLocation(),
|
||||
Sound.ITEM_BUCKET_EMPTY_LAVA);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
||||
}
|
||||
case WATER_BUCKET -> {
|
||||
|
||||
emptyCauldronHandler(block, waterCauldron, item, blockDispenser.getLocation(),
|
||||
Sound.ITEM_BUCKET_EMPTY);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
||||
}
|
||||
case POWDER_SNOW_BUCKET -> {
|
||||
|
||||
emptyCauldronHandler(block, powderSnowCauldron, item, blockDispenser.getLocation(),
|
||||
Sound.ITEM_BUCKET_EMPTY_POWDER_SNOW);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
||||
}
|
||||
default -> throw new IllegalArgumentException(
|
||||
"Unexpected value in DispenserBlockModule: " + dispensedItemType);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!dispensedItemType.equals(Material.BUCKET))
|
||||
return;
|
||||
switch (block.getType()) {
|
||||
|
||||
case LAVA_CAULDRON -> {
|
||||
|
||||
fullCauldronHandler(block, item, blockDispenser, Material.LAVA_BUCKET, Sound.ITEM_BUCKET_FILL_LAVA);
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
case WATER_CAULDRON -> {
|
||||
|
||||
cauldronLevel = (Levelled) block.getBlockData();
|
||||
if (cauldronLevel.getLevel() < 3)
|
||||
return;
|
||||
fullCauldronHandler(block, item, blockDispenser, Material.WATER_BUCKET, Sound.ITEM_BUCKET_FILL);
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
case POWDER_SNOW_CAULDRON -> {
|
||||
|
||||
cauldronLevel = (Levelled) block.getBlockData();
|
||||
if (cauldronLevel.getLevel() < 3)
|
||||
return;
|
||||
fullCauldronHandler(block, item, blockDispenser, Material.POWDER_SNOW_BUCKET,
|
||||
Sound.ITEM_BUCKET_FILL_POWDER_SNOW);
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
default -> throw new IllegalArgumentException(
|
||||
"Unexpected value in DispenserBlockModule: " + dispensedItemType);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void damageItem(ItemStack itemStack, Inventory inventory) {
|
||||
|
||||
int slot = inventory.first(itemStack);
|
||||
if (slot == -1)
|
||||
return;
|
||||
ItemStack item = inventory.getItem(slot);
|
||||
if (item == null)
|
||||
return;
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (!(meta instanceof Damageable))
|
||||
return;
|
||||
ItemStackUtil.damage(item, 1, false);
|
||||
|
||||
}
|
||||
|
||||
private ItemStack consumeItem(ItemStack itemStack) {
|
||||
|
||||
ItemStack consumed = itemStack.clone();
|
||||
consumed.setAmount(1);
|
||||
itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
return consumed;
|
||||
|
||||
}
|
||||
|
||||
private boolean tryBreakBlock(ItemStack itemStack, org.bukkit.block.Dispenser dispenser, Block block) {
|
||||
|
||||
if (block.getDestroySpeed(itemStack, false) <= 1.0f)
|
||||
return false;
|
||||
Inventory inventory = dispenser.getInventory();
|
||||
damageItem(itemStack, inventory);
|
||||
return block.breakNaturally(itemStack, true);
|
||||
|
||||
}
|
||||
|
||||
private boolean anyTrue(boolean... booleans) {
|
||||
|
||||
for (boolean b : booleans) {
|
||||
|
||||
if (b)
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private void emptyCauldronHandler(Block cauldron, BlockData cauldronType, ItemStack dispensingItem,
|
||||
Location dispLocation, Sound uniqueSound)
|
||||
{
|
||||
|
||||
cauldron.setBlockData(cauldronType);
|
||||
dispensingItem.setType(Material.BUCKET);
|
||||
dispLocation.getWorld().playSound(dispLocation, Sound.BLOCK_DISPENSER_DISPENSE, SoundCategory.BLOCKS, 1, 1);
|
||||
dispLocation.getWorld().playSound(dispLocation, uniqueSound, SoundCategory.BLOCKS, 1, 1);
|
||||
|
||||
}
|
||||
|
||||
private void fullCauldronHandler(Block cauldron, ItemStack items, org.bukkit.block.Dispenser dispenserBlock,
|
||||
Material newItem, Sound uniqueSound)
|
||||
{
|
||||
|
||||
cauldron.setType(Material.CAULDRON);
|
||||
Inventory inv = dispenserBlock.getInventory();
|
||||
ItemStack newItemDrop = new ItemStack(newItem);
|
||||
|
||||
// handling for stacked buckets
|
||||
if (items.getAmount() > 1) {
|
||||
|
||||
items.setAmount(items.getAmount() - 1);
|
||||
Map<Integer, ItemStack> map = inv.addItem(newItemDrop);
|
||||
if (!map.isEmpty()) {
|
||||
|
||||
cauldron.getWorld().dropItem(cauldron.getLocation(), newItemDrop);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
items.setType(newItem);
|
||||
|
||||
}
|
||||
|
||||
dispenserBlock.getWorld().playSound(dispenserBlock.getLocation(), Sound.BLOCK_DISPENSER_DISPENSE,
|
||||
SoundCategory.BLOCKS, 1, 1);
|
||||
dispenserBlock.getWorld().playSound(dispenserBlock.getLocation(), uniqueSound, SoundCategory.BLOCKS, 1, 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextReplacementConfig;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Allows players to send a message with a slash at the start by escaping it
|
||||
* with backslash (\/command that will appear as /command in chat).
|
||||
*/
|
||||
public class EscapeCommandSlashModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected EscapeCommandSlashModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.chat.escape-commands", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onCommandEscape(AsyncChatEvent event) {
|
||||
|
||||
String message = PlainTextComponentSerializer.plainText().serialize(event.message());
|
||||
String[] messageSplit = message.split(" ");
|
||||
String command = messageSplit[0].substring(1);
|
||||
Component component = event.message()
|
||||
.replaceText(TextReplacementConfig.builder().match("(\\\\/\\S*)").replacement(command).once().build());
|
||||
event.message(component);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import io.papermc.paper.event.entity.EntityMoveEvent;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Steerable;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
import org.spigotmc.event.entity.EntityMountEvent;
|
||||
|
||||
/**
|
||||
* If enabled, only nametagged mobs can be mounted/steered using purpur's
|
||||
* rideable option.
|
||||
*/
|
||||
public class ForceNametaggedForRidingModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected ForceNametaggedForRidingModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.rideables.mob-needs-to-be-nametagged-to-ride",
|
||||
false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onMount(EntityMountEvent event) {
|
||||
|
||||
Entity entity = event.getMount();
|
||||
|
||||
// if pig or strider with a saddle, ignore
|
||||
if (entity instanceof Steerable steerable && steerable.hasSaddle())
|
||||
return;
|
||||
|
||||
// if mountable in vanilla, ignore
|
||||
if (entity instanceof Vehicle && (!(entity instanceof Steerable)))
|
||||
return;
|
||||
|
||||
// if player, ignore
|
||||
if (entity.getType().equals(EntityType.PLAYER))
|
||||
return;
|
||||
|
||||
// if has nametag, ignore
|
||||
if (entity.customName() != null)
|
||||
return;
|
||||
|
||||
// otherwise don't allow mounting
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onMountMove(EntityMoveEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Vehicle vehicle))
|
||||
return;
|
||||
if (vehicle.getPassengers().isEmpty())
|
||||
return;
|
||||
Entity passenger = vehicle.getPassengers().get(0);
|
||||
if (!(passenger instanceof Player player))
|
||||
return;
|
||||
if (vehicle.customName() != null && player.hasPermission("allow.ride." + vehicle.getType().getKey().getKey()))
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.FurnaceBurnEvent;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, multiplier field will be used to modify fuel burn time in
|
||||
* furnaces.
|
||||
*/
|
||||
public class FurnaceBurnTimeModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final double furnaceBurnTimeMultiplier;
|
||||
|
||||
protected FurnaceBurnTimeModule() {
|
||||
|
||||
furnaceBurnTimeMultiplier = PurpurExtrasOG.getPurpurConfig().getDouble("settings.furnace.burn-time.multiplier",
|
||||
1.0);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
if (!PurpurExtrasOG.getPurpurConfig().getBoolean("settings.furnace.burn-time.enabled", false))
|
||||
return false;
|
||||
return furnaceBurnTimeMultiplier != 1.0;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onFurnaceBurn(FurnaceBurnEvent event) {
|
||||
|
||||
int burnTime = event.getBurnTime();
|
||||
event.setBurnTime((int) (burnTime * furnaceBurnTimeMultiplier));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+77
-14
@@ -1,5 +1,6 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.Map;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -14,43 +15,97 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.purpurmc.purpur.event.inventory.GrindstoneTakeResultEvent;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
import java.util.Map;
|
||||
/**
|
||||
* If enabled and player has books in their inventory while disenchanting item
|
||||
* in a grindstone, books will be consumed to return the enchantments removed
|
||||
* from the item to the player. No exp will drop when doing this.
|
||||
* <p>
|
||||
* Listeners yoinked from <a href=
|
||||
* "https://gist.github.com/BillyGalbreath/de0f899a27b39daad5f5bf7c00e11045">here</a>}
|
||||
*/
|
||||
public class GrindstoneEnchantsBooksModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
// Yoinked from https://gist.github.com/BillyGalbreath/de0f899a27b39daad5f5bf7c00e11045
|
||||
public class GrindstoneEnchantsBooksListener implements Listener {
|
||||
private final ItemStack BOOK = new ItemStack(Material.BOOK);
|
||||
|
||||
public static final ItemStack BOOK = new ItemStack(Material.BOOK);
|
||||
protected GrindstoneEnchantsBooksModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
try {
|
||||
|
||||
Class.forName("org.purpurmc.purpur.event.inventory.GrindstoneTakeResultEvent");
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
||||
PurpurExtrasOG.getInstance().getLogger().warning(
|
||||
this.getClass().getSimpleName() + " module requires you to run Purpur as your server software.");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.grindstone.gives-enchants-back", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(GrindstoneTakeResultEvent event) {
|
||||
|
||||
GrindstoneInventory grindstoneInventory = event.getInventory();
|
||||
|
||||
ItemStack lowerItem = grindstoneInventory.getLowerItem();
|
||||
if (lowerItem != null && !lowerItem.getType().isEmpty()) {
|
||||
|
||||
return; // lower slot is not empty, do nothing
|
||||
|
||||
}
|
||||
|
||||
ItemStack upperItem = grindstoneInventory.getUpperItem();
|
||||
if (upperItem == null || upperItem.getType().isEmpty()) {
|
||||
|
||||
return; // upper slot is empty, do nothing
|
||||
|
||||
}
|
||||
|
||||
Map<Enchantment, Integer> enchants;
|
||||
if (upperItem.getType() == Material.ENCHANTED_BOOK) {
|
||||
|
||||
if (!upperItem.hasItemMeta()) {
|
||||
return; // no enchants to extract
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
enchants = ((EnchantmentStorageMeta) upperItem.getItemMeta()).getStoredEnchants();
|
||||
|
||||
} else {
|
||||
|
||||
if (!upperItem.hasEnchants()) {
|
||||
return; // no enchants to extract
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
enchants = upperItem.getEnchants();
|
||||
|
||||
}
|
||||
|
||||
if (enchants.isEmpty()) {
|
||||
return; // no enchants to extract
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
@@ -59,36 +114,44 @@ public class GrindstoneEnchantsBooksListener implements Listener {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchants.entrySet()) {
|
||||
|
||||
if (entry.getKey().isCursed()) {
|
||||
|
||||
continue; // grindstones don't remove curses
|
||||
|
||||
}
|
||||
|
||||
if (player.getGameMode() != GameMode.CREATIVE) {
|
||||
|
||||
if (!playerInventory.containsAtLeast(BOOK, 1)) {
|
||||
|
||||
return; // no more books to extract to
|
||||
|
||||
}
|
||||
|
||||
if (!playerInventory.removeItem(BOOK).isEmpty()) {
|
||||
|
||||
return; // could not remove book
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// create enchanted book
|
||||
ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
|
||||
EnchantmentStorageMeta meta = (EnchantmentStorageMeta) book.getItemMeta();
|
||||
meta.addStoredEnchant(entry.getKey(), entry.getValue(), true);
|
||||
book.setItemMeta(meta);
|
||||
|
||||
// add enchanted book to player inventory
|
||||
playerInventory.addItem(book).forEach((index, stack) -> {
|
||||
// drop on ground if didn't fit in inventory
|
||||
|
||||
Item drop = world.dropItemNaturally(location, stack);
|
||||
drop.setPickupDelay(0);
|
||||
|
||||
});
|
||||
|
||||
event.setExperienceAmount(0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.bukkit.EntityEffect;
|
||||
import org.bukkit.Material;
|
||||
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.EntityDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, a totem of undying will save a player from death while it sits
|
||||
* anywhere in their hotbar, not only when held in the main hand or off hand.
|
||||
* Vanilla resurrection (totem in either hand) is left untouched; this module
|
||||
* only covers the remaining hotbar slots. Void deaths are intentionally ignored
|
||||
* because surviving them requires the teleport handled by
|
||||
* {@link VoidTotemModule}.
|
||||
*/
|
||||
public class HotbarTotemModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final Collection<PotionEffect> totemEffects = new ArrayList<>();
|
||||
|
||||
protected HotbarTotemModule() {
|
||||
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.REGENERATION, 20 * 45, 1));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 20 * 40, 0));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.ABSORPTION, 20 * 5, 1));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.totem.work-from-hotbar", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onLethalDamage(EntityDamageEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
// Void deaths are handled by VoidTotemModule, which teleports the player to
|
||||
// safety.
|
||||
if (event.getCause().equals(EntityDamageEvent.DamageCause.VOID))
|
||||
return;
|
||||
// Damage is survivable, let it through unchanged.
|
||||
if (player.getHealth() - event.getFinalDamage() > 0)
|
||||
return;
|
||||
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
// Vanilla already resurrects when a totem is held in either hand.
|
||||
if (inventory.getItemInMainHand().getType().equals(Material.TOTEM_OF_UNDYING)
|
||||
|| inventory.getItemInOffHand().getType().equals(Material.TOTEM_OF_UNDYING))
|
||||
return;
|
||||
|
||||
int slot = findHotbarTotemSlot(inventory);
|
||||
if (slot < 0)
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
consumeTotem(inventory, slot);
|
||||
applyTotemEffects(player);
|
||||
|
||||
}
|
||||
|
||||
private int findHotbarTotemSlot(PlayerInventory inventory) {
|
||||
|
||||
for (int slot = 0; slot <= 8; slot++) {
|
||||
|
||||
ItemStack item = inventory.getItem(slot);
|
||||
if (item != null && item.getType().equals(Material.TOTEM_OF_UNDYING))
|
||||
return slot;
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
private void consumeTotem(PlayerInventory inventory, int slot) {
|
||||
|
||||
ItemStack totem = inventory.getItem(slot);
|
||||
if (totem == null)
|
||||
return;
|
||||
int remaining = totem.getAmount() - 1;
|
||||
if (remaining <= 0) {
|
||||
|
||||
inventory.setItem(slot, null);
|
||||
|
||||
} else {
|
||||
|
||||
totem.setAmount(remaining);
|
||||
inventory.setItem(slot, totem);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void applyTotemEffects(Player player) {
|
||||
|
||||
player.setFallDistance(0);
|
||||
player.setHealth(1);
|
||||
player.playEffect(EntityEffect.TOTEM_RESURRECT);
|
||||
player.getActivePotionEffects().forEach(potionEffect -> player.removePotionEffect(potionEffect.getType()));
|
||||
player.addPotionEffects(this.totemEffects);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Right click when sneaking on an item frame with item inside of it will make
|
||||
* the item frame invisible. Requires purpurextras.invisibleframes permission.
|
||||
*/
|
||||
public class InvisibleItemFrameModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected InvisibleItemFrameModule() {
|
||||
|
||||
}
|
||||
|
||||
private final String invisFramePermission = "purpurextras.invisibleframes";
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
DefaultPermissions.registerPermission(invisFramePermission,
|
||||
"Allows player to shift-right-click an item frame to turn it invisible", PermissionDefault.OP);
|
||||
return PurpurExtrasOG.getPurpurConfig()
|
||||
.getBoolean("settings.blocks.shift-right-click-for-invisible-item-frames", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onItemFrameInteract(PlayerInteractEntityEvent event) {
|
||||
|
||||
if (event.getHand().equals(EquipmentSlot.OFF_HAND))
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (!player.isSneaking())
|
||||
return;
|
||||
|
||||
Entity entity = event.getRightClicked();
|
||||
if (!(entity instanceof ItemFrame itemFrame))
|
||||
return;
|
||||
if (itemFrame.getItem().getType().equals(Material.AIR))
|
||||
return;
|
||||
if (!player.hasPermission(invisFramePermission))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
itemFrame.setVisible(!itemFrame.isVisible());
|
||||
itemFrame.setFixed(!itemFrame.isFixed());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityUnleashEvent;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Adds a sound for when the leash snaps
|
||||
*/
|
||||
public class LeashSnapSoundModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private String sound;
|
||||
private double volume;
|
||||
private double pitch;
|
||||
|
||||
protected LeashSnapSoundModule() {
|
||||
|
||||
sound = PurpurExtrasOG.getPurpurConfig().getString("settings.leash-snap.sound", "minecraft:block.bamboo.break");
|
||||
volume = PurpurExtrasOG.getPurpurConfig().getDouble("settings.leash-snap.volume", 1f);
|
||||
pitch = PurpurExtrasOG.getPurpurConfig().getDouble("settings.leash-snap.pitch", 1.25f);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.leash-snap.enabled", false) && sound != null;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onLeashBreak(EntityUnleashEvent event) {
|
||||
|
||||
if (event.getReason() != EntityUnleashEvent.UnleashReason.DISTANCE)
|
||||
return;
|
||||
|
||||
event.getEntity().getWorld().playSound(event.getEntity().getLocation(), sound, SoundCategory.PLAYERS,
|
||||
(float) volume, (float) pitch);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityZapEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import me.youhavetrouble.entiddy.Entiddy;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
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.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, entities with type on the left will be transformed into entity of
|
||||
* type on the right. This overrides vanilla transformations. Vanilla mob ids
|
||||
* are used to identify mobs. There are also special cases:
|
||||
*
|
||||
* `killer_bunny` - a killer bunny `jeb_sheep` - rainbow sheep `johhny` -
|
||||
* vindicator aggressive to most mobs `toast` - special variant of rabbit
|
||||
*/
|
||||
public class LightningTransformsMobsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final HashMap<String, Object> entities = new HashMap<>();
|
||||
|
||||
protected LightningTransformsMobsModule() {
|
||||
|
||||
Map<String, Object> defaults = new HashMap<>();
|
||||
defaults.put("villager", "witch");
|
||||
defaults.put("pig", "zombie_piglin");
|
||||
ConfigurationSection section = PurpurExtrasOG.getPurpurConfig()
|
||||
.getConfigSection("settings.lightning-transforms-entities.entities", defaults);
|
||||
HashMap<String, String> lightningTransformEntities = new HashMap<>();
|
||||
for (String key : section.getKeys(false)) {
|
||||
|
||||
String value = section.getString(key);
|
||||
lightningTransformEntities.put(key, value);
|
||||
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : lightningTransformEntities.entrySet()) {
|
||||
|
||||
getEntityTypeOrSpecial(entry.getKey(), entry.getValue());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
if (entities.isEmpty())
|
||||
return false;
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.lightning-transforms-entities.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onLightningStrike(EntityDamageByEntityEvent event) {
|
||||
|
||||
if (!event.getDamager().getType().equals(EntityType.LIGHTNING))
|
||||
return;
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof LivingEntity livingEntity))
|
||||
return;
|
||||
if (entity.getEntitySpawnReason().equals(CreatureSpawnEvent.SpawnReason.LIGHTNING)) {
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Location location = entity.getLocation();
|
||||
Entiddy specialEntity = Entiddy.fromEntity(livingEntity);
|
||||
if (specialEntity != null) {
|
||||
|
||||
event.setCancelled(true);
|
||||
entity.remove();
|
||||
String specialEntityKey = specialEntity.entiddy().toString().toLowerCase(Locale.ROOT);
|
||||
Object targetEntity = entities.get(specialEntityKey);
|
||||
spawnEntity(targetEntity, location);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Object targetEntity = entities.get(entity.getType().getKey().getKey());
|
||||
if (targetEntity == null)
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
entity.remove();
|
||||
spawnEntity(targetEntity, location);
|
||||
|
||||
}
|
||||
|
||||
private void spawnEntity(Object entity, Location location) {
|
||||
|
||||
if (entity instanceof EntityType entityType) {
|
||||
|
||||
location.getWorld().spawnEntity(location, entityType, CreatureSpawnEvent.SpawnReason.LIGHTNING);
|
||||
|
||||
} else if (entity instanceof Entiddy entiddy) {
|
||||
|
||||
entiddy.entiddy().spawn(location, CreatureSpawnEvent.SpawnReason.LIGHTNING);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void getEntityTypeOrSpecial(String key, String value) {
|
||||
|
||||
String sourceKey = null;
|
||||
Object goal = null;
|
||||
for (EntityType entityType : EntityType.values()) {
|
||||
|
||||
if (!entityType.isSpawnable())
|
||||
continue;
|
||||
String entityKey = entityType.getKey().getKey();
|
||||
if (entityKey.equals(key.toLowerCase(Locale.ROOT))) {
|
||||
|
||||
sourceKey = key;
|
||||
|
||||
}
|
||||
|
||||
if (entityKey.equals(value.toLowerCase(Locale.ROOT))) {
|
||||
|
||||
goal = entityType;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sourceKey == null) {
|
||||
|
||||
try {
|
||||
|
||||
Entiddy.valueOf(key.toUpperCase(Locale.ROOT));
|
||||
sourceKey = key;
|
||||
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (goal == null) {
|
||||
|
||||
try {
|
||||
|
||||
goal = Entiddy.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
entities.put(sourceKey, goal);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onLightningStrike(EntityZapEvent event) {
|
||||
|
||||
if (event.getBolt().isEffect())
|
||||
return;
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof LivingEntity livingEntity))
|
||||
return;
|
||||
if (entity.getEntitySpawnReason().equals(CreatureSpawnEvent.SpawnReason.LIGHTNING)) {
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Location location = entity.getLocation();
|
||||
Entiddy specialEntity = Entiddy.fromEntity(livingEntity);
|
||||
if (specialEntity != null) {
|
||||
|
||||
event.setCancelled(true);
|
||||
entity.remove();
|
||||
String specialEntityKey = specialEntity.entiddy().toString().toLowerCase(Locale.ROOT);
|
||||
Object targetEntity = entities.get(specialEntityKey);
|
||||
spawnEntity(targetEntity, location);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Object targetEntity = entities.get(entity.getType().getKey().getKey());
|
||||
if (targetEntity == null) {
|
||||
|
||||
livingEntity.damage(5, event.getBolt());
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
entity.remove();
|
||||
spawnEntity(targetEntity, location);
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import com.destroystokyo.paper.MaterialSetTag;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.LoomInventory;
|
||||
import org.bukkit.inventory.meta.BannerMeta;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, banners will be able to use more than the limit of 6 layers. In
|
||||
* default config up to 6 banner layers are allowed.
|
||||
*/
|
||||
public class LoomMaxLayersModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final HashMap<Player, List<Pattern>> playerBannerData = new HashMap<>();
|
||||
private int maxLayers;
|
||||
|
||||
protected LoomMaxLayersModule() {
|
||||
|
||||
this.maxLayers = PurpurExtrasOG.getPurpurConfig().getInt("settings.loom.max-layers", 6);
|
||||
if (this.maxLayers <= 0)
|
||||
this.maxLayers = 6;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return this.maxLayers != 6;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
ItemStack currentItem = event.getCurrentItem();
|
||||
ItemStack cursorItem = event.getCursor();
|
||||
|
||||
if (!(event.getInventory() instanceof LoomInventory))
|
||||
return;
|
||||
if (currentItem != null && MaterialSetTag.BANNERS.isTagged(currentItem.getType())) {
|
||||
|
||||
if (doesNewLayerExceedMaxLayers(currentItem))
|
||||
return;
|
||||
switch (event.getSlotType()) {
|
||||
|
||||
case CRAFTING -> {
|
||||
|
||||
if (isPlaceAction(event.getAction())) {
|
||||
|
||||
saveBannerLayers(player, currentItem);
|
||||
|
||||
} else {
|
||||
|
||||
setOldPatternsToBanner(player, currentItem);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
case CONTAINER, QUICKBAR -> {
|
||||
|
||||
if (event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
|
||||
|
||||
saveBannerLayers(player, currentItem);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
case RESULT -> setNewPatternsToBanner(player, currentItem);
|
||||
default -> throw new IllegalArgumentException(
|
||||
"Unexpected value in LoomMaxLayersModule: " + event.getSlotType());
|
||||
|
||||
}
|
||||
|
||||
} else if (cursorItem != null && MaterialSetTag.BANNERS.isTagged(cursorItem.getType())) {
|
||||
|
||||
if (doesNewLayerExceedMaxLayers(cursorItem))
|
||||
return;
|
||||
if (event.getSlotType().equals(InventoryType.SlotType.CRAFTING) && isPlaceAction(event.getAction())) {
|
||||
|
||||
saveBannerLayers(player, cursorItem);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isPlaceAction(InventoryAction action) {
|
||||
|
||||
return action == InventoryAction.PLACE_SOME || action == InventoryAction.PLACE_ALL
|
||||
|| action == InventoryAction.PLACE_ONE;
|
||||
|
||||
}
|
||||
|
||||
private void saveBannerLayers(Player player, ItemStack banner) {
|
||||
|
||||
BannerMeta meta = (BannerMeta) banner.getItemMeta();
|
||||
List<Pattern> patterns = meta.getPatterns();
|
||||
if (patterns.size() <= 5)
|
||||
return;
|
||||
playerBannerData.remove(player);
|
||||
playerBannerData.put(player, patterns);
|
||||
removeExtraLayersFromBanner(banner);
|
||||
|
||||
}
|
||||
|
||||
private void removeExtraLayersFromBanner(ItemStack banner) {
|
||||
|
||||
BannerMeta meta = (BannerMeta) banner.getItemMeta();
|
||||
List<Pattern> patterns = meta.getPatterns();
|
||||
|
||||
while (patterns.size() > 5)
|
||||
patterns.remove(0);
|
||||
meta.setPatterns(patterns);
|
||||
banner.setItemMeta(meta);
|
||||
|
||||
}
|
||||
|
||||
private void setOldPatternsToBanner(Player player, ItemStack banner) {
|
||||
|
||||
if (!playerBannerData.containsKey(player))
|
||||
return;
|
||||
List<Pattern> oldPatterns = playerBannerData.get(player);
|
||||
BannerMeta meta = (BannerMeta) banner.getItemMeta();
|
||||
|
||||
meta.setPatterns(oldPatterns);
|
||||
banner.setItemMeta(meta);
|
||||
playerBannerData.remove(player);
|
||||
|
||||
}
|
||||
|
||||
private void setNewPatternsToBanner(Player player, ItemStack banner) {
|
||||
|
||||
if (!playerBannerData.containsKey(player))
|
||||
return;
|
||||
List<Pattern> oldPatterns = playerBannerData.get(player);
|
||||
BannerMeta meta = (BannerMeta) banner.getItemMeta();
|
||||
|
||||
List<Pattern> newPatterns = meta.getPatterns();
|
||||
oldPatterns.add(newPatterns.get(newPatterns.size() - 1));
|
||||
|
||||
meta.setPatterns(oldPatterns);
|
||||
banner.setItemMeta(meta);
|
||||
playerBannerData.remove(player);
|
||||
|
||||
}
|
||||
|
||||
private boolean doesNewLayerExceedMaxLayers(ItemStack banner) {
|
||||
|
||||
BannerMeta meta = (BannerMeta) banner.getItemMeta();
|
||||
List<Pattern> patterns = meta.getPatterns();
|
||||
return patterns.size() == maxLayers;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.DecoratedPot;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.loot.Lootable;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
import org.purpurmc.purpurextras.util.MessageType;
|
||||
|
||||
/**
|
||||
* Prevents players from breaking blocks with loot tables that can regenerate
|
||||
* loot.
|
||||
*/
|
||||
public class LootBlocksProtectionModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final Component message;
|
||||
private MessageType messageType;
|
||||
private final boolean allowBreakingInSneak;
|
||||
private final boolean blocksImmuneToExplosions;
|
||||
|
||||
private final String permission = "purpurextras.lootblockprotectionbypass";
|
||||
|
||||
protected LootBlocksProtectionModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
|
||||
DefaultPermissions.registerPermission(permission,
|
||||
"Players with this permission will be able to break blocks with loot tables that can regenerate loot",
|
||||
PermissionDefault.OP);
|
||||
|
||||
String defaultMessage = "<red>Prevented you from breaking this block because it can regenerate loot. Sneak to break it anyway.";
|
||||
message = MiniMessage.miniMessage()
|
||||
.deserialize(config.getString("settings.protect-blocks-with-loot.message", defaultMessage));
|
||||
allowBreakingInSneak = config.getBoolean("settings.protect-blocks-with-loot.allow-breaking-in-sneak", true);
|
||||
blocksImmuneToExplosions = config.getBoolean("settings.protect-blocks-with-loot.immune-to-explosions", false);
|
||||
try {
|
||||
|
||||
messageType = MessageType
|
||||
.valueOf(config.getString("settings.protect-blocks-with-loot.message-type", "CHAT").toUpperCase());
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
messageType = MessageType.CHAT;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.protect-blocks-with-loot.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onDestroyBlockWithLoot(BlockBreakEvent event) {
|
||||
|
||||
// decorated pots are only lootable by breaking them
|
||||
if (isProtected(event.getBlock().getState(true))) {
|
||||
|
||||
handleLootBlockDestruction(event);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onExplodingBlockWithLoot(EntityExplodeEvent event) {
|
||||
|
||||
if (!blocksImmuneToExplosions)
|
||||
return;
|
||||
event.blockList().removeIf(block -> isProtected(block.getState(true)));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onExplodingBlockWithLoot(BlockExplodeEvent event) {
|
||||
|
||||
if (!blocksImmuneToExplosions)
|
||||
return;
|
||||
event.blockList().removeIf(block -> isProtected(block.getState(true)));
|
||||
|
||||
}
|
||||
|
||||
private void handleLootBlockDestruction(BlockBreakEvent event) {
|
||||
|
||||
if (event.getPlayer().hasPermission(permission))
|
||||
return;
|
||||
if (allowBreakingInSneak && event.getPlayer().isSneaking())
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
switch (messageType) {
|
||||
|
||||
case CHAT -> event.getPlayer().sendMessage(message);
|
||||
case ACTION_BAR -> event.getPlayer().sendActionBar(message);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isProtected(BlockState blockState) {
|
||||
|
||||
if (blockState instanceof DecoratedPot)
|
||||
return false;
|
||||
if (blockState instanceof Lootable lootable) {
|
||||
|
||||
return lootable.hasLootTable();
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
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.EntityTargetEvent;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, players having target.bypass.<mojang_mob_name> permission won't
|
||||
* be targetted by that type of mob.
|
||||
*/
|
||||
public class MobNoTargetModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected MobNoTargetModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.use-notarget-permissions", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onMobTarget(EntityTargetEvent event) {
|
||||
|
||||
if (!(event.getTarget() instanceof Player player))
|
||||
return;
|
||||
if (!player.hasPermission("target.bypass." + event.getEntityType().getKey().getKey()))
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Adds a build height limit to the nether Configuration:
|
||||
*
|
||||
* **enabled** Enables the feature.
|
||||
*
|
||||
* **height-limit** Maximum height players without
|
||||
* purpurextras.netherbuildheightbypass permission can build in nether worlds.
|
||||
*
|
||||
* **no-permission-message** Message to display in action bar when trying to
|
||||
* build above set limit in nether worlds.
|
||||
*/
|
||||
public class NetherBuildHeightModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final int configBuildHeight;
|
||||
private final String noPermissionMessageContent;
|
||||
private final String netherBuildHeightBypassPermission = "purpurextras.netherbuildheightbypass";
|
||||
|
||||
protected NetherBuildHeightModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
this.configBuildHeight = config.getInt("settings.block-building-above-nether.height-limit", 128);
|
||||
this.noPermissionMessageContent = config.getString("settings.block-building-above-nether.no-permission-message",
|
||||
"<red>Max build height in this world is: <gold><height>");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
DefaultPermissions.registerPermission(netherBuildHeightBypassPermission,
|
||||
"Allows player to bypass the configured max nether build height", PermissionDefault.OP);
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.block-building-above-nether.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onNetherRoofBuild(BlockPlaceEvent event) {
|
||||
|
||||
Block block = event.getBlock();
|
||||
Player player = event.getPlayer();
|
||||
if (!(block.getWorld().getEnvironment().equals(World.Environment.NETHER)))
|
||||
return;
|
||||
if (block.getLocation().getBlockY() < configBuildHeight)
|
||||
return;
|
||||
if (player.hasPermission(netherBuildHeightBypassPermission))
|
||||
return;
|
||||
if (!"".equals(noPermissionMessageContent)) {
|
||||
|
||||
player.sendActionBar(PurpurExtrasOG.getInstance().miniMessage.deserialize(noPermissionMessageContent,
|
||||
Placeholder.unparsed("height", String.valueOf(configBuildHeight))));
|
||||
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
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;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Toggles if entities with jump boost effect will take fall damage
|
||||
*/
|
||||
public class NoFallDamageWhileHavingJumpBoostModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected NoFallDamageWhileHavingJumpBoostModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return !PurpurExtrasOG.getPurpurConfig()
|
||||
.getBoolean("settings.gameplay-settings.fall-damage-when-jump-boost-applied", true);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onFallDamage(EntityDamageEvent event) {
|
||||
|
||||
if (!EntityDamageEvent.DamageCause.FALL.equals(event.getCause()))
|
||||
return;
|
||||
if (!(event.getEntity() instanceof LivingEntity livingEntity))
|
||||
return;
|
||||
if (!livingEntity.hasPotionEffect(PotionEffectType.JUMP))
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.*;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.Scanners;
|
||||
|
||||
public interface PurpurExtrasModule {
|
||||
|
||||
Reflections reflections = new Reflections("org.purpurmc.purpurextras.modules");
|
||||
|
||||
/**
|
||||
* Enables the feature, registers the listeners.
|
||||
*/
|
||||
void enable();
|
||||
|
||||
/**
|
||||
* @return true if the feature should be enabled
|
||||
*/
|
||||
boolean shouldEnable();
|
||||
|
||||
static void reloadModules() {
|
||||
|
||||
HandlerList.unregisterAll(PurpurExtrasOG.getInstance());
|
||||
|
||||
Set<Class<?>> subTypes = reflections.get(Scanners.SubTypes.of(PurpurExtrasModule.class).asClass());
|
||||
|
||||
subTypes.forEach(clazz -> {
|
||||
|
||||
try {
|
||||
|
||||
PurpurExtrasModule module = (PurpurExtrasModule) clazz.getDeclaredConstructor().newInstance();
|
||||
if (module.shouldEnable()) {
|
||||
|
||||
module.enable();
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
PurpurExtrasOG.getInstance().getSLF4JLogger().warn("Failed to load module " + clazz.getSimpleName());
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SplittableRandom;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Raider;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.raid.RaidSpawnWaveEvent;
|
||||
import org.bukkit.event.raid.RaidStopEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Modifies the drop rate of totems from Evokers spawned in a raid
|
||||
*/
|
||||
public class RaidTotemDropsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final SplittableRandom random;
|
||||
private final int dropChance;
|
||||
private final Map<UUID, Raider> raiders = new HashMap<>();
|
||||
|
||||
protected RaidTotemDropsModule() {
|
||||
|
||||
dropChance = PurpurExtrasOG.getPurpurConfig().getInt("settings.raid-totem-drops.chance", 0);
|
||||
random = new SplittableRandom();
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
|
||||
public void onRaidSpawn(RaidSpawnWaveEvent event) {
|
||||
|
||||
event.getRaiders().forEach(r -> raiders.put(r.getUniqueId(), r));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
|
||||
public void onRaidDeath(EntityDeathEvent event) {
|
||||
|
||||
if (raiders.get(event.getEntity().getUniqueId()) == null)
|
||||
return;
|
||||
raiders.remove(event.getEntity().getUniqueId());
|
||||
if (event.getEntityType() != EntityType.EVOKER)
|
||||
return;
|
||||
boolean totem = dropChance >= 100 || random.nextInt(1, 101) <= dropChance;
|
||||
event.getDrops().stream().filter(i -> i.getType() == Material.TOTEM_OF_UNDYING).findFirst()
|
||||
.ifPresentOrElse(i ->
|
||||
{
|
||||
|
||||
if (!totem)
|
||||
event.getDrops().remove(i);
|
||||
|
||||
}, () -> {
|
||||
|
||||
if (totem)
|
||||
event.getDrops().add(new ItemStack(Material.TOTEM_OF_UNDYING));
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
|
||||
public void onRaidEnd(RaidStopEvent event) {
|
||||
|
||||
event.getRaid().getRaiders().stream().map(Entity::getUniqueId).forEach(raiders::remove);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
Bukkit.getServer().getPluginManager().registerEvents(this, PurpurExtrasOG.getInstance());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.raid-totem-drops.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Sheep;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockShearEntityEvent;
|
||||
import org.bukkit.event.player.PlayerShearEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled causes sheep named jeb_ to drop random colors of wool
|
||||
*/
|
||||
public class RandomColorJebSheepShearModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final List<Material> coloredWool = new ArrayList<>();
|
||||
|
||||
protected RandomColorJebSheepShearModule() {
|
||||
|
||||
this.coloredWool.add(Material.BLACK_WOOL);
|
||||
this.coloredWool.add(Material.BLUE_WOOL);
|
||||
this.coloredWool.add(Material.BROWN_WOOL);
|
||||
this.coloredWool.add(Material.CYAN_WOOL);
|
||||
this.coloredWool.add(Material.GRAY_WOOL);
|
||||
this.coloredWool.add(Material.GREEN_WOOL);
|
||||
this.coloredWool.add(Material.LIGHT_BLUE_WOOL);
|
||||
this.coloredWool.add(Material.LIGHT_GRAY_WOOL);
|
||||
this.coloredWool.add(Material.LIME_WOOL);
|
||||
this.coloredWool.add(Material.MAGENTA_WOOL);
|
||||
this.coloredWool.add(Material.ORANGE_WOOL);
|
||||
this.coloredWool.add(Material.PINK_WOOL);
|
||||
this.coloredWool.add(Material.PURPLE_WOOL);
|
||||
this.coloredWool.add(Material.RED_WOOL);
|
||||
this.coloredWool.add(Material.WHITE_WOOL);
|
||||
this.coloredWool.add(Material.YELLOW_WOOL);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.mobs.sheep.jeb-shear-random-color", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onJebSheepShear(PlayerShearEntityEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Sheep sheep))
|
||||
return;
|
||||
if (!isJebSheep(sheep))
|
||||
return;
|
||||
|
||||
// Remove default drops
|
||||
event.setCancelled(true);
|
||||
|
||||
// Add custom drops
|
||||
int randomIndex = new Random().nextInt(coloredWool.size());
|
||||
ItemStack customWool = new ItemStack(coloredWool.get(randomIndex));
|
||||
event.getEntity().getWorld().dropItemNaturally(event.getEntity().getLocation(), customWool);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onJebSheepShear(BlockShearEntityEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Sheep sheep))
|
||||
return;
|
||||
if (!isJebSheep(sheep))
|
||||
return;
|
||||
|
||||
// Remove default drops
|
||||
event.setCancelled(true);
|
||||
|
||||
// Add custom drops
|
||||
int randomIndex = new Random().nextInt(coloredWool.size());
|
||||
ItemStack customWool = new ItemStack(coloredWool.get(randomIndex));
|
||||
event.getEntity().getWorld().dropItemNaturally(event.getEntity().getLocation(), customWool);
|
||||
|
||||
}
|
||||
|
||||
// Helper method to check if the sheep is a Jeb Sheep.
|
||||
private boolean isJebSheep(Sheep sheep) {
|
||||
|
||||
Component customName = sheep.customName();
|
||||
if (customName != null) {
|
||||
|
||||
String name = PlainTextComponentSerializer.plainText().serialize(customName);
|
||||
return "jeb_".equals(name);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+39
-4
@@ -1,6 +1,5 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import me.youhavetrouble.purpurextras.PurpurExtras;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -12,41 +11,77 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
public class RespawnAnchorNeedsChargeListener implements Listener {
|
||||
/**
|
||||
* If false, will make it so respawn anchors will never run out of charges.
|
||||
*/
|
||||
public class RespawnAnchorNeedsChargeModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected RespawnAnchorNeedsChargeModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return !(PurpurExtrasOG.getPurpurConfig().getBoolean("settings.gameplay-settings.respawn-anchor-needs-charges",
|
||||
true));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
|
||||
if (!event.isAnchorSpawn())
|
||||
return;
|
||||
Block block = event.getRespawnLocation().getBlock();
|
||||
BoundingBox box = BoundingBox.of(block.getLocation(), 2, 2, 2);
|
||||
for (int y = (int) box.getMinY(); y < box.getMaxY(); y++) {
|
||||
|
||||
for (int x = (int) box.getMinX(); x < box.getMaxX(); x++) {
|
||||
|
||||
for (int z = (int) box.getMinZ(); z < box.getMaxZ(); z++) {
|
||||
|
||||
Location location = new Location(event.getRespawnLocation().getWorld(), x, y, z);
|
||||
if (!location.getBlock().getType().equals(Material.RESPAWN_ANCHOR))
|
||||
continue;
|
||||
Block potentialAnchor = location.getBlock();
|
||||
Bukkit.getScheduler().runTaskLater(PurpurExtras.getInstance(), () -> {
|
||||
Bukkit.getScheduler().runTaskLater(PurpurExtrasOG.getInstance(), () -> {
|
||||
|
||||
if (!potentialAnchor.getType().equals(Material.RESPAWN_ANCHOR))
|
||||
return;
|
||||
RespawnAnchor anchor = (RespawnAnchor) potentialAnchor.getBlockData();
|
||||
anchor.setCharges(anchor.getMaximumCharges());
|
||||
potentialAnchor.setBlockData(anchor);
|
||||
|
||||
}, 2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerPlaceAnchor(BlockPlaceEvent event) {
|
||||
|
||||
if (!event.getBlockPlaced().getType().equals(Material.RESPAWN_ANCHOR))
|
||||
return;
|
||||
RespawnAnchor anchor = (RespawnAnchor) event.getBlockPlaced().getBlockData();
|
||||
anchor.setCharges(anchor.getMaximumCharges());
|
||||
event.getBlockPlaced().setBlockData(anchor);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If speed-multiplier value is higher than 0, player will gain speed potion
|
||||
* effect of the level of that value. This only accepts integer values. Which
|
||||
* blocks count as paths can be configured by listing them in path-blocks list.
|
||||
*/
|
||||
public class RunFasterOnPathsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final HashSet<Material> pathBlocks = new HashSet<>();
|
||||
private final int speedMultiplier;
|
||||
|
||||
private final PotionEffect speedEffect;
|
||||
|
||||
protected RunFasterOnPathsModule() {
|
||||
|
||||
List<String> defaults = new ArrayList<>();
|
||||
defaults.add(Material.DIRT_PATH.toString());
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
Logger logger = PurpurExtrasOG.getInstance().getLogger();
|
||||
|
||||
int rawSpeedMultiplier = config.getInt("settings.gameplay-settings.run-faster-on-paths.speed-multiplier", 0);
|
||||
speedMultiplier = Math.max(0, rawSpeedMultiplier);
|
||||
int duration = config.getInt("settings.gameplay-settings.run-faster-on-paths.duration", 2);
|
||||
|
||||
speedEffect = new PotionEffect(PotionEffectType.SPEED, duration, Math.max(speedMultiplier - 1, 0), false, false,
|
||||
false);
|
||||
|
||||
List<String> rawPathBlocks = config.getList("settings.gameplay-settings.run-faster-on-paths.path-blocks",
|
||||
defaults);
|
||||
rawPathBlocks.forEach((string) -> {
|
||||
|
||||
Material material = Material.getMaterial(string.toUpperCase(Locale.ENGLISH));
|
||||
if (material == null) {
|
||||
|
||||
logger.warning(string + " is not a valid block material.");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
pathBlocks.add(material);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return speedMultiplier > 0;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
|
||||
public void onPlayerMoveOnPath(PlayerMoveEvent event) {
|
||||
|
||||
if (!event.hasChangedPosition())
|
||||
return;
|
||||
Player player = event.getPlayer();
|
||||
if (player.isFlying())
|
||||
return;
|
||||
if (player.isGliding())
|
||||
return;
|
||||
if (player.isInsideVehicle())
|
||||
return;
|
||||
|
||||
Block block = player.getLocation().clone().subtract(0.0, 0.1, 0.0).getBlock();
|
||||
if (!pathBlocks.contains(block.getType()))
|
||||
return;
|
||||
|
||||
player.addPotionEffect(speedEffect);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.event.Listener;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
import org.purpurmc.purpurextras.modules.listeners.ShieldCooldownListener;
|
||||
import org.purpurmc.purpurextras.modules.listeners.ShieldDamageReductionListener;
|
||||
|
||||
/**
|
||||
* Shield configurations {@link ShieldCooldownListener} - Amount of ticks
|
||||
* (1/20th of a second) of cooldown for a shield after hitting it with an axe
|
||||
* crit. By default this is 100 ticks (5 seconds).
|
||||
*
|
||||
* {@link ShieldDamageReductionListener} - Value between 0 and 1. This is the
|
||||
* percentage of damage reduction that defending with a shield will provide. By
|
||||
* default shield reduces 100% of the damage (1.0).
|
||||
*/
|
||||
public class ShieldSettingsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private static final double DEFAULT_SHIELD_DAMAGE_REDUCTION = 1.0;
|
||||
private static final int DEFAULT_SHIELD_COOLDOWN = 5 * 20;
|
||||
|
||||
private double shieldDamageReduction = DEFAULT_SHIELD_DAMAGE_REDUCTION;
|
||||
private int shieldCooldown = DEFAULT_SHIELD_COOLDOWN;
|
||||
|
||||
protected ShieldSettingsModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
// OldCombatMechanics owns shield reduction when present,
|
||||
// else both scale blocking and compound. Presence, not
|
||||
// enabled state, since OCM may enable after this module.
|
||||
boolean ocmOwnsShields = plugin.getServer().getPluginManager().getPlugin("OldCombatMechanics") != null;
|
||||
|
||||
if (shieldDamageReduction != DEFAULT_SHIELD_DAMAGE_REDUCTION && !ocmOwnsShields) {
|
||||
|
||||
plugin.getServer().getPluginManager()
|
||||
.registerEvents(new ShieldDamageReductionListener(shieldDamageReduction), plugin);
|
||||
|
||||
} else if (shieldDamageReduction != DEFAULT_SHIELD_DAMAGE_REDUCTION) {
|
||||
|
||||
plugin.getLogger().info("Skipping shield damage reduction: OldCombatMechanics owns it.");
|
||||
|
||||
}
|
||||
|
||||
if (shieldCooldown != DEFAULT_SHIELD_COOLDOWN) {
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(new ShieldCooldownListener(shieldCooldown), plugin);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
shieldDamageReduction = PurpurExtrasOG.getPurpurConfig().getDouble("settings.shield.damage-reduction",
|
||||
shieldDamageReduction);
|
||||
shieldDamageReduction = Math.min(1.0, Math.max(0, shieldDamageReduction));
|
||||
|
||||
shieldCooldown = PurpurExtrasOG.getPurpurConfig().getInt("settings.shield.cooldown", shieldCooldown);
|
||||
shieldCooldown = Math.max(0, shieldCooldown);
|
||||
|
||||
return shieldDamageReduction != DEFAULT_SHIELD_DAMAGE_REDUCTION || shieldCooldown != DEFAULT_SHIELD_COOLDOWN;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import io.papermc.paper.event.player.PlayerDeepSleepEvent;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.TimeSkipEvent;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, sends messages in chat containing amount of players required to
|
||||
* sleep based on playersSleepingPercentage gamerule.
|
||||
*/
|
||||
public class SleepPercentageMessageModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final MiniMessage miniMsg = PurpurExtrasOG.getInstance().miniMessage;
|
||||
private final String playerSleepMessage, nightSkipMessage;
|
||||
private final String sleepMessageBypass = "purpurextras.sleepmessagebypass";
|
||||
|
||||
protected SleepPercentageMessageModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
this.playerSleepMessage = config.getString("settings.chat.send-sleep-percentage-message.player-sleeping",
|
||||
"<grey><playername> has fallen asleep. <sleeping> out of <needed> required players in <worldname> are sleeping.");
|
||||
this.nightSkipMessage = config.getString("settings.chat.send-sleep-percentage-message.skipping-night",
|
||||
"<grey>Enough players have slept! Skipping through the night in <worldname>.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
DefaultPermissions.registerPermission(sleepMessageBypass,
|
||||
"Allows player to not display a message in chat when they sleep", PermissionDefault.OP);
|
||||
if ((playerSleepMessage == null || playerSleepMessage.isBlank())
|
||||
&& (nightSkipMessage == null || nightSkipMessage.isBlank()))
|
||||
return false;
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.chat.send-sleep-percentage-message.enabled",
|
||||
false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerDeepSleep(PlayerDeepSleepEvent event) {
|
||||
|
||||
if (playerSleepMessage == null || playerSleepMessage.isBlank())
|
||||
return;
|
||||
if (event.getPlayer().hasPermission(sleepMessageBypass))
|
||||
return;
|
||||
World world = event.getPlayer().getWorld();
|
||||
List<Player> playerList = world.getPlayers();
|
||||
String playerName = event.getPlayer().getName();
|
||||
String worldName = world.getName();
|
||||
int currentSleepCount = 0;
|
||||
int worldOnlineTotal = playerList.size();
|
||||
Integer worldSleepPercent = world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE);
|
||||
Integer neededSleepers = (int) Math.ceil((worldSleepPercent / 100.0) * worldOnlineTotal);
|
||||
for (Player player : playerList) {
|
||||
|
||||
if (player.isDeeplySleeping())
|
||||
currentSleepCount += 1;
|
||||
|
||||
}
|
||||
|
||||
world.sendMessage(miniMsg.deserialize(playerSleepMessage, Placeholder.unparsed("playername", playerName),
|
||||
Placeholder.unparsed("sleeping", String.valueOf(currentSleepCount)),
|
||||
Placeholder.unparsed("needed", String.valueOf(neededSleepers)),
|
||||
Placeholder.unparsed("worldname", worldName)));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void nightSkip(TimeSkipEvent event) {
|
||||
|
||||
if (!event.getSkipReason().equals(TimeSkipEvent.SkipReason.NIGHT_SKIP))
|
||||
return;
|
||||
if (nightSkipMessage == null || nightSkipMessage.isBlank())
|
||||
return;
|
||||
String worldName = event.getWorld().getName();
|
||||
event.getWorld()
|
||||
.sendMessage(miniMsg.deserialize(nightSkipMessage, Placeholder.unparsed("worldname", worldName)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import org.bukkit.entity.Snowman;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockShearEntityEvent;
|
||||
import org.bukkit.event.player.PlayerShearEntityEvent;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* A module that disables the dropping of pumpkins when a Snow Golem is sheared.
|
||||
*/
|
||||
public class SnowGolemShearDropsPumpkinModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return !PurpurExtrasOG.getPurpurConfig().getBoolean("settings.mobs.snow_golem.drop-pumpkin-when-sheared", true);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onSnowGolemShear(PlayerShearEntityEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Snowman snowman))
|
||||
return;
|
||||
if (snowman.isDerp())
|
||||
return;
|
||||
|
||||
// Remove default drops.
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onSnowGolemShear(BlockShearEntityEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Snowman snowman))
|
||||
return;
|
||||
if (snowman.isDerp())
|
||||
return;
|
||||
|
||||
// Remove default drops.
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import static org.bukkit.util.permissions.DefaultPermissions.registerPermission;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Players will need purpurextras.spawnerplace.<mobtype> permission to place
|
||||
* spawners of that mob.
|
||||
*/
|
||||
public class SpawnerPlacementPermissionsModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
protected SpawnerPlacementPermissionsModule() {
|
||||
|
||||
}
|
||||
|
||||
private final String spawnerPlacePermission = "purpurextras.spawnerplace";
|
||||
private final Map<String, Boolean> mobSpawners = new HashMap<String, Boolean>();
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
for (EntityType type : EntityType.values()) {
|
||||
|
||||
if (type.isAlive() && type.isSpawnable()) {
|
||||
|
||||
String entityPermission = "." + type.toString().toLowerCase(Locale.ENGLISH);
|
||||
mobSpawners.put((spawnerPlacePermission + entityPermission), true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registerPermission(spawnerPlacePermission, "Allows player to place spawner", PermissionDefault.OP, mobSpawners);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig()
|
||||
.getBoolean("settings.gameplay-settings.spawner-placement-requires-specific-permission", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onSpawnerPlace(BlockPlaceEvent event) {
|
||||
|
||||
Player player = event.getPlayer();
|
||||
String entityType;
|
||||
String entityTypePermission;
|
||||
if (event.getBlock().getState(false) instanceof CreatureSpawner spawner) {
|
||||
|
||||
entityType = String.valueOf(spawner.getSpawnedType()).toLowerCase(Locale.ENGLISH);
|
||||
entityTypePermission = ("." + entityType);
|
||||
|
||||
} else {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (player.hasPermission(spawnerPlacePermission + entityTypePermission))
|
||||
return;
|
||||
event.setCancelled(true);
|
||||
player.sendMessage(
|
||||
MiniMessage.miniMessage().deserialize("<red>You do not have permission to place a <spawner> spawner!",
|
||||
Placeholder.unparsed("spawner", entityType)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.purpurmc.purpurextras.PurpurConfig;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* If enabled, allows filtering which entity types don't get damaged by
|
||||
* stonecutters if
|
||||
* <a href="https://purpurmc.org/docs/Configuration/stonecutter_1"> stonecutter
|
||||
* dealing damage</a> Purpur feature is enabled.
|
||||
*/
|
||||
public class StonecutterDamageModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final HashSet<EntityType> stonecutterDamageBlacklist = new HashSet<>();
|
||||
|
||||
protected StonecutterDamageModule() {
|
||||
|
||||
PurpurConfig config = PurpurExtrasOG.getPurpurConfig();
|
||||
List<String> entityBlacklist = config.getList("settings.stonecutter-damage-filter.blacklist",
|
||||
List.of("player"));
|
||||
if (config.getBoolean("settings.stonecutter-damage-filter.enabled", false)) {
|
||||
|
||||
if (entityBlacklist.isEmpty())
|
||||
return;
|
||||
for (EntityType entityType : EntityType.values()) {
|
||||
|
||||
if (!entityType.isAlive())
|
||||
continue;
|
||||
for (String str : entityBlacklist) {
|
||||
|
||||
if (entityType.getKey().getKey().equals(str.toLowerCase(Locale.ENGLISH)))
|
||||
stonecutterDamageBlacklist.add(entityType);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
try {
|
||||
|
||||
Class.forName("org.purpurmc.purpur.PurpurConfig");
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
||||
PurpurExtrasOG.getInstance().getLogger().warning(
|
||||
this.getClass().getSimpleName() + " module requires you to run Purpur as your server software.");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
if (stonecutterDamageBlacklist.isEmpty())
|
||||
return false;
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.stonecutter-damage-filter.enabled", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onStonecutterDamage(EntityDamageEvent event) {
|
||||
|
||||
if (!event.getCause().equals(EntityDamageEvent.DamageCause.CONTACT))
|
||||
return;
|
||||
if (!event.getEntity().isOnGround())
|
||||
return;
|
||||
|
||||
if (stonecutterDamageBlacklist.contains(event.getEntity().getType()))
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Allows the player to Stop Drop N Roll to get extinguished from any flames.
|
||||
*/
|
||||
public class StopDropNRollModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final Map<Player, Boolean> playerLastSneakMap = new HashMap<>();
|
||||
private double chance;
|
||||
private double amount;
|
||||
|
||||
protected StopDropNRollModule() {
|
||||
|
||||
chance = PurpurExtrasOG.getPurpurConfig().getDouble("settings.twerk-to-reduce-burn-time.chance", 0);
|
||||
amount = PurpurExtrasOG.getPurpurConfig().getDouble("settings.twerk-to-reduce-burn-time.amount", 0.5);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return chance != 0;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
|
||||
|
||||
Player player = event.getPlayer();
|
||||
boolean isSneaking = event.isSneaking();
|
||||
|
||||
if (player.getFireTicks() > 0 && isSneaking && !playerLastSneakMap.get(player) && Math.random() < chance) {
|
||||
|
||||
player.setFireTicks((int) (player.getFireTicks() * (1f - amount)));
|
||||
|
||||
}
|
||||
|
||||
playerLastSneakMap.put(player, isSneaking);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
|
||||
playerLastSneakMap.put(event.getPlayer(), false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
|
||||
playerLastSneakMap.remove(event.getPlayer());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.Iterator;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
/**
|
||||
* Unlocks all available recipes on join. Players can be exempt from this by
|
||||
* denying them purpurextras.unlockallrecipesonjoin permission.
|
||||
*/
|
||||
public class UnlockAllRecipesModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final String permission = "purpurextras.unlockallrecipesonjoin";
|
||||
|
||||
protected UnlockAllRecipesModule() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
DefaultPermissions.registerPermission(permission,
|
||||
"Players with this permission will have all recipes unlocked upon login if that feature is enabled in the config",
|
||||
PermissionDefault.TRUE);
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.unlock-all-recipes-on-join", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onPlayerJoinRecipeUnlock(PlayerJoinEvent event) {
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (!player.hasPermission(permission))
|
||||
return;
|
||||
Iterator<Recipe> recipes = Bukkit.recipeIterator();
|
||||
while (recipes.hasNext()) {
|
||||
|
||||
Recipe recipe = recipes.next();
|
||||
if (!(recipe instanceof Keyed keyedRecipe))
|
||||
continue;
|
||||
player.discoverRecipe(keyedRecipe.getKey());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+66
-19
@@ -1,5 +1,9 @@
|
||||
package me.youhavetrouble.purpurextras.listeners;
|
||||
package org.purpurmc.purpurextras.modules;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.EntityEffect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -13,66 +17,109 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.purpurmc.purpurextras.PurpurExtrasOG;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class VoidTotemListener implements Listener {
|
||||
/**
|
||||
* If enabled, totem of undying will save players from death in the void and
|
||||
* will teleport them to the last place their feet touched the ground. If for
|
||||
* any reason that position is not found, they will be teleported to world
|
||||
* spawn.
|
||||
*/
|
||||
public class VoidTotemModule implements PurpurExtrasModule, Listener {
|
||||
|
||||
private final Collection<PotionEffect> totemEffects = new ArrayList<>();
|
||||
private final HashMap<UUID, Location> lastGroundedLocations = new HashMap<>();
|
||||
|
||||
public VoidTotemListener() {
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.REGENERATION, 20*45, 1));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 20*40, 0));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.ABSORPTION, 20*5, 1));
|
||||
protected VoidTotemModule() {
|
||||
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.REGENERATION, 20 * 45, 1));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 20 * 40, 0));
|
||||
totemEffects.add(new PotionEffect(PotionEffectType.ABSORPTION, 20 * 5, 1));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
|
||||
PurpurExtrasOG plugin = PurpurExtrasOG.getInstance();
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldEnable() {
|
||||
|
||||
return PurpurExtrasOG.getPurpurConfig().getBoolean("settings.totem.work-on-void-death", false);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if (!event.hasChangedPosition()) return;
|
||||
|
||||
if (!event.hasChangedPosition())
|
||||
return;
|
||||
Location location = event.getTo().clone();
|
||||
if (location.subtract(0, 0.05, 0).getBlock().getType().isAir()) return;
|
||||
if (location.subtract(0, 0.05, 0).getBlock().getType().isAir())
|
||||
return;
|
||||
lastGroundedLocations.put(event.getPlayer().getUniqueId(), event.getTo().toCenterLocation());
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
|
||||
lastGroundedLocations.remove(event.getPlayer().getUniqueId());
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onPlayerDeathInVoid(EntityDamageEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player)) return;
|
||||
if (!event.getCause().equals(EntityDamageEvent.DamageCause.VOID)) return;
|
||||
Location location = player.getLocation();
|
||||
if (location.getY() > location.getWorld().getMinHeight()) return;
|
||||
|
||||
if (player.getHealth() - event.getFinalDamage() > 0) return;
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
if (!event.getCause().equals(EntityDamageEvent.DamageCause.VOID))
|
||||
return;
|
||||
Location location = player.getLocation();
|
||||
if (location.getY() > location.getWorld().getMinHeight())
|
||||
return;
|
||||
|
||||
if (player.getHealth() - event.getFinalDamage() > 0)
|
||||
return;
|
||||
|
||||
if (!player.getInventory().getItemInMainHand().getType().equals(Material.TOTEM_OF_UNDYING)
|
||||
&& !player.getInventory().getItemInOffHand().getType().equals(Material.TOTEM_OF_UNDYING)
|
||||
) return;
|
||||
&& !player.getInventory().getItemInOffHand().getType().equals(Material.TOTEM_OF_UNDYING))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
Location safeLocation = lastGroundedLocations.getOrDefault(player.getUniqueId(), location.getWorld().getSpawnLocation());
|
||||
Location safeLocation = lastGroundedLocations.getOrDefault(player.getUniqueId(),
|
||||
location.getWorld().getSpawnLocation());
|
||||
player.teleportAsync(safeLocation).thenRun(() -> useTotem(player));
|
||||
|
||||
}
|
||||
|
||||
private void useTotem(Player player) {
|
||||
|
||||
ItemStack totem = null;
|
||||
if (player.getInventory().getItemInMainHand().getType().equals(Material.TOTEM_OF_UNDYING)) {
|
||||
|
||||
totem = player.getInventory().getItemInMainHand();
|
||||
|
||||
} else if (player.getInventory().getItemInOffHand().getType().equals(Material.TOTEM_OF_UNDYING)) {
|
||||
|
||||
totem = player.getInventory().getItemInOffHand();
|
||||
|
||||
}
|
||||
if (totem == null) return;
|
||||
|
||||
if (totem == null)
|
||||
return;
|
||||
totem.subtract();
|
||||
player.setFallDistance(0);
|
||||
player.setHealth(1);
|
||||
player.playEffect(EntityEffect.TOTEM_RESURRECT);
|
||||
player.getActivePotionEffects().forEach(potionEffect -> player.removePotionEffect(potionEffect.getType()));
|
||||
player.addPotionEffects(this.totemEffects);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.purpurmc.purpurextras.modules.listeners;
|
||||
|
||||
import io.papermc.paper.event.player.PlayerItemCooldownEvent;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class ShieldCooldownListener implements Listener {
|
||||
|
||||
private final int shieldCooldown;
|
||||
|
||||
public ShieldCooldownListener(int cooldown) {
|
||||
|
||||
this.shieldCooldown = cooldown;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onShieldHit(PlayerItemCooldownEvent event) {
|
||||
|
||||
if (!event.getType().equals(Material.SHIELD))
|
||||
return;
|
||||
event.setCooldown(shieldCooldown);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package org.purpurmc.purpurextras.modules.listeners;
|
||||
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
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;
|
||||
|
||||
public class ShieldDamageReductionListener implements Listener {
|
||||
|
||||
private final double shieldDamageReduction;
|
||||
|
||||
public ShieldDamageReductionListener(double reductionModifier) {
|
||||
|
||||
this.shieldDamageReduction = reductionModifier;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onShieldHit(EntityDamageByEntityEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof HumanEntity humanEntity))
|
||||
return;
|
||||
if (!humanEntity.isBlocking())
|
||||
return;
|
||||
|
||||
// Scale only the blocking modifier. Writing a post-armour value
|
||||
// into BASE made armour and resistance apply a second time.
|
||||
if (!event.isApplicable(EntityDamageEvent.DamageModifier.BLOCKING))
|
||||
return;
|
||||
|
||||
double blocking = event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING);
|
||||
if (blocking == 0.0)
|
||||
return;
|
||||
|
||||
event.setDamage(EntityDamageEvent.DamageModifier.BLOCKING, blocking * shieldDamageReduction);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.purpurmc.purpurextras.util;
|
||||
|
||||
import com.destroystokyo.paper.MaterialTags;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class ItemStackUtil {
|
||||
|
||||
/**
|
||||
* Damages an item stack
|
||||
*
|
||||
* @param itemStack the item stack to damage
|
||||
* @param amount the amount of damage to deal
|
||||
* @param ignoreUnbreaking whether to ignore unbreaking
|
||||
* @return whether the item broke
|
||||
*/
|
||||
public static boolean damage(ItemStack itemStack, int amount, boolean ignoreUnbreaking) {
|
||||
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
Damageable damageable = (Damageable) itemStack.getItemMeta();
|
||||
if (amount > 0) {
|
||||
|
||||
int unbreaking = meta.getEnchantLevel(Enchantment.DURABILITY);
|
||||
int reduce = 0;
|
||||
for (int i = 0; unbreaking > 0 && i < amount; ++i) {
|
||||
|
||||
if (reduceDamage(itemStack, ThreadLocalRandom.current(), unbreaking)) {
|
||||
|
||||
++reduce;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
amount -= reduce;
|
||||
if (amount <= 0) {
|
||||
|
||||
return isBroke(itemStack, damageable.getDamage());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int damage = damageable.getDamage() + amount;
|
||||
damageable.setDamage(damage);
|
||||
itemStack.setItemMeta(damageable);
|
||||
return isBroke(itemStack, damage);
|
||||
|
||||
}
|
||||
|
||||
public static boolean isBroke(ItemStack itemStack, int damage) {
|
||||
|
||||
if (damage > itemStack.getType().getMaxDurability()) {
|
||||
|
||||
if (itemStack.getAmount() > 0) {
|
||||
|
||||
// Ensure it "breaks".
|
||||
itemStack.setAmount(0);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private static boolean reduceDamage(ItemStack itemStack, Random random, int unbreaking) {
|
||||
|
||||
if (MaterialTags.ARMOR.isTagged(itemStack.getType())) {
|
||||
|
||||
return random.nextFloat() < 0.6F;
|
||||
|
||||
}
|
||||
|
||||
return random.nextInt(unbreaking + 1) > 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.purpurmc.purpurextras.util;
|
||||
|
||||
public enum MessageType {
|
||||
CHAT, ACTION_BAR;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
settings:
|
||||
rideables:
|
||||
mob-needs-to-be-nametagged-to-ride: false
|
||||
twerk-to-reduce-burn-time:
|
||||
chance: 0.0
|
||||
amount: 0.5
|
||||
block-building-above-nether:
|
||||
height-limit: 128
|
||||
no-permission-message: '<red>Max build height in this world is: <gold><height>'
|
||||
enabled: false
|
||||
chat:
|
||||
send-sleep-percentage-message:
|
||||
player-sleeping: <grey><playername> has fallen asleep. <sleeping> out of <needed>
|
||||
required players in <worldname> are sleeping.
|
||||
skipping-night: <grey>Enough players have now slept! Skipping through the night
|
||||
in <worldname>.
|
||||
enabled: true
|
||||
escape-commands: true
|
||||
mobs:
|
||||
snow_golem:
|
||||
drop-pumpkin-when-sheared: true
|
||||
sheep:
|
||||
jeb-shear-random-color: false
|
||||
dye-boss-bars: false
|
||||
lightning-transforms-entities:
|
||||
entities:
|
||||
villager: no
|
||||
pig: no
|
||||
enabled: false
|
||||
gameplay-settings:
|
||||
respawn-anchor-needs-charges: true
|
||||
spawner-placement-requires-specific-permission: true
|
||||
run-faster-on-paths:
|
||||
speed-multiplier: 1.2
|
||||
duration: 2
|
||||
path-blocks:
|
||||
- DIRT_PATH
|
||||
cancel-damage-from-pet-owner: true
|
||||
fall-damage-when-jump-boost-applied: true
|
||||
shield:
|
||||
damage-reduction: 0.5
|
||||
cooldown: 0
|
||||
unlock-all-recipes-on-join: true
|
||||
use-notarget-permissions: false
|
||||
items:
|
||||
beehive-lore:
|
||||
bees: '<reset><yellow>Bees: <white><bees>/<maxbees>'
|
||||
honey: '<reset><gold>Honey level: <white><honey>/<maxhoney>'
|
||||
enabled: true
|
||||
leash-snap:
|
||||
sound: minecraft:block.bamboo.break
|
||||
volume: 0.75
|
||||
pitch: 1.50
|
||||
enabled: true
|
||||
totem:
|
||||
work-on-void-death: true
|
||||
work-from-hotbar: true
|
||||
blocks:
|
||||
shift-right-click-for-invisible-item-frames: false
|
||||
chorus-flowers-always-drop: true
|
||||
anvil-splits-minecarts: true
|
||||
anvil-splits-boats: true
|
||||
loom:
|
||||
max-layers: 6
|
||||
dispenser:
|
||||
break-blocks:
|
||||
pickaxe: false
|
||||
shovel: false
|
||||
hoe: false
|
||||
axe: false
|
||||
shears: false
|
||||
shears-shear-pumpkin: false
|
||||
puts-discs-in-jukebox: false
|
||||
interact-with-cauldron: false
|
||||
furnace:
|
||||
burn-time:
|
||||
multiplier: 1.0
|
||||
enabled: false
|
||||
anvil-crushes-blocks:
|
||||
blocks:
|
||||
cobblestone: sand
|
||||
enabled: false
|
||||
stonecutter-damage-filter:
|
||||
blacklist:
|
||||
- player
|
||||
enabled: false
|
||||
creeper-squid:
|
||||
enabled: false
|
||||
protect-blocks-with-loot:
|
||||
message: <red>Prevented you from breaking this block because it can regenerate
|
||||
loot. Sneak to break it anyway.
|
||||
allow-breaking-in-sneak: true
|
||||
immune-to-explosions: false
|
||||
message-type: CHAT
|
||||
enabled: false
|
||||
raid-totem-drops:
|
||||
chance: 0
|
||||
enabled: false
|
||||
grindstone:
|
||||
gives-enchants-back: false
|
||||
@@ -1,9 +1,9 @@
|
||||
name: PurpurExtras
|
||||
version: ${project.version}
|
||||
main: me.youhavetrouble.purpurextras.PurpurExtras
|
||||
api-version: 1.18
|
||||
authors: [ YouHaveTrouble ]
|
||||
description: "\"This should be a plugin\" features from Purpur"
|
||||
name: "${pluginName}"
|
||||
version: '${version}'
|
||||
main: "org.purpurmc.purpurextras.PurpurExtrasOG"
|
||||
api-version: '${apiVersion}'
|
||||
authors: [ YouHaveTrouble, NotAlexNoyle ]
|
||||
description: "${description}"
|
||||
commands:
|
||||
purpurextras:
|
||||
description: Command controlling PurpurExtras
|
||||
|
||||
Reference in new issue
Block a user