23 Commits
Author SHA1 Message Date
NotAlexNoyle 0264f60621 Exclude CODEOWNERS from language statistics 2026-10-29 16:19:04 -04:00
NotAlexNoyle fd09a1712d Add CODEOWNERS (one staff approval) 2026-10-29 16:19:03 -04:00
NotAlexNoyle b5e589ba41 Dupe prevention update 2026-06-01 14:41:34 -04:00
NotAlexNoyle 92709bf88d 1.1 update 2025-12-09 15:34:23 -05:00
NotAlexNoyle 5de68e9b72 Merge pull request #1 from true-og/codex/fix-shulker-box-stacking-implementation
Improve empty shulker auto stacking and merging
2025-12-09 15:15:17 -05:00
NotAlexNoyle f1089443db Fix empty shulker stacking behavior 2025-12-09 15:14:43 -05:00
NotAlexNoyle 437c5c95ce Update gradle to 8.14.3, add formatting 2025-08-15 16:23:04 -04:00
NotAlexNoyle 3f4ff4678f Update gradle to 8.14.2, add auto formatting 2025-06-21 14:47:49 -04:00
NotAlexNoyle cd4c1f90a9 Update gradle to 8.14.1 2025-06-05 09:10:14 -04:00
NotAlexNoyle 38edb20d6c Update gradle to 8.14.1 2025-05-30 12:31:43 -04:00
NotAlexNoyle 5c740a4d20 Update gradle 2024-10-25 06:42:55 +00:00
christianniehaus c926a21129 remove unused code 2024-02-08 16:48:58 -05:00
christianniehaus b3b5ca93e5 Merge branch 'main' of https://github.com/cnie109/ShulkerStacking-OG 2024-02-08 16:48:11 -05:00
christianniehaus 0ac0e3dbf2 Fix dupe prevention to work on more than just one player 2024-02-08 16:46:24 -05:00
cnie109 f58162995a Update README.md 2023-12-10 20:39:37 -05:00
cnie109 0ece313e83 Update README.md 2023-12-10 20:39:23 -05:00
christianniehaus 888c980549 Merge branch 'main' of https://github.com/christianniehaus/ShulkerStacking-OG 2023-12-10 20:38:47 -05:00
christianniehaus c25e801026 Fix inventory dragging without Mouse Tweaks 2023-12-10 20:38:14 -05:00
cnie109 77ecc81205 Update README.md 2023-12-01 12:45:14 -05:00
cnie109 5e512f28f7 Update README.md 2023-12-01 12:40:49 -05:00
cnie109 2001e62305 Update README.md 2023-12-01 12:39:26 -05:00
cnie109 0192910d1f Update README.md 2023-12-01 10:00:28 -05:00
christianniehaus e23e3eea27 Add hopper functionality 2023-12-01 09:59:34 -05:00
37 changed files with 1758 additions and 1014 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
.gitea/CODEOWNERS linguist-detectable=false
+3
View File
@@ -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
+6
View File
@@ -16,6 +16,12 @@ atlassian-ide-plugin.xml
# Compiled class file
*.class
# Eclipse files
.classpath
.project
.settings/
bin/
# Log file
*.log
+19 -3
View File
@@ -1,6 +1,22 @@
# ShulkerStacking-OG
Allow shulker boxes to stack like normal items
Allow empty shulker boxes to stack like normal items. Not currently complete, but is in a usable state.
Currently, only inventory actions are supported.
Current Target: Purpur 1.19.4
In order for inventory dragging behaviors to work properly, the client side mod mouse tweaks needs to be installed. You can get it here: https://modrinth.com/mod/mouse-tweaks
Authors: Barny1094875.
<h3>To build:</h3>
./gradlew build
The resulting .jar file will be in build/libs
# Changelog:
v1.1
- Update shadow to 8.3.9
- Update spotless to 8.1.0
- Rename package to net.trueog.shulkerstacking-og
- Fix shulkers getting eaten when merging
- Fix double click behavior
- Merge exactly like a vanilla item
-50
View File
@@ -1,50 +0,0 @@
plugins {
id 'java'
}
group = 'me.barny1094875'
version = '1.18'
repositories {
mavenCentral()
maven {
name = "papermc-repo"
url = "https://repo.papermc.io/repository/maven-public/"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/groups/public/"
}
maven {
url "https://repo.purpurmc.org/snapshots"
}
}
dependencies {
compileOnly "org.purpurmc.purpur:purpur-api:1.18.2-R0.1-SNAPSHOT"
}
def targetJavaVersion = 17
java {
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
if (JavaVersion.current() < javaVersion) {
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
}
}
tasks.withType(JavaCompile).configureEach {
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
options.release = targetJavaVersion
}
}
processResources {
def props = [version: version]
inputs.properties props
filteringCharset 'UTF-8'
filesMatching('plugin.yml') {
expand props
}
}
+104
View File
@@ -0,0 +1,104 @@
/* This is free and unencumbered software released into the public domain */
/* ------------------------------ Plugins ------------------------------ */
plugins {
id("java") // Import Java plugin.
id("java-library") // Import Java Library plugin.
id("com.diffplug.spotless") version "8.1.0" // Import Spotless plugin.
id("com.gradleup.shadow") version "8.3.9" // 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 = "net.trueog.shulkerstacking-og" // Declare bundle identifier.
version = "1.2" // Declare plugin version (will be in .jar).
val apiVersion = "1.19" // Declare minecraft server target version.
/* ----------------------------- Resources ----------------------------- */
tasks.named<ProcessResources>("processResources") {
val props = mapOf("version" to version, "apiVersion" to apiVersion)
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 { url = uri("https://repo.purpurmc.org/snapshots") } // Import the PurpurMC 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.
compileOnly("io.github.miniplaceholders:miniplaceholders-api:2.2.3") // Import MiniPlaceholders API.
}
/* ---------------------- 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.
minimize()
}
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
tasks.build { dependsOn(tasks.spotlessApply, tasks.shadowJar) } // Build depends on spotless and shadow.
/* --------------------------- 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.
}
+34
View File
@@ -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*&quot;Not yet implemented&quot;\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="(?&lt;!\w)fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="severity" value="warning"/>
</module>
</module>
+404
View File
@@ -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>
View File
Whitespace-only changes.
Binary file not shown.
+2 -1
View File
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Regular → Executable
+18 -12
View File
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# 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/.
@@ -83,7 +85,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# 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
@@ -111,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
@@ -130,10 +133,13 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
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.
@@ -141,7 +147,7 @@ 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=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -149,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -198,16 +204,16 @@ 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 $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# 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" \
org.gradle.wrapper.GradleWrapperMain \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
Vendored
+94 -92
View File
@@ -1,92 +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
@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.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
: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
@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
View File
@@ -1 +0,0 @@
rootProject.name = 'ShulkerStacking-OG'
+1
View File
@@ -0,0 +1 @@
rootProject.name = "ShulkerStacking-OG"
@@ -1,16 +0,0 @@
//package me.barny1094875.shulkerstackingog.Listeners;
//
//import org.bukkit.event.EventHandler;
//import org.bukkit.event.Listener;
//import org.bukkit.event.inventory.HopperInventorySearchEvent;
//
//public class ShulkerBoxHopperHandler implements Listener
//{
//
// @EventHandler
// public void shulkerBoxHopperHandler(HopperInventorySearchEvent event)
// {
//
// }
//
//}
@@ -1,90 +0,0 @@
package me.barny1094875.shulkerstackingog.Listeners;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public class ShulkerBoxPickupHandler implements Listener
{
@EventHandler
public void shulkerBoxStacking(EntityPickupItemEvent event)
{
ItemStack item = event.getItem().getItemStack();
if (!event.getEntity().getType().equals(EntityType.PLAYER))
{
return;
}
Player player = (Player) event.getEntity();
Inventory playerInventory = player.getInventory();
if (item.getType().toString().contains("SHULKER_BOX"))
{
BlockStateMeta shulker1Meta = (BlockStateMeta) item.getItemMeta();
ShulkerBox shulker1 = (ShulkerBox) shulker1Meta.getBlockState();
// check the inventory of the ground item shulker
if (shulker1.getInventory().isEmpty())
{
// check for shulker box stacks to add to
for (int i = 0; i < playerInventory.getSize(); i++)
{
ItemStack inventoryItem = playerInventory.getItem(i);
if (inventoryItem == null)
{
continue;
}
if (inventoryItem.getType().equals(item.getType()))
{
BlockStateMeta shulker2Meta = (BlockStateMeta) inventoryItem.getItemMeta();
ShulkerBox shulker2 = (ShulkerBox) shulker2Meta.getBlockState();
// check the inventory of the inventory shulker
if (shulker2.getInventory().isEmpty())
{
if (inventoryItem.getAmount() + item.getAmount() <= 64)
{
inventoryItem.setAmount(inventoryItem.getAmount() + item.getAmount());
event.getItem().setHealth(-1);
event.setCancelled(true);
return;
}
if (inventoryItem.getAmount() <= 64)
{
item.setAmount((item.getAmount() + inventoryItem.getAmount()) - 64);
if (item.getAmount() <= 0)
{
event.getItem().setHealth(-1);
return;
}
event.getItem().setItemStack(item);
inventoryItem.setAmount(64);
event.setCancelled(true);
}
}
}
}
// look for air gaps to add the shulkers to
for (int i = 0; i < playerInventory.getSize(); i++)
{
ItemStack inventoryItem = playerInventory.getItem(i);
if (inventoryItem == null)
{
playerInventory.setItem(i, item);
event.getItem().setHealth(-1);
event.setCancelled(true);
return;
}
}
}
}
}
}
@@ -1,123 +0,0 @@
package me.barny1094875.shulkerstackingog.Listeners;
import me.barny1094875.shulkerstackingog.ShulkerBoxHelpers.DoubleClick;
import me.barny1094875.shulkerstackingog.ShulkerBoxHelpers.NormalLeftClick;
import me.barny1094875.shulkerstackingog.ShulkerBoxHelpers.NormalRightClick;
import me.barny1094875.shulkerstackingog.ShulkerBoxHelpers.ShiftRightLeftClick;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class ShulkerBoxStackingController implements Listener
{
@EventHandler
public void shulkerBoxStacking(InventoryClickEvent event)
{
if (event.getCurrentItem() == null)
{
return;
}
if (event.getCursor() == null)
{
return;
}
ItemStack currentItem = event.getCurrentItem();
ItemStack cursorItem = event.getCursor();
Inventory inventory = event.getInventory();
// if the player combines two shulker stacks
if (event.getClick().equals(ClickType.LEFT))
{
if (currentItem.getType().toString().contains("SHULKER_BOX"))
{
if (cursorItem.getType().equals(currentItem.getType()))
{
NormalLeftClick.NormalLeftClickShulkerBox(currentItem, cursorItem, event);
return;
}
}
}
// if the player sets down just one shulker box from a stack
if (event.getClick().equals(ClickType.RIGHT))
{
if (currentItem.getType().toString().contains("SHULKER_BOX"))
{
if (cursorItem.getType().equals(currentItem.getType()))
{
NormalRightClick.NormalRightClickShulkerBox(currentItem, cursorItem, event);
}
}
}
// if the player puts down a shulker box stack
if (event.getClick().equals(ClickType.LEFT))
{
if (cursorItem.getType().toString().contains("SHULKER_BOX"))
{
// check if the shulker box stack only contains one shulker box
if (cursorItem.getAmount() != 1)
{
// remove the stack from their cursor
// and replace it with whatever was in the slot
event.getWhoClicked().setItemOnCursor(currentItem);
// place down the whole stack
event.setCurrentItem(cursorItem);
// stop default behaviors
event.setCancelled(true);
return;
}
}
}
// if the player double clicked in the inventory on a shulker box
// gather all of the shulker boxes in the inventory to the player's cursor
// including in their inventory
if (event.getClick().equals(ClickType.DOUBLE_CLICK))
{
if (cursorItem.getType().toString().contains("SHULKER_BOX"))
{
DoubleClick.DoubleClickShulkerBox(cursorItem, event);
return;
}
}
// if the player shift clicks on a shukler box stack
// we need to handle the stacking logic
if (event.getClick().equals(ClickType.SHIFT_LEFT) ||
event.getClick().equals(ClickType.SHIFT_RIGHT))
{
if (currentItem.getType().toString().contains("SHULKER_BOX"))
{
ShiftRightLeftClick.ShiftRightLeftClickShulkerBox(event);
}
}
// if the player users CTRL+<drop> on the shulkers
// drop the whole stack, instead of just one
if (event.getClick().equals(ClickType.CONTROL_DROP))
{
if (currentItem.getType().toString().contains("SHULKER_BOX"))
{
event.getWhoClicked().getWorld().dropItem(event.getWhoClicked().getLocation(),
event.getCurrentItem(), (Item) ->
{
Item.setVelocity(event.getWhoClicked().getLocation().getDirection().multiply(0.35).setY(0.25));
});
event.getCurrentItem().setAmount(0);
}
}
}
}
@@ -1,20 +0,0 @@
package me.barny1094875.shulkerstackingog.Listeners;
import me.barny1094875.shulkerstackingog.ShulkerStacking_OG;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryCloseEvent;
public class ShulkerDragDupePrevention implements Listener
{
@EventHandler(priority = EventPriority.LOWEST)
public void shulkerDragDupePrevent(InventoryCloseEvent event)
{
ShulkerStacking_OG.isInventoryClosed = true;
Bukkit.getScheduler().runTaskLater(ShulkerStacking_OG.getPlugin(),
() -> ShulkerStacking_OG.isInventoryClosed = false, 2);
}
}
@@ -1,110 +0,0 @@
package me.barny1094875.shulkerstackingog.Listeners;
import me.barny1094875.shulkerstackingog.ShulkerStacking_OG;
import org.bukkit.Bukkit;
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.inventory.DragType;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
public class ShulkerDragHandler implements Listener
{
@EventHandler(priority = EventPriority.MONITOR)
public void shulkerBoxDrag(InventoryDragEvent event)
{
if (!event.getOldCursor().getType().toString().contains("SHULKER_BOX"))
{
return;
}
// disable default behavior
event.setCancelled(true);
Bukkit.getScheduler().runTask(ShulkerStacking_OG.getPlugin(), () ->
{
// check if the inventory was closed in the last tick
// this prevents a dupe glitch from occurring
if (ShulkerStacking_OG.isInventoryClosed)
{
return;
}
ItemStack shulkerBoxes = event.getOldCursor();
int numberOfSlotsDragged = event.getInventorySlots().size();
ArrayList<Integer> slotsDragged = new ArrayList<>(event.getInventorySlots().stream().toList());
Inventory dragInventory = event.getView().getBottomInventory();
// right click drag
if (event.getType().equals(DragType.SINGLE))
{
// System.out.println("single");
// if the player drags a stack of shulker boxes
if (shulkerBoxes.getAmount() <= 1)
{
return;
}
// set each slot to the appropriate amount of shulkers
for (int i = 0; i < numberOfSlotsDragged; i++)
{
if (dragInventory.getItem(slotsDragged.get(i)) == null ||
dragInventory.getItem(slotsDragged.get(i)).getType() == Material.AIR)
{
dragInventory.setItem(slotsDragged.get(i), new ItemStack(shulkerBoxes.getType(), 1));
}
else if (dragInventory.getItem(slotsDragged.get(i)) != null && dragInventory.getItem(slotsDragged.get(i)).getType().equals(shulkerBoxes.getType()))
{
dragInventory.getItem(slotsDragged.get(i)).setAmount(dragInventory.getItem(slotsDragged.get(i)).getAmount() + 1);
}
}
}
// left click drag
else if (event.getType().equals(DragType.EVEN))
{
// if the player drags a stack of shulker boxes
if (shulkerBoxes.getAmount() <= 1)
{
return;
}
// set each slot to the appropriate amount of shulkers
for (int i = 0; i < numberOfSlotsDragged; i++)
{
if (dragInventory.getItem(slotsDragged.get(i)) == null || dragInventory.getItem(slotsDragged.get(i)).getType() == Material.AIR)
{
ItemStack newShulkerBoxes = new ItemStack(shulkerBoxes.getType(), shulkerBoxes.getAmount() / numberOfSlotsDragged);
dragInventory.setItem(slotsDragged.get(i), newShulkerBoxes);
if (newShulkerBoxes.getAmount() > 64)
{
shulkerBoxes.setAmount(shulkerBoxes.getAmount() - (64 - shulkerBoxes.getAmount()));
newShulkerBoxes.setAmount(64);
slotsDragged.remove(i);
break;
}
dragInventory.setItem(slotsDragged.get(i), newShulkerBoxes);
}
else if (dragInventory.getItem(slotsDragged.get(i)) != null && dragInventory.getItem(slotsDragged.get(i)).getType().equals(shulkerBoxes.getType()))
{
ItemStack newShulkerBoxes = new ItemStack(shulkerBoxes.getType(), shulkerBoxes.getAmount() / numberOfSlotsDragged);
dragInventory.getItem(slotsDragged.get(i)).setAmount(dragInventory.getItem(slotsDragged.get(i)).getAmount() + shulkerBoxes.getAmount() / numberOfSlotsDragged);
if (newShulkerBoxes.getAmount() > 64)
{
shulkerBoxes.setAmount(shulkerBoxes.getAmount() - (64 - shulkerBoxes.getAmount()));
newShulkerBoxes.setAmount(64);
slotsDragged.remove(i);
break;
}
dragInventory.setItem(slotsDragged.get(i), newShulkerBoxes);
}
}
event.getWhoClicked().setItemOnCursor(new ItemStack(shulkerBoxes.getType(), shulkerBoxes.getAmount() % numberOfSlotsDragged));
((Player) event.getWhoClicked()).updateInventory();
}
});
}
}
@@ -1,155 +0,0 @@
package me.barny1094875.shulkerstackingog.ShulkerBoxHelpers;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public class DoubleClick
{
public static void DoubleClickShulkerBox(ItemStack cursorItem, InventoryClickEvent event)
{
// check that the held shulker box is empty
Inventory heldShulkerInventory = ((ShulkerBox) ((BlockStateMeta) cursorItem.getItemMeta()).getBlockState()).getInventory();
if (heldShulkerInventory.isEmpty())
{
// loop through the inventory, and the player's inventory
// and count up the shulker boxes
// ignore boxes in result slots
// delete the shulker boxes, up to 64, and set the cursor stack
// to the number of boxes, up to 64
InventoryView eventView = event.getView();
Inventory playerInventory = eventView.getBottomInventory();
Inventory containerInventory = eventView.getTopInventory();
Material shulkerType = cursorItem.getType();
int containerSize = containerInventory.getSize();
// store a temporary inventory so that we can handle
// full shulker boxes
Inventory tempPlayerInventory = Bukkit.createInventory(null, 36);
tempPlayerInventory.setContents(playerInventory.getContents());
// make the inventory size the max of 54 so that it will hold any size inventory
Inventory tempContainerInventory = Bukkit.createInventory(null, 54);
tempContainerInventory.setContents(containerInventory.getContents());
// use these two inventories to loop through the inventories
// we can delete full shulkers from these temporary inventories
// without deleting them from the main inventory
// and then just copy over the empty shulker deletes to the main
// inventories
// loop through the container inventory until there are no
// more shulker boxes, counting them up, and removing them
// up to 64 boxes
int shulkerBoxCount = cursorItem.getAmount();
while (tempContainerInventory.first(shulkerType) != -1)
{
int firstShulker = tempContainerInventory.first(shulkerType);
// grab the inventory of the shulker box in that slot
Inventory shulkerInventory = ((ShulkerBox) ((BlockStateMeta) tempContainerInventory.getItem(firstShulker).getItemMeta()).getBlockState()).getInventory();
// if that inventory is not empty, delete it from the temporary inventory, and continue on
// otherwise, do the rest of the logic
if (!shulkerInventory.isEmpty())
{
tempContainerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
continue;
}
// if the shulker box is in a RESULT slot, then break from
// the loop, since that is always the last slot
InventoryType.SlotType slotType = eventView.getSlotType(firstShulker);
if (slotType.equals(InventoryType.SlotType.RESULT))
{
break;
}
// if the shulker box count would have gone above 64
ItemStack shulkerStackItem = containerInventory.getItem(firstShulker);
int shulkerStackAmount = shulkerStackItem.getAmount();
if (shulkerBoxCount + shulkerStackAmount > 64)
{
// get how many shulker boxes we need to get to 64
int shulkersRequired = 64 - shulkerBoxCount;
// remove that many boxes from the stack
shulkerStackItem.setAmount(shulkerStackAmount - shulkersRequired);
shulkerBoxCount += shulkersRequired;
// break from the loop, since we have a stack of shulkers collected
break;
}
else
{
// add the shulkerStackAmount to shulkerBoxCount
shulkerBoxCount += shulkerStackAmount;
// remove the shulkers from that slot
containerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
tempContainerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
}
}
// loop through the player's inventory
while (tempPlayerInventory.first(shulkerType) != -1)
{
int firstShulker = tempPlayerInventory.first(shulkerType);
// grab the inventory of the shulker box in that slot
Inventory shulkerInventory = ((ShulkerBox) ((BlockStateMeta) tempPlayerInventory.getItem(firstShulker).getItemMeta()).getBlockState()).getInventory();
// if that inventory is not empty, delete it from the temporary inventory, and continue on
// otherwise, do the rest of the logic
if (!shulkerInventory.isEmpty())
{
// remove this non-empty shulker from the temporary inventory
tempPlayerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
continue;
}
// if the shulker box is in a RESULT slot, then break from
// the loop, since that is always the last slot
// add the container's size to the here to offset it to the player's inventory
InventoryType.SlotType slotType = eventView.getSlotType(firstShulker + containerSize);
if (slotType.equals(InventoryType.SlotType.RESULT))
{
break;
}
// if the shulker box count would have gone above 64
ItemStack shulkerStackItem = playerInventory.getItem(firstShulker);
int shulkerStackAmount = shulkerStackItem.getAmount();
if (shulkerBoxCount + shulkerStackAmount > 64)
{
// get how many shulker boxes we need to get to 64
int shulkersRequired = 64 - shulkerBoxCount;
// remove that many boxes from the stack
shulkerStackItem.setAmount(shulkerStackAmount - shulkersRequired);
shulkerBoxCount += shulkersRequired;
// break from the loop, since we have a stack of shulkers collected
break;
}
else
{
// add the shulkerStackAmount to shulkerBoxCount
shulkerBoxCount += shulkerStackAmount;
// remove the shulkers from that slot
playerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
tempPlayerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
}
}
// now that we have the number of shulkers to grab, put them into the cursor
// if the shulkerBoxCount was 1, then don't do anything
if (shulkerBoxCount != 1)
{
ItemStack newShulkers = new ItemStack(shulkerType);
newShulkers.setAmount(shulkerBoxCount);
event.getWhoClicked().setItemOnCursor(newShulkers);
// cancel default behavior
event.setCancelled(true);
}
}
}
}
@@ -1,273 +0,0 @@
package me.barny1094875.shulkerstackingog.ShulkerBoxHelpers;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
public class ShiftRightLeftClick
{
public static void ShiftRightLeftClickShulkerBox(InventoryClickEvent event)
{
// check what kind of inventory was shift-clicked in
// regardless, loop through the inventory(ies) and add the
// shulker box stack to the
InventoryView eventInventory = event.getView();
InventoryType inventoryType = eventInventory.getType();
Inventory containerInventory = eventInventory.getTopInventory();
Inventory playerInventory = eventInventory.getBottomInventory();
// store a temporary inventory so that we can handle
// full shulker boxes
Inventory tempPlayerInventory = Bukkit.createInventory(null, 36);
tempPlayerInventory.setContents(playerInventory.getContents());
// make the inventory size the max of 54 so that it will hold any size inventory
Inventory tempContainerInventory = Bukkit.createInventory(null, 54);
tempContainerInventory.setContents(containerInventory.getContents());
Material shulkerBoxType = event.getCurrentItem().getType();
int shulkerStackAmount = event.getCurrentItem().getAmount();
// if it was the player's inventory
if (inventoryType.equals(InventoryType.CRAFTING))
{
// check if the slot was a hotbar slot or not
if (event.getSlotType().equals(InventoryType.SlotType.QUICKBAR))
{
// remove the hotbar of the tempInventory
for (int i = 0; i < 9; i++)
{
tempPlayerInventory.setItem(i, new ItemStack(Material.AIR));
}
// check the top part of the inventory for any shulker stacks that are not 64 yet
while (tempPlayerInventory.first(shulkerBoxType) != -1)
{
int firstShulkerSlot = tempPlayerInventory.first(shulkerBoxType);
ItemStack shulkerStack = tempPlayerInventory.getItem(firstShulkerSlot);
// if the shulker stack has 64 shulker boxes in it
// remove it from the temporary inventory and continue on
if (shulkerStack.getAmount() >= 64)
{
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
continue;
}
// cancel default behavior since shulker boxes are being moved
event.setCancelled(true);
// stack up to 64 shulkers into the stack, and then continue on
if (shulkerStack.getAmount() + shulkerStackAmount <= 64)
{
playerInventory.getItem(firstShulkerSlot).setAmount(shulkerStack.getAmount() + shulkerStackAmount);
shulkerStackAmount = 0;
break;
}
else
{
// remove shulker boxes until the shulker stack has 64 boxes
shulkerStackAmount -= 64 - shulkerStack.getAmount();
playerInventory.getItem(firstShulkerSlot).setAmount(64);
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
}
}
// change the shulker stack amount to what is left
// or remove it if nothing is left
if (shulkerStackAmount == 0)
{
event.setCurrentItem(new ItemStack(Material.AIR));
}
else
{
event.getCurrentItem().setAmount(shulkerStackAmount);
// look for an air gap to put the rest of the shulker boxes
for (int i = 9; i < playerInventory.getSize(); i++)
{
if (playerInventory.getItem(i) == null)
{
playerInventory.setItem(i, event.getCurrentItem());
event.setCurrentItem(new ItemStack(Material.AIR));
}
}
}
}
// the slot was an inventory slot, so check the hotbar for boxes
else
{
// remove everything from the upper inventory to prevent it from causing problems
for (int i = 35; i > 8; i--)
{
tempPlayerInventory.setItem(i, new ItemStack(Material.AIR));
}
while (tempPlayerInventory.first(shulkerBoxType) != -1)
{
int firstShulkerSlot = tempPlayerInventory.first(shulkerBoxType);
ItemStack shulkerStack = tempPlayerInventory.getItem(firstShulkerSlot);
// if the shulker stack has 64 shulker boxes in it
// remove it from the temporary inventory and continue on
if (shulkerStack.getAmount() >= 64)
{
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
continue;
}
// cancel default behavior since shulker boxes are being moved
event.setCancelled(true);
// stack up to 64 shulkers into the stack, and then continue on
if (shulkerStack.getAmount() + shulkerStackAmount <= 64)
{
playerInventory.getItem(firstShulkerSlot).setAmount(shulkerStack.getAmount() + shulkerStackAmount);
shulkerStackAmount = 0;
break;
}
else
{
// remove shulker boxes until the shulker stack has 64 boxes
shulkerStackAmount -= 64 - shulkerStack.getAmount();
playerInventory.getItem(firstShulkerSlot).setAmount(64);
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
}
}
// change the shulker stack amount to what is left
// or remove it if nothing is left
if (shulkerStackAmount == 0)
{
event.setCurrentItem(new ItemStack(Material.AIR));
}
else
{
event.getCurrentItem().setAmount(shulkerStackAmount);
// look for an air gap to put the rest of the shulker boxes
for (int i = 0; i < 9; i++)
{
if (playerInventory.getItem(i) == null)
{
playerInventory.setItem(i, event.getCurrentItem());
event.setCurrentItem(new ItemStack(Material.AIR));
}
}
}
}
}
// if it was anything else
else
{
// check if the click was in the bottom
if (event.getRawSlot() > containerInventory.getSize())
{
while (tempContainerInventory.first(shulkerBoxType) != -1)
{
int firstShulkerSlot = tempContainerInventory.first(shulkerBoxType);
ItemStack shulkerStack = tempContainerInventory.getItem(firstShulkerSlot);
// if the shulker stack has 64 shulker boxes in it
// remove it from the temporary inventory and continue on
if (shulkerStack.getAmount() >= 64)
{
tempContainerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
continue;
}
// cancel default behavior since shulker boxes are being moved
event.setCancelled(true);
// stack up to 64 shulkers into the stack, and then continue on
if (shulkerStack.getAmount() + shulkerStackAmount <= 64)
{
containerInventory.getItem(firstShulkerSlot).setAmount(shulkerStack.getAmount() + shulkerStackAmount);
shulkerStackAmount = 0;
break;
}
else
{
// remove shulker boxes until the shulker stack has 64 boxes
shulkerStackAmount -= 64 - shulkerStack.getAmount();
containerInventory.getItem(firstShulkerSlot).setAmount(64);
tempContainerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
}
}
// change the shulker stack amount to what is left
// or remove it if nothing is left
if (shulkerStackAmount == 0)
{
event.setCurrentItem(new ItemStack(Material.AIR));
}
else
{
event.getCurrentItem().setAmount(shulkerStackAmount);
// look for an air gap to put the rest of the shulker boxes
for (int i = 0; i < containerInventory.getSize(); i++)
{
if (containerInventory.getItem(i) == null)
{
containerInventory.setItem(i, event.getCurrentItem());
event.setCurrentItem(new ItemStack(Material.AIR));
}
}
}
}
// the click was in the top inventory
else
{
while (tempPlayerInventory.first(shulkerBoxType) != -1)
{
int firstShulkerSlot = tempPlayerInventory.first(shulkerBoxType);
ItemStack shulkerStack = tempPlayerInventory.getItem(firstShulkerSlot);
// if the shulker stack has 64 shulker boxes in it
// remove it from the temporary inventory and continue on
if (shulkerStack.getAmount() >= 64)
{
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
continue;
}
// cancel default behavior since shulker boxes are being moved
event.setCancelled(true);
// stack up to 64 shulkers into the stack, and then continue on
if (shulkerStack.getAmount() + shulkerStackAmount <= 64)
{
playerInventory.getItem(firstShulkerSlot).setAmount(shulkerStack.getAmount() + shulkerStackAmount);
shulkerStackAmount = 0;
break;
}
else
{
// remove shulker boxes until the shulker stack has 64 boxes
shulkerStackAmount -= 64 - shulkerStack.getAmount();
playerInventory.getItem(firstShulkerSlot).setAmount(64);
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
}
}
// change the shulker stack amount to what is left
// or remove it if nothing is left
if (shulkerStackAmount == 0)
{
event.setCurrentItem(new ItemStack(Material.AIR));
}
else
{
event.getCurrentItem().setAmount(shulkerStackAmount);
// look for an air gap to put the rest of the shulker boxes
for (int i = 0; i < playerInventory.getSize(); i++)
{
if (playerInventory.getItem(i) == null)
{
playerInventory.setItem(i, event.getCurrentItem());
event.setCurrentItem(new ItemStack(Material.AIR));
}
}
}
}
}
}
}
@@ -1,33 +0,0 @@
package me.barny1094875.shulkerstackingog;
import me.barny1094875.shulkerstackingog.Listeners.ShulkerBoxPickupHandler;
import me.barny1094875.shulkerstackingog.Listeners.ShulkerBoxStackingController;
import me.barny1094875.shulkerstackingog.Listeners.ShulkerDragDupePrevention;
import me.barny1094875.shulkerstackingog.Listeners.ShulkerDragHandler;
import org.bukkit.plugin.java.JavaPlugin;
public final class ShulkerStacking_OG extends JavaPlugin
{
private static ShulkerStacking_OG plugin;
// used to prevent dupe glitches from inventory drag events
public static boolean isInventoryClosed = false;
@Override
public void onEnable()
{
plugin = this;
// Plugin startup logic
getServer().getPluginManager().registerEvents(new ShulkerBoxStackingController(), this);
getServer().getPluginManager().registerEvents(new ShulkerBoxPickupHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerDragHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerDragDupePrevention(), this);
// getServer().getPluginManager().registerEvents(new ShulkerBoxHopperHandler(), this);
}
public static ShulkerStacking_OG getPlugin()
{
return plugin;
}
}
@@ -0,0 +1,67 @@
package plugin.Listeners;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
public class ShulkerBoxHopperHandler implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void shulkerBoxHopperHandler(InventoryMoveItemEvent event) {
ItemStack eventItem = event.getItem();
Inventory eventDestination = event.getDestination();
Inventory eventSource = event.getSource();
if (!ShulkerBoxUtils.isEmptyShulkerBox(eventItem)) {
return;
}
int toMove = eventItem.getAmount();
if (toMove <= 0) {
return;
}
event.setCancelled(true);
for (int i = 0; i < eventSource.getSize() && toMove > 0; i++) {
ItemStack sourceItem = eventSource.getItem(i);
if (!ShulkerBoxUtils.isEmptyShulkerBox(sourceItem)) {
continue;
}
if (!sourceItem.getType().equals(eventItem.getType())) {
continue;
}
int moveAmount = Math.min(sourceItem.getAmount(), toMove);
int remaining = ShulkerBoxUtils.mergeIntoExistingStacks(eventDestination, eventItem, moveAmount);
remaining = ShulkerBoxUtils.fillEmptySlots(eventDestination, eventItem, remaining);
int moved = moveAmount - remaining;
if (moved > 0) {
sourceItem.setAmount(sourceItem.getAmount() - moved);
eventSource.setItem(i, sourceItem.getAmount() <= 0 ? null : sourceItem);
toMove -= moved;
}
}
}
}
@@ -0,0 +1,59 @@
package plugin.Listeners;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ItemMergeEvent;
import org.bukkit.inventory.ItemStack;
import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
public class ShulkerBoxMergeHandler implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onItemMerge(ItemMergeEvent event) {
ItemStack target = event.getTarget().getItemStack();
ItemStack source = event.getEntity().getItemStack();
if (!ShulkerBoxUtils.isEmptyShulkerBox(target) || !ShulkerBoxUtils.isEmptyShulkerBox(source)) {
return;
}
if (!target.getType().equals(source.getType())) {
return;
}
event.setCancelled(true);
int space = 64 - target.getAmount();
if (space <= 0) {
return;
}
int moved = Math.min(space, source.getAmount());
target.setAmount(target.getAmount() + moved);
// Write back because Item#getItemStack may return a defensive copy.
event.getTarget().setItemStack(target);
int remaining = source.getAmount() - moved;
if (remaining <= 0) {
event.getEntity().remove();
} else {
source.setAmount(remaining);
event.getEntity().setItemStack(source);
}
}
}
@@ -0,0 +1,64 @@
package plugin.Listeners;
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.entity.EntityPickupItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
public class ShulkerBoxPickupHandler implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void shulkerBoxStacking(EntityPickupItemEvent event) {
ItemStack item = event.getItem().getItemStack();
if (!event.getEntity().getType().equals(EntityType.PLAYER)) {
return;
}
if (!ShulkerBoxUtils.isEmptyShulkerBox(item)) {
return;
}
event.setCancelled(true);
Player player = (Player) event.getEntity();
Inventory playerInventory = player.getInventory();
int original = item.getAmount();
int remaining = original;
remaining = ShulkerBoxUtils.mergeIntoExistingStacks(playerInventory, item, remaining);
remaining = ShulkerBoxUtils.fillEmptySlots(playerInventory, item, remaining);
if (remaining <= 0) {
event.getItem().remove();
player.updateInventory();
return;
}
// Preserve entity metadata when the inventory could not accept any items.
if (remaining < original) {
ItemStack remainingItem = item.clone();
remainingItem.setAmount(remaining);
event.getItem().setItemStack(remainingItem);
}
player.updateInventory();
}
}
@@ -0,0 +1,158 @@
package plugin.Listeners;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Item;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import plugin.ShulkerBoxHelpers.DoubleClick;
import plugin.ShulkerBoxHelpers.NormalLeftClick;
import plugin.ShulkerBoxHelpers.NormalRightClick;
import plugin.ShulkerBoxHelpers.ShiftRightLeftClick;
import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
public class ShulkerBoxStackingController implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void shulkerBoxStacking(InventoryClickEvent event) {
ItemStack currentItem = event.getCurrentItem();
ItemStack cursorItem = event.getCursor();
ClickType click = event.getClick();
boolean currentIsShulker = ShulkerBoxUtils.isShulkerBoxMaterial(currentItem);
boolean cursorIsShulker = ShulkerBoxUtils.isShulkerBoxMaterial(cursorItem);
if (click.equals(ClickType.LEFT) && currentIsShulker && cursorIsShulker
&& currentItem.getType().equals(cursorItem.getType()))
{
if (ShulkerBoxUtils.isEmptyShulkerBox(currentItem) && ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
NormalLeftClick.NormalLeftClickShulkerBox(currentItem, cursorItem, event);
} else {
// Filled shulkers cannot use vanilla NBT stacking.
event.setCancelled(true);
}
return;
}
if (click.equals(ClickType.RIGHT) && currentIsShulker && cursorIsShulker
&& currentItem.getType().equals(cursorItem.getType()))
{
if (ShulkerBoxUtils.isEmptyShulkerBox(currentItem) && ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
NormalRightClick.NormalRightClickShulkerBox(currentItem, cursorItem, event);
} else {
event.setCancelled(true);
}
return;
}
// Place the whole empty cursor stack into air or a non-shulker slot.
if (click.equals(ClickType.LEFT) && cursorIsShulker && cursorItem.getAmount() > 1) {
if (!ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
return;
}
if (currentItem == null || currentItem.getType() == Material.AIR) {
event.setCurrentItem(cursorItem);
event.getWhoClicked().setItemOnCursor(new ItemStack(Material.AIR));
event.setCancelled(true);
} else if (!currentIsShulker) {
event.getWhoClicked().setItemOnCursor(currentItem);
event.setCurrentItem(cursorItem);
event.setCancelled(true);
}
return;
}
if (click.equals(ClickType.DOUBLE_CLICK) && cursorIsShulker) {
if (ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
DoubleClick.DoubleClickShulkerBox(cursorItem, event);
}
return;
}
if ((click.equals(ClickType.SHIFT_LEFT) || click.equals(ClickType.SHIFT_RIGHT)) && currentIsShulker) {
if (ShulkerBoxUtils.isEmptyShulkerBox(currentItem)) {
ShiftRightLeftClick.ShiftRightLeftClickShulkerBox(event);
}
return;
}
// Drop the whole empty stack; vanilla correctly drops filled single boxes.
if (click.equals(ClickType.CONTROL_DROP) && currentIsShulker && currentItem.getAmount() > 1) {
if (!ShulkerBoxUtils.isEmptyShulkerBox(currentItem)) {
return;
}
event.setCancelled(true);
HumanEntity who = event.getWhoClicked();
Location dropLoc = who.getLocation();
ItemStack dropStack = currentItem.clone();
Item dropped = who.getWorld().dropItem(dropLoc, dropStack, (Item entity) -> {
entity.setVelocity(dropLoc.getDirection().multiply(0.35).setY(0.25));
});
// Clear the slot only if ItemSpawnEvent allowed the drop entity.
if (dropped != null && dropped.isValid() && !dropped.isDead()) {
event.setCurrentItem(new ItemStack(Material.AIR));
}
return;
}
// Block creative middle-clone because empty shulkers would be synthesized.
if (click.equals(ClickType.MIDDLE) && currentIsShulker) {
event.setCancelled(true);
}
}
}
@@ -0,0 +1,20 @@
package plugin.Listeners;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import plugin.ShulkerStackingOG;
public class ShulkerCleanupHandler implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent event) {
// Remove the close flag when the player quits to prevent stale entries.
ShulkerStackingOG.isInventoryClosed.remove(event.getPlayer().getUniqueId());
}
}
@@ -0,0 +1,24 @@
package plugin.Listeners;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryCloseEvent;
import plugin.ShulkerStackingOG;
public class ShulkerDragDupePrevention implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void shulkerDragDupePrevent(InventoryCloseEvent event) {
java.util.UUID uuid = event.getPlayer().getUniqueId();
ShulkerStackingOG.isInventoryClosed.put(uuid, true);
// Reset flags only if present so delayed tasks cannot recreate stale state.
Bukkit.getScheduler().runTaskLater(ShulkerStackingOG.getPlugin(),
() -> ShulkerStackingOG.isInventoryClosed.computeIfPresent(uuid, (k, v) -> false), 2);
}
}
@@ -0,0 +1,220 @@
package plugin.Listeners;
import java.util.Set;
import java.util.logging.Level;
import org.bukkit.Bukkit;
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.inventory.DragType;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
import plugin.ShulkerStackingOG;
public class ShulkerDragHandler implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void shulkerBoxDrag(InventoryDragEvent event) {
ItemStack cursor = event.getOldCursor();
if (!ShulkerBoxUtils.isShulkerBoxMaterial(cursor)) {
return;
}
// Cancel leaked filled stacks before vanilla can split duplicate NBT.
if (!ShulkerBoxUtils.isEmptyShulkerBox(cursor)) {
if (cursor.getAmount() > 1) {
event.setCancelled(true);
}
return;
}
event.setCancelled(true);
final int total = cursor.getAmount();
if (total < 1) {
return;
}
final Material shulkerType = cursor.getType();
final DragType dragType = event.getType();
final Set<Integer> rawSlots = event.getRawSlots();
final int slotCount = rawSlots.size();
if (slotCount == 0) {
return;
}
final int perSlot;
if (dragType.equals(DragType.SINGLE)) {
perSlot = 1;
} else if (dragType.equals(DragType.EVEN)) {
perSlot = total / slotCount;
} else {
return;
}
if (perSlot <= 0) {
return;
}
final InventoryView view = event.getView();
Bukkit.getScheduler().runTask(ShulkerStackingOG.getPlugin(), () -> {
// Skip if inventory just closed: vanilla already ejected cursor contents.
Boolean closed = ShulkerStackingOG.isInventoryClosed.get(event.getWhoClicked().getUniqueId());
if (closed != null && closed) {
return;
}
// Abort if vanilla dropped the cursor while the player went offline.
if (!(event.getWhoClicked() instanceof Player player) || !player.isOnline()) {
return;
}
// Abort if a Q-drop, hotbar swap, or outside-click changed the cursor.
ItemStack live = player.getItemOnCursor();
if (!ShulkerBoxUtils.isEmptyShulkerBox(live) || !live.getType().equals(shulkerType)
|| live.getAmount() < total)
{
return;
}
// Increment before slot writes so exceptions bias toward loss, not duplication.
int[] placedRef = new int[] { 0 };
int[] pendingRef = new int[] { 0 };
try {
for (Integer rawSlot : rawSlots) {
if (placedRef[0] >= total) {
break;
}
Inventory targetInv = view.getInventory(rawSlot);
if (targetInv == null) {
continue;
}
int slotIdx = view.convertSlot(rawSlot);
if (slotIdx < 0 || slotIdx >= targetInv.getSize()) {
continue;
}
ItemStack existing = targetInv.getItem(slotIdx);
int desired = Math.min(perSlot, total - placedRef[0]);
if (existing == null || existing.getType() == Material.AIR) {
int toPlace = Math.min(desired, 64);
pendingRef[0] = toPlace;
placedRef[0] += toPlace;
targetInv.setItem(slotIdx, new ItemStack(shulkerType, toPlace));
pendingRef[0] = 0;
continue;
}
if (!ShulkerBoxUtils.isEmptyShulkerBox(existing)) {
continue;
}
if (!existing.getType().equals(shulkerType)) {
continue;
}
int space = 64 - existing.getAmount();
if (space <= 0) {
continue;
}
int toAdd = Math.min(desired, space);
pendingRef[0] = toAdd;
placedRef[0] += toAdd;
existing.setAmount(existing.getAmount() + toAdd);
targetInv.setItem(slotIdx, existing);
pendingRef[0] = 0;
}
} catch (RuntimeException exception) {
if (pendingRef[0] > 0) {
ShulkerStackingOG.getPlugin().getLogger().log(Level.SEVERE,
"Suspected loss of up to " + pendingRef[0] + " " + shulkerType
+ " shulker boxes during an inventory drag for " + player.getName() + " ("
+ player.getUniqueId() + ").",
exception);
}
throw exception;
} finally {
int leftover = total - placedRef[0];
if (leftover <= 0) {
player.setItemOnCursor(new ItemStack(Material.AIR));
} else {
player.setItemOnCursor(new ItemStack(shulkerType, leftover));
}
player.updateInventory();
}
});
}
}
@@ -0,0 +1,134 @@
package plugin.ShulkerBoxHelpers;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public class DoubleClick {
public static void DoubleClickShulkerBox(ItemStack cursorItem, InventoryClickEvent event) {
// Only empty shulkers can be collected.
Inventory heldShulkerInventory = ((ShulkerBox) ((BlockStateMeta) cursorItem.getItemMeta()).getBlockState())
.getInventory();
if (heldShulkerInventory.isEmpty()) {
// Collect up to 64 matching empty shulkers from both inventories.
InventoryView eventView = event.getView();
Inventory playerInventory = eventView.getBottomInventory();
Inventory containerInventory = eventView.getTopInventory();
Material shulkerType = cursorItem.getType();
int containerSize = containerInventory.getSize();
// Use temporary inventories to skip filled shulkers without removing them.
Inventory tempPlayerInventory = Bukkit.createInventory(null, 36);
tempPlayerInventory.setContents(playerInventory.getContents());
// Use the maximum container size so every view fits.
Inventory tempContainerInventory = Bukkit.createInventory(null, 54);
tempContainerInventory.setContents(containerInventory.getContents());
// Collect empty shulkers from the container first.
int shulkerBoxCount = cursorItem.getAmount();
while (tempContainerInventory.first(shulkerType) != -1) {
int firstShulker = tempContainerInventory.first(shulkerType);
Inventory shulkerInventory = ((ShulkerBox) ((BlockStateMeta) tempContainerInventory
.getItem(firstShulker).getItemMeta()).getBlockState()).getInventory();
// Skip filled shulkers in the temporary inventory.
if (!shulkerInventory.isEmpty()) {
tempContainerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
continue;
}
// Result slots terminate the top-inventory scan.
InventoryType.SlotType slotType = eventView.getSlotType(firstShulker);
if (slotType.equals(InventoryType.SlotType.RESULT)) {
break;
}
ItemStack shulkerStackItem = containerInventory.getItem(firstShulker);
int shulkerStackAmount = shulkerStackItem.getAmount();
if (shulkerBoxCount + shulkerStackAmount > 64) {
int shulkersRequired = 64 - shulkerBoxCount;
shulkerStackItem.setAmount(shulkerStackAmount - shulkersRequired);
shulkerBoxCount += shulkersRequired;
break;
} else {
shulkerBoxCount += shulkerStackAmount;
containerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
tempContainerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
}
}
// Collect empty shulkers from the player's inventory next.
while (tempPlayerInventory.first(shulkerType) != -1) {
int firstShulker = tempPlayerInventory.first(shulkerType);
Inventory shulkerInventory = ((ShulkerBox) ((BlockStateMeta) tempPlayerInventory.getItem(firstShulker)
.getItemMeta()).getBlockState()).getInventory();
// Skip filled shulkers in the temporary inventory.
if (!shulkerInventory.isEmpty()) {
tempPlayerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
continue;
}
// Offset by the container size before checking the raw slot type.
InventoryType.SlotType slotType = eventView.getSlotType(firstShulker + containerSize);
if (slotType.equals(InventoryType.SlotType.RESULT)) {
break;
}
ItemStack shulkerStackItem = playerInventory.getItem(firstShulker);
int shulkerStackAmount = shulkerStackItem.getAmount();
if (shulkerBoxCount + shulkerStackAmount > 64) {
int shulkersRequired = 64 - shulkerBoxCount;
shulkerStackItem.setAmount(shulkerStackAmount - shulkersRequired);
shulkerBoxCount += shulkersRequired;
break;
} else {
shulkerBoxCount += shulkerStackAmount;
playerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
tempPlayerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
}
}
// Update the cursor only after collecting more than one shulker.
if (shulkerBoxCount != 1) {
ItemStack newShulkers = new ItemStack(shulkerType);
newShulkers.setAmount(shulkerBoxCount);
event.getWhoClicked().setItemOnCursor(newShulkers);
event.setCancelled(true);
}
}
}
}
@@ -1,42 +1,50 @@
package me.barny1094875.shulkerstackingog.ShulkerBoxHelpers;
package plugin.ShulkerBoxHelpers;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public class NormalLeftClick
{
public class NormalLeftClick {
public static void NormalLeftClickShulkerBox(ItemStack currentItem, ItemStack cursorItem, InventoryClickEvent event)
public static void NormalLeftClickShulkerBox(ItemStack currentItem, ItemStack cursorItem,
InventoryClickEvent event)
{
// check that both shulker boxes are empty
// get the inventories of the shulker boxes
// Read both inventories before stacking empty shulkers.
BlockStateMeta shulker1Meta = (BlockStateMeta) currentItem.getItemMeta();
BlockStateMeta shulker2Meta = (BlockStateMeta) cursorItem.getItemMeta();
ShulkerBox shulker1 = (ShulkerBox) shulker1Meta.getBlockState();
ShulkerBox shulker2 = (ShulkerBox) shulker2Meta.getBlockState();
// check the inventory of each shulker
if (shulker1.getInventory().isEmpty())
{
if (shulker2.getInventory().isEmpty())
{
if (currentItem.getAmount() + cursorItem.getAmount() <= 64)
{
if (shulker1.getInventory().isEmpty()) {
if (shulker2.getInventory().isEmpty()) {
if (currentItem.getAmount() + cursorItem.getAmount() <= 64) {
// add the shulker itemStacks together
event.getCurrentItem().setAmount(event.getCursor().getAmount() + event.getCurrentItem().getAmount());
event.getWhoClicked().getItemOnCursor().setAmount(0);
}
else
{
// add the shulkers until we are at 64
event.getWhoClicked().getItemOnCursor().setAmount((currentItem.getAmount() + cursorItem.getAmount()) - 64);
event.getCurrentItem()
.setAmount(event.getCursor().getAmount() + event.getCurrentItem().getAmount());
event.getWhoClicked().setItemOnCursor(new ItemStack(Material.AIR));
} else {
// Add shulkers until the target reaches 64.
event.getWhoClicked().getItemOnCursor()
.setAmount((currentItem.getAmount() + cursorItem.getAmount()) - 64);
event.getCurrentItem().setAmount(64);
}
// stop default behaviors
event.setCancelled(true);
}
}
}
}
@@ -1,34 +1,49 @@
package me.barny1094875.shulkerstackingog.ShulkerBoxHelpers;
package plugin.ShulkerBoxHelpers;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public class NormalRightClick
{
public class NormalRightClick {
public static void NormalRightClickShulkerBox(ItemStack currentItem, ItemStack cursorItem, InventoryClickEvent event)
public static void NormalRightClickShulkerBox(ItemStack currentItem, ItemStack cursorItem,
InventoryClickEvent event)
{
// check that both shulker boxes are empty
// get the inventories of the shulker boxes
// Read both inventories before stacking empty shulkers.
BlockStateMeta shulker1Meta = (BlockStateMeta) currentItem.getItemMeta();
BlockStateMeta shulker2Meta = (BlockStateMeta) cursorItem.getItemMeta();
ShulkerBox shulker1 = (ShulkerBox) shulker1Meta.getBlockState();
ShulkerBox shulker2 = (ShulkerBox) shulker2Meta.getBlockState();
// check the inventory of each shulker
if (shulker1.getInventory().isEmpty())
{
if (shulker2.getInventory().isEmpty())
{
if (currentItem.getAmount() < 64)
{
if (shulker1.getInventory().isEmpty()) {
if (shulker2.getInventory().isEmpty()) {
if (currentItem.getAmount() < 64) {
event.getCurrentItem().setAmount(currentItem.getAmount() + 1);
event.getCursor().setAmount(cursorItem.getAmount() - 1);
int newCursorAmount = cursorItem.getAmount() - 1;
if (newCursorAmount <= 0) {
event.getWhoClicked().setItemOnCursor(new ItemStack(Material.AIR));
} else {
event.getCursor().setAmount(newCursorAmount);
}
event.setCancelled(true);
}
}
}
}
}
@@ -0,0 +1,116 @@
package plugin.ShulkerBoxHelpers;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
public class ShiftRightLeftClick {
public static void ShiftRightLeftClickShulkerBox(InventoryClickEvent event) {
ItemStack source = event.getCurrentItem();
if (!ShulkerBoxUtils.isEmptyShulkerBox(source)) {
return;
}
InventoryView view = event.getView();
Inventory top = view.getTopInventory();
Inventory bottom = view.getBottomInventory();
InventoryType viewType = view.getType();
Material shulkerType = source.getType();
int rawSlot = event.getRawSlot();
int topSize = top.getSize();
boolean clickedTop = rawSlot < topSize;
// Cancel default handling before redistributing the stack.
event.setCancelled(true);
int remaining = source.getAmount();
if (viewType.equals(InventoryType.CRAFTING)) {
// Without a container open, shift within storage slots 0-35 only.
boolean fromHotbar = event.getSlotType().equals(InventoryType.SlotType.QUICKBAR);
int destStart = fromHotbar ? 9 : 0;
int destEnd = fromHotbar ? Math.min(bottom.getSize(), 36) : 9;
remaining = redistribute(bottom, destStart, destEnd, shulkerType, remaining);
} else {
Inventory destination = clickedTop ? bottom : top;
int destStart = 0;
// Limit player destinations to storage slots 0-35, including non-vanilla views.
int destEnd = (destination == bottom) ? Math.min(destination.getSize(), 36) : destination.getSize();
remaining = redistribute(destination, destStart, destEnd, shulkerType, remaining);
}
if (remaining <= 0) {
event.setCurrentItem(new ItemStack(Material.AIR));
} else {
event.setCurrentItem(new ItemStack(shulkerType, remaining));
}
}
private static int redistribute(Inventory inv, int start, int end, Material shulkerType, int amount) {
// Phase 1: top off existing empty stacks of the same material.
for (int i = start; i < end && amount > 0; i++) {
ItemStack slot = inv.getItem(i);
if (!ShulkerBoxUtils.isEmptyShulkerBox(slot)) {
continue;
}
if (!slot.getType().equals(shulkerType)) {
continue;
}
int space = 64 - slot.getAmount();
if (space <= 0) {
continue;
}
int moved = Math.min(space, amount);
slot.setAmount(slot.getAmount() + moved);
amount -= moved;
}
// Phase 2: drop leftovers into AIR slots, one stack at a time.
for (int i = start; i < end && amount > 0; i++) {
ItemStack slot = inv.getItem(i);
if (slot != null && slot.getType() != Material.AIR) {
continue;
}
int placed = Math.min(64, amount);
inv.setItem(i, new ItemStack(shulkerType, placed));
amount -= placed;
}
return amount;
}
}
@@ -0,0 +1,107 @@
package plugin.ShulkerBoxHelpers;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public final class ShulkerBoxUtils {
private ShulkerBoxUtils() {
}
public static boolean isShulkerBoxMaterial(ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR) {
return false;
}
return itemStack.getType().toString().contains("SHULKER_BOX");
}
public static boolean isEmptyShulkerBox(ItemStack itemStack) {
if (!isShulkerBoxMaterial(itemStack)) {
return false;
}
if (!(itemStack.getItemMeta() instanceof BlockStateMeta)) {
return false;
}
BlockStateMeta meta = (BlockStateMeta) itemStack.getItemMeta();
if (!(meta.getBlockState() instanceof ShulkerBox shulkerBox)) {
return false;
}
return shulkerBox.getInventory().isEmpty();
}
public static int mergeIntoExistingStacks(Inventory inventory, ItemStack prototype, int amountToAdd) {
for (int i = 0; i < inventory.getSize() && amountToAdd > 0; i++) {
ItemStack slot = inventory.getItem(i);
if (!isEmptyShulkerBox(slot)) {
continue;
}
if (!slot.getType().equals(prototype.getType())) {
continue;
}
int space = 64 - slot.getAmount();
if (space <= 0) {
continue;
}
int moved = Math.min(space, amountToAdd);
slot.setAmount(slot.getAmount() + moved);
amountToAdd -= moved;
}
return amountToAdd;
}
public static int fillEmptySlots(Inventory inventory, ItemStack prototype, int amountToAdd) {
for (int i = 0; i < inventory.getSize() && amountToAdd > 0; i++) {
ItemStack slot = inventory.getItem(i);
if (slot != null && slot.getType() != Material.AIR) {
continue;
}
int moved = Math.min(64, amountToAdd);
inventory.setItem(i, new ItemStack(prototype.getType(), moved));
amountToAdd -= moved;
}
return amountToAdd;
}
}
@@ -0,0 +1,45 @@
package plugin;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.plugin.java.JavaPlugin;
import plugin.Listeners.ShulkerBoxHopperHandler;
import plugin.Listeners.ShulkerBoxMergeHandler;
import plugin.Listeners.ShulkerBoxPickupHandler;
import plugin.Listeners.ShulkerBoxStackingController;
import plugin.Listeners.ShulkerCleanupHandler;
import plugin.Listeners.ShulkerDragDupePrevention;
import plugin.Listeners.ShulkerDragHandler;
public final class ShulkerStackingOG extends JavaPlugin {
private static ShulkerStackingOG plugin;
// Used to prevent duplication glitches from inventory drag events.
public static HashMap<UUID, Boolean> isInventoryClosed = new HashMap<>();
@Override
public void onEnable() {
plugin = this;
// Plugin startup logic.
getServer().getPluginManager().registerEvents(new ShulkerBoxStackingController(), this);
getServer().getPluginManager().registerEvents(new ShulkerBoxPickupHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerDragHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerDragDupePrevention(), this);
getServer().getPluginManager().registerEvents(new ShulkerBoxHopperHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerBoxMergeHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerCleanupHandler(), this);
}
public static ShulkerStackingOG getPlugin() {
return plugin;
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
name: ShulkerStacking-OG
version: '${version}'
main: me.barny1094875.shulkerstackingog.ShulkerStacking_OG
api-version: 1.18
authors: [Barny1094875]
api-version: '${apiVersion}'
main: plugin.ShulkerStackingOG
authors: [Barny1094875, NotAlexNoyle]