Add formatting

This commit is contained in:
NotAlexNoyle committed 2025-08-27 17:19:37 -04:00
1 parent 77ca73cef6
commit e7c4cfe662
98 files changed
+8984 -5537

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@
src/test/
build/
bin/
target/
.gradle/
*.iml
dependency-reduced-pom.xml
.classpath
+22 -3
View File
@@ -61,7 +61,6 @@ repositories {
mavenLocal()
}
}
}
/* ---------------------- Java project deps ---------------------------- */
@@ -69,7 +68,7 @@ dependencies {
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare Purpur API version to be packaged.
implementation("com.google.code.gson:gson:2.9.0")
implementation("com.github.GeyserMC:opennbt:1.5")
implementation("commons-lang:commons-lang:2.6")
implementation("commons-lang:commons-lang:2.6")
compileOnly(files("libs/ProtocolLib-5.0.jar")) // Import Legacy ProtocolLib API.
compileOnly("com.meowj:LangUtils:1.9")
compileOnly("com.viaversion:viaversion-api:5.0.3")
@@ -122,10 +121,30 @@ tasks.withType<JavaCompile>().configureEach {
options.encoding = "UTF-8" // Use UTF-8 file encoding.
}
/* ------------------------------- Checkstyle --------------------------- */
/* ----------------------------- 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.
}
+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>
+11 -6
View File
@@ -6,11 +6,16 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class C {
public static TextComponent text(String s) {
return LegacyComponentSerializer.legacySection().deserialize(s);
}
public static TextComponent text(String s) {
return LegacyComponentSerializer.legacySection().deserialize(s);
}
public static String string(Component c) {
return LegacyComponentSerializer.legacySection().serialize(c);
}
public static String string(Component c) {
return LegacyComponentSerializer.legacySection().serialize(c);
}
}
+284 -194
View File
@@ -51,221 +51,311 @@ import me.dadus33.chatitem.utils.Version;
public class ChatItem extends JavaPlugin {
private static final List<IPlaceholders> PLACEHOLDERS = new ArrayList<>();
public static List<IPlaceholders> getPlaceholders() {
return PLACEHOLDERS;
}
public static String replace(Player p, String text) {
for(IPlaceholders ip : getPlaceholders())
text = ip.replace(p, text);
return text;
}
private static final IPlatform platform = Utils.IS_PAPER ? new PaperPlatform() : new SpigotPlatform();
public static IPlatform getPlatform() {
return platform;
}
public final static int CFG_VER = 13;
public static boolean discordSrvSupport = false, hasNewVersion = false;
private static ChatItem instance;
private final String brandChannelName = Version.getVersion().isNewerOrEquals(Version.V1_13) ? "minecraft:brand" : "MC|Brand";
private final List<ChatManager> chatManager = new ArrayList<>();
private Storage storage;
private static final List<IPlaceholders> PLACEHOLDERS = new ArrayList<>();
public static void reload(CommandSender sender) {
ChatItem pl = getInstance();
if (pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
pl.reloadConfig();
pl.storage = new Storage(pl.getConfig());
//pl.chooseManagers();
Translation.load(pl);
InvShower.getInvShower().clear();
if(sender != null) {
if (!pl.storage.messageReload.isEmpty())
sender.sendMessage(pl.storage.messageReload);
}
ChatManager.setTesting(null);
}
public static List<IPlaceholders> getPlaceholders() {
public static ChatItem getInstance() {
return instance;
}
return PLACEHOLDERS;
public static void debug(String msg) {
if (getInstance().getStorage().debug)
getInstance().getLogger().info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S').replace(ChatManager.SEPARATOR_END, 'E'));
}
public static boolean hasDebug() {
return getInstance().getStorage().debug;
}
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
this.chatManager.add(new PacketEditingChatManager(this));
this.chatManager.add(new ChatListenerChatManager(this));
if(Utils.IS_PAPER) {
this.chatManager.add(new PaperChatManager(this));
this.chatManager.add(new OwnManager());
}
String managerName = getStorage().manager;
public static String replace(Player p, String text) {
switch (managerName.toLowerCase(Locale.ROOT)) {
case "both":
case "all":
case "auto":
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "paper":
case "packet":
case "chat":
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
default:
getLogger().severe("----- WARN -----");
getLogger().severe("Failed to find manager: " + managerName + ".");
getLogger().severe("Please reset your config and/or check wiki for more information");
getLogger().severe("Using default manager: chat.");
getLogger().severe("----- WARN -----");
break;
}
for (IPlaceholders ip : getPlaceholders())
text = ip.replace(p, text);
return text;
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
}
NamerManager.load(this);
PlayerNamerManager.load(this);
}
private static final IPlatform platform = Utils.IS_PAPER ? new PaperPlatform() : new SpigotPlatform();
public static List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat", "ItemsAdder");
}
public static IPlatform getPlatform() {
@Override
public void onEnable() {
// Save the instance (we're basically a singleton)
instance = this;
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase() + " (Platform: " + getPlatform().getName() + ")");
return platform;
// Load config
if (!new File(getDataFolder(), "config.yml").exists()) {
getLogger().info("--------------");
getLogger().info("");
getLogger().info("Welcome on ChatItem !");
getLogger().info("If you need help for setup, USE: /chatitem select");
getLogger().info("Then follow steps.");
getLogger().info("");
getLogger().info("--------------");
saveDefaultConfig();
}
storage = new Storage(getConfig());
}
// Commands
loadCommand(getCommand("cireload"), new CIReloadCommand());
loadCommand(getCommand("chatitem"), new ChatItemCommand());
public final static int CFG_VER = 13;
public static boolean discordSrvSupport = false, hasNewVersion = false;
private static ChatItem instance;
private final String brandChannelName = Version.getVersion().isNewerOrEquals(Version.V1_13) ? "minecraft:brand"
: "MC|Brand";
private final List<ChatManager> chatManager = new ArrayList<>();
private Storage storage;
// events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new JoinListener(), this);
pm.registerEvents(new InventoryListener(), this);
pm.registerEvents(new TranslationInventoryListener(), this);
pm.registerEvents(new ChatEventListener(), this);
public static void reload(CommandSender sender) {
chooseManagers();
ChatItem pl = getInstance();
if (pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
pl.reloadConfig();
pl.storage = new Storage(pl.getConfig());
// pl.chooseManagers();
Translation.load(pl);
InvShower.getInvShower().clear();
if (sender != null) {
StringJoiner plugins = new StringJoiner(", ");
if (pm.isPluginEnabled("DiscordSRV")) {
discordSrvSupport = true;
plugins.add("DiscordSRV");
}
if (pm.isPluginEnabled("ChatControl") && ReflectionUtils.isClassExist("org.mineacademy.chatcontrol.settings.Settings")) {
ChatControlSupport.init(this);
plugins.add("ChatControl");
}
if (pm.isPluginEnabled("ChatManager") && ReflectionUtils.isClassExist("me.h1dd3nxn1nja.chatmanager.Main")) {
ChatManagerSupport.init(this);
plugins.add("ChatManager");
}
if (pm.isPluginEnabled("EcoEnchants") && EcoEnchantsSupport.load()) {
plugins.add("EcoEnchants");
}
if (pm.isPluginEnabled("PlaceholderAPI")) {
plugins.add("PlaceholderAPI");
PLACEHOLDERS.add(new PlaceholderAPIHook());
}
if (pm.isPluginEnabled("Essentials")) {
plugins.add("Essentials");
PLACEHOLDERS.add(new EssentialsPlaceholdersHook());
}
if (pm.isPluginEnabled("MVdWPlaceholderAPI")) {
plugins.add("MVdWPlaceholderAPI");
PLACEHOLDERS.add(new MVdWPlaceholderAPIHook());
}
if (pm.isPluginEnabled("Vault")) {
plugins.add("Vault");
PLACEHOLDERS.add(new VaultPlaceholderHook());
}
if (!pl.storage.messageReload.isEmpty())
sender.sendMessage(pl.storage.messageReload);
if (plugins.length() > 0)
getLogger().info("Load " + plugins.toString() + " support.");
}
PLACEHOLDERS.add(new OwnPlaceholder());
Translation.load(this);
ChatManager.setTesting(null);
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> ItemPlayer.getPlayer(p).setClientName(new String(msg).substring(1)));
}
if (storage.checkUpdate) {
CompletableFuture.runAsync(() -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
if (Strings.isNullOrEmpty(content))
return;
SemVer currentVersion = SemVer.parse(getPlatform().getPluginVersion(this));
if (currentVersion == null)
return;
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getPlatform().getPluginVersion(this));
if (hasNewVersion)
getLogger().info(storage.updateMessage);
}
});
}
}
public static ChatItem getInstance() {
public void loadCommand(PluginCommand cmd, Object obj) {
if (obj instanceof CommandExecutor)
cmd.setExecutor((CommandExecutor) obj);
if (obj instanceof TabCompleter)
cmd.setTabCompleter((TabCompleter) obj);
}
return instance;
public Storage getStorage() {
return storage;
}
}
public List<ChatManager> getChatManager() {
return chatManager;
}
public boolean isManagerEnabled(String id) {
for (ChatManager cm : chatManager) {
if(cm.getId().equalsIgnoreCase(id))
return true;
}
return false;
}
public static void debug(String msg) {
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for (ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
}
if (getInstance().getStorage().debug)
getInstance().getLogger()
.info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S').replace(ChatManager.SEPARATOR_END, 'E'));
}
public static boolean hasDebug() {
return getInstance().getStorage().debug;
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
this.chatManager.add(new PacketEditingChatManager(this));
this.chatManager.add(new ChatListenerChatManager(this));
if (Utils.IS_PAPER) {
this.chatManager.add(new PaperChatManager(this));
this.chatManager.add(new OwnManager());
}
String managerName = getStorage().manager;
switch (managerName.toLowerCase(Locale.ROOT)) {
case "both":
case "all":
case "auto":
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "paper":
case "packet":
case "chat":
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
default:
getLogger().severe("----- WARN -----");
getLogger().severe("Failed to find manager: " + managerName + ".");
getLogger().severe("Please reset your config and/or check wiki for more information");
getLogger().severe("Using default manager: chat.");
getLogger().severe("----- WARN -----");
break;
}
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
NamerManager.load(this);
PlayerNamerManager.load(this);
}
public static List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat", "ItemsAdder");
}
@Override
public void onEnable() {
// Save the instance (we're basically a singleton)
instance = this;
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase() + " (Platform: "
+ getPlatform().getName() + ")");
// Load config
if (!new File(getDataFolder(), "config.yml").exists()) {
getLogger().info("--------------");
getLogger().info("");
getLogger().info("Welcome on ChatItem !");
getLogger().info("If you need help for setup, USE: /chatitem select");
getLogger().info("Then follow steps.");
getLogger().info("");
getLogger().info("--------------");
saveDefaultConfig();
}
storage = new Storage(getConfig());
// Commands
loadCommand(getCommand("cireload"), new CIReloadCommand());
loadCommand(getCommand("chatitem"), new ChatItemCommand());
// events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new JoinListener(), this);
pm.registerEvents(new InventoryListener(), this);
pm.registerEvents(new TranslationInventoryListener(), this);
pm.registerEvents(new ChatEventListener(), this);
chooseManagers();
StringJoiner plugins = new StringJoiner(", ");
if (pm.isPluginEnabled("DiscordSRV")) {
discordSrvSupport = true;
plugins.add("DiscordSRV");
}
if (pm.isPluginEnabled("ChatControl")
&& ReflectionUtils.isClassExist("org.mineacademy.chatcontrol.settings.Settings"))
{
ChatControlSupport.init(this);
plugins.add("ChatControl");
}
if (pm.isPluginEnabled("ChatManager") && ReflectionUtils.isClassExist("me.h1dd3nxn1nja.chatmanager.Main")) {
ChatManagerSupport.init(this);
plugins.add("ChatManager");
}
if (pm.isPluginEnabled("EcoEnchants") && EcoEnchantsSupport.load()) {
plugins.add("EcoEnchants");
}
if (pm.isPluginEnabled("PlaceholderAPI")) {
plugins.add("PlaceholderAPI");
PLACEHOLDERS.add(new PlaceholderAPIHook());
}
if (pm.isPluginEnabled("Essentials")) {
plugins.add("Essentials");
PLACEHOLDERS.add(new EssentialsPlaceholdersHook());
}
if (pm.isPluginEnabled("MVdWPlaceholderAPI")) {
plugins.add("MVdWPlaceholderAPI");
PLACEHOLDERS.add(new MVdWPlaceholderAPIHook());
}
if (pm.isPluginEnabled("Vault")) {
plugins.add("Vault");
PLACEHOLDERS.add(new VaultPlaceholderHook());
}
if (plugins.length() > 0)
getLogger().info("Load " + plugins.toString() + " support.");
PLACEHOLDERS.add(new OwnPlaceholder());
Translation.load(this);
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName,
(chan, p, msg) -> ItemPlayer.getPlayer(p).setClientName(new String(msg).substring(1)));
if (storage.checkUpdate) {
CompletableFuture.runAsync(() -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
if (Strings.isNullOrEmpty(content))
return;
SemVer currentVersion = SemVer.parse(getPlatform().getPluginVersion(this));
if (currentVersion == null)
return;
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getPlatform().getPluginVersion(this));
if (hasNewVersion)
getLogger().info(storage.updateMessage);
}
});
}
}
public void loadCommand(PluginCommand cmd, Object obj) {
if (obj instanceof CommandExecutor)
cmd.setExecutor((CommandExecutor) obj);
if (obj instanceof TabCompleter)
cmd.setTabCompleter((TabCompleter) obj);
}
public Storage getStorage() {
return storage;
}
public List<ChatManager> getChatManager() {
return chatManager;
}
public boolean isManagerEnabled(String id) {
for (ChatManager cm : chatManager) {
if (cm.getId().equalsIgnoreCase(id))
return true;
}
return false;
}
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for (ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
}
public boolean isHasNewVersion() {
return hasNewVersion;
}
public boolean isHasNewVersion() {
return hasNewVersion;
}
}
+102 -69
View File
@@ -11,73 +11,106 @@ import me.dadus33.chatitem.utils.Version;
public class ItemPlayer {
private static final ConcurrentHashMap<UUID, ItemPlayer> PLAYERS = new ConcurrentHashMap<>();
public static ItemPlayer getPlayer(Player p) {
return PLAYERS.computeIfAbsent(p.getUniqueId(), ItemPlayer::new);
}
public static ItemPlayer getPlayer(UUID uuid) {
return PLAYERS.computeIfAbsent(uuid, ItemPlayer::new);
}
private final UUID uuid;
private int protocolVersion = 0;
private Version version = null;
private String clientName = "unknow";
public ItemPlayer(UUID uuid) {
this.uuid = uuid;
Player p = Bukkit.getPlayer(uuid);
if(p != null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p));
}
public UUID getUUID() {
return uuid;
}
public Player getPlayer() {
return Bukkit.getPlayer(uuid);
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public int getProtocolVersion() {
if(protocolVersion == 0)
setProtocolVersion(PlayerVersionManager.getPlayerVersionAdapter().getProtocolVersion(getPlayer()));
return protocolVersion;
}
public void setProtocolVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
if(version == Version.getVersion()) {// if is default
version = Version.getVersion(protocolVersion);
ChatItem.debug("Detected version " + version.name() + " (protocol: " + protocolVersion + ")");
}
}
public Version getVersion() {
if(version == null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(getPlayer()));
return version;
}
public void setVersion(Version version) {
this.version = version;
if(protocolVersion == 0)
this.protocolVersion = version.MAX_VER;
}
public boolean isBuggedClient() {
return (!getVersion().isNewerOrEquals(Version.V1_15) && Version.getVersion().isNewerOrEquals(Version.V1_16));
}
@Override
public String toString() {
return "ItemPlayer[uuid=" + uuid + ",name=" + (getPlayer() != null ? getPlayer().getName() : "-") + ",version=" + version.name() + ",protocol=" + protocolVersion + ",client=" + clientName + "]";
}
private static final ConcurrentHashMap<UUID, ItemPlayer> PLAYERS = new ConcurrentHashMap<>();
public static ItemPlayer getPlayer(Player p) {
return PLAYERS.computeIfAbsent(p.getUniqueId(), ItemPlayer::new);
}
public static ItemPlayer getPlayer(UUID uuid) {
return PLAYERS.computeIfAbsent(uuid, ItemPlayer::new);
}
private final UUID uuid;
private int protocolVersion = 0;
private Version version = null;
private String clientName = "unknow";
public ItemPlayer(UUID uuid) {
this.uuid = uuid;
Player p = Bukkit.getPlayer(uuid);
if (p != null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p));
}
public UUID getUUID() {
return uuid;
}
public Player getPlayer() {
return Bukkit.getPlayer(uuid);
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public int getProtocolVersion() {
if (protocolVersion == 0)
setProtocolVersion(PlayerVersionManager.getPlayerVersionAdapter().getProtocolVersion(getPlayer()));
return protocolVersion;
}
public void setProtocolVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
if (version == Version.getVersion()) {// if is default
version = Version.getVersion(protocolVersion);
ChatItem.debug("Detected version " + version.name() + " (protocol: " + protocolVersion + ")");
}
}
public Version getVersion() {
if (version == null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(getPlayer()));
return version;
}
public void setVersion(Version version) {
this.version = version;
if (protocolVersion == 0)
this.protocolVersion = version.MAX_VER;
}
public boolean isBuggedClient() {
return (!getVersion().isNewerOrEquals(Version.V1_15) && Version.getVersion().isNewerOrEquals(Version.V1_16));
}
@Override
public String toString() {
return "ItemPlayer[uuid=" + uuid + ",name=" + (getPlayer() != null ? getPlayer().getName() : "-") + ",version="
+ version.name() + ",protocol=" + protocolVersion + ",client=" + clientName + "]";
}
}
+115 -76
View File
@@ -7,80 +7,119 @@ import me.dadus33.chatitem.utils.Colors;
public enum ItemSlot {
HAND("", false),
HELMET("helmet", false),
CHESTPLATE("chestplate", false),
LEGGINGS("leggings", false),
BOOTS("boots", false),
INVENTORY("inventory", true),
ENDERCHEST("enderchest", true);
private final boolean command;
private final String key;
private ItemSlot(String key, boolean command) {
this.command = command;
this.key = key;
}
public String getKey() {
return key;
}
public boolean isBasic() {
return key.equalsIgnoreCase("");
}
public boolean isCommand() {
return command;
}
public List<String> getPlaceholders() {
return ChatItem.getInstance().getConfig().getStringList(isBasic() ? "general.placeholders" : "general.other-placeholders." + key + ".keys");
}
public boolean isEnabled() {
return isBasic() || ChatItem.getInstance().getConfig().getBoolean("general.other-placeholders." + key + ".enabled", true);
}
public boolean isDenyIfNoItem() {
return ChatItem.getInstance().getConfig().getBoolean("general" + (isBasic() ? "" : ".other-placeholders." + key) + ".deny-if-no-item", true);
}
public String getShowMessage() {
return Colors.color(ChatItem.getInstance().getConfig().getString("general" + (isBasic() ? "" : ".other-placeholders." + key) + ".show", ""));
}
public boolean hasPlaceholders(String message) {
for (String rep : getPlaceholders()) {
if (message.contains(rep)) {
return true;
}
}
return false;
}
public String replacePlaceholdersToSeparator(String message) {
for(String rep : getPlaceholders())
message = message.replace(rep, Character.toString(ChatManager.SEPARATOR));
return message;
}
public static ItemSlot getItemSlotFromMessage(String message) {
for(ItemSlot slot : ItemSlot.values()) {
if(slot.isEnabled() && slot.hasPlaceholders(message)) {
return slot;
}
}
return null;
}
public static ItemSlot getItemSlotByKey(String key) {
for(ItemSlot slot : ItemSlot.values()) {
if(slot.isEnabled() && slot.getKey().equalsIgnoreCase(key)) {
return slot;
}
}
return null;
}
HAND("", false), HELMET("helmet", false), CHESTPLATE("chestplate", false), LEGGINGS("leggings", false),
BOOTS("boots", false), INVENTORY("inventory", true), ENDERCHEST("enderchest", true);
private final boolean command;
private final String key;
private ItemSlot(String key, boolean command) {
this.command = command;
this.key = key;
}
public String getKey() {
return key;
}
public boolean isBasic() {
return key.equalsIgnoreCase("");
}
public boolean isCommand() {
return command;
}
public List<String> getPlaceholders() {
return ChatItem.getInstance().getConfig()
.getStringList(isBasic() ? "general.placeholders" : "general.other-placeholders." + key + ".keys");
}
public boolean isEnabled() {
return isBasic() || ChatItem.getInstance().getConfig()
.getBoolean("general.other-placeholders." + key + ".enabled", true);
}
public boolean isDenyIfNoItem() {
return ChatItem.getInstance().getConfig()
.getBoolean("general" + (isBasic() ? "" : ".other-placeholders." + key) + ".deny-if-no-item", true);
}
public String getShowMessage() {
return Colors.color(ChatItem.getInstance().getConfig()
.getString("general" + (isBasic() ? "" : ".other-placeholders." + key) + ".show", ""));
}
public boolean hasPlaceholders(String message) {
for (String rep : getPlaceholders()) {
if (message.contains(rep)) {
return true;
}
}
return false;
}
public String replacePlaceholdersToSeparator(String message) {
for (String rep : getPlaceholders())
message = message.replace(rep, Character.toString(ChatManager.SEPARATOR));
return message;
}
public static ItemSlot getItemSlotFromMessage(String message) {
for (ItemSlot slot : ItemSlot.values()) {
if (slot.isEnabled() && slot.hasPlaceholders(message)) {
return slot;
}
}
return null;
}
public static ItemSlot getItemSlotByKey(String key) {
for (ItemSlot slot : ItemSlot.values()) {
if (slot.isEnabled() && slot.getKey().equalsIgnoreCase(key)) {
return slot;
}
}
return null;
}
}
+97 -73
View File
@@ -9,84 +9,108 @@ import me.dadus33.chatitem.utils.Colors;
public class Storage {
public String handName, nameFormat, amountFormat, commandFormat, manager, permissionName, buggedClientAction, language;
public final String messageNoPermission, messageDeny, messageReload, messageCooldown, messageLimit, messageIgnoredItem;
public final String SECONDS, minutes, hours;
public final String updateMessage, updateHover;
public final List<String> tooltipHand, tooltipBuggedClient, ignoredItems;
public boolean colorIfColored, addAmountForced, letMessageThrough, debug, handDisabled, showNoPermissionMessage, checkUpdate, permissionEnabled, cmdBroadcast, cmdShow, discordSrvSendMsg, replaceInConsole;
public int configVersion, limit, cooldown;
private FileConfiguration conf;
public String handName, nameFormat, amountFormat, commandFormat, manager, permissionName, buggedClientAction,
language;
public final String messageNoPermission, messageDeny, messageReload, messageCooldown, messageLimit,
messageIgnoredItem;
public final String SECONDS, minutes, hours;
public final String updateMessage, updateHover;
public final List<String> tooltipHand, tooltipBuggedClient, ignoredItems;
public boolean colorIfColored, addAmountForced, letMessageThrough, debug, handDisabled, showNoPermissionMessage,
checkUpdate, permissionEnabled, cmdBroadcast, cmdShow, discordSrvSendMsg, replaceInConsole;
public int configVersion, limit, cooldown;
private FileConfiguration conf;
public Storage(FileConfiguration cnf) {
this.conf = cnf;
configVersion = conf.getInt("config-version", 13);
checkConfigVersion();
this.manager = conf.getString("manager", "auto");
if(manager == "both")
manager = "all";
language = conf.getString("general.language", "en_gb");
debug = conf.getBoolean("debug", false);
nameFormat = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
amountFormat = color(conf.getString("general.amount-format", "x{times}"));
commandFormat = color(conf.getString("general.command-format", "&6%name%'s item is %item%"));
colorIfColored = conf.getBoolean("general.color-if-already-colored", true);
letMessageThrough = conf.getBoolean("general.let-message-through", true);
addAmountForced = conf.getBoolean("general.force-add-amount", true);
limit = conf.getInt("general.limit", 8);
cooldown = conf.getInt("general.cooldown", 60);
showNoPermissionMessage = conf.getBoolean("general.show-no-permission-message.normal", true);
permissionEnabled = conf.getBoolean("general.permission.enabled", false);
permissionName = conf.getString("general.permission.name", "chatitem.use");
handDisabled = conf.getBoolean("general.hand.disabled", false);
handName = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
tooltipHand = conf.getStringList("general.hand.tooltip").stream().map(Storage::color).collect(Collectors.toList());
buggedClientAction = conf.getString("general.bugged_client.action", "show_both");
tooltipBuggedClient = conf.getStringList("general.bugged_client.tooltip").stream().map(Storage::color).collect(Collectors.toList());
ignoredItems = conf.getStringList("general.ignored_items");
checkUpdate = conf.getBoolean("general.check-update", true);
cmdShow = conf.getBoolean("general.sub-commands.broadcast", true);
cmdBroadcast = conf.getBoolean("general.sub-commands.show", true);
replaceInConsole = conf.getBoolean("general.replace-in-console", true);
messageDeny = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
messageReload = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
messageNoPermission = color(conf.getString("messages.no-permission", "&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"));
messageCooldown = color(conf.getString("messages.cooldown-message", "&c&lYou can only use items in chat once a minute! You have {remaining} left!"));
updateMessage = color(conf.getString("messages.join-update.message", "&cA new version of ChatItem is available. &aClick here to download."));
updateHover = color(conf.getString("messages.join-update.hover", "&6Click to go to spigot page !"));
messageLimit = color(conf.getString("messages.limit-message", "&c&lYou can only add 8 item placeholders per message!"));
messageIgnoredItem = color(conf.getString("messages.ignored-item", "&cThis item is not allowed to be showed."));
discordSrvSendMsg = conf.getBoolean("discord-srv-send-our", true);
public Storage(FileConfiguration cnf) {
SECONDS = color(conf.getString("messages.seconds", " seconds"));
minutes = color(conf.getString("messages.minutes", " minutes"));
hours = color(conf.getString("messages.hours", " hours"));
colorStringList(tooltipHand);
}
this.conf = cnf;
configVersion = conf.getInt("config-version", 13);
checkConfigVersion();
this.manager = conf.getString("manager", "auto");
if (manager == "both")
manager = "all";
language = conf.getString("general.language", "en_gb");
debug = conf.getBoolean("debug", false);
nameFormat = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
amountFormat = color(conf.getString("general.amount-format", "x{times}"));
commandFormat = color(conf.getString("general.command-format", "&6%name%'s item is %item%"));
colorIfColored = conf.getBoolean("general.color-if-already-colored", true);
letMessageThrough = conf.getBoolean("general.let-message-through", true);
addAmountForced = conf.getBoolean("general.force-add-amount", true);
limit = conf.getInt("general.limit", 8);
cooldown = conf.getInt("general.cooldown", 60);
showNoPermissionMessage = conf.getBoolean("general.show-no-permission-message.normal", true);
permissionEnabled = conf.getBoolean("general.permission.enabled", false);
permissionName = conf.getString("general.permission.name", "chatitem.use");
handDisabled = conf.getBoolean("general.hand.disabled", false);
handName = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
tooltipHand = conf.getStringList("general.hand.tooltip").stream().map(Storage::color)
.collect(Collectors.toList());
buggedClientAction = conf.getString("general.bugged_client.action", "show_both");
tooltipBuggedClient = conf.getStringList("general.bugged_client.tooltip").stream().map(Storage::color)
.collect(Collectors.toList());
ignoredItems = conf.getStringList("general.ignored_items");
checkUpdate = conf.getBoolean("general.check-update", true);
cmdShow = conf.getBoolean("general.sub-commands.broadcast", true);
cmdBroadcast = conf.getBoolean("general.sub-commands.show", true);
replaceInConsole = conf.getBoolean("general.replace-in-console", true);
messageDeny = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
messageReload = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
messageNoPermission = color(conf.getString("messages.no-permission",
"&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"));
messageCooldown = color(conf.getString("messages.cooldown-message",
"&c&lYou can only use items in chat once a minute! You have {remaining} left!"));
updateMessage = color(conf.getString("messages.join-update.message",
"&cA new version of ChatItem is available. &aClick here to download."));
updateHover = color(conf.getString("messages.join-update.hover", "&6Click to go to spigot page !"));
messageLimit = color(
conf.getString("messages.limit-message", "&c&lYou can only add 8 item placeholders per message!"));
messageIgnoredItem = color(conf.getString("messages.ignored-item", "&cThis item is not allowed to be showed."));
discordSrvSendMsg = conf.getBoolean("discord-srv-send-our", true);
public static String color(String s) {
return s == null || s.isEmpty() ? s : Colors.translateAlternateColorCodes('&', s);
}
SECONDS = color(conf.getString("messages.seconds", " seconds"));
minutes = color(conf.getString("messages.minutes", " minutes"));
hours = color(conf.getString("messages.hours", " hours"));
colorStringList(tooltipHand);
private static void colorStringList(List<String> input) {
for (int i = 0; i < input.size(); ++i) {
input.set(i, color(input.get(i)));
}
}
}
private void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != configVersion) {
ChatItem pl = ChatItem.getInstance();
pl.getLogger().warning("ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
performOverwrite();
conf = pl.getConfig();
pl.getLogger().warning("Replacement complete!");
}
}
public static String color(String s) {
private void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
return s == null || s.isEmpty() ? s : Colors.translateAlternateColorCodes('&', s);
}
private static void colorStringList(List<String> input) {
for (int i = 0; i < input.size(); ++i) {
input.set(i, color(input.get(i)));
}
}
private void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != configVersion) {
ChatItem pl = ChatItem.getInstance();
pl.getLogger().warning(
"ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
performOverwrite();
conf = pl.getConfig();
pl.getLogger().warning("Replacement complete!");
}
}
private void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
}
@@ -23,102 +23,160 @@ import me.dadus33.chatitem.utils.Utils;
@SuppressWarnings("deprecation")
public class Translation {
private static File folder;
private static YamlConfiguration legacy, allLangsConfig;
private static JsonObject messages;
private static HashMap<String, String> allLangs = new HashMap<>();
private static File folder;
private static YamlConfiguration legacy, allLangsConfig;
private static JsonObject messages;
private static HashMap<String, String> allLangs = new HashMap<>();
public static void load(ChatItem pl) {
folder = new File(pl.getDataFolder(), "lang");
if (!folder.exists())
folder.mkdir();
legacy = Utils.copyLoadFile(folder, "legacy.yml", "lang/legacy.yml");
allLangsConfig = Utils.copyLoadFile(pl.getDataFolder(), "langs.yml", "langs.yml");
public static void load(ChatItem pl) {
allLangsConfig.getStringList("all").forEach(langKey -> {
try {
JsonObject content = JsonParser.parseReader(new InputStreamReader(pl.getResource("lang/" + langKey + ".json"))).getAsJsonObject();
allLangs.put(langKey, content.get("language.name").getAsString() + " (" + content.get("language.region").getAsString() + ")");
} catch (Exception e) {
pl.getLogger().severe("Failed to load lang with key " + langKey + " : " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
allLangs = allLangs.entrySet().stream().sorted(Entry.comparingByValue()).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
loadLang(pl.getStorage().language);
}
folder = new File(pl.getDataFolder(), "lang");
if (!folder.exists())
folder.mkdir();
legacy = Utils.copyLoadFile(folder, "legacy.yml", "lang/legacy.yml");
allLangsConfig = Utils.copyLoadFile(pl.getDataFolder(), "langs.yml", "langs.yml");
public static HashMap<String, String> getAllLangs() {
return allLangs;
}
public static JsonObject getMessages() {
return messages;
}
public static String getMessage(String key) {
JsonElement result = messages.get(key);
return result == null ? "" : result.getAsString();
}
public static void loadLang(String lang) {
ChatItem pl = ChatItem.getInstance();
File langFile = new File(folder, lang + ".json");
if (!langFile.exists()) {
if (pl.getResource("lang/" + lang + ".json") != null) {
Utils.copyFile("lang/" + lang + ".json", langFile);
} else {
pl.getLogger().severe("Failed to find lang file for " + lang);
if(lang != "en_gb")
loadLang("en_gb");
return;
}
}
allLangsConfig.getStringList("all").forEach(langKey -> {
try {
messages = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
} catch (Exception e) {
e.printStackTrace();
}
pl.getLogger().info("Loaded translation for " + lang + ".");
}
try {
public static String get(ItemStack item) {
String key = (item.getType().isBlock() ? "block" : "item") + ".minecraft." + item.getType().name().toLowerCase();
if (messages != null && messages.has(key)) {
return messages.get(key).getAsString();
} else
ChatItem.debug("Failed to find translation for " + key);
return legacy.getString(item.getType().name() + "." + item.getDurability(), item.getType().name().toLowerCase().replace("_", " "));
}
public static String getOr(ItemStack item, String def) {
String key = (item.getType().isBlock() ? "block" : "item") + ".minecraft." + item.getType().name().toLowerCase();
if (messages != null && messages.has(key)) {
return messages.get(key).getAsString();
} else
ChatItem.debug("Failed to find translation for " + key);
return legacy.getString(item.getType().name() + "." + item.getDurability(), def);
}
JsonObject content = JsonParser
.parseReader(new InputStreamReader(pl.getResource("lang/" + langKey + ".json")))
.getAsJsonObject();
allLangs.put(langKey, content.get("language.name").getAsString() + " ("
+ content.get("language.region").getAsString() + ")");
} catch (Exception e) {
pl.getLogger().severe("Failed to load lang with key " + langKey + " : " + e.getMessage() + " ("
+ e.getStackTrace()[0].toString() + ")");
}
});
allLangs = allLangs.entrySet().stream().sorted(Entry.comparingByValue())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
loadLang(pl.getStorage().language);
}
public static HashMap<String, String> getAllLangs() {
return allLangs;
}
public static JsonObject getMessages() {
return messages;
}
public static String getMessage(String key) {
JsonElement result = messages.get(key);
return result == null ? "" : result.getAsString();
}
public static void loadLang(String lang) {
ChatItem pl = ChatItem.getInstance();
File langFile = new File(folder, lang + ".json");
if (!langFile.exists()) {
if (pl.getResource("lang/" + lang + ".json") != null) {
Utils.copyFile("lang/" + lang + ".json", langFile);
} else {
pl.getLogger().severe("Failed to find lang file for " + lang);
if (lang != "en_gb")
loadLang("en_gb");
return;
}
}
try {
messages = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
} catch (Exception e) {
e.printStackTrace();
}
pl.getLogger().info("Loaded translation for " + lang + ".");
}
public static String get(ItemStack item) {
String key = (item.getType().isBlock() ? "block" : "item") + ".minecraft."
+ item.getType().name().toLowerCase();
if (messages != null && messages.has(key)) {
return messages.get(key).getAsString();
} else
ChatItem.debug("Failed to find translation for " + key);
return legacy.getString(item.getType().name() + "." + item.getDurability(),
item.getType().name().toLowerCase().replace("_", " "));
}
public static String getOr(ItemStack item, String def) {
String key = (item.getType().isBlock() ? "block" : "item") + ".minecraft."
+ item.getType().name().toLowerCase();
if (messages != null && messages.has(key)) {
return messages.get(key).getAsString();
} else
ChatItem.debug("Failed to find translation for " + key);
return legacy.getString(item.getType().name() + "." + item.getDurability(), def);
}
protected void thisMethodShouldNotBeUsed_InsteadToUpdateLangFileFromLocalInstall() throws Exception {
File dir = new File("dir/to/result");
File folder = new File("C:\\Dir\\To\\AppData\\Roaming\\.minecraft\\assets");// here we are looking for 1.19
JsonObject json = JsonParser.parseReader(new FileReader(new File(folder, "indexes/1.19.json")))
.getAsJsonObject().get("objects").getAsJsonObject();
for (String key : json.keySet()) {
if (key.startsWith("minecraft/lang")) { // only lang files
String lang = key.toString().replace("minecraft/lang/", "");
String hash = json.get(key).getAsJsonObject().get("hash").getAsString();
File langFile = new File(folder, "objects/" + hash.substring(0, 2) + "/" + hash);
JsonObject langs = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
for (String langKey : new ArrayList<>(langs.keySet())) {
if (!(langKey.startsWith("block.") || langKey.startsWith("language"))) { // only what we want
langs.remove(langKey); // removing not needed
}
}
File langDir = new File(dir, lang);
Files.write(langDir.toPath(), Arrays.asList(langs.toString()));
System.out.println("Copied " + lang); // using sysout as it's made for basic java, not mc
}
}
}
protected void thisMethodShouldNotBeUsed_InsteadToUpdateLangFileFromLocalInstall() throws Exception {
File dir = new File("dir/to/result");
File folder = new File("C:\\Dir\\To\\AppData\\Roaming\\.minecraft\\assets");// here we are looking for 1.19
JsonObject json = JsonParser.parseReader(new FileReader(new File(folder, "indexes/1.19.json"))).getAsJsonObject().get("objects").getAsJsonObject();
for (String key : json.keySet()) {
if (key.startsWith("minecraft/lang")) { // only lang files
String lang = key.toString().replace("minecraft/lang/", "");
String hash = json.get(key).getAsJsonObject().get("hash").getAsString();
File langFile = new File(folder, "objects/" + hash.substring(0, 2) + "/" + hash);
JsonObject langs = JsonParser.parseReader(new FileReader(langFile)).getAsJsonObject();
for (String langKey : new ArrayList<>(langs.keySet())) {
if (!(langKey.startsWith("block.") || langKey.startsWith("language"))) { // only what we want
langs.remove(langKey); // removing not needed
}
}
File langDir = new File(dir, lang);
Files.write(langDir.toPath(), Arrays.asList(langs.toString()));
System.out.println("Copied " + lang); // using sysout as it's made for basic java, not mc
}
}
}
}
@@ -12,86 +12,123 @@ import me.dadus33.chatitem.ItemSlot;
import me.dadus33.chatitem.utils.Utils;
public class Chat {
private static int actualId = 0;
private static final List<Chat> CHAT = new ArrayList<>();
public static Optional<Chat> getChat(int id) {
synchronized (CHAT) {
CHAT.removeIf(Chat::isOld);
return CHAT.stream().filter(o -> o.getId() == id).findFirst();
}
}
public static Chat create(Player p, String message, ChatAction action) {
return new Chat(actualId++, p, message, action);
}
public static Chat getFrom(String message) {
boolean found = false;
String id = "";
for(char c : ChatManager.fixSeparator(message).toCharArray()) {
if(c == ChatManager.SEPARATOR)
found = true;
else if(c == ChatManager.SEPARATOR_END)
break;
else if(found)
id += c;
}
ChatItem.debug("Search in " + message + ", id found: " + id);
return (id != "" && Utils.isInteger(id)) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private final long time;
private final int id;
private final Player p;
private final String message;
private final ChatAction action;
public Chat(int id, Player p, String message, ChatAction action) {
this.time = System.currentTimeMillis();
this.id = id;
this.p = p;
this.message = message;
this.action = action;
CHAT.add(this);
}
public long getTime() {
return time;
}
public int getId() {
return id;
}
public Player getPlayer() {
return p;
}
public String getMessage() {
return message;
}
public ItemSlot getSlot() {
return action.getSlot();
}
public ChatAction getAction() {
return action;
}
public ItemPlayer getItemPlayer() {
return ItemPlayer.getPlayer(getPlayer());
}
private boolean isOld() {
return System.currentTimeMillis() > time + 10000;
}
public void remove() {
CHAT.remove(this);
}
@Override
public String toString() {
return "Chat{id=" + id + ",message=" + message + ",time=" + time + "}";
}
private static int actualId = 0;
private static final List<Chat> CHAT = new ArrayList<>();
public static Optional<Chat> getChat(int id) {
synchronized (CHAT) {
CHAT.removeIf(Chat::isOld);
return CHAT.stream().filter(o -> o.getId() == id).findFirst();
}
}
public static Chat create(Player p, String message, ChatAction action) {
return new Chat(actualId++, p, message, action);
}
public static Chat getFrom(String message) {
boolean found = false;
String id = "";
for (char c : ChatManager.fixSeparator(message).toCharArray()) {
if (c == ChatManager.SEPARATOR)
found = true;
else if (c == ChatManager.SEPARATOR_END)
break;
else if (found)
id += c;
}
ChatItem.debug("Search in " + message + ", id found: " + id);
return (id != "" && Utils.isInteger(id)) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private final long time;
private final int id;
private final Player p;
private final String message;
private final ChatAction action;
public Chat(int id, Player p, String message, ChatAction action) {
this.time = System.currentTimeMillis();
this.id = id;
this.p = p;
this.message = message;
this.action = action;
CHAT.add(this);
}
public long getTime() {
return time;
}
public int getId() {
return id;
}
public Player getPlayer() {
return p;
}
public String getMessage() {
return message;
}
public ItemSlot getSlot() {
return action.getSlot();
}
public ChatAction getAction() {
return action;
}
public ItemPlayer getItemPlayer() {
return ItemPlayer.getPlayer(getPlayer());
}
private boolean isOld() {
return System.currentTimeMillis() > time + 10000;
}
public void remove() {
CHAT.remove(this);
}
@Override
public String toString() {
return "Chat{id=" + id + ",message=" + message + ",time=" + time + "}";
}
}
@@ -8,53 +8,72 @@ import me.dadus33.chatitem.ItemSlot;
public class ChatAction {
private boolean hasItem;
private ItemSlot slot;
private String command;
private ItemStack item;
private Player origin;
public ChatAction(ItemSlot slot, Player origin, ItemStack item, String command) {
this.slot = slot;
this.item = item == null ? new ItemStack(Material.AIR) : item;
this.command = command;
this.origin = origin;
this.hasItem = true;
}
public ChatAction(ItemSlot slot, Player origin, String command) {
this.slot = slot;
this.command = command;
this.origin = origin;
this.hasItem = false;
}
public Player getOrigin() {
return origin;
}
public ItemSlot getSlot() {
return slot;
}
public boolean hasItem() {
return hasItem;
}
public String getCommand() {
return command;
}
public boolean hasCommand() {
return command != null && command != "";
}
public ItemStack getItem() {
return item == null ? new ItemStack(Material.AIR) : item;
}
@Override
public String toString() {
return "ChatAction[slot=" + slot + ",command=" + command + ",item=" + item + ",origin=" + origin + "]";
}
private boolean hasItem;
private ItemSlot slot;
private String command;
private ItemStack item;
private Player origin;
public ChatAction(ItemSlot slot, Player origin, ItemStack item, String command) {
this.slot = slot;
this.item = item == null ? new ItemStack(Material.AIR) : item;
this.command = command;
this.origin = origin;
this.hasItem = true;
}
public ChatAction(ItemSlot slot, Player origin, String command) {
this.slot = slot;
this.command = command;
this.origin = origin;
this.hasItem = false;
}
public Player getOrigin() {
return origin;
}
public ItemSlot getSlot() {
return slot;
}
public boolean hasItem() {
return hasItem;
}
public String getCommand() {
return command;
}
public boolean hasCommand() {
return command != null && command != "";
}
public ItemStack getItem() {
return item == null ? new ItemStack(Material.AIR) : item;
}
@Override
public String toString() {
return "ChatAction[slot=" + slot + ",command=" + command + ",item=" + item + ",origin=" + origin + "]";
}
}
@@ -17,36 +17,51 @@ import me.dadus33.chatitem.utils.Utils;
@SuppressWarnings("deprecation")
public class ChatEventListener implements Listener {
private Storage getStorage() {
return ChatItem.getInstance().getStorage();
}
private Storage getStorage() {
@EventHandler(priority = EventPriority.LOWEST)
public void onChat(AsyncPlayerChatEvent e) {
if (ChatManager.containsSeparator(e.getMessage())) { // If the BELL character is found, we have to remove it
e.setMessage(ChatManager.removeSeparator(e.getMessage()));
}
Player p = e.getPlayer();
String oldMsg = e.getMessage();
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
if (slot == null) {
ChatItem.debug("(general) not found placeholders in: " + e.getMessage());
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
if(!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
String s = slot.replacePlaceholdersToSeparator(e.getMessage());
if (Utils.countMatches(s, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
e.setCancelled(true);
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
return;
}
return ChatItem.getInstance().getStorage();
}
@EventHandler(priority = EventPriority.LOWEST)
public void onChat(AsyncPlayerChatEvent e) {
if (ChatManager.containsSeparator(e.getMessage())) { // If the BELL character is found, we have to remove it
e.setMessage(ChatManager.removeSeparator(e.getMessage()));
}
Player p = e.getPlayer();
String oldMsg = e.getMessage();
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
if (slot == null) {
ChatItem.debug("(general) not found placeholders in: " + e.getMessage());
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
if (!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
String s = slot.replacePlaceholdersToSeparator(e.getMessage());
if (Utils.countMatches(s, Character.toString(ChatManager.SEPARATOR)) > getStorage().limit) {
e.setCancelled(true);
if (!getStorage().messageLimit.isEmpty())
p.sendMessage(getStorage().messageLimit);
return;
}
Chat c = Chat.create(p, oldMsg, action);
ChatItem.debug("(general) Set placeholder to message " + c);
e.setMessage(s.replace(Character.toString(ChatManager.SEPARATOR),
SEPARATOR + Integer.toString(c.getId()) + SEPARATOR_END));
e.setFormat(e.getFormat().replace(oldMsg, e.getMessage())); // set own message for plugin that already put the
// message into the format
}
Chat c = Chat.create(p, oldMsg, action);
ChatItem.debug("(general) Set placeholder to message " + c);
e.setMessage(s.replace(Character.toString(ChatManager.SEPARATOR), SEPARATOR + Integer.toString(c.getId()) + SEPARATOR_END));
e.setFormat(e.getFormat().replace(oldMsg, e.getMessage())); // set own message for plugin that already put the message into the format
}
}
@@ -37,361 +37,544 @@ import me.dadus33.chatitem.utils.Version;
@SuppressWarnings("deprecation")
public abstract class ChatManager {
public static String inTest = null;
private final static HashMap<UUID, Long> COOLDOWNS = new HashMap<>();
private final static HashMap<UUID, Long> LAST_INFO_MESSAGE = new HashMap<>();
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private final static String LEFT = "{remaining}";
public final static char SEPARATOR = ((char) 0x0007);
public final static String SEPARATOR_STR = "\\u0007";
public final static char SEPARATOR_END = ((char) 0x0003);
public final static String SEPARATOR_END_STR = "\\u0003";
public static String inTest = null;
private final static HashMap<UUID, Long> COOLDOWNS = new HashMap<>();
private final static HashMap<UUID, Long> LAST_INFO_MESSAGE = new HashMap<>();
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private final static String LEFT = "{remaining}";
public final static char SEPARATOR = ((char) 0x0007);
public final static String SEPARATOR_STR = "\\u0007";
public final static char SEPARATOR_END = ((char) 0x0003);
public final static String SEPARATOR_END_STR = "\\u0003";
public static String addSeparator(int id) {
return SEPARATOR + Integer.toString(id) + SEPARATOR_END;
}
public static String removeSeparator(String message) {
return fixSeparator(message).replace(Character.toString(SEPARATOR), "").replace(Character.toString(SEPARATOR_END), "");
}
public static String addSeparator(int id) {
public static String replaceSeparator(Chat chat, String message, String replacement) {
return fixSeparator(message).replace(Character.toString(SEPARATOR) + (chat != null ? chat.getId() : "") + Character.toString(SEPARATOR_END), replacement);
}
return SEPARATOR + Integer.toString(id) + SEPARATOR_END;
public static String fixSeparator(String s) {
return s == null ? "" : s.replace(SEPARATOR_STR, Character.toString(SEPARATOR)).replace(SEPARATOR_END_STR, Character.toString(SEPARATOR_END));
}
}
public static boolean equalsSeparator(String s) {
return s != null && (s.equalsIgnoreCase(SEPARATOR_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR)));
}
public static String removeSeparator(String message) {
public static boolean containsSeparator(String s) {
return s != null && (s.contains(SEPARATOR_STR) || s.contains(Character.toString(SEPARATOR)));
}
return fixSeparator(message).replace(Character.toString(SEPARATOR), "")
.replace(Character.toString(SEPARATOR_END), "");
public static boolean equalsSeparatorEnd(String s) {
return s != null && (s.equalsIgnoreCase(SEPARATOR_END_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR_END)));
}
}
public static boolean containsSeparatorEnd(String s) {
return s != null && (s.contains(SEPARATOR_END_STR) || s.contains(Character.toString(SEPARATOR_END)));
}
public static String replaceSeparator(Chat chat, String message, String replacement) {
protected Storage s;
return fixSeparator(message).replace(
Character.toString(SEPARATOR) + (chat != null ? chat.getId() : "") + Character.toString(SEPARATOR_END),
replacement);
public ChatManager() {
}
}
public static String fixSeparator(String s) {
public abstract String getName();
return s == null ? ""
: s.replace(SEPARATOR_STR, Character.toString(SEPARATOR)).replace(SEPARATOR_END_STR,
Character.toString(SEPARATOR_END));
public abstract String getId();
}
public Storage getStorage() {
return s;
}
public static boolean equalsSeparator(String s) {
public void load(ChatItem pl, Storage s) {
this.s = s;
}
return s != null && (s.equalsIgnoreCase(SEPARATOR_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR)));
public abstract void unload(ChatItem pl);
}
/**
* Get the item in hand as usable one.<br>
* Will include, in lore, all informations from other plugins.
*
* @param p the player
* @return the usable item
*/
public static ItemStack getUsableItem(Player p, ItemSlot slot) {
if (slot == null)
return null;
ItemStack betterItem = HandItem.getBetterItem(p, slot);
if (betterItem == null)
return null;
public static boolean containsSeparator(String s) {
ItemStack item = betterItem.clone();
if (slot.isDenyIfNoItem() && ItemUtils.isEmpty(item))
return null;
if (EcoEnchantsSupport.hasSupport()) {
item = EcoEnchantsSupport.manageItem(item);
} else if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if (meta instanceof BookMeta) { // filtering written books
BookMeta bm = (BookMeta) item.getItemMeta();
bm.setPages(Collections.emptyList());
item.setItemMeta(bm);
} else if (meta instanceof BlockStateMeta && Version.getVersion().isNewerOrEquals(Version.V1_9)) { // if it's a block
BlockStateMeta bsm = (BlockStateMeta) item.getItemMeta();
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
ItemUtils.stripData(itemInv);
}
bsm.setBlockState(sb);
}
item.setItemMeta(bsm);
}
}
return item;
}
return s != null && (s.contains(SEPARATOR_STR) || s.contains(Character.toString(SEPARATOR)));
public static ChatAction getChatAction(ItemSlot slot, Player p) {
if (slot.isCommand()) {
UUID uuid = UUID.randomUUID();
InvShower.add(uuid.toString(), slot == ItemSlot.INVENTORY ? new PlayerInventoryShower(p) : new EnderChestShower(p));
return new ChatAction(slot, p, "/chatitem seeinv " + uuid.toString());
}
UUID uuid = UUID.randomUUID();
ItemStack item = getUsableItem(p, slot);
InvShower.add(uuid.toString(), new OneItemShower(p, item));
return new ChatAction(slot, p, item, "/chatitem seeinv " + uuid.toString());
}
}
/**
* Get all lores lines of an item, to replace the show_item action which is not
* working with ViaBackwards
*
* @param item the item to get lines from
* @return all lores
*/
public static List<String> getMaxLinesFromItem(Player viewer, ItemStack item) {
List<String> lines = new ArrayList<>();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
lines.add(NamerManager.getName(viewer, item, ChatItem.getInstance().getStorage()));
if (meta.hasEnchants()) {
meta.getEnchants().forEach((enchant, lvl) -> {
lines.add(Colors.RESET + Utils.getEnchantName(enchant) + " " + Utils.toRoman(lvl));
});
}
if (meta.hasLore())
lines.addAll(meta.getLore());
} else {
lines.add(NamerManager.getName(viewer, item, ChatItem.getInstance().getStorage()));
}
return lines;
}
public static boolean equalsSeparatorEnd(String s) {
/**
* Get the name of item according to player & config<br>
* Prefer use {@link #getNameOfItem(Player, ItemStack, Storage)} if you want
* take in count the empty item
*
* @param viewer the player
* @param item the item
* @param c the config
* @return the name of item
*/
public static String styleItem(Player viewer, ItemStack item, Storage c) {
String replacer = c.nameFormat;
String amount = c.amountFormat;
if (item.getAmount() == 1) {
if (c.addAmountForced) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
return replacer.replace(NAME, NamerManager.getName(viewer, item, c));
}
return s != null
&& (s.equalsIgnoreCase(SEPARATOR_END_STR) || s.equalsIgnoreCase(Character.toString(SEPARATOR_END)));
/**
* Get the name of item according to player & config
*
* @param p the player that is owner of item
* @param item the item
* @param c the config
* @return the name of item or hand
*/
public static String getNameOfItem(Player p, ItemStack item, Player viewer, Storage c) {
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return ItemSlot.HAND.getPlaceholders().get(0);
return getHandName(p);
}
return ChatItem.replace(p, styleItem(viewer, item, c));
}
}
public static String getNameForChatAction(Player viewer, Chat chat, Storage c) {
ChatAction action = chat.getAction();
if (action.hasItem()) {
ItemStack item = action.getItem();
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return chat.getSlot().getPlaceholders().get(0);
return getHandName(chat);
}
return ChatItem.replace(chat.getPlayer(), styleItem(viewer, item, c));
}
return ChatItem.replace(chat.getPlayer(), Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", action.getOrigin().getName()));
}
public static boolean containsSeparatorEnd(String s) {
public static String getNameForChatAction(Player viewer, ChatAction action, Storage c) {
if (action.hasItem()) {
ItemStack item = action.getItem();
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return action.getSlot().getPlaceholders().get(0);
else
return getHandName(action.getOrigin());
}
return ChatItem.replace(action.getOrigin(), styleItem(viewer, item, c));
}
return ChatItem.replace(action.getOrigin(), Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", action.getOrigin().getName()));
}
return s != null && (s.contains(SEPARATOR_END_STR) || s.contains(Character.toString(SEPARATOR_END)));
@Deprecated
public static String getHandName(Player p) {
return ChatItem.replace(p, ChatItem.getInstance().getStorage().handName.replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName()));
}
}
public static String getHandName(Chat c) {
Player p = c.getPlayer();
return ChatItem.replace(p, ChatItem.getInstance().getStorage().handName.replace("{name}", p.getName()).replace("{display-name}", p.getDisplayName()));
}
protected Storage s;
public static String calculateTime(long seconds) {
Storage c = ChatItem.getInstance().getStorage();
if (seconds < 60) {
return seconds + c.SECONDS;
}
if (seconds < 3600) {
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(c.minutes);
int secs = (int) seconds - minutes * 60;
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(c.hours);
int minutes = (int) (seconds / 60) - (hours * 60);
if (minutes != 0) {
builder.append(" ").append(minutes).append(c.minutes);
}
int secs = (int) (seconds - ((seconds / 60) * 60));
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
public ChatManager() {
public static boolean canUsePlaceholder(Player p, ChatAction action, ItemSlot slot, @Nullable Cancellable e) {
Storage c = ChatItem.getInstance().getStorage();
if (c.permissionEnabled && !p.hasPermission(c.permissionName)) {
if (!c.letMessageThrough) {
if (e != null)
e.setCancelled(true);
}
if (!c.messageNoPermission.isEmpty() && c.showNoPermissionMessage) {
sendIfNeed(p, c.messageNoPermission);
}
return false;
}
if (action.hasItem() && action.getItem().getType().equals(Material.AIR) && slot.isBasic()) {
if (slot.isDenyIfNoItem()) {
if (e != null)
e.setCancelled(true);
if (!c.messageDeny.isEmpty())
sendIfNeed(p, c.messageDeny);
return false;
}
if (c.handDisabled) {
return false;
}
}
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
if (COOLDOWNS.containsKey(p.getUniqueId())) {
long start = COOLDOWNS.get(p.getUniqueId());
long current = System.currentTimeMillis() / 1000;
long elapsed = current - start;
if (elapsed >= c.cooldown) {
COOLDOWNS.remove(p.getUniqueId());
} else {
if (!c.letMessageThrough) {
if (e != null)
e.setCancelled(true);
}
if (!c.messageCooldown.isEmpty()) {
long left = (start + c.cooldown) - current;
sendIfNeed(p, c.messageCooldown.replace(LEFT, ChatManager.calculateTime(left)));
}
ChatItem.debug("Cooldown");
return false;
}
}
}
if (action.hasItem()) {
for (String ignored : c.ignoredItems) {
if (action.getItem().getType().name().toLowerCase().contains(ignored.toLowerCase())) {
return false;
}
}
}
}
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis()); // prevent showing item then send cooldown error message
return true;
}
public abstract String getName();
private static void sendIfNeed(Player p, String msg) {
Long time = LAST_INFO_MESSAGE.remove(p.getUniqueId());
if (time != null) {
long diff = System.currentTimeMillis() - time;
if (diff < 100)
return; // don't show message
}
p.sendMessage(msg);
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis());
}
public abstract String getId();
public static void clear(Player p) {
COOLDOWNS.remove(p.getUniqueId());
LAST_INFO_MESSAGE.remove(p.getUniqueId());
}
public Storage getStorage() {
public static void applyCooldown(Player p) {
COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
return s;
public static boolean isTestingEnabled() {
return inTest != null;
}
}
public static boolean isTesting(String actual) {
return inTest != null && (inTest == "both" || inTest == "all" || inTest.equalsIgnoreCase(actual));
}
public void load(ChatItem pl, Storage s) {
public static void setTesting(String actual) {
inTest = actual;
}
this.s = s;
}
public abstract void unload(ChatItem pl);
/**
* Get the item in hand as usable one.<br>
* Will include, in lore, all informations from other plugins.
*
* @param p the player
* @return the usable item
*/
public static ItemStack getUsableItem(Player p, ItemSlot slot) {
if (slot == null)
return null;
ItemStack betterItem = HandItem.getBetterItem(p, slot);
if (betterItem == null)
return null;
ItemStack item = betterItem.clone();
if (slot.isDenyIfNoItem() && ItemUtils.isEmpty(item))
return null;
if (EcoEnchantsSupport.hasSupport()) {
item = EcoEnchantsSupport.manageItem(item);
} else if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if (meta instanceof BookMeta) { // filtering written books
BookMeta bm = (BookMeta) item.getItemMeta();
bm.setPages(Collections.emptyList());
item.setItemMeta(bm);
} else if (meta instanceof BlockStateMeta && Version.getVersion().isNewerOrEquals(Version.V1_9)) { // if
// it's a
// block
BlockStateMeta bsm = (BlockStateMeta) item.getItemMeta();
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
ItemUtils.stripData(itemInv);
}
bsm.setBlockState(sb);
}
item.setItemMeta(bsm);
}
}
return item;
}
public static ChatAction getChatAction(ItemSlot slot, Player p) {
if (slot.isCommand()) {
UUID uuid = UUID.randomUUID();
InvShower.add(uuid.toString(),
slot == ItemSlot.INVENTORY ? new PlayerInventoryShower(p) : new EnderChestShower(p));
return new ChatAction(slot, p, "/chatitem seeinv " + uuid.toString());
}
UUID uuid = UUID.randomUUID();
ItemStack item = getUsableItem(p, slot);
InvShower.add(uuid.toString(), new OneItemShower(p, item));
return new ChatAction(slot, p, item, "/chatitem seeinv " + uuid.toString());
}
/**
* Get all lores lines of an item, to replace the show_item action which is not
* working with ViaBackwards
*
* @param item the item to get lines from
* @return all lores
*/
public static List<String> getMaxLinesFromItem(Player viewer, ItemStack item) {
List<String> lines = new ArrayList<>();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
lines.add(NamerManager.getName(viewer, item, ChatItem.getInstance().getStorage()));
if (meta.hasEnchants()) {
meta.getEnchants().forEach((enchant, lvl) -> {
lines.add(Colors.RESET + Utils.getEnchantName(enchant) + " " + Utils.toRoman(lvl));
});
}
if (meta.hasLore())
lines.addAll(meta.getLore());
} else {
lines.add(NamerManager.getName(viewer, item, ChatItem.getInstance().getStorage()));
}
return lines;
}
/**
* Get the name of item according to player & config<br>
* Prefer use {@link #getNameOfItem(Player, ItemStack, Storage)} if you want
* take in count the empty item
*
* @param viewer the player
* @param item the item
* @param c the config
* @return the name of item
*/
public static String styleItem(Player viewer, ItemStack item, Storage c) {
String replacer = c.nameFormat;
String amount = c.amountFormat;
if (item.getAmount() == 1) {
if (c.addAmountForced) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
return replacer.replace(NAME, NamerManager.getName(viewer, item, c));
}
/**
* Get the name of item according to player & config
*
* @param p the player that is owner of item
* @param item the item
* @param c the config
* @return the name of item or hand
*/
public static String getNameOfItem(Player p, ItemStack item, Player viewer, Storage c) {
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return ItemSlot.HAND.getPlaceholders().get(0);
return getHandName(p);
}
return ChatItem.replace(p, styleItem(viewer, item, c));
}
public static String getNameForChatAction(Player viewer, Chat chat, Storage c) {
ChatAction action = chat.getAction();
if (action.hasItem()) {
ItemStack item = action.getItem();
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return chat.getSlot().getPlaceholders().get(0);
return getHandName(chat);
}
return ChatItem.replace(chat.getPlayer(), styleItem(viewer, item, c));
}
return ChatItem.replace(chat.getPlayer(), Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat",
"%cible%", action.getOrigin().getName()));
}
public static String getNameForChatAction(Player viewer, ChatAction action, Storage c) {
if (action.hasItem()) {
ItemStack item = action.getItem();
if (ItemUtils.isEmpty(item)) {
if (c.handDisabled)
return action.getSlot().getPlaceholders().get(0);
else
return getHandName(action.getOrigin());
}
return ChatItem.replace(action.getOrigin(), styleItem(viewer, item, c));
}
return ChatItem.replace(action.getOrigin(), Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat",
"%cible%", action.getOrigin().getName()));
}
@Deprecated
public static String getHandName(Player p) {
return ChatItem.replace(p, ChatItem.getInstance().getStorage().handName.replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName()));
}
public static String getHandName(Chat c) {
Player p = c.getPlayer();
return ChatItem.replace(p, ChatItem.getInstance().getStorage().handName.replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName()));
}
public static String calculateTime(long seconds) {
Storage c = ChatItem.getInstance().getStorage();
if (seconds < 60) {
return seconds + c.SECONDS;
}
if (seconds < 3600) {
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(c.minutes);
int secs = (int) seconds - minutes * 60;
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(c.hours);
int minutes = (int) (seconds / 60) - (hours * 60);
if (minutes != 0) {
builder.append(" ").append(minutes).append(c.minutes);
}
int secs = (int) (seconds - ((seconds / 60) * 60));
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
public static boolean canUsePlaceholder(Player p, ChatAction action, ItemSlot slot, @Nullable Cancellable e) {
Storage c = ChatItem.getInstance().getStorage();
if (c.permissionEnabled && !p.hasPermission(c.permissionName)) {
if (!c.letMessageThrough) {
if (e != null)
e.setCancelled(true);
}
if (!c.messageNoPermission.isEmpty() && c.showNoPermissionMessage) {
sendIfNeed(p, c.messageNoPermission);
}
return false;
}
if (action.hasItem() && action.getItem().getType().equals(Material.AIR) && slot.isBasic()) {
if (slot.isDenyIfNoItem()) {
if (e != null)
e.setCancelled(true);
if (!c.messageDeny.isEmpty())
sendIfNeed(p, c.messageDeny);
return false;
}
if (c.handDisabled) {
return false;
}
}
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
if (COOLDOWNS.containsKey(p.getUniqueId())) {
long start = COOLDOWNS.get(p.getUniqueId());
long current = System.currentTimeMillis() / 1000;
long elapsed = current - start;
if (elapsed >= c.cooldown) {
COOLDOWNS.remove(p.getUniqueId());
} else {
if (!c.letMessageThrough) {
if (e != null)
e.setCancelled(true);
}
if (!c.messageCooldown.isEmpty()) {
long left = (start + c.cooldown) - current;
sendIfNeed(p, c.messageCooldown.replace(LEFT, ChatManager.calculateTime(left)));
}
ChatItem.debug("Cooldown");
return false;
}
}
}
if (action.hasItem()) {
for (String ignored : c.ignoredItems) {
if (action.getItem().getType().name().toLowerCase().contains(ignored.toLowerCase())) {
return false;
}
}
}
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis()); // prevent showing item then send cooldown
// error message
return true;
}
private static void sendIfNeed(Player p, String msg) {
Long time = LAST_INFO_MESSAGE.remove(p.getUniqueId());
if (time != null) {
long diff = System.currentTimeMillis() - time;
if (diff < 100)
return; // don't show message
}
p.sendMessage(msg);
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis());
}
public static void clear(Player p) {
COOLDOWNS.remove(p.getUniqueId());
LAST_INFO_MESSAGE.remove(p.getUniqueId());
}
public static void applyCooldown(Player p) {
COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
public static boolean isTestingEnabled() {
return inTest != null;
}
public static boolean isTesting(String actual) {
return inTest != null && (inTest == "both" || inTest == "all" || inTest.equalsIgnoreCase(actual));
}
public static void setTesting(String actual) {
inTest = actual;
}
public static boolean isSelected(String actual) {
if (isTestingEnabled())
return true;
String selected = ChatItem.getInstance().getStorage().manager;
if (selected.equalsIgnoreCase("both") || selected.equalsIgnoreCase("all"))
return true;
if (selected == "auto") {
if (Utils.IS_PAPER && actual == "paper")
return true;
else if (actual == "packet" && ChatItem.getPluginThatRequirePacket().stream()
.map(Bukkit.getPluginManager()::getPlugin).anyMatch(Objects::nonNull))
return true;
else if (actual == "chat")
return true;
}
return selected.equalsIgnoreCase(actual);
}
public static boolean isSelected(String actual) {
if(isTestingEnabled())
return true;
String selected = ChatItem.getInstance().getStorage().manager;
if (selected.equalsIgnoreCase("both") || selected.equalsIgnoreCase("all"))
return true;
if (selected == "auto") {
if (Utils.IS_PAPER && actual == "paper")
return true;
else if (actual == "packet" && ChatItem.getPluginThatRequirePacket().stream().map(Bukkit.getPluginManager()::getPlugin).anyMatch(Objects::nonNull))
return true;
else if (actual == "chat")
return true;
}
return selected.equalsIgnoreCase(actual);
}
}
@@ -9,30 +9,38 @@ import me.dadus33.chatitem.utils.Version;
public class HandItem {
@SuppressWarnings("deprecation")
public static ItemStack getBetterItem(Player p, ItemSlot slot) {
switch (slot) {
case HAND:
if(Version.getVersion().isNewerOrEquals(Version.V1_9)) {
ItemStack main = p.getInventory().getItemInMainHand();
if(!ItemUtils.isEmpty(main))
return main;
return p.getInventory().getItemInOffHand();
}
return p.getItemInHand();
case HELMET:
return p.getInventory().getHelmet();
case CHESTPLATE:
return p.getInventory().getChestplate();
case LEGGINGS:
return p.getInventory().getLeggings();
case BOOTS:
return p.getInventory().getBoots();
case ENDERCHEST:
break;
case INVENTORY:
break;
}
return null; // should never happen
}
@SuppressWarnings("deprecation")
public static ItemStack getBetterItem(Player p, ItemSlot slot) {
switch (slot) {
case HAND:
if (Version.getVersion().isNewerOrEquals(Version.V1_9)) {
ItemStack main = p.getInventory().getItemInMainHand();
if (!ItemUtils.isEmpty(main))
return main;
return p.getInventory().getItemInOffHand();
}
return p.getItemInHand();
case HELMET:
return p.getInventory().getHelmet();
case CHESTPLATE:
return p.getInventory().getChestplate();
case LEGGINGS:
return p.getInventory().getLeggings();
case BOOTS:
return p.getInventory().getBoots();
case ENDERCHEST:
break;
case INVENTORY:
break;
}
return null; // should never happen
}
}
@@ -18,168 +18,262 @@ import me.dadus33.chatitem.utils.Utils;
public class PacketEditingChatManager extends ChatManager {
private boolean baseComponentAvailable = true;
private final ChatItemPacketManager packetManager;
private final ChatPacketManager chatPacketManager;
private boolean baseComponentAvailable = true;
private final ChatItemPacketManager packetManager;
private final ChatPacketManager chatPacketManager;
public PacketEditingChatManager(ChatItem pl) {
packetManager = new ChatItemPacketManager(pl);
chatPacketManager = new ChatPacketManager(this);
public PacketEditingChatManager(ChatItem pl) {
// Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
packetManager = new ChatItemPacketManager(pl);
chatPacketManager = new ChatPacketManager(this);
@Override
public String getName() {
return "PacketEditing";
}
// Check for existence of BaseComponent class (only on spigot)
try {
@Override
public String getId() {
return "packet";
}
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
} catch (ClassNotFoundException e) {
PacketManager pm = packetManager.getPacketManager();
pm.addHandler(chatPacketManager);
Bukkit.getOnlinePlayers().forEach(pm::addPlayer); // add actual online players
}
baseComponentAvailable = false;
@Override
public void unload(ChatItem pl) {
PacketManager pm = packetManager.getPacketManager();
pm.removeHandler(chatPacketManager);
pm.stop();
}
}
public boolean supportsChatComponentApi() {
return baseComponentAvailable;
}
private static String checkPacketSize(String packet, int maxSize) {
int size = packet.getBytes().length;
while(size > maxSize) {
packet = packet.replaceFirst(" ", " ");
if(size == packet.getBytes().length)
break; // could not fix myself
size = packet.getBytes().length;
}
return packet;
}
}
public static Object createSystemChatPacket(String json, Object old) throws Exception {
json = checkPacketSize(json, 150000);
if(json.contains("tag:{{")) { // this is to fix for MC 1.20.4 (at least on purpur)
ChatItem.debug("Found strange JSON formatting. Cleaning...");
boolean replaced = false;
String next = "";
for(String part : json.split("tag:\\{\\{")) {
if(replaced) {
next += "tag:{";
next += part.replaceFirst("\\}\\}", "}");
} else
next += part;
replaced = true;
}
json = next;
}
Object packet = internalCreateSystemChatPacket(json, old);
if(packet != null)
return packet;
Object icb = ChatItem.getPlatform().jsonToBaseComponent(json);
if(icb != null)
packet = internalCreateSystemChatPacket(icb, old);
if(packet != null)
return packet;
ChatItem.getInstance().getLogger().warning("Can't create a new packet for json " + json);
return null;
}
private static Object internalCreateSystemChatPacket(Object obj, Object old) throws Exception {
ChatItem.debug("Creating internal chat system packet from " + old + " to " + obj);
Class<?> packetClass = PacketUtils.getNmsClass("ClientboundSystemChatPacket", "network.protocol.game.", "ClientboundPlayerChatPacket", "PacketPlayOutChat");
Class<?> chatMessageTypeClass = Utils.isClassExist("net.minecraft.network.chat.ChatMessageType") ? PacketUtils.getNmsClass("ChatMessageType", "network.chat.") : null;
Constructor<?> betterOne = null;
Object[] betterParam = null;
for (Constructor<?> cons : packetClass.getDeclaredConstructors()) {
if (!cons.isAccessible())
cons.setAccessible(true);
@Override
public String getName() {
return "PacketEditing";
}
@Override
public String getId() {
return "packet";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
PacketManager pm = packetManager.getPacketManager();
pm.addHandler(chatPacketManager);
Bukkit.getOnlinePlayers().forEach(pm::addPlayer); // add actual online players
}
@Override
public void unload(ChatItem pl) {
PacketManager pm = packetManager.getPacketManager();
pm.removeHandler(chatPacketManager);
pm.stop();
}
public boolean supportsChatComponentApi() {
return baseComponentAvailable;
}
private static String checkPacketSize(String packet, int maxSize) {
int size = packet.getBytes().length;
while (size > maxSize) {
packet = packet.replaceFirst(" ", " ");
if (size == packet.getBytes().length)
break; // could not fix myself
size = packet.getBytes().length;
}
return packet;
}
public static Object createSystemChatPacket(String json, Object old) throws Exception {
json = checkPacketSize(json, 150000);
if (json.contains("tag:{{")) { // this is to fix for MC 1.20.4 (at least on purpur)
ChatItem.debug("Found strange JSON formatting. Cleaning...");
boolean replaced = false;
String next = "";
for (String part : json.split("tag:\\{\\{")) {
if (replaced) {
next += "tag:{";
next += part.replaceFirst("\\}\\}", "}");
} else
next += part;
replaced = true;
}
json = next;
}
Object packet = internalCreateSystemChatPacket(json, old);
if (packet != null)
return packet;
Object icb = ChatItem.getPlatform().jsonToBaseComponent(json);
if (icb != null)
packet = internalCreateSystemChatPacket(icb, old);
if (packet != null)
return packet;
ChatItem.getInstance().getLogger().warning("Can't create a new packet for json " + json);
return null;
}
private static Object internalCreateSystemChatPacket(Object obj, Object old) throws Exception {
ChatItem.debug("Creating internal chat system packet from " + old + " to " + obj);
Class<?> packetClass = PacketUtils.getNmsClass("ClientboundSystemChatPacket", "network.protocol.game.",
"ClientboundPlayerChatPacket", "PacketPlayOutChat");
Class<?> chatMessageTypeClass = Utils.isClassExist("net.minecraft.network.chat.ChatMessageType")
? PacketUtils.getNmsClass("ChatMessageType", "network.chat.")
: null;
Constructor<?> betterOne = null;
Object[] betterParam = null;
for (Constructor<?> cons : packetClass.getDeclaredConstructors()) {
if (!cons.isAccessible())
cons.setAccessible(true);
// check for basic method
if (obj instanceof String) {
if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class)
&& cons.getParameterTypes()[1].equals(int.class))
{ // "string, int"
return cons.newInstance(obj, 1);
} else if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class)
&& cons.getParameterTypes()[1].equals(boolean.class))
{ // "string, boolean"
return cons.newInstance(obj, false); // false for no overlay
} else if (cons.getParameterCount() == 3 && cons.getParameterTypes()[1].equals(String.class)) { // "component",
// "string",
// <something
// not
// checked>
Class<?> secondParam = cons.getParameterTypes()[2];
if (secondParam.equals(int.class)) // "component", "string", "int"
return cons.newInstance(null, obj, 1);
else if (secondParam.equals(boolean.class)) // "component", "string", "boolean"
return cons.newInstance(null, obj, false);
}
} else if (obj.getClass().isAssignableFrom(PacketUtils.COMPONENT_CLASS)) {
if (cons.getParameterCount() == 2
&& cons.getParameterTypes()[0].isAssignableFrom(PacketUtils.COMPONENT_CLASS)
&& cons.getParameterTypes()[1].equals(boolean.class)) // "string, boolean"
return cons.newInstance(obj, false);
}
int nbPut = 0;
Object[] params = new Object[cons.getParameterCount()];
for (int i = 0; i < params.length; i++) {
Class<?> type = cons.getParameterTypes()[i];
if (type.isAssignableFrom(obj.getClass())) {
params[i] = obj;
nbPut++;
} else if (chatMessageTypeClass != null && type.isAssignableFrom(chatMessageTypeClass)) {
params[i] = getChatMessageType();
} else if (type.isAssignableFrom(boolean.class)) // need to set primitives
params[i] = false;
else if (type.isAssignableFrom(int.class)) // need to set primitives
params[i] = 0;
else {
boolean found = false;
for (Class<?> prim : Arrays.asList(float.class, long.class)) { // if not primitive
if (type.isAssignableFrom(prim)) {
found = true;
}
}
if (!found) {
params[i] = new PacketContent(old).getSpecificModifier(type).readSafely(0);
}
}
}
if (nbPut == 1) {
if ((betterOne == null && betterParam == null) || betterParam.length > params.length) {
betterOne = cons;
betterParam = params;
if (params.length == 1) // only what we need
break;
continue; // check for something better?
}
} else if (nbPut > 1)
ChatItem.getInstance().getLogger().warning("Some constructor seems to have too many "
+ obj.getClass().getSimpleName() + ". Class: " + packetClass.getSimpleName());
}
if (betterOne != null && betterParam != null) {
try {
return betterOne.newInstance(betterParam);
} catch (IllegalArgumentException e) {
ChatItem.getInstance().getLogger()
.warning("Failed to create a new packet to send. " + betterOne.getParameterCount() + " ("
+ Utils.arrayToString(betterOne.getParameterTypes()) + "). Params: "
+ Utils.arrayToString(betterParam));
return null;
}
}
return null;
}
private static Object getChatMessageType() throws Exception {
Class<?> c = PacketUtils.getNmsClass("ChatMessageType", "network.chat.");
return ReflectionUtils.getMethod(c, c, byte.class).invoke(null, (byte) 0);
}
// check for basic method
if(obj instanceof String) {
if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class) && cons.getParameterTypes()[1].equals(int.class)) { // "string, int"
return cons.newInstance(obj, 1);
} else if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].equals(String.class) && cons.getParameterTypes()[1].equals(boolean.class)) { // "string, boolean"
return cons.newInstance(obj, false); // false for no overlay
} else if (cons.getParameterCount() == 3 && cons.getParameterTypes()[1].equals(String.class)) { // "component", "string", <something not checked>
Class<?> secondParam = cons.getParameterTypes()[2];
if (secondParam.equals(int.class)) // "component", "string", "int"
return cons.newInstance(null, obj, 1);
else if (secondParam.equals(boolean.class)) // "component", "string", "boolean"
return cons.newInstance(null, obj, false);
}
} else if(obj.getClass().isAssignableFrom(PacketUtils.COMPONENT_CLASS)) {
if (cons.getParameterCount() == 2 && cons.getParameterTypes()[0].isAssignableFrom(PacketUtils.COMPONENT_CLASS) && cons.getParameterTypes()[1].equals(boolean.class)) // "string, boolean"
return cons.newInstance(obj, false);
}
int nbPut = 0;
Object[] params = new Object[cons.getParameterCount()];
for(int i = 0; i < params.length; i++) {
Class<?> type = cons.getParameterTypes()[i];
if(type.isAssignableFrom(obj.getClass())) {
params[i] = obj;
nbPut++;
} else if(chatMessageTypeClass != null && type.isAssignableFrom(chatMessageTypeClass)) {
params[i] = getChatMessageType();
} else if(type.isAssignableFrom(boolean.class)) // need to set primitives
params[i] = false;
else if(type.isAssignableFrom(int.class)) // need to set primitives
params[i] = 0;
else {
boolean found = false;
for(Class<?> prim : Arrays.asList(float.class, long.class)) { // if not primitive
if(type.isAssignableFrom(prim)) {
found = true;
}
}
if(!found) {
params[i] = new PacketContent(old).getSpecificModifier(type).readSafely(0);
}
}
}
if(nbPut == 1) {
if((betterOne == null && betterParam == null) || betterParam.length > params.length) {
betterOne = cons;
betterParam = params;
if(params.length == 1) // only what we need
break;
continue; // check for something better?
}
} else if(nbPut > 1)
ChatItem.getInstance().getLogger().warning("Some constructor seems to have too many " + obj.getClass().getSimpleName() + ". Class: " + packetClass.getSimpleName());
}
if(betterOne != null && betterParam != null) {
try {
return betterOne.newInstance(betterParam);
} catch (IllegalArgumentException e) {
ChatItem.getInstance().getLogger().warning("Failed to create a new packet to send. " + betterOne.getParameterCount() + " (" + Utils.arrayToString(betterOne.getParameterTypes()) + "). Params: " + Utils.arrayToString(betterParam));
return null;
}
}
return null;
}
private static Object getChatMessageType() throws Exception {
Class<?> c = PacketUtils.getNmsClass("ChatMessageType", "network.chat.");
return ReflectionUtils.getMethod(c, c, byte.class).invoke(null, (byte) 0);
}
}
@@ -21,118 +21,179 @@ import me.dadus33.chatitem.utils.Utils;
public interface IComponentManager {
default boolean hasConditions() {
return true;
}
default boolean hasConditions() {
String getBaseComponentAsJSON(ChatItemPacket packet);
return true;
void writeJson(ChatItemPacket packet, String json);
}
default @Nullable Chat getChat(String json) {
json = ChatManager.fixSeparator(json);
try {
Chat possibleChat = Chat.getFrom(json);
if (possibleChat != null) // found something with basic search
return possibleChat;
Chat chat = new Searching(json).search();
if (chat == null)
ChatItem.debug("Failed to find chat for JSON " + json);
return chat;
} catch (Exception e) {
e.printStackTrace();
} // not JSON
return null;
}
String getBaseComponentAsJSON(ChatItemPacket packet);
default Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) throws Exception {
String message;
if (Utils.isBeforeChatJson(viewer))
message = JSONManipulator.getInstance().parseEmpty(chat, json, chat.getAction().hasItem() ? ChatManager.getMaxLinesFromItem(viewer, chat.getAction().getItem()) : new ArrayList<>(), chat.getPlayer());
else
message = JSONManipulator.getInstance().parse(chat, json, chat.getAction(), ChatManager.getNameForChatAction(viewer, chat, c));
if (message != null) {
ChatItem.debug("(v1) Writing message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
void writeJson(ChatItemPacket packet, String json);
default Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
String message = JSONManipulator.getInstance().parseEmpty(chat, json, c.tooltipHand, chat.getPlayer());
if (message != null) {
ChatItem.debug("(v1) Writing empty message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
default @Nullable Chat getChat(String json) {
public static class Searching {
json = ChatManager.fixSeparator(json);
try {
private boolean found = false;
private String id = "", json;
Chat possibleChat = Chat.getFrom(json);
if (possibleChat != null) // found something with basic search
return possibleChat;
Chat chat = new Searching(json).search();
if (chat == null)
ChatItem.debug("Failed to find chat for JSON " + json);
return chat;
public Searching(String json) {
this.json = json;
}
} catch (Exception e) {
private Chat search() {
JsonObject jsonObj;
try {
jsonObj = JsonParser.parseString(json).getAsJsonObject();
} catch (Exception e) {
if(searchInString(json))
return getWithId();
return null;
}
if (jsonObj.has("extra")) {
if (searchInExtra(jsonObj.getAsJsonArray("extra"))) {
return getWithId();
}
}
if (jsonObj.has("text")) {
JsonElement text = jsonObj.get("text");
if (text.isJsonObject() && searchInObject(text.getAsJsonObject()))
return getWithId();
else if (text.isJsonArray() && searchInExtra(text.getAsJsonArray()))
return getWithId();
else if (text.isJsonPrimitive() && searchInString(text.getAsString()))
return getWithId();
}
return null;
}
e.printStackTrace();
private Chat getWithId() {
return id != "" && Utils.isInteger(id) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
} // not JSON
private boolean searchInExtra(JsonArray json) {
for (JsonElement element : json) {
if (element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if (withObj.has("extra") && searchInExtra(withObj.getAsJsonArray("extra")))
return true;
else if (withObj.has("text") && searchInObject(withObj))
return true;
}
}
return false;
}
return null;
private boolean searchInObject(JsonObject json) {
return json.has("text") && json.get("text").isJsonPrimitive() && searchInString(json.get("text").getAsString());
}
}
default Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c)
throws Exception
{
String message;
if (Utils.isBeforeChatJson(viewer))
message = JSONManipulator.getInstance().parseEmpty(chat, json,
chat.getAction().hasItem() ? ChatManager.getMaxLinesFromItem(viewer, chat.getAction().getItem())
: new ArrayList<>(),
chat.getPlayer());
else
message = JSONManipulator.getInstance().parse(chat, json, chat.getAction(),
ChatManager.getNameForChatAction(viewer, chat, c));
if (message != null) {
ChatItem.debug("(v1) Writing message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
default Object manageEmpty(Player p, Chat chat, ChatItemPacket packet, String json, Storage c) {
String message = JSONManipulator.getInstance().parseEmpty(chat, json, c.tooltipHand, chat.getPlayer());
if (message != null) {
ChatItem.debug("(v1) Writing empty message: " + message);
writeJson(packet, message);
}
return packet.getPacket();
}
public static class Searching {
private boolean found = false;
private String id = "", json;
public Searching(String json) {
this.json = json;
}
private Chat search() {
JsonObject jsonObj;
try {
jsonObj = JsonParser.parseString(json).getAsJsonObject();
} catch (Exception e) {
if (searchInString(json))
return getWithId();
return null;
}
if (jsonObj.has("extra")) {
if (searchInExtra(jsonObj.getAsJsonArray("extra"))) {
return getWithId();
}
}
if (jsonObj.has("text")) {
JsonElement text = jsonObj.get("text");
if (text.isJsonObject() && searchInObject(text.getAsJsonObject()))
return getWithId();
else if (text.isJsonArray() && searchInExtra(text.getAsJsonArray()))
return getWithId();
else if (text.isJsonPrimitive() && searchInString(text.getAsString()))
return getWithId();
}
return null;
}
private Chat getWithId() {
return id != "" && Utils.isInteger(id) ? Chat.getChat(Integer.parseInt(id)).orElse(null) : null;
}
private boolean searchInExtra(JsonArray json) {
for (JsonElement element : json) {
if (element.isJsonObject()) {
JsonObject withObj = element.getAsJsonObject();
if (withObj.has("extra") && searchInExtra(withObj.getAsJsonArray("extra")))
return true;
else if (withObj.has("text") && searchInObject(withObj))
return true;
}
}
return false;
}
private boolean searchInObject(JsonObject json) {
return json.has("text") && json.get("text").isJsonPrimitive()
&& searchInString(json.get("text").getAsString());
}
private boolean searchInString(String s) {
for (char c : ChatManager.fixSeparator(s).toCharArray()) {
if (c == ChatManager.SEPARATOR)
found = true;
else if (c == ChatManager.SEPARATOR_END)
return true;
else if (found)
id += c;
}
return id != "" && Utils.isInteger(id) && Chat.getChat(Integer.parseInt(id)).isPresent();
}
}
private boolean searchInString(String s) {
for (char c : ChatManager.fixSeparator(s).toCharArray()) {
if (c == ChatManager.SEPARATOR)
found = true;
else if (c == ChatManager.SEPARATOR_END)
return true;
else if (found)
id += c;
}
return id != "" && Utils.isInteger(id) && Chat.getChat(Integer.parseInt(id)).isPresent();
}
}
}
@@ -30,103 +30,168 @@ import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class AdventureComponentManager implements IComponentManager {
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.kyori.adventure.text.Component", "net.kyori.adventure.text.serializer.gson.GsonComponentSerializer"))
Class.forName(cl);
} catch (Throwable e) { // can't support this, adventure comp not found
ChatItem.debug("Can't load AdventureComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
}
@Override
public boolean hasConditions() {
public void writeComponentToPacket(ChatItemPacket packet, Component next) {
if(packet.getContent().getSpecificModifier(Component.class).readSafely(0) == null && ReflectionUtils.hasObject(packet.getPacket(), "unsignedContent")) { // hard way
ReflectionUtils.setField(ReflectionUtils.getObject(packet.getPacket(), "unsignedContent"), "adventure", next);
} else { // easy way
packet.getContent().getSpecificModifier(Component.class).write(0, next);
}
}
try {
public Component getComponentFromPacket(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if (comp == null && packet.getPacketName().equalsIgnoreCase("ClientboundPlayerChatPacket") && ReflectionUtils.hasObject(packet.getPacket(), "unsignedContent")) { // if can get one more
comp = (Component) ReflectionUtils.getObject(ReflectionUtils.getObject(packet.getPacket(), "unsignedContent"), "adventure");
}
return comp;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = getComponentFromPacket(packet);
if(comp == null) // if comp stay null
return null;
try {
String json = GsonComponentSerializer.gson().serialize(comp);
ChatItem.debug("AdventureJSON : " + json);
JsonObject jsonObj = JSONManipulator.parseOrGet(json);
if (jsonObj.has("with")) {
JsonObject next = new JsonObject();
next.add("extra", jsonObj.get("with"));
return next.toString();
}
return json;
} catch (JsonParseException e) { // ignore this and just let skip this
e.printStackTrace();
return null;
}
}
for (String cl : Arrays.asList("net.kyori.adventure.text.Component",
"net.kyori.adventure.text.serializer.gson.GsonComponentSerializer"))
Class.forName(cl);
@SuppressWarnings("deprecation")
@Override
public Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) throws Exception {
ChatAction action = chat.getAction();
if (action.hasItem()) {
ItemStack item = action.getItem();
String itemName = ChatManager.getNameForChatAction(viewer, chat, c);
ChatItem.debug("NBT tag: " + PacketUtils.getNbtTag(item));
HoverEvent<?> hover;
if(Utils.IS_PAPER)
hover = item.asHoverEvent();
else
hover = HoverEvent.showItem(Key.key(item.getType().getKey().getKey()), item.getAmount(), BinaryTagHolder.of(PacketUtils.getNbtTag(item)));
return manage(viewer, chat, packet, itemName, hover, null);
}
return manage(viewer, chat, packet, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName()),
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()))),
ClickEvent.runCommand(action.getCommand()));
}
} catch (Throwable e) { // can't support this, adventure comp not found
@Override
public Object manageEmpty(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) {
Component builder = Component.text("");
c.tooltipHand.forEach(s -> builder.append(Component.text(s)));
ChatAction action = chat.getAction();
if (action.hasItem()) {
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c), HoverEvent.showText(builder), null);
}
return manage(viewer, chat, packet, Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName()),
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()))),
ClickEvent.runCommand(action.getCommand()));
}
ChatItem.debug("Can't load AdventureComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
}
public void writeComponentToPacket(ChatItemPacket packet, Component next) {
if (packet.getContent().getSpecificModifier(Component.class).readSafely(0) == null
&& ReflectionUtils.hasObject(packet.getPacket(), "unsignedContent"))
{ // hard way
ReflectionUtils.setField(ReflectionUtils.getObject(packet.getPacket(), "unsignedContent"), "adventure",
next);
} else { // easy way
packet.getContent().getSpecificModifier(Component.class).write(0, next);
}
}
public Component getComponentFromPacket(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if (comp == null && packet.getPacketName().equalsIgnoreCase("ClientboundPlayerChatPacket")
&& ReflectionUtils.hasObject(packet.getPacket(), "unsignedContent"))
{ // if can get one more
comp = (Component) ReflectionUtils
.getObject(ReflectionUtils.getObject(packet.getPacket(), "unsignedContent"), "adventure");
}
return comp;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = getComponentFromPacket(packet);
if (comp == null) // if comp stay null
return null;
try {
String json = GsonComponentSerializer.gson().serialize(comp);
ChatItem.debug("AdventureJSON : " + json);
JsonObject jsonObj = JSONManipulator.parseOrGet(json);
if (jsonObj.has("with")) {
JsonObject next = new JsonObject();
next.add("extra", jsonObj.get("with"));
return next.toString();
}
return json;
} catch (JsonParseException e) { // ignore this and just let skip this
e.printStackTrace();
return null;
}
}
@SuppressWarnings("deprecation")
@Override
public Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c)
throws Exception
{
ChatAction action = chat.getAction();
if (action.hasItem()) {
ItemStack item = action.getItem();
String itemName = ChatManager.getNameForChatAction(viewer, chat, c);
ChatItem.debug("NBT tag: " + PacketUtils.getNbtTag(item));
HoverEvent<?> hover;
if (Utils.IS_PAPER)
hover = item.asHoverEvent();
else
hover = HoverEvent.showItem(Key.key(item.getType().getKey().getKey()), item.getAmount(),
BinaryTagHolder.of(PacketUtils.getNbtTag(item)));
return manage(viewer, chat, packet, itemName, hover, null);
}
return manage(viewer, chat, packet,
Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%",
chat.getPlayer().getName()),
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover",
"%cible%", chat.getPlayer().getName()))),
ClickEvent.runCommand(action.getCommand()));
}
@Override
public Object manageEmpty(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) {
Component builder = Component.text("");
c.tooltipHand.forEach(s -> builder.append(Component.text(s)));
ChatAction action = chat.getAction();
if (action.hasItem()) {
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c),
HoverEvent.showText(builder), null);
}
return manage(viewer, chat, packet,
Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%",
chat.getPlayer().getName()),
HoverEvent.showText(Component.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover",
"%cible%", chat.getPlayer().getName()))),
ClickEvent.runCommand(action.getCommand()));
}
private Object manage(Player viewer, Chat chat, ChatItemPacket packet, String replacement, HoverEvent<?> hover,
ClickEvent click)
{
Component comp = getComponentFromPacket(packet);
if (comp == null) {
ChatItem.debug("The component is null.");
return null;
}
comp = comp.replaceText(TextReplacementConfig.builder()
.matchLiteral(ChatManager.SEPARATOR + "" + chat.getId() + ChatManager.SEPARATOR_END)
.replacement(Component.text(replacement).hoverEvent(hover).clickEvent(click)).build());
if (ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage() && viewer == chat.getPlayer())
DiscordSrvSupport.sendChatMessage(chat.getPlayer(), comp, null);
viewer.sendMessage(comp);
return null;
}
private Object manage(Player viewer, Chat chat, ChatItemPacket packet, String replacement, HoverEvent<?> hover, ClickEvent click) {
Component comp = getComponentFromPacket(packet);
if (comp == null) {
ChatItem.debug("The component is null.");
return null;
}
comp = comp.replaceText(TextReplacementConfig.builder().matchLiteral(ChatManager.SEPARATOR + "" + chat.getId() + ChatManager.SEPARATOR_END).replacement(Component.text(replacement).hoverEvent(hover).clickEvent(click)).build());
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage() && viewer == chat.getPlayer())
DiscordSrvSupport.sendChatMessage(chat.getPlayer(), comp, null);
viewer.sendMessage(comp);
return null;
}
}
@@ -10,37 +10,57 @@ import me.dadus33.chatitem.hook.DiscordSrvSupport;
public class ComponentNMSManager implements IComponentManager {
@Override
public boolean hasConditions() {
return ChatItem.getPlatform().hasBaseComponentSerializer();
}
@Override
public boolean hasConditions() {
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Object chatBaseComp = packet.getContent().getChatComponents().readSafely(0);
if (chatBaseComp != null) {
try {
Object o = ChatItem.getPlatform().baseComponentToJson(chatBaseComp);
if(o != null && o instanceof String && JsonParser.parseString((String) o).isJsonObject()) {
return (String) o;
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
return ChatItem.getPlatform().hasBaseComponentSerializer();
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Object chatBaseComp = packet.getContent().getChatComponents().readSafely(0);
if (chatBaseComp != null) {
try {
Object o = ChatItem.getPlatform().baseComponentToJson(chatBaseComp);
if (o != null && o instanceof String && JsonParser.parseString((String) o).isJsonObject()) {
return (String) o;
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
// Not compatible with that for now
if (ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
ChatItem.debug("(v1 ComponentNMS) Can't send message to discord");
// DiscordSrvSupport.sendChatMessage(p, comp, null);
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
// Not compatible with that for now
if(ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage())
ChatItem.debug("(v1 ComponentNMS) Can't send message to discord");
// DiscordSrvSupport.sendChatMessage(p, comp, null);
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -7,28 +7,44 @@ import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
public class IChatBaseComponentManager implements IComponentManager {
@Override
public boolean hasConditions() {
return ChatItem.getPlatform().hasBaseComponentSerializer();
}
@Override
public boolean hasConditions() {
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
try {
Object obj = packet.getContent().getChatComponents().readSafely(0);
return obj == null ? null : (String) ChatItem.getPlatform().baseComponentToJson(obj);
} catch (Exception exc) {
exc.printStackTrace();
}
return null;
}
return ChatItem.getPlatform().hasBaseComponentSerializer();
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
try {
Object obj = packet.getContent().getChatComponents().readSafely(0);
return obj == null ? null : (String) ChatItem.getPlatform().baseComponentToJson(obj);
} catch (Exception exc) {
exc.printStackTrace();
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -12,57 +12,88 @@ import me.dadus33.chatitem.utils.ReflectionUtils;
public class PCMComponentManager implements IComponentManager {
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.minecraft.network.chat.PlayerChatMessage"))
Class.forName(cl);
} catch (Exception e) { // can't support this
ChatItem.debug("Can't load PCMComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public boolean hasConditions() {
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
Object pcm = packet.getContent().getSpecificModifier(pcmClass).readSafely(0);
if (pcm != null) {
try {
Object chatBaseComp = ReflectionUtils.getMethod(pcmClass, PacketUtils.COMPONENT_CLASS).invoke(pcm);
if(chatBaseComp != null)
ChatItem.debug("[PCMManager] Founded " + chatBaseComp.getClass().getSimpleName());
return chatBaseComp == null ? null : ChatItem.getPlatform().baseComponentToJson(chatBaseComp);
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
try {
for (String cl : Arrays.asList("net.minecraft.network.chat.PlayerChatMessage"))
Class.forName(cl);
} catch (Exception e) { // can't support this
ChatItem.debug("Can't load PCMComponentManager : " + e.getMessage());
return false;
}
return true;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
Object pcm = packet.getContent().getSpecificModifier(pcmClass).readSafely(0);
if (pcm != null) {
try {
Object chatBaseComp = ReflectionUtils.getMethod(pcmClass, PacketUtils.COMPONENT_CLASS).invoke(pcm);
if (chatBaseComp != null)
ChatItem.debug("[PCMManager] Founded " + chatBaseComp.getClass().getSimpleName());
return chatBaseComp == null ? null : ChatItem.getPlatform().baseComponentToJson(chatBaseComp);
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
Object chatComp = ChatItem.getPlatform().jsonToBaseComponent(json);
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
ContentModifier<Object> pcmModifier = packet.getContent().getSpecificModifier((Class<Object>) pcmClass);
Object pcm = ReflectionUtils.getMethod(pcmClass, pcmClass, PacketUtils.COMPONENT_CLASS)
.invoke(pcmModifier.readSafely(0), chatComp);
for (Constructor<?> cons : packet.getPacket().getClass().getConstructors()) {
if (cons.getParameterCount() <= 1)
continue;
Object[] params = new Object[cons.getParameterCount()];
for (int i = 0; i < params.length; i++) {
Class<?> cls = cons.getParameterTypes()[i];
if (cls.equals(pcmClass)) {
params[i] = pcm;
} else
params[i] = packet.getContent().getSpecificModifier(cls).readSafely(0);
}
packet.setPacket(cons.newInstance(params));
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
Object chatComp = ChatItem.getPlatform().jsonToBaseComponent(json);
Class<?> pcmClass = PacketUtils.getNmsClass("PlayerChatMessage", "network.chat.");
ContentModifier<Object> pcmModifier = packet.getContent().getSpecificModifier((Class<Object>) pcmClass);
Object pcm = ReflectionUtils.getMethod(pcmClass, pcmClass, PacketUtils.COMPONENT_CLASS).invoke(pcmModifier.readSafely(0), chatComp);
for(Constructor<?> cons : packet.getPacket().getClass().getConstructors()) {
if(cons.getParameterCount() <= 1)
continue;
Object[] params = new Object[cons.getParameterCount()];
for(int i = 0; i < params.length; i++) {
Class<?> cls = cons.getParameterTypes()[i];
if(cls.equals(pcmClass)) {
params[i] = pcm;
} else
params[i] = packet.getContent().getSpecificModifier(cls).readSafely(0);
}
packet.setPacket(cons.newInstance(params));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -29,126 +29,203 @@ import net.md_5.bungee.chat.ComponentSerializer;
public class StringComponentManager implements IComponentManager {
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if (element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
} else if (json == null) {
BaseComponent[] comp = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (comp != null)
return ComponentSerializer.toString(comp);
}
return json;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
@Override
public Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) throws Exception {
ChatAction action = chat.getAction();
if (action.hasItem())
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c), Utils.createItemHover(action.getItem(), viewer), null);
else
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c),
Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName())), Utils.createRunCommand(action.getCommand()));
}
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
@Override
public Object manageEmpty(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) {
ComponentBuilder builder = new ComponentBuilder("");
c.tooltipHand.forEach(s -> builder.append(s));
HoverEvent hover;
ClickEvent click;
String rep;
ChatAction action = chat.getAction();
if (action.hasItem()) {
hover = Utils.createTextHover(builder.create());
rep = ChatManager.getHandName(chat);
click = null;
} else {
hover = Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getPlayer().getName()));
rep = Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%", chat.getPlayer().getName());
click = Utils.createRunCommand(action.getCommand());
}
return manage(viewer, chat, packet, rep, hover, click);
}
if (element.isJsonObject()) { // ignore this
private Object manage(Player viewer, Chat chat, ChatItemPacket packet, String replacement, HoverEvent hover, ClickEvent click) {
BaseComponent[] components = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (components == null) {
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if (element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
}
ChatItem.debug("[StringComponentManager] Using JSON " + json);
try {
components = ComponentSerializer.parse(json);
} catch (Exception e) {
ChatItem.getInstance().getLogger().severe("Failed to parse JSON: " + json + ". Error:");
e.printStackTrace();
return packet.getPacket();
}
}
ChatItem.debug("Checking for " + components.length + " components");
Arrays.asList(components).forEach(comp -> checkComponent(comp, hover, click, replacement, chat));
extra.add(element);
if (ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage() && viewer == chat.getPlayer())
DiscordSrvSupport.sendChatMessage(viewer, TextComponent.toLegacyText(components), null);
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(ComponentSerializer.toString(components), packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
return packet.getPacket();
}
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
} else if (json == null) {
BaseComponent[] comp = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (comp != null)
return ComponentSerializer.toString(comp);
}
return json;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(json, packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object manageContent(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c)
throws Exception
{
ChatAction action = chat.getAction();
if (action.hasItem())
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c),
Utils.createItemHover(action.getItem(), viewer), null);
else
return manage(viewer, chat, packet, ChatManager.getNameForChatAction(viewer, chat, c),
Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover",
"%cible%", chat.getPlayer().getName())),
Utils.createRunCommand(action.getCommand()));
}
@Override
public Object manageEmpty(Player viewer, Chat chat, ChatItemPacket packet, String json, Storage c) {
ComponentBuilder builder = new ComponentBuilder("");
c.tooltipHand.forEach(s -> builder.append(s));
HoverEvent hover;
ClickEvent click;
String rep;
ChatAction action = chat.getAction();
if (action.hasItem()) {
hover = Utils.createTextHover(builder.create());
rep = ChatManager.getHandName(chat);
click = null;
} else {
hover = Utils.createTextHover(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover",
"%cible%", chat.getPlayer().getName()));
rep = Messages.getMessage(action.getSlot().name().toLowerCase() + ".chat", "%cible%",
chat.getPlayer().getName());
click = Utils.createRunCommand(action.getCommand());
}
return manage(viewer, chat, packet, rep, hover, click);
}
private Object manage(Player viewer, Chat chat, ChatItemPacket packet, String replacement, HoverEvent hover,
ClickEvent click)
{
BaseComponent[] components = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
if (components == null) {
String json = packet.getContent().getStrings().readSafely(0);
if (json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for (JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if (element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
}
ChatItem.debug("[StringComponentManager] Using JSON " + json);
try {
components = ComponentSerializer.parse(json);
} catch (Exception e) {
ChatItem.getInstance().getLogger().severe("Failed to parse JSON: " + json + ". Error:");
e.printStackTrace();
return packet.getPacket();
}
}
ChatItem.debug("Checking for " + components.length + " components");
Arrays.asList(components).forEach(comp -> checkComponent(comp, hover, click, replacement, chat));
if (ChatItem.discordSrvSupport && DiscordSrvSupport.isSendingMessage() && viewer == chat.getPlayer())
DiscordSrvSupport.sendChatMessage(viewer, TextComponent.toLegacyText(components), null);
try {
packet.setPacket(PacketEditingChatManager.createSystemChatPacket(ComponentSerializer.toString(components),
packet.getPacket()));
} catch (Exception e) {
e.printStackTrace();
}
return packet.getPacket();
}
private void checkComponent(BaseComponent comp, HoverEvent hover, ClickEvent click, String itemName, Chat chat) {
if (comp instanceof TextComponent) {
TextComponent tc = (TextComponent) comp;
if (ChatManager.containsSeparator(tc.getText())) {
String oldText = tc.getText();
ChatItem.debug("Changing text " + oldText + " to " + itemName + ", extra: "
+ (tc.getExtra() == null ? "-" : tc.getExtra().size()));
tc.setText(ChatManager.replaceSeparator(chat, oldText, itemName));
tc.setHoverEvent(hover);
if (click != null)
tc.setClickEvent(click);
} else
ChatItem.debug("No insert of text without separator: " + tc.getText() + " (legacy: " + tc.toLegacyText()
+ ")");
}
if (comp.getExtra() != null) {
for (BaseComponent extra : comp.getExtra()) {
checkComponent(extra, hover, click, itemName, chat);
}
}
}
private void checkComponent(BaseComponent comp, HoverEvent hover, ClickEvent click, String itemName, Chat chat) {
if (comp instanceof TextComponent) {
TextComponent tc = (TextComponent) comp;
if (ChatManager.containsSeparator(tc.getText())) {
String oldText = tc.getText();
ChatItem.debug("Changing text " + oldText + " to " + itemName + ", extra: " + (tc.getExtra() == null ? "-" : tc.getExtra().size()));
tc.setText(ChatManager.replaceSeparator(chat, oldText, itemName));
tc.setHoverEvent(hover);
if (click != null)
tc.setClickEvent(click);
} else
ChatItem.debug("No insert of text without separator: " + tc.getText() + " (legacy: " + tc.toLegacyText() + ")");
}
if (comp.getExtra() != null) {
for (BaseComponent extra : comp.getExtra()) {
checkComponent(extra, hover, click, itemName, chat);
}
}
}
}
@@ -25,209 +25,305 @@ import me.dadus33.chatitem.utils.ReflectionUtils;
public class JSONManipulator {
private static JSONManipulator instance = new JSONManipulator();
private static JSONManipulator instance = new JSONManipulator();
public static JSONManipulator getInstance() {
return instance;
}
public static JSONManipulator getInstance() {
public static final Class<?> CRAFT_ITEM_STACK_CLASS = PacketUtils.getObcClass("inventory.CraftItemStack");
public static final Class<?> NMS_ITEM_STACK_CLASS = getNmsClass("ItemStack", "world.item.");
public static final Method AS_NMS_COPY = ReflectionUtils.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class);
public static final Class<?> NBT_TAG_COMPOUND = getNmsClass("NBTTagCompound", "nbt.", "CompoundTag");
public static final Method SAVE_NMS_ITEM_STACK_METHOD = ReflectionUtils.getMethod(NMS_ITEM_STACK_CLASS, NBT_TAG_COMPOUND, NBT_TAG_COMPOUND);
public static final Field MAP = ReflectionUtils.getField(NBT_TAG_COMPOUND, "map", "x");
return instance;
private JsonArray classicTooltip;
public static JsonObject parseOrGet(String json) {
if(json.startsWith("\"") && json.endsWith("\"")) {// seems to be simple line
if(json.startsWith("\"{") && json.endsWith("}\"")) // json in string
return JsonParser.parseString(json.substring(1, json.length() - 1).replace("\\\"", "\"")).getAsJsonObject();
return JsonParser.parseString("{\"text\":" + json + "}").getAsJsonObject();
}
try {
return JsonParser.parseString(json).getAsJsonObject();
} catch (Exception e) {
JsonObject obj = new JsonObject();
obj.addProperty("text", json);
return obj;
}
}
}
public String parse(Chat chat, String json, ChatAction action, String replacement) throws Exception {
JsonObject obj = parseOrGet(json);
public static final Class<?> CRAFT_ITEM_STACK_CLASS = PacketUtils.getObcClass("inventory.CraftItemStack");
public static final Class<?> NMS_ITEM_STACK_CLASS = getNmsClass("ItemStack", "world.item.");
public static final Method AS_NMS_COPY = ReflectionUtils.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy",
ItemStack.class);
public static final Class<?> NBT_TAG_COMPOUND = getNmsClass("NBTTagCompound", "nbt.", "CompoundTag");
public static final Method SAVE_NMS_ITEM_STACK_METHOD = ReflectionUtils.getMethod(NMS_ITEM_STACK_CLASS,
NBT_TAG_COMPOUND, NBT_TAG_COMPOUND);
public static final Field MAP = ReflectionUtils.getField(NBT_TAG_COMPOUND, "map", "x");
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
JsonArray use = Translator.toJson(replacement); // We get the json representation of the old color
// formatting method
ChatItem.debug("Remplacement: " + replacement + " use: " + use.toString());
// There's no public clone method for JSONObjects so we need to parse them every
// time
JsonObject hover = new JsonObject();
if (action.hasItem()) {
hover.addProperty("action", "show_item");
private JsonArray classicTooltip;
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
String item = ChatItem.getPlatform().stringifyItem(action.getItem());
hover.addProperty("value", item);
hover.add("contents", parseOrGet(item));
} else {
hover.addProperty("action", "show_text");
public static JsonObject parseOrGet(String json) {
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
JsonArray hoverArray = new JsonArray();
hoverArray.add(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", chat.getItemPlayer().getPlayer().getName()));
hover.add("value", hoverArray);
if (json.startsWith("\"") && json.endsWith("\"")) {// seems to be simple line
JsonObject click = new JsonObject();
click.addProperty("action", "run_command");
click.addProperty("value", action.getCommand());
wrapper.add("clickEvent", click);
}
if (json.startsWith("\"{") && json.endsWith("}\"")) // json in string
return JsonParser.parseString(json.substring(1, json.length() - 1).replace("\\\"", "\""))
.getAsJsonObject();
return JsonParser.parseString("{\"text\":" + json + "}").getAsJsonObject();
if (use.size() == 1) {
JsonElement extraElement = use.get(0);
if (extraElement.isJsonPrimitive())
wrapper.addProperty("text", extraElement.getAsString());
else if (extraElement.isJsonObject())
wrapper.addProperty("text", extraElement.getAsJsonObject().get("text").getAsString());
else
wrapper.add("extra", use); // add it only if
} else if (!use.isEmpty())
wrapper.add("extra", use); // add it only if
if (!wrapper.has("text"))
wrapper.addProperty("text", ""); // The text field is compulsory, even if it's empty
ChatItem.debug("Wrapper " + wrapper + " > " + use);
wrapper.add("hoverEvent", hover);
}
if (obj.size() == 1 && obj.has("text")) {
wrapper.add("text", obj.get("text"));
ChatItem.debug("[JsonManipulator] Parsed quick: " + obj.toString() + ", wrapper: " + wrapper);
return ChatManager.replaceSeparator(chat, wrapper.toString(), replacement);
}
if(!obj.has("extra"))
obj.add("extra", new JsonArray());
ChatItem.debug("Parsing array " + obj.getAsJsonArray("extra") + " FROM: " + obj + ". Result: " + parseArray(obj.getAsJsonArray("extra"), wrapper));
obj.add("extra", parseArray(obj.getAsJsonArray("extra"), wrapper));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
try {
@SuppressWarnings("deprecation")
public String parseEmpty(Chat chat, String json, List<String> tooltip, Player sender) {
JsonObject obj = parseOrGet(json);
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
JsonArray use = Translator.toJson(ChatManager.getNameForChatAction(chat.getPlayer(), chat, ChatItem.getInstance().getStorage()).replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
JsonObject hover = JsonParser.parseString("{\"action\":\"show_text\", \"value\": \"\"}").getAsJsonObject();
return JsonParser.parseString(json).getAsJsonObject();
StringBuilder oneLineTooltip = new StringBuilder("");
int index = 0;
for (String m : tooltip) {
oneLineTooltip.append(m.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
++index;
if (index != tooltip.size()) {
oneLineTooltip.append('\n');
}
}
} catch (Exception e) {
hover.add("value", new JsonPrimitive(oneLineTooltip.toString()));
if (!tooltip.isEmpty()) {
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
classicTooltip = use;
}
obj.add("extra", parseArray(array, classicTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
JsonObject obj = new JsonObject();
obj.addProperty("text", json);
return obj;
private JsonArray parseArray(JsonArray arr, JsonElement tooltip) {
JsonArray replacer = new JsonArray();
for (int i = 0; i < arr.size(); ++i) {
JsonElement element = arr.get(i);
if(element.isJsonNull())
continue;
/*if(separator) {
if(ChatManager.containsSeparatorEnd(element.toString()))
separator = false;
continue;
}*/
if (element.isJsonObject()) {
JsonObject o = element.getAsJsonObject();
JsonElement text = o.get("text");
ChatItem.debug("adding JsonObject " + o + " (text: " + text + ")");
if(text != null && !text.getAsString().isEmpty()) {
addParsedStringToArray(text.getAsString(), replacer, o, tooltip);
}
if (o.has("extra") && !o.get("extra").getAsJsonArray().isEmpty()) {
JsonArray jar = o.get("extra").getAsJsonArray();
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty()) {
o.add("extra", tmpArray);
replacer.add(o);
}
ChatItem.debug("[addParsedJsonObjectToArray] " + jar + " parsed " + tmpArray + " into " + replacer);
}
} else if (element.isJsonArray()) {
JsonArray jar = element.getAsJsonArray();
if (!jar.isEmpty()) {
replacer.set(i, parseArray(element.getAsJsonArray(), tooltip));
}
} else if(element.isJsonPrimitive()) {
if(ChatManager.containsSeparator(element.getAsString())) {
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
} else
replacer.add(element); // add basic element
}
}
return replacer;
}
}
}
public String parse(Chat chat, String json, ChatAction action, String replacement) throws Exception {
JsonObject obj = parseOrGet(json);
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
JsonArray use = Translator.toJson(replacement); // We get the json representation of the old color
// formatting method
ChatItem.debug("Remplacement: " + replacement + " use: " + use.toString());
// There's no public clone method for JSONObjects so we need to parse them every
// time
JsonObject hover = new JsonObject();
if (action.hasItem()) {
hover.addProperty("action", "show_item");
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
String item = ChatItem.getPlatform().stringifyItem(action.getItem());
hover.addProperty("value", item);
hover.add("contents", parseOrGet(item));
} else {
hover.addProperty("action", "show_text");
// Get the JSON representation of the item (well, not really JSON, but rather a
// string representation of NBT data)
JsonArray hoverArray = new JsonArray();
hoverArray.add(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%",
chat.getItemPlayer().getPlayer().getName()));
hover.add("value", hoverArray);
JsonObject click = new JsonObject();
click.addProperty("action", "run_command");
click.addProperty("value", action.getCommand());
wrapper.add("clickEvent", click);
}
if (use.size() == 1) {
JsonElement extraElement = use.get(0);
if (extraElement.isJsonPrimitive())
wrapper.addProperty("text", extraElement.getAsString());
else if (extraElement.isJsonObject())
wrapper.addProperty("text", extraElement.getAsJsonObject().get("text").getAsString());
else
wrapper.add("extra", use); // add it only if
} else if (!use.isEmpty())
wrapper.add("extra", use); // add it only if
if (!wrapper.has("text"))
wrapper.addProperty("text", ""); // The text field is compulsory, even if it's empty
ChatItem.debug("Wrapper " + wrapper + " > " + use);
wrapper.add("hoverEvent", hover);
if (obj.size() == 1 && obj.has("text")) {
wrapper.add("text", obj.get("text"));
ChatItem.debug("[JsonManipulator] Parsed quick: " + obj.toString() + ", wrapper: " + wrapper);
return ChatManager.replaceSeparator(chat, wrapper.toString(), replacement);
}
if (!obj.has("extra"))
obj.add("extra", new JsonArray());
ChatItem.debug("Parsing array " + obj.getAsJsonArray("extra") + " FROM: " + obj + ". Result: "
+ parseArray(obj.getAsJsonArray("extra"), wrapper));
obj.add("extra", parseArray(obj.getAsJsonArray("extra"), wrapper));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
@SuppressWarnings("deprecation")
public String parseEmpty(Chat chat, String json, List<String> tooltip, Player sender) {
JsonObject obj = parseOrGet(json);
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
JsonArray use = Translator
.toJson(ChatManager.getNameForChatAction(chat.getPlayer(), chat, ChatItem.getInstance().getStorage())
.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
JsonObject hover = JsonParser.parseString("{\"action\":\"show_text\", \"value\": \"\"}").getAsJsonObject();
StringBuilder oneLineTooltip = new StringBuilder("");
int index = 0;
for (String m : tooltip) {
oneLineTooltip
.append(m.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
++index;
if (index != tooltip.size()) {
oneLineTooltip.append('\n');
}
}
hover.add("value", new JsonPrimitive(oneLineTooltip.toString()));
if (!tooltip.isEmpty()) {
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
classicTooltip = use;
}
obj.add("extra", parseArray(array, classicTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
private JsonArray parseArray(JsonArray arr, JsonElement tooltip) {
JsonArray replacer = new JsonArray();
for (int i = 0; i < arr.size(); ++i) {
JsonElement element = arr.get(i);
if (element.isJsonNull())
continue;
/*
* if(separator) { if(ChatManager.containsSeparatorEnd(element.toString()))
* separator = false; continue; }
*/
if (element.isJsonObject()) {
JsonObject o = element.getAsJsonObject();
JsonElement text = o.get("text");
ChatItem.debug("adding JsonObject " + o + " (text: " + text + ")");
if (text != null && !text.getAsString().isEmpty()) {
addParsedStringToArray(text.getAsString(), replacer, o, tooltip);
}
if (o.has("extra") && !o.get("extra").getAsJsonArray().isEmpty()) {
JsonArray jar = o.get("extra").getAsJsonArray();
JsonArray tmpArray = parseArray(jar, tooltip);
if (!tmpArray.isEmpty()) {
o.add("extra", tmpArray);
replacer.add(o);
}
ChatItem.debug("[addParsedJsonObjectToArray] " + jar + " parsed " + tmpArray + " into " + replacer);
}
} else if (element.isJsonArray()) {
JsonArray jar = element.getAsJsonArray();
if (!jar.isEmpty()) {
replacer.set(i, parseArray(element.getAsJsonArray(), tooltip));
}
} else if (element.isJsonPrimitive()) {
if (ChatManager.containsSeparator(element.getAsString())) {
addParsedStringToArray(element.getAsString(), replacer, element, tooltip);
} else
replacer.add(element); // add basic element
}
}
return replacer;
}
private void addParsedStringToArray(String msg, JsonArray rep, JsonElement o, JsonElement tooltip) {
if (!ChatManager.containsSeparator(msg)) {
rep.add(o.deepCopy());
return;
}
ChatItem.debug("[JSONManipulator] Parsed string " + msg + ", rep: " + rep);
String current = "";
boolean wasSep = false;
for (String parts : msg.split("")) {
if (ChatManager.equalsSeparator(parts)) {
if (!current.isEmpty()) {
if (o.isJsonObject()) {
JsonObject jsonObj = o.getAsJsonObject().deepCopy();
jsonObj.addProperty("text", current); // edit text
rep.add(jsonObj); // add with all basic coloring things
} else {
rep.add(current);
}
current = "";
}
rep.add(tooltip);
wasSep = true;
} else if (wasSep) {
if (ChatManager.equalsSeparatorEnd(parts)) // sep finished
wasSep = false;
} else {
current += parts;
}
}
if (!current.isEmpty()) {
if (o.isJsonObject()) {
JsonObject jsonObj = o.getAsJsonObject().deepCopy();
jsonObj.addProperty("text", current); // edit text
rep.add(jsonObj); // add with all basic coloring things
} else {
rep.add(current);
}
}
}
private void addParsedStringToArray(String msg, JsonArray rep, JsonElement o, JsonElement tooltip) {
if (!ChatManager.containsSeparator(msg)) {
rep.add(o.deepCopy());
return;
}
ChatItem.debug("[JSONManipulator] Parsed string " + msg + ", rep: " + rep);
String current = "";
boolean wasSep = false;
for (String parts : msg.split("")) {
if (ChatManager.equalsSeparator(parts)) {
if (!current.isEmpty()) {
if(o.isJsonObject()) {
JsonObject jsonObj = o.getAsJsonObject().deepCopy();
jsonObj.addProperty("text", current); // edit text
rep.add(jsonObj); // add with all basic coloring things
} else {
rep.add(current);
}
current = "";
}
rep.add(tooltip);
wasSep = true;
} else if (wasSep) {
if (ChatManager.equalsSeparatorEnd(parts)) // sep finished
wasSep = false;
} else {
current += parts;
}
}
if (!current.isEmpty()) {
if(o.isJsonObject()) {
JsonObject jsonObj = o.getAsJsonObject().deepCopy();
jsonObj.addProperty("text", current); // edit text
rep.add(jsonObj); // add with all basic coloring things
} else {
rep.add(current);
}
}
}
}
@@ -11,196 +11,297 @@ import net.md_5.bungee.api.ChatColor;
//Based on DarkSeraphim's system, but using Gson and supporting some more edge cases
public class Translator {
private static final String STYLES = "klmnor"; //All style codes
private static final String STYLES = "klmnor"; // All style codes
public static JsonArray toJson(String old) {
if (old.lastIndexOf(ChatColor.COLOR_CHAR) == -1) {
public static JsonArray toJson(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
JsonArray arr = new JsonArray();
JsonObject obj = new JsonObject();
obj.addProperty("text", old);
arr.add(obj);
return arr;
}
JsonArray message = new JsonArray();
JsonObject next = new JsonObject();
String colorCode = "", text = "";
boolean waiting = false;
for (char args : old.toCharArray()) {
if (args == '§') { // begin of color
if(!text.isEmpty()) {
next.addProperty("text", text);
message.add(next);
next = new JsonObject();
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if(isStyle(args)) { // is style and not making rich color code
String colorCode = "", text = "";
boolean waiting = false;
for (char args : old.toCharArray()) {
if (args == '§') { // begin of color
if (!text.isEmpty()) {
next.addProperty("text", text);
message.add(next);
next = new JsonObject();
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (isStyle(args)) { // is style and not making rich color code
next.addProperty(getStyleName(args), true);
continue;
}
if(args == 'x' && !colorCode.isEmpty()) {
if(!text.isEmpty()) // ignore this if no text before
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else if(!colorCode.isEmpty() && !colorCode.startsWith("x")) { // already color and not hex
text += ColorManager.COLOR_CHAR + colorCode; // add the color to text
colorCode = args + "";
} else
colorCode += args; // a color by itself
} else {
if(!colorCode.isEmpty()) { // manage color
if(colorCode.startsWith("x") && colorCode.length() == 7) { // hex color code
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if(colorCode.length() == 1) { // if only one color code
if(next.has("color"))
text += ColorManager.getColor(colorCode);
else
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if(!text.isEmpty()) // no text before -> color will be used as "color"
text += ColorManager.getColorString(colorCode);
ChatItem.debug("[Translator] Add color code " + colorCode + " to " + text + args + ", msg: " + message);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if(!next.has("color") || colorCode.length() == 1) // if no color or a color that can override it
next.addProperty("color", (colorCode.length() == 1 ? ColorManager.getColor(colorCode).getName() : "white"));
if(!text.isEmpty() || message.isEmpty() || next.size() > 0) {
next.addProperty("text", text);
ChatItem.debug("[Translator] Added content " + next + " to message" + message);
message.add(next);
}
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
if (!text.isEmpty()) // ignore this if no text before
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else if (!colorCode.isEmpty() && !colorCode.startsWith("x")) { // already color and not hex
text += ColorManager.COLOR_CHAR + colorCode; // add the color to text
colorCode = args + "";
} else
colorCode += args; // a color by itself
} else {
if (!colorCode.isEmpty()) { // manage color
if (colorCode.startsWith("x") && colorCode.length() == 7) { // hex color code
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if (colorCode.length() == 1) { // if only one color code
if (next.has("color"))
text += ColorManager.getColor(colorCode);
else
next.addProperty("color", ColorManager.getColor(colorCode).getName());
} else if (!text.isEmpty()) // no text before -> color will be used as "color"
text += ColorManager.getColorString(colorCode);
ChatItem.debug(
"[Translator] Add color code " + colorCode + " to " + text + args + ", msg: " + message);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
if (!next.has("color") || colorCode.length() == 1) // if no color or a color that can override it
next.addProperty("color", (colorCode.length() == 1 ? ColorManager.getColor(colorCode).getName() : "white"));
if (!text.isEmpty() || message.isEmpty() || next.size() > 0) {
next.addProperty("text", text);
ChatItem.debug("[Translator] Added content " + next + " to message" + message);
message.add(next);
}
return message;
}
public static JsonArray toJsonOld(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
public static JsonArray toJsonOld(String old) {
if (old.lastIndexOf(ChatColor.COLOR_CHAR) == -1) {
JsonArray arr = new JsonArray();
JsonObject obj = new JsonObject();
obj.addProperty("text", old);
arr.add(obj);
return arr;
}
boolean startsWithCode = old.startsWith(Character.toString(ChatColor.COLOR_CHAR));
JsonArray message = new JsonArray();
String[] parts = old.split(Character.toString(ChatColor.COLOR_CHAR));
JsonObject next = null; //refers to the object we created before (in time) but next in the message, as we're going from end to start
for(int i = parts.length-1; i >= 0; --i){ //We go in reverse order
JsonObject next = null; // refers to the object we created before (in time) but next in the message, as
// we're going from end to start
for (int i = parts.length - 1; i >= 0; --i) { // We go in reverse order
String part = parts[i];
if(part.isEmpty()){
if (part.isEmpty()) {
continue;
}
if(i == 0 && !startsWithCode){
if (i == 0 && !startsWithCode) {
JsonObject toAdd = new JsonObject();
toAdd.addProperty("text", part);
message.add(toAdd);
break;
}
char code = Character.toLowerCase(part.charAt(0));
if(!isColorOrStyle(code)){
if(next != null){
if (!isColorOrStyle(code)) {
if (next != null) {
String text = next.get("text").getAsString();
text = ChatColor.COLOR_CHAR + part + text;
next.addProperty("text", text);
}else{
} else {
JsonObject added = new JsonObject();
added.addProperty("text", ChatColor.COLOR_CHAR + part);
message.add(added);
next = added;
}
continue;
}
if(part.length() == 1){ //If it's just format and no text, we try to format the next element, if it wasn't formatted already (and it's not null)
if(next == null){
if (part.length() == 1) { // If it's just format and no text, we try to format the next element, if it
// wasn't formatted already (and it's not null)
if (next == null) {
continue;
}
if(isStyle(code)){
if (isStyle(code)) {
next.addProperty(getStyleName(code), true);
}else{ //it's a color
if(isAlreadyColored(next)){
} else { // it's a color
if (isAlreadyColored(next)) {
continue;
}
next.addProperty("color", getColorName(code));
}
continue;
}
//Last possibility that remains is that we have a normal color/format + text situation
// Last possibility that remains is that we have a normal color/format + text
// situation
JsonObject added = new JsonObject();
added.addProperty("text", part.substring(1));
if(isStyle(code)){
if (isStyle(code)) {
added.addProperty(getStyleName(code), true);
message.add(added);
next = added;
continue;
}
//else it can only be a color
// else it can only be a color
added.addProperty("color", getColorName(code));
//also try to color the next element if not colored already
if(next != null){
if(!isAlreadyColored(next)){
// also try to color the next element if not colored already
if (next != null) {
if (!isAlreadyColored(next)) {
next.addProperty("color", getColorName(code));
}
}
message.add(added);
next = added;
}
int i = message.size()-1;
JsonArray orderedMessage = new JsonArray();//This is where we'll store the reverted message (in proper order for being sent to the client)
//First we have to copy all elements
for(JsonElement el : message){
int i = message.size() - 1;
JsonArray orderedMessage = new JsonArray();// This is where we'll store the reverted message (in proper order
// for being sent to the client)
// First we have to copy all elements
for (JsonElement el : message) {
orderedMessage.add(el);
}
for(JsonElement element : message){
for (JsonElement element : message) {
JsonObject obj = (JsonObject) element;
orderedMessage.set(i, obj); //And then we add the object to the properly ordered array
orderedMessage.set(i, obj); // And then we add the object to the properly ordered array
--i;
}
return orderedMessage;
}
private static String getColorName(char code){
private static String getColorName(char code) {
return ChatColor.getByChar(code).getName().toLowerCase();
}
private static String getStyleName(char code){
switch(code){
case 'k': return "obfuscated";
case 'l': return "bold";
case 'm': return "strikethrough";
case 'n': return "underlined";
case 'o': return "italic";
case 'r': return "reset";
private static String getStyleName(char code) {
switch (code) {
case 'k':
return "obfuscated";
case 'l':
return "bold";
case 'm':
return "strikethrough";
case 'n':
return "underlined";
case 'o':
return "italic";
case 'r':
return "reset";
default:
ChatItem.getInstance().getLogger().severe("Can't find code for style " + code);
return null; //Should never happen. Made it return null to throw errors if a new format pops up and it really happens
ChatItem.getInstance().getLogger().severe("Can't find code for style " + code);
return null; // Should never happen. Made it return null to throw errors if a new format pops
// up and it really happens
}
}
private static boolean isColorOrStyle(char code){
private static boolean isColorOrStyle(char code) {
return ChatColor.getByChar(code) != null;
}
private static boolean isStyle(char c){
private static boolean isStyle(char c) {
return STYLES.indexOf(c) != -1;
}
private static boolean isAlreadyColored(JsonObject obj){
private static boolean isAlreadyColored(JsonObject obj) {
return obj.has("color");
}
}
@@ -36,155 +36,232 @@ import me.dadus33.chatitem.utils.Version;
public class ChatPacketManager extends PacketHandler {
private Object lastSentPacket = null;
private PacketEditingChatManager manager;
private final List<IComponentManager> componentManager = new ArrayList<>();
private Object lastSentPacket = null;
private PacketEditingChatManager manager;
private final List<IComponentManager> componentManager = new ArrayList<>();
public ChatPacketManager(PacketEditingChatManager manager) {
this.manager = manager;
public ChatPacketManager(PacketEditingChatManager manager) {
for (IComponentManager getter : Arrays.asList(new StringComponentManager(), new ComponentNMSManager(), new PCMComponentManager())) {
tryRegister(getter);
}
try {
Class.forName("net.kyori.adventure.text.Component");
tryRegister(new AdventureComponentManager());
} catch (Exception e) {
}
ChatItem.debug("ComponentManager: " + String.join(", ", componentManager.stream().map(IComponentManager::getClass).map(Class::getSimpleName).collect(Collectors.toList())));
}
this.manager = manager;
private void tryRegister(IComponentManager getter) {
if (getter.hasConditions())
componentManager.add(getter);
else
ChatItem.debug("Component " + getter.getClass().getSimpleName() + " doesn't answer conditions");
}
for (IComponentManager getter : Arrays.asList(new StringComponentManager(), new ComponentNMSManager(),
new PCMComponentManager()))
{
@SuppressWarnings("deprecation")
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT))
return;
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("packet"))
return;
if(!ChatManager.isSelected("packet"))
return;
if (lastSentPacket != null && lastSentPacket == e.getPacket())
return; // prevent infinite loop
ChatItem.debug("Checking: " + e.getPacket().getClass().getSimpleName() + " to " + e.getPlayername());
PacketContent packet = e.getContent();
Version version = Version.getVersion();
String json = "{}";
IComponentManager choosedGetter = null;
if (version.isNewerOrEquals(Version.V1_19)) {
choosedGetter = new StringComponentManager();
json = choosedGetter.getBaseComponentAsJSON(e); // if null, will be re-checked so anyway
} else if (version.isNewerOrEquals(Version.V1_12)) {
// only if action bar messages are supported
if (((Enum<?>) packet.getSpecificModifier(PacketUtils.getNmsClass("ChatMessageType", "network.chat.")).read(0)).name().equals("GAME_INFO"))
return; // It's an actionbar message, ignoring
} else if (version.isNewerOrEquals(Version.V1_8) && packet.getBytes().readSafely(0) == (byte) 2)
return; // It's an actionbar message, ignoring
if (json == null || choosedGetter == null || !ChatManager.containsSeparator(json)) {
for (IComponentManager getters : componentManager) {
String tmpJson = getters.getBaseComponentAsJSON(e);
if (tmpJson != null) {
json = ChatManager.fixSeparator(tmpJson);
choosedGetter = getters;
ChatItem.debug("Seems to have one nice manager with " + getters.getClass().getSimpleName() + " (json: " + json + ")");
if (ChatManager.containsSeparator(json))
break; // be sure it's valid one
} else
ChatItem.debug("Null JSON for manager " + getters.getClass().getSimpleName());
}
}
if (json == null || choosedGetter == null) {
ChatItem.debug("Can't find valid json getter or json itself");
ChatItem.debug("String: " + packet.getStrings().getContent());
PacketUtils.printPacketToDebug(e.getPacket());
return; // can't find something
}
if (!ChatManager.containsSeparator(json)) // if the message doesn't contain the BELL separator
return;
ChatItem.debug("Found with " + choosedGetter.getClass().getName());
Chat chat = choosedGetter.getChat(json);
if (chat == null) { // something went really bad, so we run away and hide (AKA the player left or is
// on another server)
ChatItem.debug("Chat null for " + json);
return;
}
Player itemPlayer = chat.getPlayer();
if (getStorage().cooldown > 0 && !itemPlayer.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(itemPlayer);
IComponentManager getter = choosedGetter;
String fjson = json;
ChatItem.debug("Final json used: " + fjson);
e.setCancelled(true); // We cancel the packet as we're going to resends it anyways
CompletableFuture.runAsync(() -> {
Player p = e.getPlayer();
String message = null;
try {
if(chat.getAction().hasItem()) {
ItemStack item = ChatManager.getUsableItem(itemPlayer, chat.getSlot());
if (!ItemUtils.isEmpty(item)) {
ItemStack copy = item.clone();
if (ItemPlayer.getPlayer(p).isBuggedClient()) { // if the guy that will receive it is bugged
String act = getStorage().buggedClientAction;
List<String> tooltip;
if (act.equalsIgnoreCase("tooltip"))
tooltip = getStorage().tooltipBuggedClient;
else if (act.equalsIgnoreCase("item"))
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
else if (act.equalsIgnoreCase("show_both")) {
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
tooltip.addAll(getStorage().tooltipBuggedClient);
} else
tooltip = new ArrayList<>();
message = JSONManipulator.getInstance().parseEmpty(chat, fjson, tooltip, chat.getPlayer());
if (message != null) {
getter.writeJson(e, message);
}
lastSentPacket = e.getPacket();
}
if (copy.hasItemMeta()) {
ItemMeta meta = copy.getItemMeta();
if (meta instanceof BookMeta) { // filtering written books
BookMeta bm = (BookMeta) copy.getItemMeta();
bm.setPages(Collections.emptyList());
copy.setItemMeta(bm);
} else if (meta instanceof BlockStateMeta && Version.getVersion().isNewerOrEquals(Version.V1_9)) { // if it's a block
BlockStateMeta bsm = (BlockStateMeta) copy.getItemMeta();
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
ItemUtils.stripData(itemInv);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
lastSentPacket = getter.manageContent(p, chat, e, fjson, getStorage());
} else {
if (!getStorage().handDisabled) {
lastSentPacket = getter.manageEmpty(p, chat, e, fjson, getStorage());
}
}
} else
lastSentPacket = getter.manageContent(p, chat, e, fjson, getStorage());
if (lastSentPacket == null) // maybe sent by the manager directly
ChatItem.debug("(v1) No packet to sent with manager " + getter.getClass().getName());
else
PacketUtils.sendPacket(p, lastSentPacket);
} catch (Exception e1) {
e1.printStackTrace();
}
});
}
tryRegister(getter);
}
try {
Class.forName("net.kyori.adventure.text.Component");
tryRegister(new AdventureComponentManager());
} catch (Exception e) {
}
ChatItem.debug("ComponentManager: " + String.join(", ", componentManager.stream()
.map(IComponentManager::getClass).map(Class::getSimpleName).collect(Collectors.toList())));
}
private void tryRegister(IComponentManager getter) {
if (getter.hasConditions())
componentManager.add(getter);
else
ChatItem.debug("Component " + getter.getClass().getSimpleName() + " doesn't answer conditions");
}
@SuppressWarnings("deprecation")
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT))
return;
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("packet"))
return;
if (!ChatManager.isSelected("packet"))
return;
if (lastSentPacket != null && lastSentPacket == e.getPacket())
return; // prevent infinite loop
ChatItem.debug("Checking: " + e.getPacket().getClass().getSimpleName() + " to " + e.getPlayername());
PacketContent packet = e.getContent();
Version version = Version.getVersion();
String json = "{}";
IComponentManager choosedGetter = null;
if (version.isNewerOrEquals(Version.V1_19)) {
choosedGetter = new StringComponentManager();
json = choosedGetter.getBaseComponentAsJSON(e); // if null, will be re-checked so anyway
} else if (version.isNewerOrEquals(Version.V1_12)) {
// only if action bar messages are supported
if (((Enum<?>) packet.getSpecificModifier(PacketUtils.getNmsClass("ChatMessageType", "network.chat."))
.read(0)).name().equals("GAME_INFO"))
return; // It's an actionbar message, ignoring
} else if (version.isNewerOrEquals(Version.V1_8) && packet.getBytes().readSafely(0) == (byte) 2)
return; // It's an actionbar message, ignoring
if (json == null || choosedGetter == null || !ChatManager.containsSeparator(json)) {
for (IComponentManager getters : componentManager) {
String tmpJson = getters.getBaseComponentAsJSON(e);
if (tmpJson != null) {
json = ChatManager.fixSeparator(tmpJson);
choosedGetter = getters;
ChatItem.debug("Seems to have one nice manager with " + getters.getClass().getSimpleName()
+ " (json: " + json + ")");
if (ChatManager.containsSeparator(json))
break; // be sure it's valid one
} else
ChatItem.debug("Null JSON for manager " + getters.getClass().getSimpleName());
}
}
if (json == null || choosedGetter == null) {
ChatItem.debug("Can't find valid json getter or json itself");
ChatItem.debug("String: " + packet.getStrings().getContent());
PacketUtils.printPacketToDebug(e.getPacket());
return; // can't find something
}
if (!ChatManager.containsSeparator(json)) // if the message doesn't contain the BELL separator
return;
ChatItem.debug("Found with " + choosedGetter.getClass().getName());
Chat chat = choosedGetter.getChat(json);
if (chat == null) { // something went really bad, so we run away and hide (AKA the player left or is
// on another server)
ChatItem.debug("Chat null for " + json);
return;
}
Player itemPlayer = chat.getPlayer();
if (getStorage().cooldown > 0 && !itemPlayer.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(itemPlayer);
IComponentManager getter = choosedGetter;
String fjson = json;
ChatItem.debug("Final json used: " + fjson);
e.setCancelled(true); // We cancel the packet as we're going to resends it anyways
CompletableFuture.runAsync(() -> {
Player p = e.getPlayer();
String message = null;
try {
if (chat.getAction().hasItem()) {
ItemStack item = ChatManager.getUsableItem(itemPlayer, chat.getSlot());
if (!ItemUtils.isEmpty(item)) {
ItemStack copy = item.clone();
if (ItemPlayer.getPlayer(p).isBuggedClient()) { // if the guy that will receive it is bugged
String act = getStorage().buggedClientAction;
List<String> tooltip;
if (act.equalsIgnoreCase("tooltip"))
tooltip = getStorage().tooltipBuggedClient;
else if (act.equalsIgnoreCase("item"))
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
else if (act.equalsIgnoreCase("show_both")) {
tooltip = ChatManager.getMaxLinesFromItem(p, copy);
tooltip.addAll(getStorage().tooltipBuggedClient);
} else
tooltip = new ArrayList<>();
message = JSONManipulator.getInstance().parseEmpty(chat, fjson, tooltip, chat.getPlayer());
if (message != null) {
getter.writeJson(e, message);
}
lastSentPacket = e.getPacket();
}
if (copy.hasItemMeta()) {
ItemMeta meta = copy.getItemMeta();
if (meta instanceof BookMeta) { // filtering written books
BookMeta bm = (BookMeta) copy.getItemMeta();
bm.setPages(Collections.emptyList());
copy.setItemMeta(bm);
} else if (meta instanceof BlockStateMeta
&& Version.getVersion().isNewerOrEquals(Version.V1_9))
{ // if it's a block
BlockStateMeta bsm = (BlockStateMeta) copy.getItemMeta();
if (bsm.hasBlockState() && bsm.getBlockState() instanceof ShulkerBox) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
ItemUtils.stripData(itemInv);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
lastSentPacket = getter.manageContent(p, chat, e, fjson, getStorage());
} else {
if (!getStorage().handDisabled) {
lastSentPacket = getter.manageEmpty(p, chat, e, fjson, getStorage());
}
}
} else
lastSentPacket = getter.manageContent(p, chat, e, fjson, getStorage());
if (lastSentPacket == null) // maybe sent by the manager directly
ChatItem.debug("(v1) No packet to sent with manager " + getter.getClass().getName());
else
PacketUtils.sendPacket(p, lastSentPacket);
} catch (Exception e1) {
e1.printStackTrace();
}
});
}
public Storage getStorage() {
return manager.getStorage();
}
public Storage getStorage() {
return manager.getStorage();
}
}
@@ -4,54 +4,77 @@ import org.bukkit.entity.Player;
public class ChatItemPacket {
protected final Player player;
protected Object packet;
protected PacketType type;
protected boolean cancel = false;
public ChatItemPacket(PacketType type, Object packet, Player player) {
this.player = player;
this.packet = packet;
this.type = type;
}
public Player getPlayer() {
return player;
}
protected final Player player;
protected Object packet;
protected PacketType type;
protected boolean cancel = false;
public boolean hasPlayer() {
return player != null;
}
public String getPlayername() {
return getPlayer().getName();
}
public Object getPacket() {
return packet;
}
public void setPacket(Object packet) {
this.packet = packet;
}
public ChatItemPacket(PacketType type, Object packet, Player player) {
public String getPacketName() {
return packet.getClass().getSimpleName();
}
public PacketType getPacketType() {
return type;
}
public boolean isCancelled() {
return cancel;
}
public void setCancelled(boolean cancel) {
this.cancel = cancel;
}
this.player = player;
this.packet = packet;
this.type = type;
}
public Player getPlayer() {
return player;
}
public boolean hasPlayer() {
return player != null;
}
public String getPlayername() {
return getPlayer().getName();
}
public Object getPacket() {
return packet;
}
public void setPacket(Object packet) {
this.packet = packet;
}
public String getPacketName() {
return packet.getClass().getSimpleName();
}
public PacketType getPacketType() {
return type;
}
public boolean isCancelled() {
return cancel;
}
public void setCancelled(boolean cancel) {
this.cancel = cancel;
}
public PacketContent getContent() {
return new PacketContent(this);
}
public PacketContent getContent() {
return new PacketContent(this);
}
}
@@ -11,36 +11,61 @@ import me.dadus33.chatitem.chatmanager.v1.packets.protocollib.ProtocollibPacketM
public class ChatItemPacketManager {
private PacketManager packetManager;
public ChatItemPacketManager(ChatItem pl) {
Plugin protocolLibPlugin = Bukkit.getPluginManager().getPlugin("ProtocolLib");
if (protocolLibPlugin != null) {
if(checkProtocollibConditions()) {
pl.getLogger().info("The plugin ProtocolLib has been detected. Loading Protocollib support ...");
packetManager = new ProtocollibPacketManager(pl);
} else {
pl.getLogger().warning("The plugin ProtocolLib has been detected but you have an old or too new version, so we cannot use it.");
pl.getLogger().warning("Fallback to default Packet system ...");
packetManager = new CustomPacketManager(pl);
}
} else {
pl.getLogger().info("Loading own packet system.");
packetManager = new CustomPacketManager(pl);
}
}
public PacketManager getPacketManager() {
return packetManager;
}
private boolean checkProtocollibConditions() {
for(String searchedClass : Arrays.asList("com.comphenix.protocol.injector.server.TemporaryPlayer", "com.comphenix.protocol.injector.temporary.TemporaryPlayer")) { // class since 4.4.0 until 4.8.0, then the new one
try {
Class.forName(searchedClass);
return true; // class found
} catch (ClassNotFoundException e) {}
}
return false;
}
private PacketManager packetManager;
public ChatItemPacketManager(ChatItem pl) {
Plugin protocolLibPlugin = Bukkit.getPluginManager().getPlugin("ProtocolLib");
if (protocolLibPlugin != null) {
if (checkProtocollibConditions()) {
pl.getLogger().info("The plugin ProtocolLib has been detected. Loading Protocollib support ...");
packetManager = new ProtocollibPacketManager(pl);
} else {
pl.getLogger().warning(
"The plugin ProtocolLib has been detected but you have an old or too new version, so we cannot use it.");
pl.getLogger().warning("Fallback to default Packet system ...");
packetManager = new CustomPacketManager(pl);
}
} else {
pl.getLogger().info("Loading own packet system.");
packetManager = new CustomPacketManager(pl);
}
}
public PacketManager getPacketManager() {
return packetManager;
}
private boolean checkProtocollibConditions() {
for (String searchedClass : Arrays.asList("com.comphenix.protocol.injector.server.TemporaryPlayer",
"com.comphenix.protocol.injector.temporary.TemporaryPlayer"))
{ // class since 4.4.0 until 4.8.0, then the new one
try {
Class.forName(searchedClass);
return true; // class found
} catch (ClassNotFoundException e) {
}
}
return false;
}
}
@@ -11,200 +11,270 @@ import me.dadus33.chatitem.utils.PacketUtils;
public class PacketContent {
private final ChatItemPacket packet;
private final Object obj;
/**
* Create a PacketContent to easily read and write value in it
*
* @param packet the Negativity's packet
*/
public PacketContent(ChatItemPacket packet) {
this.packet = packet;
this.obj = packet.getPacket();
}
/**
* Create a PacketContent to easily read and write to the specified object
*
* @param obj the object that will be read or edit
*/
public PacketContent(Object obj) {
this.packet = null;
this.obj = obj;
}
public ChatItemPacket getPacket() {
return packet;
}
public <T> ContentModifier<T> getSpecificModifier(T type){
return new ContentModifier<T>(obj, type.getClass());
}
public <T> ContentModifier<T> getSpecificModifier(Class<T> clazz){
return new ContentModifier<T>(obj, clazz);
}
public ContentModifier<String> getStrings(){
return new ContentModifier<String>(obj, String.class);
}
public ContentModifier<Byte> getBytes(){
return new ContentModifier<Byte>(obj, byte.class);
}
public ContentModifier<Boolean> getBooleans(){
return new ContentModifier<Boolean>(obj, boolean.class);
}
public ContentModifier<Integer> getIntegers(){
return new ContentModifier<Integer>(obj, int.class);
}
public ContentModifier<byte[]> getByteArrays(){
return new ContentModifier<byte[]>(obj, byte[].class);
}
private final ChatItemPacket packet;
private final Object obj;
public ContentModifier<Object> getChatComponents() {
return (ContentModifier<Object>) getSpecificModifier(PacketUtils.COMPONENT_CLASS);
}
public static class ContentModifier<T> {
private Object obj;
private HashMap<Field, T> content = new HashMap<>();
/**
* Create a PacketContent to easily read and write value in it
*
* @param packet the Negativity's packet
*/
public PacketContent(ChatItemPacket packet) {
public ContentModifier(Object obj, Class<?> clazz) {
this.obj = obj;
for(Field f : obj.getClass().getDeclaredFields()) {
try {
if(f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
if(!obj.getClass().getSuperclass().equals(Object.class)) {
for(Field f : obj.getClass().getSuperclass().getDeclaredFields()) {
try {
if(f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public Object getObj() {
return obj;
}
/**
* Get the size of the Map of content
*
* @return the number of content
*/
public int size() {
return content.size();
}
this.packet = packet;
this.obj = packet.getPacket();
}
/**
* Create a PacketContent to easily read and write to the specified object
*
* @param obj the object that will be read or edit
*/
public PacketContent(Object obj) {
this.packet = null;
this.obj = obj;
}
public ChatItemPacket getPacket() {
return packet;
}
public <T> ContentModifier<T> getSpecificModifier(T type) {
return new ContentModifier<T>(obj, type.getClass());
}
public <T> ContentModifier<T> getSpecificModifier(Class<T> clazz) {
return new ContentModifier<T>(obj, clazz);
}
public ContentModifier<String> getStrings() {
return new ContentModifier<String>(obj, String.class);
}
public ContentModifier<Byte> getBytes() {
return new ContentModifier<Byte>(obj, byte.class);
}
public ContentModifier<Boolean> getBooleans() {
return new ContentModifier<Boolean>(obj, boolean.class);
}
public ContentModifier<Integer> getIntegers() {
return new ContentModifier<Integer>(obj, int.class);
}
public ContentModifier<byte[]> getByteArrays() {
return new ContentModifier<byte[]>(obj, byte[].class);
}
public ContentModifier<Object> getChatComponents() {
return (ContentModifier<Object>) getSpecificModifier(PacketUtils.COMPONENT_CLASS);
}
public static class ContentModifier<T> {
private Object obj;
private HashMap<Field, T> content = new HashMap<>();
public ContentModifier(Object obj, Class<?> clazz) {
this.obj = obj;
for (Field f : obj.getClass().getDeclaredFields()) {
try {
if (f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (!obj.getClass().getSuperclass().equals(Object.class)) {
for (Field f : obj.getClass().getSuperclass().getDeclaredFields()) {
try {
if (f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public Object getObj() {
return obj;
}
/**
* Get the size of the Map of content
*
* @return the number of content
*/
public int size() {
return content.size();
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @return the value of the field
*/
public T read(String fieldName) {
for (Field field : content.keySet())
if (field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return null;
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @param defaultValue the returned value if there is no value
* @return the value of the field
*/
public T read(String fieldName, T defaultValue) {
for (Field field : content.keySet())
if (field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return defaultValue;
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value.
*
* @throws NoSuchElementException if the value doesn't exist
*/
public T read(int i) {
return content.values().stream().filter(Objects::nonNull).collect(Collectors.toList()).get(i);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value, or null if it doesn't exist.
*/
public T readSafely(int i) {
return readSafely(i, null);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @param defaultValue the value which is return if the key doesn't exist
* @return the requested value.
*/
public T readSafely(int i, T defaultValue) {
List<T> vals = content.values().stream().filter(Objects::nonNull).collect(Collectors.toList());
return vals.size() <= i ? defaultValue : vals.get(i);
}
/**
* Set the value in the specified object.
*
* @param i the key of the value to set
* @param value the new value which will be set
*/
public void write(int i, T value) {
Field key = content.keySet().toArray(new Field[] {})[i];
if (key == null) {
new NoSuchFieldException("Not enough value in " + obj.getClass() + ".").printStackTrace();
} else {
content.put(key, value);
try {
key.setAccessible(true);
key.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Get field which her value
*
* @return all content
*/
public HashMap<Field, T> getContent() {
return content;
}
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @return the value of the field
*/
public T read(String fieldName) {
for(Field field : content.keySet())
if(field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return null;
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @param defaultValue the returned value if there is no value
* @return the value of the field
*/
public T read(String fieldName, T defaultValue) {
for(Field field : content.keySet())
if(field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return defaultValue;
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value.
*
* @throws NoSuchElementException if the value doesn't exist
*/
public T read(int i) {
return content.values().stream().filter(Objects::nonNull).collect(Collectors.toList()).get(i);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value, or null if it doesn't exist.
*/
public T readSafely(int i) {
return readSafely(i, null);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @param defaultValue the value which is return if the key doesn't exist
* @return the requested value.
*/
public T readSafely(int i, T defaultValue) {
List<T> vals = content.values().stream().filter(Objects::nonNull).collect(Collectors.toList());
return vals.size() <= i ? defaultValue : vals.get(i);
}
/**
* Set the value in the specified object.
*
* @param i the key of the value to set
* @param value the new value which will be set
*/
public void write(int i, T value) {
Field key = content.keySet().toArray(new Field[] {})[i];
if(key == null) {
new NoSuchFieldException("Not enough value in " + obj.getClass() + ".").printStackTrace();
} else {
content.put(key, value);
try {
key.setAccessible(true);
key.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Get field which her value
*
* @return all content
*/
public HashMap<Field, T> getContent(){
return content;
}
}
}
@@ -2,6 +2,12 @@ package me.dadus33.chatitem.chatmanager.v1.packets;
public abstract class PacketHandler {
public void onReceive(ChatItemPacket packet) {}
public void onSend(ChatItemPacket packet) {}
public void onReceive(ChatItemPacket packet) {
}
public void onSend(ChatItemPacket packet) {
}
}
@@ -6,29 +6,48 @@ import org.bukkit.entity.Player;
public abstract class PacketManager {
public void addPlayer(Player p) {}
public void removePlayer(Player p) {}
public abstract void stop();
public void addPlayer(Player p) {
private final ArrayList<PacketHandler> handlers = new ArrayList<>();
public boolean addHandler(PacketHandler handler) {
return !handlers.add(handler);
}
}
public boolean removeHandler(PacketHandler handler) {
return handlers.remove(handler);
}
public void removePlayer(Player p) {
public void notifyHandlersSent(ChatItemPacket packet) {
handlers.forEach((handler) -> handler.onSend(packet));
}
}
public abstract void stop();
private final ArrayList<PacketHandler> handlers = new ArrayList<>();
public boolean addHandler(PacketHandler handler) {
return !handlers.add(handler);
}
public boolean removeHandler(PacketHandler handler) {
return handlers.remove(handler);
}
public void notifyHandlersSent(ChatItemPacket packet) {
handlers.forEach((handler) -> handler.onSend(packet));
}
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
if (type == null) {
return null;
}
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
notifyHandlersSent(customPacket);
return customPacket;
}
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
if(type == null) {
return null;
}
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
notifyHandlersSent(customPacket);
return customPacket;
}
}
@@ -6,101 +6,133 @@ import java.util.List;
public interface PacketType {
String name();
String getPacketName();
String getFullName();
List<String> getAlias();
public static List<PacketType> values() {
List<PacketType> list = new ArrayList<>();
list.addAll(Arrays.asList(Server.values()));
list.addAll(Arrays.asList(Handshake.values()));
return list;
}
static final String SERVER_PREFIX = "PacketPlayOut", HANDSHAKE_PREFIX = "PacketHandshaking";
public static PacketType getType(String packetName) {
if(packetName.startsWith(SERVER_PREFIX)) {
return getPacketTypeFor(packetName, Server.values(), Server.UNSET);
} else if(packetName.startsWith(HANDSHAKE_PREFIX)) {
return getPacketTypeFor(packetName, Handshake.values(), Handshake.UNSET);
} else {
for(PacketType types : values()) {
if(types.getFullName().equalsIgnoreCase(packetName) || types.getAlias().contains(packetName))
return types;
}
return null;
}
}
static PacketType getPacketTypeFor(String packetName, PacketType[] types, PacketType unset) {
for(PacketType packet : types)
if(packet.getFullName().equalsIgnoreCase(packetName) || packet.getPacketName().equalsIgnoreCase(packetName) || packet.getAlias().contains(packetName))
return packet;
return unset;
}
public static enum Server implements PacketType {
CHAT("Chat", "ClientboundPlayerChatPacket", "ClientboundSystemChatPacket"),
UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Server(String packetName, String... alias) {
this.packetName = packetName;
this.fullName = SERVER_PREFIX + packetName;
for(String al : alias)
this.alias.add(al);
}
String name();
String getPacketName();
String getFullName();
List<String> getAlias();
@Override
public String getPacketName() {
return packetName;
}
public static List<PacketType> values() {
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
public static enum Handshake implements PacketType {
IS_SET_PROTOCOL("InSetProtocol"),
UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Handshake(String packetName, String... alias) {
this.packetName = packetName;
for(String al : alias)
this.alias.add(HANDSHAKE_PREFIX + al);
this.fullName = HANDSHAKE_PREFIX + packetName;
}
List<PacketType> list = new ArrayList<>();
list.addAll(Arrays.asList(Server.values()));
list.addAll(Arrays.asList(Handshake.values()));
return list;
@Override
public String getPacketName() {
return packetName;
}
}
static final String SERVER_PREFIX = "PacketPlayOut", HANDSHAKE_PREFIX = "PacketHandshaking";
public static PacketType getType(String packetName) {
if (packetName.startsWith(SERVER_PREFIX)) {
return getPacketTypeFor(packetName, Server.values(), Server.UNSET);
} else if (packetName.startsWith(HANDSHAKE_PREFIX)) {
return getPacketTypeFor(packetName, Handshake.values(), Handshake.UNSET);
} else {
for (PacketType types : values()) {
if (types.getFullName().equalsIgnoreCase(packetName) || types.getAlias().contains(packetName))
return types;
}
return null;
}
}
static PacketType getPacketTypeFor(String packetName, PacketType[] types, PacketType unset) {
for (PacketType packet : types)
if (packet.getFullName().equalsIgnoreCase(packetName) || packet.getPacketName().equalsIgnoreCase(packetName)
|| packet.getAlias().contains(packetName))
return packet;
return unset;
}
public static enum Server implements PacketType {
CHAT("Chat", "ClientboundPlayerChatPacket", "ClientboundSystemChatPacket"), UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Server(String packetName, String... alias) {
this.packetName = packetName;
this.fullName = SERVER_PREFIX + packetName;
for (String al : alias)
this.alias.add(al);
}
@Override
public String getPacketName() {
return packetName;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
public static enum Handshake implements PacketType {
IS_SET_PROTOCOL("InSetProtocol"), UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Handshake(String packetName, String... alias) {
this.packetName = packetName;
for (String al : alias)
this.alias.add(HANDSHAKE_PREFIX + al);
this.fullName = HANDSHAKE_PREFIX + packetName;
}
@Override
public String getPacketName() {
return packetName;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
}
@@ -18,61 +18,78 @@ import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
public class CustomPacketManager extends PacketManager implements Listener {
private ChannelAbstract channel;
private Plugin pl;
public HashMap<Object, Integer> protocolVersionPerChannel = new HashMap<>();
private boolean isStarted = false;
public CustomPacketManager(Plugin pl) {
this.pl = pl;
Version version = Version.getVersion();
if (version.isNewerOrEquals(Version.V1_17))
channel = new INC2Channel(this);
else
channel = new INCChannel(this);
pl.getServer().getPluginManager().registerEvents(this, pl);
// we wait the start server
CompletableFuture.runAsync(() -> {
isStarted = true;
for(Player p : Utils.getOnlinePlayers())
addPlayer(p);
});
}
public Plugin getPlugin() {
return pl;
}
private ChannelAbstract channel;
private Plugin pl;
public HashMap<Object, Integer> protocolVersionPerChannel = new HashMap<>();
private boolean isStarted = false;
@EventHandler
public void onJoin(PlayerJoinEvent e) {
addPlayer(e.getPlayer());
}
public CustomPacketManager(Plugin pl) {
@EventHandler
public void onQuit(PlayerQuitEvent e) {
removePlayer(e.getPlayer());
}
this.pl = pl;
Version version = Version.getVersion();
if (version.isNewerOrEquals(Version.V1_17))
channel = new INC2Channel(this);
else
channel = new INCChannel(this);
pl.getServer().getPluginManager().registerEvents(this, pl);
@Override
public void addPlayer(Player p) {
if(isStarted)
channel.addPlayer(p);
}
// we wait the start server
CompletableFuture.runAsync(() -> {
@Override
public void removePlayer(Player p) {
channel.removePlayer(p);
}
isStarted = true;
for (Player p : Utils.getOnlinePlayers())
addPlayer(p);
});
}
public Plugin getPlugin() {
return pl;
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
addPlayer(e.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent e) {
removePlayer(e.getPlayer());
}
@Override
public void addPlayer(Player p) {
if (isStarted)
channel.addPlayer(p);
}
@Override
public void removePlayer(Player p) {
channel.removePlayer(p);
}
@Override
public void stop() {
for (Player player : Utils.getOnlinePlayers())
removePlayer(player);
if (channel.getAddChannelExecutor() != null)
channel.getAddChannelExecutor().shutdownNow();
if (channel.getRemoveChannelExecutor() != null)
channel.getRemoveChannelExecutor().shutdownNow();
}
@Override
public void stop() {
for(Player player : Utils.getOnlinePlayers())
removePlayer(player);
if(channel.getAddChannelExecutor() != null)
channel.getAddChannelExecutor().shutdownNow();
if(channel.getRemoveChannelExecutor() != null)
channel.getRemoveChannelExecutor().shutdownNow();
}
}
@@ -14,73 +14,100 @@ import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
public abstract class ChannelAbstract {
private ExecutorService addChannelExecutor, removeChannelExecutor;
static final String KEY_HANDSHAKE = "packet_handshake_chatitem", KEY_HANDLER_SERVER = "packet_handler", KEY_SERVER = "packet_server_chatitem";
private ExecutorService addChannelExecutor, removeChannelExecutor;
static final String KEY_HANDSHAKE = "packet_handshake_chatitem", KEY_HANDLER_SERVER = "packet_handler",
KEY_SERVER = "packet_server_chatitem";
private CustomPacketManager customPacketManager;
private HashSet<UUID> players = new HashSet<>();
protected ChannelAbstract(CustomPacketManager customPacketManager) {
this.customPacketManager = customPacketManager;
}
public CustomPacketManager getPacketManager() {
return customPacketManager;
}
public ExecutorService getAddChannelExecutor() {
return addChannelExecutor;
}
public ExecutorService getOrCreateAddChannelExecutor() {
if(addChannelExecutor == null || addChannelExecutor.isTerminated())
addChannelExecutor = Executors.newSingleThreadExecutor();
return addChannelExecutor;
}
public ExecutorService getRemoveChannelExecutor() {
return removeChannelExecutor;
}
public ExecutorService getOrCreateRemoveChannelExecutor() {
if(removeChannelExecutor == null || removeChannelExecutor.isTerminated())
removeChannelExecutor = Executors.newSingleThreadExecutor();
return removeChannelExecutor;
}
private CustomPacketManager customPacketManager;
private HashSet<UUID> players = new HashSet<>();
public void addPlayer(Player p) {
if(players.add(p.getUniqueId())) {
addChannel(p, p.getUniqueId().toString());
try {
Integer protocol = customPacketManager.protocolVersionPerChannel.remove(getChannel(p));
if(protocol != null)
ItemPlayer.getPlayer(p).setProtocolVersion(protocol);
} catch (Exception e) {
e.printStackTrace();
}
}
}
protected ChannelAbstract(CustomPacketManager customPacketManager) {
public void removePlayer(Player p) {
if(players.remove(p.getUniqueId()))
removeChannel(p, p.getUniqueId().toString());
}
public void removeAllPlayers() {
new ArrayList<>(players).forEach((uuid) -> {
Player p = Bukkit.getPlayer(uuid);
if(p != null) // player don't left
removeChannel(Bukkit.getPlayer(uuid), uuid.toString());
});
players.clear();
}
protected abstract void stopPipelines();
public abstract void addChannel(Player player, String endChannelName);
this.customPacketManager = customPacketManager;
public abstract void removeChannel(Player player, String endChannelName);
public abstract Object getChannel(Player p) throws Exception;
}
public CustomPacketManager getPacketManager() {
return customPacketManager;
}
public ExecutorService getAddChannelExecutor() {
return addChannelExecutor;
}
public ExecutorService getOrCreateAddChannelExecutor() {
if (addChannelExecutor == null || addChannelExecutor.isTerminated())
addChannelExecutor = Executors.newSingleThreadExecutor();
return addChannelExecutor;
}
public ExecutorService getRemoveChannelExecutor() {
return removeChannelExecutor;
}
public ExecutorService getOrCreateRemoveChannelExecutor() {
if (removeChannelExecutor == null || removeChannelExecutor.isTerminated())
removeChannelExecutor = Executors.newSingleThreadExecutor();
return removeChannelExecutor;
}
public void addPlayer(Player p) {
if (players.add(p.getUniqueId())) {
addChannel(p, p.getUniqueId().toString());
try {
Integer protocol = customPacketManager.protocolVersionPerChannel.remove(getChannel(p));
if (protocol != null)
ItemPlayer.getPlayer(p).setProtocolVersion(protocol);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void removePlayer(Player p) {
if (players.remove(p.getUniqueId()))
removeChannel(p, p.getUniqueId().toString());
}
public void removeAllPlayers() {
new ArrayList<>(players).forEach((uuid) -> {
Player p = Bukkit.getPlayer(uuid);
if (p != null) // player don't left
removeChannel(Bukkit.getPlayer(uuid), uuid.toString());
});
players.clear();
}
protected abstract void stopPipelines();
public abstract void addChannel(Player player, String endChannelName);
public abstract void removeChannel(Player player, String endChannelName);
public abstract Object getChannel(Player p) throws Exception;
}
@@ -19,74 +19,111 @@ import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
public class ChannelInboundHandler extends ChannelInboundHandlerAdapter {
private CustomPacketManager packetManager;
private List<ChannelPipeline> pipelines = new ArrayList<>();
public ChannelInboundHandler(CustomPacketManager packetManager) {
this.packetManager = packetManager;
}
public void clean() {
pipelines.forEach(ChannelPipeline::removeFirst);
pipelines.clear();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
ChannelPipeline pipe = ((Channel) msg).pipeline();
pipelines.add(pipe);
pipe.addFirst(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.eventLoop().submit(() -> {
try {
ChannelHandler interceptor = channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new ChannelHandlerHandshakeReceive(channel);
channel.pipeline().addBefore("packet_handler", ChannelAbstract.KEY_HANDSHAKE, interceptor);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
}
});
} catch (Exception e) {
packetManager.getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incoming channel " + channel, e);
}
}
});
}
public class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
private Channel channel;
public ChannelHandlerHandshakeReceive(Channel channel) {
this.channel = channel;
}
private CustomPacketManager packetManager;
private List<ChannelPipeline> pipelines = new ArrayList<>();
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
ContentModifier<Integer> ints = new PacketContent(packet).getIntegers();
int possibleProtocol = ints.readSafely(0, 0);
if(possibleProtocol == Bukkit.getPort())
possibleProtocol = ints.readSafely(1, 0);
if(possibleProtocol == -1 || possibleProtocol == 255 || possibleProtocol == Bukkit.getPort())
possibleProtocol = ints.readSafely(2, 0);
packetManager.protocolVersionPerChannel.put(channel, possibleProtocol);
}
super.channelRead(ctx, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
public ChannelInboundHandler(CustomPacketManager packetManager) {
this.packetManager = packetManager;
}
public void clean() {
pipelines.forEach(ChannelPipeline::removeFirst);
pipelines.clear();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
ChannelPipeline pipe = ((Channel) msg).pipeline();
pipelines.add(pipe);
pipe.addFirst(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.eventLoop().submit(() -> {
try {
ChannelHandler interceptor = channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new ChannelHandlerHandshakeReceive(channel);
channel.pipeline().addBefore("packet_handler", ChannelAbstract.KEY_HANDSHAKE,
interceptor);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
}
});
} catch (Exception e) {
packetManager.getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incoming channel " + channel,
e);
}
}
});
}
public class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
private Channel channel;
public ChannelHandlerHandshakeReceive(Channel channel) {
this.channel = channel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if (packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
ContentModifier<Integer> ints = new PacketContent(packet).getIntegers();
int possibleProtocol = ints.readSafely(0, 0);
if (possibleProtocol == Bukkit.getPort())
possibleProtocol = ints.readSafely(1, 0);
if (possibleProtocol == -1 || possibleProtocol == 255 || possibleProtocol == Bukkit.getPort())
possibleProtocol = ints.readSafely(2, 0);
packetManager.protocolVersionPerChannel.put(channel, possibleProtocol);
}
super.channelRead(ctx, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@@ -22,89 +22,139 @@ import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Version;
public class INC2Channel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
public INC2Channel(CustomPacketManager customPacketManager) {
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
try {
Object mcServer = ReflectionUtils.callMethod(PacketUtils.getCraftServer(), Version.getVersion().equals(Version.V1_17) ? "getServer" : "b");
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "server.network."));
((List<ChannelFuture>) ReflectionUtils.getObject(co, "f")).forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if(!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
public INC2Channel(CustomPacketManager customPacketManager) {
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = ReflectionUtils.getFirstWith(playerConnection, PacketUtils.getNmsClass("NetworkManager", "network."));
return ReflectionUtils.getFirstWith(networkManager, Channel.class);
}
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
try {
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
Object mcServer = ReflectionUtils.callMethod(PacketUtils.getCraftServer(),
Version.getVersion().equals(Version.V1_17) ? "getServer" : "b");
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."),
PacketUtils.getNmsClass("ServerConnection", "server.network."));
((List<ChannelFuture>) ReflectionUtils.getObject(co, "f")).forEach((channelFuture) -> {
private final Player owner;
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
public ChannelHandlerSent(Player player) {
this.owner = player;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if (!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName,
new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger()
.warning("Please, don't use reload, this can produce some problem. Currently, "
+ player.getName() + " isn't fully checked because of that. More details: "
+ e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. "
+ e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if (channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName()
+ ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = ReflectionUtils.getFirstWith(playerConnection,
PacketUtils.getNmsClass("NetworkManager", "network."));
return ReflectionUtils.getFirstWith(networkManager, Channel.class);
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager()
.onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if (nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -23,100 +23,155 @@ import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
public class INCChannel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
public INCChannel(CustomPacketManager customPacketManager) {
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
getFuturChannel().forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
});
}
public List<ChannelFuture> getFuturChannel() {
try {
Object dedicatedSrv = PacketUtils.getCraftServer();
Object mcServer = dedicatedSrv.getClass().getMethod("getServer").invoke(dedicatedSrv);
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "network."));
try {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "g");
} catch (NoSuchFieldException e) {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "listeningChannels");
}
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<>();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if(!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
public INCChannel(CustomPacketManager customPacketManager) {
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
getFuturChannel().forEach((channelFuture) -> {
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
return new PacketContent(networkManager).getSpecificModifier(Channel.class).readSafely(0);//(Channel) networkManager.getClass().getDeclaredField("channel").get(networkManager);
}
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
});
private final Player owner;
}
public List<ChannelFuture> getFuturChannel() {
try {
Object dedicatedSrv = PacketUtils.getCraftServer();
Object mcServer = dedicatedSrv.getClass().getMethod("getServer").invoke(dedicatedSrv);
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."),
PacketUtils.getNmsClass("ServerConnection", "network."));
try {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "g");
} catch (NoSuchFieldException e) {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "listeningChannels");
}
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<>();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if (!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName,
new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger()
.warning("Please, don't use reload, this can produce some problem. Currently, "
+ player.getName() + " isn't fully checked because of that. More details: "
+ e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. "
+ e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if (channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName()
+ ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
return new PacketContent(networkManager).getSpecificModifier(Channel.class).readSafely(0);// (Channel)
// networkManager.getClass().getDeclaredField("channel").get(networkManager);
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager()
.onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if (nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -19,36 +19,54 @@ import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
public class ProtocollibPacketManager extends PacketManager {
private final ProtocolManager protocolManager;
public ProtocollibPacketManager(ChatItem pl) {
protocolManager = ProtocolLibrary.getProtocolManager();
List<com.comphenix.protocol.PacketType> list = new ArrayList<>();
list.add(Play.Server.CHAT);
try {
list.add((com.comphenix.protocol.PacketType) Play.Server.class.getDeclaredField("SYSTEM_CHAT").get(null));
} catch (Exception e) {
// ignore because using old version
}
protocolManager.addPacketListener(new PacketAdapter(pl, ListenerPriority.LOWEST, list) {
@Override
public void onPacketSending(PacketEvent e) {
Player p = e.getPlayer();
if (p == null || e.isPlayerTemporary())
return;
ChatItemPacket packet = onPacketSent(PacketType.getType(e.getPacket().getHandle().getClass().getSimpleName()), p, e.getPacket().getHandle());
if(packet == null) {
ChatItem.debug("Can't find packet: " + e.getPacket().getHandle().getClass().getName());
return;
}
if(!e.isCancelled())
e.setCancelled(packet.isCancelled());
}
});
}
@Override
public void stop() {
protocolManager.removePacketListeners(ChatItem.getInstance());
}
private final ProtocolManager protocolManager;
public ProtocollibPacketManager(ChatItem pl) {
protocolManager = ProtocolLibrary.getProtocolManager();
List<com.comphenix.protocol.PacketType> list = new ArrayList<>();
list.add(Play.Server.CHAT);
try {
list.add((com.comphenix.protocol.PacketType) Play.Server.class.getDeclaredField("SYSTEM_CHAT").get(null));
} catch (Exception e) {
// ignore because using old version
}
protocolManager.addPacketListener(new PacketAdapter(pl, ListenerPriority.LOWEST, list) {
@Override
public void onPacketSending(PacketEvent e) {
Player p = e.getPlayer();
if (p == null || e.isPlayerTemporary())
return;
ChatItemPacket packet = onPacketSent(
PacketType.getType(e.getPacket().getHandle().getClass().getSimpleName()), p,
e.getPacket().getHandle());
if (packet == null) {
ChatItem.debug("Can't find packet: " + e.getPacket().getHandle().getClass().getName());
return;
}
if (!e.isCancelled())
e.setCancelled(packet.isCancelled());
}
});
}
@Override
public void stop() {
protocolManager.removePacketListeners(ChatItem.getInstance());
}
}
@@ -1,44 +1,61 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
@Deprecated
public class Item {
private String id;
private byte amount;
private short data;
private CompoundTag tag;
public CompoundTag getTag(){
public CompoundTag getTag() {
return tag;
}
public void setTag(CompoundTag newTag){
public void setTag(CompoundTag newTag) {
this.tag = newTag;
}
public void setId(String newId){
public void setId(String newId) {
this.id = newId;
}
public void setData(short newData){
public void setData(short newData) {
data = newData;
}
public String getId(){
public String getId() {
return id;
}
public short getData(){
public short getData() {
return data;
}
public void setAmount(byte newAmount){
public void setAmount(byte newAmount) {
this.amount = newAmount;
}
public byte getAmount(){
public byte getAmount() {
return amount;
}
}
@@ -10,41 +10,70 @@ import org.bukkit.inventory.ItemStack;
@Deprecated
public class ItemRewriter {
public static String remapIds(int server, int player, ItemStack is) {
Item item = new Item();
item.setAmount((byte)is.getAmount());
//item.setData(is.getDurability());
//item.setId(id);
//item.setTag(tag);
if (areIdsCompatible(server, player)) {
return item.getId();
}
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER) || (player >= V1_9.MIN_VER && server <= V1_8.MAX_VER)) {
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER)) {
ItemRewriter_1_9_TO_1_8.reversedToClient(item);
} else
ItemRewriter_1_9_TO_1_8.toClient(item);
}
if ((server <= V1_10.MAX_VER && player >= V1_11.MIN_VER)
|| (player <= V1_10.MAX_VER && server >= V1_11.MIN_VER)) {
if (server <= V1_10.MAX_VER && player >= V1_11.MIN_VER) {
ItemRewriter_1_11_TO_1_10.toClient(item);
} else {
ItemRewriter_1_11_TO_1_10.reverseToClient(item);
}
}
return item.getId();
}
public static String remapIds(int server, int player, ItemStack is) {
Item item = new Item();
item.setAmount((byte) is.getAmount());
// item.setData(is.getDurability());
// item.setId(id);
// item.setTag(tag);
if (areIdsCompatible(server, player)) {
return item.getId();
}
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER) || (player >= V1_9.MIN_VER && server <= V1_8.MAX_VER)) {
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER)) {
ItemRewriter_1_9_TO_1_8.reversedToClient(item);
} else
ItemRewriter_1_9_TO_1_8.toClient(item);
}
if ((server <= V1_10.MAX_VER && player >= V1_11.MIN_VER)
|| (player <= V1_10.MAX_VER && server >= V1_11.MIN_VER))
{
if (server <= V1_10.MAX_VER && player >= V1_11.MIN_VER) {
ItemRewriter_1_11_TO_1_10.toClient(item);
} else {
ItemRewriter_1_11_TO_1_10.reverseToClient(item);
}
}
return item.getId();
}
public static boolean areIdsCompatible(int version1, int version2) {
if ((version1 >= V1_9.MIN_VER && version2 <= V1_8.MAX_VER)
|| (version2 >= V1_9.MIN_VER && version1 <= V1_8.MAX_VER))
{
return false;
}
if ((version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)
|| (version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER))
{
return false;
}
return true;
}
public static boolean areIdsCompatible(int version1, int version2) {
if ((version1 >= V1_9.MIN_VER && version2 <= V1_8.MAX_VER)
|| (version2 >= V1_9.MIN_VER && version1 <= V1_8.MAX_VER)) {
return false;
}
if ((version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)
|| (version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)) {
return false;
}
return true;
}
}
@@ -1,20 +1,20 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
/**
* Thanks to the developers of ViaVersion for this!
*/
@Deprecated
public class ItemRewriter_1_11_TO_1_10 {
private static BiMap<String, String> oldToNewNames = HashBiMap.create();
static {
oldToNewNames.put("AreaEffectCloud", "minecraft:area_effect_cloud");
oldToNewNames.put("ArmorStand", "minecraft:armor_stand");
oldToNewNames.put("Arrow", "minecraft:arrow");
@@ -90,43 +90,68 @@ public class ItemRewriter_1_11_TO_1_10 {
oldToNewNames.put("Zombie", "minecraft:zombie");
oldToNewNames.put("ZombieHorse", "minecraft:zombie_horse");
oldToNewNames.put("ZombieVillager", "minecraft:zombie_villager");
}
static void toClient(Item item) {
if (hasEntityTag(item)) {
CompoundTag entityTag = item.getTag().get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (oldToNewNames.containsKey(id.getValue())) {
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
static void reverseToClient(Item item) {
if (hasEntityTag(item)) {
CompoundTag entityTag = item.getTag().get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (oldToNewNames.containsKey(id.getValue())) {
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
private static boolean hasEntityTag(Item item) {
if (item != null && item.getId().equals("minecraft:spawn_egg")) { // Monster Egg
CompoundTag tag = item.getTag();
if (tag != null && tag.contains("EntityTag") && tag.get("EntityTag") instanceof CompoundTag) {
if (((CompoundTag) tag.get("EntityTag")).get("id") instanceof StringTag) {
return true;
}
}
}
return false;
}
}
@@ -1,11 +1,11 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import java.util.HashMap;
import java.util.Map;
/**
* Thanks to the developers of ViaVersion for this!
*/
@@ -20,6 +20,7 @@ public class ItemRewriter_1_9_TO_1_8 {
private static final Map<Integer, Integer> POTION_INDEX = new HashMap<>();
static {
/* Entities */
registerEntity(1, "Item");
registerEntity(2, "XPOrb");
@@ -137,107 +138,166 @@ public class ItemRewriter_1_9_TO_1_8 {
}
static void toClient(Item item) {
if (item != null) {
if (item.getId().equals("minecraft:spawn_egg") && item.getData() != 0) { // Monster Egg
CompoundTag tag = item.getTag();
if (tag == null) {
tag = new CompoundTag("tag");
}
CompoundTag entityTag = new CompoundTag("EntityTag");
if (ENTTIY_ID_TO_NAME.containsKey((int) item.getData())) {
StringTag id = new StringTag("id", ENTTIY_ID_TO_NAME.get((int) item.getData()));
entityTag.put(id);
tag.put(entityTag);
}
item.setTag(tag);
item.setData((short) 0);
}
if (item.getId().equals("minecraft:potion")) { // Potion
CompoundTag tag = item.getTag();
if (tag == null) {
tag = new CompoundTag("tag");
}
if (item.getData() >= 16384) {
item.setId("minecraft:splash_potion"); // splash id
item.setData((short) (item.getData() - 8192));
}
String name = potionNameFromDamage(item.getData());
StringTag potion = new StringTag("Potion", "minecraft:" + name);
tag.put(potion);
item.setTag(tag);
item.setData((short) 0);
}
}
}
static void reversedToClient(Item item) {
if (item != null) {
if (item.getId().equals("minecraft:spawn_egg") && item.getData() == 0) { // Monster Egg
CompoundTag tag = item.getTag();
int data = 0;
if(tag != null) {
if (tag != null) {
if (tag.get("EntityTag") instanceof CompoundTag) {
CompoundTag entityTag = tag.get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (ENTTIY_NAME_TO_ID.containsKey(id.getValue()))
data = ENTTIY_NAME_TO_ID.get(id.getValue());
}
tag.remove("EntityTag");
}
}
item.setTag(tag);
item.setData((short) data);
}
if (item.getId().equals("minecraft:potion")) { // Potion
CompoundTag tag = item.getTag();
int data = 0;
if(tag != null) {
if (tag != null) {
if (tag.get("Potion") instanceof StringTag) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName);
}
tag.remove("Potion");
}
}
item.setTag(tag);
item.setData((short) data);
}
// Splash potion
if (item.getId().equals("minecraft:splash_potion")) {
CompoundTag tag = item.getTag();
int data = 0;
item.setId("minecraft:potion"); // Potion
if(tag != null) {
if (tag != null) {
if (tag.get("Potion") instanceof StringTag) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName) + 8192;
}
tag.remove("Potion");
}
}
item.setTag(tag);
item.setData((short) data);
}
}
}
private static String potionNameFromDamage(short damage) {
String cached = POTION_ID_TO_NAME.get((int) damage);
if (cached != null) {
return cached;
}
if (damage == 0) {
return "water";
}
int effect = damage & 0xF;
@@ -250,6 +310,7 @@ public class ItemRewriter_1_9_TO_1_8 {
String id;
switch (effect) {
case 1:
id = "regeneration";
break;
@@ -299,11 +360,11 @@ public class ItemRewriter_1_9_TO_1_8 {
canEnhance = false;
break;
default:
canEnhance = false;
canExtend = false;
switch (name) {
case 0:
id = "mundane";
break;
@@ -315,28 +376,42 @@ public class ItemRewriter_1_9_TO_1_8 {
break;
default:
id = "empty";
}
}
if (effect > 0) {
if (canEnhance && enhanced) {
id = "strong_" + id;
} else if (canExtend && extended) {
id = "long_" + id;
}
}
return id;
}
private static void registerEntity(Integer id, String name) {
ENTTIY_ID_TO_NAME.put(id, name);
ENTTIY_NAME_TO_ID.put(name, id);
}
private static void registerPotion(Integer id, String name) {
POTION_INDEX.put(id, POTION_ID_TO_NAME.size());
POTION_ID_TO_NAME.put(id, name);
POTION_NAME_TO_ID.put(name, id);
}
}
@@ -24,79 +24,120 @@ import net.md_5.bungee.api.ChatColor;
@SuppressWarnings("deprecation")
public class ChatListener implements Listener {
private ChatListenerChatManager manage;
private ChatListenerChatManager manage;
public ChatListener(ChatListenerChatManager manage) {
this.manage = manage;
}
public ChatListener(ChatListenerChatManager manage) {
public Storage getStorage() {
return manage.getStorage();
}
this.manage = manage;
}
public Storage getStorage() {
return manage.getStorage();
}
@EventHandler(priority = EventPriority.HIGH)
public void onChat(AsyncPlayerChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("chat"))
return;
if (!ChatManager.isSelected("chat"))
return;
Storage c = getStorage();
if (e.isCancelled()) {
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
String msg = e.getMessage().toLowerCase();
for (ItemSlot slot : ItemSlot.values()) {
for (String rep : slot.getPlaceholders()) {
if (msg.contains(rep)) {
ChatItem.debug(
"You choose 'chat' manager but it seems to don't be the good choice. More informations here: https://github.com/dadus33-plugins/ChatItem/wiki");
return;
}
}
}
}
ChatItem.debug("Chat cancelled for " + e.getPlayer().getName());
return;
}
Player p = e.getPlayer();
String targetReplace = ChatManager.SEPARATOR + "";
if (ChatManager.containsSeparator(e.getMessage())) { // fix for v1
Chat chat = Chat.getFrom(e.getMessage());
if (chat != null) {
targetReplace = ChatManager.SEPARATOR + "" + chat.getId() + ChatManager.SEPARATOR_END;
e.setMessage(
ChatManager.replaceSeparator(chat, e.getMessage(), chat.getSlot().getPlaceholders().get(0)));
}
}
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
if (slot == null) { // if not found
ChatItem.debug("(v2) Can't found placeholder in: " + e.getMessage() + " > "
+ PlayerNamerManager.getPlayerNamer().getName(p));
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
if (!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
e.setCancelled(true);
String format = e.getFormat().replace(targetReplace, slot.getPlaceholders().get(0));
ChatItem.debug("(v2) Using format: " + format + " and message: " + e.getMessage());
String defMsg = slot.replacePlaceholdersToSeparator(e.getMessage());
if (Utils.countMatches(defMsg, Character.toString(ChatManager.SEPARATOR)) > c.limit) {
if (!c.messageLimit.isEmpty())
p.sendMessage(c.messageLimit);
return;
}
String msg;
if (format.contains("%1$s") || format.contains("%2$s")) {
msg = (format.contains("%2$s") ? String.format(format, p.getDisplayName(), defMsg)
: String.format(format, p.getDisplayName()));
} else {
msg = format.replace(e.getMessage(), defMsg);
}
String itemName = ChatManager.getNameForChatAction(p, action, c);
String loggedMessage = msg.replace(ChatManager.SEPARATOR + "", itemName);
Bukkit.getConsoleSender().sendMessage(c.replaceInConsole ? loggedMessage : msg); // show in log
if (ChatItem.discordSrvSupport)
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName), e);
Set<Player> recipients = e.getRecipients().isEmpty() ? new HashSet<>(Bukkit.getOnlinePlayers())
: e.getRecipients();
ChatItem.debug("(v2) Msg: " + ChatItem.replace(p, msg).replace(ChatColor.COLOR_CHAR, '&') + ", format: "
+ format + " to " + recipients.size() + " players");
recipients.forEach((pl) -> ChatItem.getPlatform().sendMessage(pl, p, action, ChatItem.replace(p, msg)));
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
@EventHandler(priority = EventPriority.HIGH)
public void onChat(AsyncPlayerChatEvent e) {
if(ChatManager.isTestingEnabled() && !ChatManager.isTesting("chat"))
return;
if(!ChatManager.isSelected("chat"))
return;
Storage c = getStorage();
if (e.isCancelled()) {
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
String msg = e.getMessage().toLowerCase();
for(ItemSlot slot : ItemSlot.values()) {
for (String rep : slot.getPlaceholders()) {
if (msg.contains(rep)) {
ChatItem.debug("You choose 'chat' manager but it seems to don't be the good choice. More informations here: https://github.com/dadus33-plugins/ChatItem/wiki");
return;
}
}
}
}
ChatItem.debug("Chat cancelled for " + e.getPlayer().getName());
return;
}
Player p = e.getPlayer();
String targetReplace = ChatManager.SEPARATOR + "";
if(ChatManager.containsSeparator(e.getMessage())) { // fix for v1
Chat chat = Chat.getFrom(e.getMessage());
if(chat != null) {
targetReplace = ChatManager.SEPARATOR + "" + chat.getId() + ChatManager.SEPARATOR_END;
e.setMessage(ChatManager.replaceSeparator(chat, e.getMessage(), chat.getSlot().getPlaceholders().get(0)));
}
}
ItemSlot slot = ItemSlot.getItemSlotFromMessage(e.getMessage());
if (slot == null) { // if not found
ChatItem.debug("(v2) Can't found placeholder in: " + e.getMessage() + " > " + PlayerNamerManager.getPlayerNamer().getName(p));
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
if(!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
e.setCancelled(true);
String format = e.getFormat().replace(targetReplace, slot.getPlaceholders().get(0));
ChatItem.debug("(v2) Using format: " + format + " and message: " + e.getMessage());
String defMsg = slot.replacePlaceholdersToSeparator(e.getMessage());
if (Utils.countMatches(defMsg, Character.toString(ChatManager.SEPARATOR)) > c.limit) {
if (!c.messageLimit.isEmpty())
p.sendMessage(c.messageLimit);
return;
}
String msg;
if (format.contains("%1$s") || format.contains("%2$s")) {
msg = (format.contains("%2$s") ? String.format(format, p.getDisplayName(), defMsg) : String.format(format, p.getDisplayName()));
} else {
msg = format.replace(e.getMessage(), defMsg);
}
String itemName = ChatManager.getNameForChatAction(p, action, c);
String loggedMessage = msg.replace(ChatManager.SEPARATOR + "", itemName);
Bukkit.getConsoleSender().sendMessage(c.replaceInConsole ? loggedMessage : msg); // show in log
if (ChatItem.discordSrvSupport)
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName), e);
Set<Player> recipients = e.getRecipients().isEmpty() ? new HashSet<>(Bukkit.getOnlinePlayers()) : e.getRecipients();
ChatItem.debug("(v2) Msg: " + ChatItem.replace(p, msg).replace(ChatColor.COLOR_CHAR, '&') + ", format: " + format + " to " + recipients.size() + " players");
recipients.forEach((pl) -> ChatItem.getPlatform().sendMessage(pl, p, action, ChatItem.replace(p, msg)));
if (c.cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
}
@@ -9,43 +9,60 @@ import me.dadus33.chatitem.chatmanager.ChatManager;
public class ChatListenerChatManager extends ChatManager {
private final ChatListener chatListener;
private boolean baseComponentAvailable = true;
public ChatListenerChatManager(ChatItem pl) {
chatListener = new ChatListener(this);
private final ChatListener chatListener;
private boolean baseComponentAvailable = true;
//Check for existence of BaseComponent class (only on spigot)
public ChatListenerChatManager(ChatItem pl) {
chatListener = new ChatListener(this);
// Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
@Override
public String getName() {
return "ChatListener";
}
@Override
public String getId() {
return "chat";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
Bukkit.getPluginManager().registerEvents(chatListener, pl);
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatListener);
}
public boolean supportsChatComponentApi(){
return baseComponentAvailable;
}
@Override
public String getName() {
return "ChatListener";
}
@Override
public String getId() {
return "chat";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
Bukkit.getPluginManager().registerEvents(chatListener, pl);
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatListener);
}
public boolean supportsChatComponentApi() {
return baseComponentAvailable;
}
}
@@ -9,32 +9,42 @@ import me.dadus33.chatitem.chatmanager.ChatManager;
public class PaperChatManager extends ChatManager {
private PaperListener paperListener;
public PaperChatManager(ChatItem pl) {
paperListener = new PaperListener(this);
}
@Override
public String getName() {
return "Paper";
}
private PaperListener paperListener;
@Override
public String getId() {
return "paper";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
public PaperChatManager(ChatItem pl) {
Bukkit.getPluginManager().registerEvents(paperListener, pl);
}
paperListener = new PaperListener(this);
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(paperListener);
}
}
@Override
public String getName() {
return "Paper";
}
@Override
public String getId() {
return "paper";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
Bukkit.getPluginManager().registerEvents(paperListener, pl);
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(paperListener);
}
}
@@ -26,74 +26,107 @@ import net.kyori.adventure.text.event.HoverEventSource;
public class PaperListener implements Listener {
private PaperChatManager manage;
private PaperChatManager manage;
public PaperListener(PaperChatManager manage) {
this.manage = manage;
}
public PaperListener(PaperChatManager manage) {
public Storage getStorage() {
return manage.getStorage();
}
this.manage = manage;
@EventHandler(priority = EventPriority.HIGHEST)
public void onChat(AsyncChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("paper"))
return;
if (!ChatManager.isSelected("paper"))
return;
}
public Storage getStorage() {
return manage.getStorage();
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onChat(AsyncChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("paper"))
return;
if (!ChatManager.isSelected("paper"))
return;
Player p = e.getPlayer();
Component message = e.message();
String rawMessage = C.string(message);
if (ChatManager.containsSeparator(rawMessage)) { // fix for v1
Chat chat = Chat.getFrom(rawMessage);
if (chat != null) {
message = message.replaceText(
TextReplacementConfig.builder().matchLiteral(ChatManager.addSeparator(chat.getId()))
.replacement(C.text(chat.getSlot().getPlaceholders().get(0))).build());
rawMessage = C.string(message);
}
}
ItemSlot slot = ItemSlot.getItemSlotFromMessage(rawMessage);
ChatItem.debug("(v3) Raw message: " + rawMessage + ", slot: " + slot);
if (slot == null) // if not found
return;
ChatAction action = ChatManager.getChatAction(slot, p);
if (!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
HoverEventSource<?> hoverEvent = null;
if (action.hasItem()) {
if (!action.getItem().getType().equals(Material.AIR))
hoverEvent = action.getItem().asHoverEvent();
else {
Component t = null;
for (String line : Messages.getMessageList("general.hand.tooltip", "%cible%", p.getName())) {
if (t == null) {
t = Component.text("");
} else
t.append(Component.newline());
t.append(C.text(line));
}
hoverEvent = HoverEvent.showText(t);
}
} else
hoverEvent = HoverEvent.showText(C.text(
Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", p.getName())));
TextComponent like = C.text(ChatManager.getNameForChatAction(p, action, getStorage())).hoverEvent(hoverEvent);
if (action.hasCommand())
like.clickEvent(ClickEvent.runCommand(action.getCommand()));
for (String s : slot.getPlaceholders()) {
message = message.replaceText(TextReplacementConfig.builder().matchLiteral(s).replacement(like).build());
}
if (ChatItem.getInstance().getConfig().getBoolean("manager-config.paper.send-ourself", true)) {
for (Audience a : e.viewers().isEmpty() ? Bukkit.getOnlinePlayers() : e.viewers())
a.sendMessage(e.renderer().render(p, p.displayName(), message, a));
e.setCancelled(true);
ChatItem.debug("Sent message by ourself : " + C.string(message));
} else {
e.message(message);
ChatItem.debug("Changed message to " + C.string(message));
}
if (getStorage().cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
Player p = e.getPlayer();
Component message = e.message();
String rawMessage = C.string(message);
if (ChatManager.containsSeparator(rawMessage)) { // fix for v1
Chat chat = Chat.getFrom(rawMessage);
if (chat != null) {
message = message.replaceText(TextReplacementConfig.builder().matchLiteral(ChatManager.addSeparator(chat.getId()))
.replacement(C.text(chat.getSlot().getPlaceholders().get(0))).build());
rawMessage = C.string(message);
}
}
ItemSlot slot = ItemSlot.getItemSlotFromMessage(rawMessage);
ChatItem.debug("(v3) Raw message: " + rawMessage + ", slot: " + slot);
if (slot == null) // if not found
return;
ChatAction action = ChatManager.getChatAction(slot, p);
if (!ChatManager.canUsePlaceholder(p, action, slot, e))
return;
HoverEventSource<?> hoverEvent = null;
if(action.hasItem()) {
if(!action.getItem().getType().equals(Material.AIR))
hoverEvent = action.getItem().asHoverEvent();
else {
Component t = null;
for(String line : Messages.getMessageList("general.hand.tooltip", "%cible%", p.getName())) {
if(t == null) {
t = Component.text("");
} else
t.append(Component.newline());
t.append(C.text(line));
}
hoverEvent = HoverEvent.showText(t);
}
} else
hoverEvent = HoverEvent.showText(C.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", p.getName())));
TextComponent like = C.text(ChatManager.getNameForChatAction(p, action, getStorage())).hoverEvent(hoverEvent);
if (action.hasCommand())
like.clickEvent(ClickEvent.runCommand(action.getCommand()));
for (String s : slot.getPlaceholders()) {
message = message.replaceText(TextReplacementConfig.builder().matchLiteral(s).replacement(like).build());
}
if (ChatItem.getInstance().getConfig().getBoolean("manager-config.paper.send-ourself", true)) {
for (Audience a : e.viewers().isEmpty() ? Bukkit.getOnlinePlayers() : e.viewers())
a.sendMessage(e.renderer().render(p, p.displayName(), message, a));
e.setCancelled(true);
ChatItem.debug("Sent message by ourself : " + C.string(message));
} else {
e.message(message);
ChatItem.debug("Changed message to " + C.string(message));
}
if (getStorage().cooldown > 0 && !p.hasPermission("chatitem.ignore-cooldown"))
ChatManager.applyCooldown(p);
}
}
@@ -9,18 +9,20 @@ import me.dadus33.chatitem.chatmanager.ChatManager;
public class OwnListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onChat(AsyncChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("ownformatter"))
return;
if (!ChatManager.isSelected("ownformatter"))
return;
if (e.isCancelled())
return;
e.setCancelled(true);
/*Player p = e.getPlayer();
Component msg = e.message();*/
}
@EventHandler(priority = EventPriority.MONITOR)
public void onChat(AsyncChatEvent e) {
if (ChatManager.isTestingEnabled() && !ChatManager.isTesting("ownformatter"))
return;
if (!ChatManager.isSelected("ownformatter"))
return;
if (e.isCancelled())
return;
e.setCancelled(true);
/*
* Player p = e.getPlayer(); Component msg = e.message();
*/
}
}
@@ -5,18 +5,23 @@ import me.dadus33.chatitem.chatmanager.ChatManager;
public class OwnManager extends ChatManager {
@Override
public String getName() {
return "Own Formatter";
}
@Override
public String getName() {
@Override
public String getId() {
return "ownformatter";
}
return "Own Formatter";
}
@Override
public String getId() {
return "ownformatter";
}
@Override
public void unload(ChatItem pl) {
}
@Override
public void unload(ChatItem pl) {
}
}
@@ -10,7 +10,10 @@ public class CIReloadCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
ChatItem.reload(sender);
ChatItem.reload(sender);
return false;
}
}
@@ -31,161 +31,253 @@ import net.md_5.bungee.api.chat.TextComponent;
@SuppressWarnings("deprecation")
public class ChatItemCommand implements CommandExecutor, TabExecutor {
private static final List<String> ORDERS;
static {
if(Utils.IS_PAPER)
ORDERS = Arrays.asList("chat", "paper", "packet", "all");
else
ORDERS = Arrays.asList("chat", "packet", "all");
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
Messages.sendMessage(sender, "only-players");
return false;
}
Player p = (Player) sender;
if (args.length == 0) {
Messages.sendMessage(p, "chatitem-cmd.help");
} else if (args[0].equalsIgnoreCase("admin") && p.hasPermission("chatitem.reload")) {
InventoryListener.open(p);
} else if (args[0].equalsIgnoreCase("reload") && p.hasPermission("chatitem.reload")) {
ChatItem.reload(sender);
} else if (args[0].equalsIgnoreCase("ec") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.ENDERCHEST, Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("inv") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.INVENTORY, Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("show") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.getItemSlotByKey(args.length <= 1 ? "" : args[1]), Arrays.asList(p));
} else if (args[0].equalsIgnoreCase("broadcast") && ChatItem.getInstance().getStorage().cmdBroadcast) {
sendCommandFormatFrom(p, ItemSlot.getItemSlotByKey(args.length <= 1 ? "" : args[1]), Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("links")) {
ConfigurationSection config = ChatItem.getInstance().getConfig()
.getConfigurationSection("messages.chatitem-cmd.links");
TextComponent text = new TextComponent(Storage.color(config.getString("begin")));
for (String key : config.getConfigurationSection("list").getKeys(false)) {
ConfigurationSection linkConfig = config.getConfigurationSection("list." + key);
TextComponent linkComp = new TextComponent(Storage.color(linkConfig.getString("message")));
String hover = Storage.color(linkConfig.getString("hover"));
if (hover != null)
linkComp.setHoverEvent(Utils.createTextHover(hover));
String link = linkConfig.getString("link");
if (link != null)
linkComp.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link));
text.addExtra(linkComp);
}
p.spigot().sendMessage(text);
} else if (args[0].equalsIgnoreCase("select") && p.hasPermission("chatitem.reload")) {
if(args.length == 1) {
p.sendMessage(Colors.GRAY + "----------" + Colors.GOLD + " ChatItem - Setup " + Colors.GRAY + "----------");
p.sendMessage(Colors.AQUA + "Welcome in the help of setup." + Colors.YELLOW + " Please follow step by simply answer to test.");
sendCheckSelectMessage(p, ORDERS.get(0));
} else {
String tested = args[1];
if(!ORDERS.contains(tested)) {
p.sendMessage(Colors.RED + "Unknow test for " + tested + ".");
return false;
}
if(args.length == 2) {
p.sendMessage(Colors.RED + "Can't find if it works");
return false;
}
if(args[2].equalsIgnoreCase("yes")) {
ChatManager.setTesting(null);
InventoryListener.setInConfig("manager", tested);
p.sendMessage(Colors.GREEN + "Perfect ! Updating config ...");
ChatItem.reload(p);
} else if(args[2].equalsIgnoreCase("no")) {
int index = ORDERS.indexOf(tested);
if(ORDERS.size() == (index + 1)) {
p.sendMessage(Colors.RED + "Sad. Sorry but nothing is available. I suggest you to come on discord for more help. Do '/chatitem link' for all links.");
ChatManager.setTesting(null);
} else {
p.sendMessage(Colors.RED + "Sad. Checking for next manager ...");
sendCheckSelectMessage(p, ORDERS.get(index + 1));
}
} else {
p.sendMessage(Colors.RED + "Can't find if it works");
}
}
} else if (args[0].equalsIgnoreCase("seeinv")) {
if(args.length == 2 && Utils.isUUID(args[1])) {
InvShower inv = InvShower.get(args[1]);
if(inv == null) {
Messages.sendMessage(p, "seeinv_not_found");
} else {
inv.open(p);
}
} // else just ignore
} else {
Messages.sendMessage(p, "chatitem-cmd.help");
}
return false;
}
private void sendCommandFormatFrom(Player p, ItemSlot slot, Collection<? extends Player> receivers) {
if(slot == null) {
Messages.sendMessage(p, "chatitem-cmd.help");
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
ChatItem.debug("Action: " + action);
if(action.hasItem() && ItemUtils.isEmpty(action.getItem())) {
Messages.sendMessage(p, "empty-item");
return;
}
for(Player all : receivers)
ChatItem.getPlatform().sendMessage(all, p, action, slot.getShowMessage().replace("%name%", p.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
}
private void sendCheckSelectMessage(Player p, String testing) {
ChatManager.setTesting(testing);
p.chat("Checking for " + testing + ": [i]");
private static final List<String> ORDERS;
Bukkit.getScheduler().runTaskLater(ChatItem.getInstance(), () -> {
TextComponent text = new TextComponent(Colors.GOLD + "Did it worked fine? ");
TextComponent agree = new TextComponent(Colors.GREEN + "Yes");
agree.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " yes"));
agree.setHoverEvent(Utils.createTextHover(Colors.GRAY + "Click to say it worked fine"));
text.addExtra(agree);
text.addExtra(", ");
TextComponent decline = new TextComponent(Colors.RED + "No");
decline.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " no"));
decline.setHoverEvent(Utils.createTextHover(Colors.GRAY + "Click to say it's not working as expected"));
text.addExtra(decline);
if(testing.equalsIgnoreCase("packet"))
text.addExtra(" (This manager can have different result between 'chatitem select' and default chat for technical reasons. If nothing works, it's recommended to select it and try again)");
p.spigot().sendMessage(text);
}, 2);
}
static {
if (Utils.IS_PAPER)
ORDERS = Arrays.asList("chat", "paper", "packet", "all");
else
ORDERS = Arrays.asList("chat", "packet", "all");
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
Messages.sendMessage(sender, "only-players");
return false;
}
Player p = (Player) sender;
if (args.length == 0) {
Messages.sendMessage(p, "chatitem-cmd.help");
} else if (args[0].equalsIgnoreCase("admin") && p.hasPermission("chatitem.reload")) {
InventoryListener.open(p);
} else if (args[0].equalsIgnoreCase("reload") && p.hasPermission("chatitem.reload")) {
ChatItem.reload(sender);
} else if (args[0].equalsIgnoreCase("ec") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.ENDERCHEST, Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("inv") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.INVENTORY, Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("show") && ChatItem.getInstance().getStorage().cmdShow) {
sendCommandFormatFrom(p, ItemSlot.getItemSlotByKey(args.length <= 1 ? "" : args[1]), Arrays.asList(p));
} else if (args[0].equalsIgnoreCase("broadcast") && ChatItem.getInstance().getStorage().cmdBroadcast) {
sendCommandFormatFrom(p, ItemSlot.getItemSlotByKey(args.length <= 1 ? "" : args[1]),
Bukkit.getOnlinePlayers());
} else if (args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("links")) {
ConfigurationSection config = ChatItem.getInstance().getConfig()
.getConfigurationSection("messages.chatitem-cmd.links");
TextComponent text = new TextComponent(Storage.color(config.getString("begin")));
for (String key : config.getConfigurationSection("list").getKeys(false)) {
ConfigurationSection linkConfig = config.getConfigurationSection("list." + key);
TextComponent linkComp = new TextComponent(Storage.color(linkConfig.getString("message")));
String hover = Storage.color(linkConfig.getString("hover"));
if (hover != null)
linkComp.setHoverEvent(Utils.createTextHover(hover));
String link = linkConfig.getString("link");
if (link != null)
linkComp.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link));
text.addExtra(linkComp);
}
p.spigot().sendMessage(text);
} else if (args[0].equalsIgnoreCase("select") && p.hasPermission("chatitem.reload")) {
if (args.length == 1) {
p.sendMessage(
Colors.GRAY + "----------" + Colors.GOLD + " ChatItem - Setup " + Colors.GRAY + "----------");
p.sendMessage(Colors.AQUA + "Welcome in the help of setup." + Colors.YELLOW
+ " Please follow step by simply answer to test.");
sendCheckSelectMessage(p, ORDERS.get(0));
} else {
String tested = args[1];
if (!ORDERS.contains(tested)) {
p.sendMessage(Colors.RED + "Unknow test for " + tested + ".");
return false;
}
if (args.length == 2) {
p.sendMessage(Colors.RED + "Can't find if it works");
return false;
}
if (args[2].equalsIgnoreCase("yes")) {
ChatManager.setTesting(null);
InventoryListener.setInConfig("manager", tested);
p.sendMessage(Colors.GREEN + "Perfect ! Updating config ...");
ChatItem.reload(p);
} else if (args[2].equalsIgnoreCase("no")) {
int index = ORDERS.indexOf(tested);
if (ORDERS.size() == (index + 1)) {
p.sendMessage(Colors.RED
+ "Sad. Sorry but nothing is available. I suggest you to come on discord for more help. Do '/chatitem link' for all links.");
ChatManager.setTesting(null);
} else {
p.sendMessage(Colors.RED + "Sad. Checking for next manager ...");
sendCheckSelectMessage(p, ORDERS.get(index + 1));
}
} else {
p.sendMessage(Colors.RED + "Can't find if it works");
}
}
} else if (args[0].equalsIgnoreCase("seeinv")) {
if (args.length == 2 && Utils.isUUID(args[1])) {
InvShower inv = InvShower.get(args[1]);
if (inv == null) {
Messages.sendMessage(p, "seeinv_not_found");
} else {
inv.open(p);
}
} // else just ignore
} else {
Messages.sendMessage(p, "chatitem-cmd.help");
}
return false;
}
private void sendCommandFormatFrom(Player p, ItemSlot slot, Collection<? extends Player> receivers) {
if (slot == null) {
Messages.sendMessage(p, "chatitem-cmd.help");
return;
}
ChatAction action = ChatManager.getChatAction(slot, p);
ChatItem.debug("Action: " + action);
if (action.hasItem() && ItemUtils.isEmpty(action.getItem())) {
Messages.sendMessage(p, "empty-item");
return;
}
for (Player all : receivers)
ChatItem.getPlatform().sendMessage(all, p, action,
slot.getShowMessage().replace("%name%", p.getName()).replace("%item%", ChatManager.SEPARATOR + ""));
}
private void sendCheckSelectMessage(Player p, String testing) {
ChatManager.setTesting(testing);
p.chat("Checking for " + testing + ": [i]");
Bukkit.getScheduler().runTaskLater(ChatItem.getInstance(), () -> {
TextComponent text = new TextComponent(Colors.GOLD + "Did it worked fine? ");
TextComponent agree = new TextComponent(Colors.GREEN + "Yes");
agree.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " yes"));
agree.setHoverEvent(Utils.createTextHover(Colors.GRAY + "Click to say it worked fine"));
text.addExtra(agree);
text.addExtra(", ");
TextComponent decline = new TextComponent(Colors.RED + "No");
decline.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/chatitem select " + testing + " no"));
decline.setHoverEvent(Utils.createTextHover(Colors.GRAY + "Click to say it's not working as expected"));
text.addExtra(decline);
if (testing.equalsIgnoreCase("packet"))
text.addExtra(
" (This manager can have different result between 'chatitem select' and default chat for technical reasons. If nothing works, it's recommended to select it and try again)");
p.spigot().sendMessage(text);
}, 2);
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] arg) {
List<String> list = new ArrayList<>();
String prefix = arg[arg.length - 1].toLowerCase(Locale.ROOT);
if (arg.length <= 1) {
if (sender.hasPermission("chatitem.reload")) {
for (String s : Arrays.asList("admin", "reload", "select"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
if (ChatItem.getInstance().getStorage().cmdShow) {
for (String s : Arrays.asList("show", "ec", "inv"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
if (ChatItem.getInstance().getStorage().cmdBroadcast
&& (prefix.isEmpty() || "broadcast".startsWith(prefix)))
list.add("broadcast");
for (String s : Arrays.asList("help", "link"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
} else if (arg[0].equalsIgnoreCase("show") || arg[0].equalsIgnoreCase("broadcast")) {
for (ItemSlot slot : ItemSlot.values())
if (prefix.isEmpty() || slot.getKey().startsWith(prefix))
list.add(slot.getKey());
}
return list;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] arg) {
List<String> list = new ArrayList<>();
String prefix = arg[arg.length - 1].toLowerCase(Locale.ROOT);
if(arg.length <= 1) {
if(sender.hasPermission("chatitem.reload")) {
for (String s : Arrays.asList("admin", "reload", "select"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
if(ChatItem.getInstance().getStorage().cmdShow) {
for (String s : Arrays.asList("show", "ec", "inv"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
}
if (ChatItem.getInstance().getStorage().cmdBroadcast && (prefix.isEmpty() || "broadcast".startsWith(prefix)))
list.add("broadcast");
for (String s : Arrays.asList("help", "link"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
} else if(arg[0].equalsIgnoreCase("show") || arg[0].equalsIgnoreCase("broadcast")) {
for (ItemSlot slot : ItemSlot.values())
if (prefix.isEmpty() || slot.getKey().startsWith(prefix))
list.add(slot.getKey());
}
return list;
}
}
@@ -4,15 +4,21 @@ import me.dadus33.chatitem.ChatItem;
public class ChatControlSupport {
public static void init(ChatItem pl) {
try {
Class<?> clz = Class.forName("org.mineacademy.chatcontrol.settings.Settings$Chat$Grammar");
clz.getField("CAPITALIZE").setBoolean(null, false);
clz.getField("INSERT_DOT").setBoolean(null, false);
pl.getLogger().info("Loaded ChatControl support by disabling 2 options in 'Chat.Grammar' config.");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void init(ChatItem pl) {
try {
Class<?> clz = Class.forName("org.mineacademy.chatcontrol.settings.Settings$Chat$Grammar");
clz.getField("CAPITALIZE").setBoolean(null, false);
clz.getField("INSERT_DOT").setBoolean(null, false);
pl.getLogger().info("Loaded ChatControl support by disabling 2 options in 'Chat.Grammar' config.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -8,9 +8,12 @@ import me.h1dd3nxn1nja.chatmanager.Main;
public class ChatManagerSupport {
public static void init(ChatItem pl) {
List<String> whitelist = Main.settings.getConfig().getStringList("Anti_Unicode.Whitelist");
whitelist.add(ChatManager.SEPARATOR_STR);
whitelist.add(ChatManager.SEPARATOR_END_STR);
}
public static void init(ChatItem pl) {
List<String> whitelist = Main.settings.getConfig().getStringList("Anti_Unicode.Whitelist");
whitelist.add(ChatManager.SEPARATOR_STR);
whitelist.add(ChatManager.SEPARATOR_END_STR);
}
}
@@ -9,18 +9,28 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
public class DiscordSrvSupport {
public static boolean isSendingMessage() {
return ChatItem.getInstance().getStorage().discordSrvSendMsg;
}
public static void sendChatMessage(Player p, String message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false, e);
}
public static boolean isSendingMessage() {
return ChatItem.getInstance().getStorage().discordSrvSendMsg;
}
public static void sendChatMessage(Player p, String message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false, e);
}
public static void sendChatMessage(Player p, Component message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
pl.processChatMessage(p,
github.scarsz.discordsrv.dependencies.kyori.adventure.text.serializer.gson.GsonComponentSerializer
.gson().deserialize(GsonComponentSerializer.gson().serialize(message)),
pl.getOptionalChannel("global"), false, e);
}
public static void sendChatMessage(Player p, Component message, Event e) {
DiscordSRV pl = DiscordSRV.getPlugin();
pl.processChatMessage(p, github.scarsz.discordsrv.dependencies.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(GsonComponentSerializer.gson().serialize(message)), pl.getOptionalChannel("global"), false, e);
}
}
@@ -11,47 +11,63 @@ import me.dadus33.chatitem.ChatItem;
public class EcoEnchantsSupport {
private static int supportedVersion = 0;
public static boolean hasSupport() {
return supportedVersion > 0;
}
public static boolean load() {
String ver = ChatItem.getPlatform().getPluginVersion(Bukkit.getPluginManager().getPlugin("EcoEnchants"));
if(ver.startsWith("8."))
supportedVersion = 8;
else if(ver.startsWith("10."))
supportedVersion = 10;
else if(ver.startsWith("11."))
supportedVersion = 11;
else if(ver.startsWith("12."))
supportedVersion = 12;
else {
ChatItem.getInstance().getLogger().warning("Failed to find support version for EcoEnchants " + ver);
return false;
}
return true;
}
@SuppressWarnings("deprecation")
public static ItemStack manageItem(ItemStack item) {
if(supportedVersion == 8) {
List<String> addLore = EcoEnchantsV8Support.getLores(item);
if (!addLore.isEmpty()) {
ItemMeta meta = item.getItemMeta();
List<String> lores = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for (int i = 0; i < addLore.size(); i++)
lores.add(i, addLore.get(i));
private static int supportedVersion = 0;
public static boolean hasSupport() {
return supportedVersion > 0;
}
public static boolean load() {
String ver = ChatItem.getPlatform().getPluginVersion(Bukkit.getPluginManager().getPlugin("EcoEnchants"));
if (ver.startsWith("8."))
supportedVersion = 8;
else if (ver.startsWith("10."))
supportedVersion = 10;
else if (ver.startsWith("11."))
supportedVersion = 11;
else if (ver.startsWith("12."))
supportedVersion = 12;
else {
ChatItem.getInstance().getLogger().warning("Failed to find support version for EcoEnchants " + ver);
return false;
}
return true;
}
@SuppressWarnings("deprecation")
public static ItemStack manageItem(ItemStack item) {
if (supportedVersion == 8) {
List<String> addLore = EcoEnchantsV8Support.getLores(item);
if (!addLore.isEmpty()) {
ItemMeta meta = item.getItemMeta();
List<String> lores = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for (int i = 0; i < addLore.size(); i++)
lores.add(i, addLore.get(i));
meta.setLore(lores);
item.setItemMeta(meta);
ChatItem.debug("Added " + addLore.size() + " lores from EcoEnchants");
} else
ChatItem.debug("No lore to add from EcoEnchants");
} else if (supportedVersion >= 10) {
EcoEnchantsV10Support.display(item);
}
return item;
}
meta.setLore(lores);
item.setItemMeta(meta);
ChatItem.debug("Added " + addLore.size() + " lores from EcoEnchants");
} else
ChatItem.debug("No lore to add from EcoEnchants");
} else if(supportedVersion >= 10) {
EcoEnchantsV10Support.display(item);
}
return item;
}
}
@@ -10,26 +10,44 @@ import com.willfp.ecoenchants.display.EnchantDisplay;
public class EcoEnchantsV10Support {
private static EnchantDisplay enchantDisplay;
private static EnchantDisplay enchantDisplay;
public static EnchantDisplay getEnchantDisplay() {
if (enchantDisplay == null) {
try {
enchantDisplay = EnchantDisplay.class.getConstructor(EcoEnchantsPlugin.class).newInstance(Bukkit.getPluginManager().getPlugin("EcoEnchants"));
} catch (Exception e) {
e.printStackTrace();
}
}
return enchantDisplay;
}
public static EnchantDisplay getEnchantDisplay() {
public static void display(ItemStack item) {
try {
DisplayProperties display = DisplayProperties.class.getDeclaredConstructor(boolean.class, boolean.class, ItemStack.class).newInstance(false, false, item);
getEnchantDisplay().display(item, (Player) null, display, new Object[] { false });
} catch (Exception e) {
e.printStackTrace();
}
}
if (enchantDisplay == null) {
try {
enchantDisplay = EnchantDisplay.class.getConstructor(EcoEnchantsPlugin.class)
.newInstance(Bukkit.getPluginManager().getPlugin("EcoEnchants"));
} catch (Exception e) {
e.printStackTrace();
}
}
return enchantDisplay;
}
public static void display(ItemStack item) {
try {
DisplayProperties display = DisplayProperties.class
.getDeclaredConstructor(boolean.class, boolean.class, ItemStack.class)
.newInstance(false, false, item);
getEnchantDisplay().display(item, (Player) null, display, new Object[] { false });
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -10,12 +10,16 @@ import com.willfp.ecoenchants.enchantments.util.EnchantChecks;
public class EcoEnchantsV8Support {
public static List<String> getLores(ItemStack item) {
List<String> lores = new ArrayList<>();
EnchantChecks.getEnchantsOnItem(item).forEach((en, lvl) -> {
lores.add(EnchantmentCache.getEntry(en).getNameWithLevel(lvl));
});
return lores;
}
public static List<String> getLores(ItemStack item) {
List<String> lores = new ArrayList<>();
EnchantChecks.getEnchantsOnItem(item).forEach((en, lvl) -> {
lores.add(EnchantmentCache.getEntry(en).getNameWithLevel(lvl));
});
return lores;
}
}
@@ -12,29 +12,41 @@ import com.earth2me.essentials.utils.FormatUtil;
public class EssentialsPlaceholdersHook implements IPlaceholders {
private Essentials getEssentials() {
return ((Essentials) Bukkit.getPluginManager().getPlugin("Essentials"));
}
private Essentials getEssentials() {
@SuppressWarnings("deprecation")
@Override
public String replace(Player p, String text) {
User user = getEssentials().getUser(p);
if (user == null) {
return null;
}
String world = user.getWorld().getName();
String username = user.getName();
String nickname = user.getFormattedNickname();
Player player = user.getBase();
Team team = player.getScoreboard().getPlayerTeam(player);
return ((Essentials) Bukkit.getPluginManager().getPlugin("Essentials"));
return text.replace("{GROUP}", user.getGroup()).replace("{WORLD}", getEssentials().getSettings().getWorldAlias(world)).replace("{WORLDNAME}", world)
.replace("{SHORTWORLDNAME}", world.substring(0, 1).toUpperCase(Locale.ENGLISH)).replace("{TEAMNAME}", team == null ? "" : team.getDisplayName())
.replace("{TEAMPREFIX}", team == null ? "" : team.getPrefix()).replace("{TEAMSUFFIX}", team == null ? "" : team.getSuffix())
.replace("{PREFIX}", FormatUtil.replaceFormat(getEssentials().getPermissionsHandler().getPrefix(player)))
.replace("{SUFFIX}", FormatUtil.replaceFormat(getEssentials().getPermissionsHandler().getSuffix(player))).replace("{USERNAME}", username)
.replace("{NICKNAME}", nickname == null ? username : nickname);
}
}
@SuppressWarnings("deprecation")
@Override
public String replace(Player p, String text) {
User user = getEssentials().getUser(p);
if (user == null) {
return null;
}
String world = user.getWorld().getName();
String username = user.getName();
String nickname = user.getFormattedNickname();
Player player = user.getBase();
Team team = player.getScoreboard().getPlayerTeam(player);
return text.replace("{GROUP}", user.getGroup())
.replace("{WORLD}", getEssentials().getSettings().getWorldAlias(world)).replace("{WORLDNAME}", world)
.replace("{SHORTWORLDNAME}", world.substring(0, 1).toUpperCase(Locale.ENGLISH))
.replace("{TEAMNAME}", team == null ? "" : team.getDisplayName())
.replace("{TEAMPREFIX}", team == null ? "" : team.getPrefix())
.replace("{TEAMSUFFIX}", team == null ? "" : team.getSuffix())
.replace("{PREFIX}",
FormatUtil.replaceFormat(getEssentials().getPermissionsHandler().getPrefix(player)))
.replace("{SUFFIX}",
FormatUtil.replaceFormat(getEssentials().getPermissionsHandler().getSuffix(player)))
.replace("{USERNAME}", username).replace("{NICKNAME}", nickname == null ? username : nickname);
}
}
@@ -4,6 +4,6 @@ import org.bukkit.entity.Player;
public interface IPlaceholders {
String replace(Player p, String text);
String replace(Player p, String text);
}
@@ -6,8 +6,11 @@ import be.maximvdw.placeholderapi.PlaceholderAPI;
public class MVdWPlaceholderAPIHook implements IPlaceholders {
@Override
public String replace(Player p, String text) {
return PlaceholderAPI.replacePlaceholders(p, text);
}
@Override
public String replace(Player p, String text) {
return PlaceholderAPI.replacePlaceholders(p, text);
}
}
@@ -4,9 +4,11 @@ import org.bukkit.entity.Player;
public class OwnPlaceholder implements IPlaceholders {
@Override
public String replace(Player p, String text) {
return text.replace("{name}", p.getName()).replace("%name%", p.getName());
}
@Override
public String replace(Player p, String text) {
return text.replace("{name}", p.getName()).replace("%name%", p.getName());
}
}
@@ -6,9 +6,11 @@ import me.clip.placeholderapi.PlaceholderAPI;
public class PlaceholderAPIHook implements IPlaceholders {
@Override
public String replace(Player p, String text) {
return PlaceholderAPI.setPlaceholders(p, text);
}
@Override
public String replace(Player p, String text) {
return PlaceholderAPI.setPlaceholders(p, text);
}
}
@@ -8,23 +8,31 @@ import net.milkbowl.vault.chat.Chat;
public class VaultPlaceholderHook implements IPlaceholders {
private Chat chat = null;
private Chat chat = null;
public Chat getChat() {
if (chat == null) {
RegisteredServiceProvider<Chat> rs = Bukkit.getServicesManager().getRegistration(Chat.class);
if (rs != null) // chat well setup
chat = rs.getProvider();
}
return chat;
}
public Chat getChat() {
@Override
public String replace(Player p, String text) {
Chat chat = getChat();
if (chat == null)
return text;
return text.replace("{prefix}", chat.getPlayerPrefix(p)).replace("{suffix}", chat.getPlayerSuffix(p)).replace("%prefix%", chat.getPlayerPrefix(p)).replace("%suffix%", chat.getPlayerSuffix(p));
}
if (chat == null) {
RegisteredServiceProvider<Chat> rs = Bukkit.getServicesManager().getRegistration(Chat.class);
if (rs != null) // chat well setup
chat = rs.getProvider();
}
return chat;
}
@Override
public String replace(Player p, String text) {
Chat chat = getChat();
if (chat == null)
return text;
return text.replace("{prefix}", chat.getPlayerPrefix(p)).replace("{suffix}", chat.getPlayerSuffix(p))
.replace("%prefix%", chat.getPlayerPrefix(p)).replace("%suffix%", chat.getPlayerSuffix(p));
}
}
@@ -11,47 +11,71 @@ import me.dadus33.chatitem.ChatItem;
public abstract class InvShower {
private static final HashMap<String, InvShower> INV_SHOWER = new HashMap<>();
public static InvShower get(String s) {
return INV_SHOWER.get(s);
}
public static void add(String s, InvShower shower) {
INV_SHOWER.put(s, shower);
}
public static HashMap<String, InvShower> getInvShower() {
return INV_SHOWER;
}
static {
Bukkit.getScheduler().runTaskTimer(ChatItem.getInstance(), () -> {
for(Entry<String, InvShower> entries : new HashMap<>(INV_SHOWER).entrySet())
if(entries.getValue().hasExpired())
INV_SHOWER.remove(entries.getKey());
}, 200, 200);
}
protected final long time;
protected final UUID uuid;
protected final String name;
public InvShower(String id, Player cible) {
this.time = System.currentTimeMillis() + ChatItem.getInstance().getConfig().getInt("general.other-placeholders." + id + ".time-expire", 1800) * 1000;
this.uuid = cible.getUniqueId();
this.name = cible.getName();
}
public UUID getUuid() {
return uuid;
}
public long getTimeExpire() {
return time;
}
public boolean hasExpired() {
return System.currentTimeMillis() > time || Bukkit.getPlayer(uuid) == null || !Bukkit.getPlayer(uuid).isOnline();
}
public abstract void open(Player p);
private static final HashMap<String, InvShower> INV_SHOWER = new HashMap<>();
public static InvShower get(String s) {
return INV_SHOWER.get(s);
}
public static void add(String s, InvShower shower) {
INV_SHOWER.put(s, shower);
}
public static HashMap<String, InvShower> getInvShower() {
return INV_SHOWER;
}
static {
Bukkit.getScheduler().runTaskTimer(ChatItem.getInstance(), () -> {
for (Entry<String, InvShower> entries : new HashMap<>(INV_SHOWER).entrySet())
if (entries.getValue().hasExpired())
INV_SHOWER.remove(entries.getKey());
}, 200, 200);
}
protected final long time;
protected final UUID uuid;
protected final String name;
public InvShower(String id, Player cible) {
this.time = System.currentTimeMillis()
+ ChatItem.getInstance().getConfig().getInt("general.other-placeholders." + id + ".time-expire", 1800)
* 1000;
this.uuid = cible.getUniqueId();
this.name = cible.getName();
}
public UUID getUuid() {
return uuid;
}
public long getTimeExpire() {
return time;
}
public boolean hasExpired() {
return System.currentTimeMillis() > time || Bukkit.getPlayer(uuid) == null
|| !Bukkit.getPlayer(uuid).isOnline();
}
public abstract void open(Player p);
}
@@ -12,25 +12,31 @@ import me.dadus33.chatitem.utils.Messages;
public class EnderChestShower extends InvShower {
private final ItemStack[] items;
public EnderChestShower(Player cible) {
super("enderchest", cible);
Inventory ec = cible.getEnderChest();
ItemStack[] tmp = ec.getContents();
items = new ItemStack[tmp.length];
for(int i = 0; i < ec.getSize(); i++)
items[i] = ItemUtils.copyIfExist(tmp[i]);
}
@Override
public void open(Player p) {
Inventory inv = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), items.length, Messages.getMessage("enderchest.name", "%cible%", name));
private final ItemStack[] items;
for(int i = 0; i < items.length; i++)
inv.setItem(i, items[i]);
public EnderChestShower(Player cible) {
super("enderchest", cible);
Inventory ec = cible.getEnderChest();
ItemStack[] tmp = ec.getContents();
items = new ItemStack[tmp.length];
for (int i = 0; i < ec.getSize(); i++)
items[i] = ItemUtils.copyIfExist(tmp[i]);
}
@Override
public void open(Player p) {
Inventory inv = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), items.length,
Messages.getMessage("enderchest.name", "%cible%", name));
for (int i = 0; i < items.length; i++)
inv.setItem(i, items[i]);
p.openInventory(inv);
}
p.openInventory(inv);
}
}
@@ -12,24 +12,29 @@ import me.dadus33.chatitem.utils.Messages;
public class OneItemShower extends InvShower {
private final ItemStack item;
public OneItemShower(Player cible, ItemStack item) {
super("one_item", cible);
this.item = item.clone();
}
@Override
public void open(Player p) {
Inventory inv = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), 9, Messages.getMessage("inventory.name", "%cible%", name));
for(int i = 0; i < 9; i++)
inv.setItem(i, ItemUtils.ITEM_EMPTY_BROWN);
inv.setItem(4, item);
private final ItemStack item;
public OneItemShower(Player cible, ItemStack item) {
super("one_item", cible);
this.item = item.clone();
}
@Override
public void open(Player p) {
Inventory inv = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), 9,
Messages.getMessage("inventory.name", "%cible%", name));
for (int i = 0; i < 9; i++)
inv.setItem(i, ItemUtils.ITEM_EMPTY_BROWN);
inv.setItem(4, item);
p.openInventory(inv);
}
p.openInventory(inv);
}
}
@@ -15,35 +15,41 @@ import me.dadus33.chatitem.utils.Messages;
public class PlayerInventoryShower extends InvShower {
private final HashMap<Integer, ItemStack> items = new HashMap<>();
private final int level;
public PlayerInventoryShower(Player cible) {
super("inventory", cible);
this.level = cible.getLevel();
PlayerInventory pi = cible.getInventory();
items.put(4, ItemUtils.copyIfExist(pi.getHelmet()));
items.put(5, ItemUtils.copyIfExist(pi.getChestplate()));
items.put(6, ItemUtils.copyIfExist(pi.getLeggings()));
items.put(7, ItemUtils.copyIfExist(pi.getBoots()));
for(int i = 0; i < pi.getContents().length && i < (54 - 18); i++)
items.put(i + 18, ItemUtils.copyIfExist(pi.getContents()[i]));
}
@Override
public void open(Player p) {
Inventory inv = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), 54, Messages.getMessage("inventory.name", "%cible%", name));
for(int i = 0; i < 18; i++)
inv.setItem(i, ItemUtils.ITEM_EMPTY_BROWN);
inv.setItem(2, new ItemStack(ItemUtils.getMaterialWithCompatibility("EXPERIENCE_BOTTLE", "EXP_BOTTLE"), level == 0 ? 1 : (level >= 64 ? 64 : level)));
items.forEach(inv::setItem);
private final HashMap<Integer, ItemStack> items = new HashMap<>();
private final int level;
public PlayerInventoryShower(Player cible) {
super("inventory", cible);
this.level = cible.getLevel();
PlayerInventory pi = cible.getInventory();
items.put(4, ItemUtils.copyIfExist(pi.getHelmet()));
items.put(5, ItemUtils.copyIfExist(pi.getChestplate()));
items.put(6, ItemUtils.copyIfExist(pi.getLeggings()));
items.put(7, ItemUtils.copyIfExist(pi.getBoots()));
for (int i = 0; i < pi.getContents().length && i < (54 - 18); i++)
items.put(i + 18, ItemUtils.copyIfExist(pi.getContents()[i]));
}
@Override
public void open(Player p) {
Inventory inv = ChatItem.getPlatform().createInventory(new CustomInventoryHolder(), 54,
Messages.getMessage("inventory.name", "%cible%", name));
for (int i = 0; i < 18; i++)
inv.setItem(i, ItemUtils.ITEM_EMPTY_BROWN);
inv.setItem(2, new ItemStack(ItemUtils.getMaterialWithCompatibility("EXPERIENCE_BOTTLE", "EXP_BOTTLE"),
level == 0 ? 1 : (level >= 64 ? 64 : level)));
items.forEach(inv::setItem);
p.openInventory(inv);
}
p.openInventory(inv);
}
}
@@ -10,45 +10,50 @@ import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.Storage;
public interface INamer {
/**
* Get priority of this namer.<br>
* Get first name that is not null, with this order:
* - MAJOR
*
*
* @return priority
*/
Priority getPriority();
/**
* Get the name of the item thanks to this namer.
*
* @param item the item to get the name
* @param storage the actual config
* @return the name or null if can't find a name
*/
String getName(Player p, ItemStack item, Storage storage);
public enum Priority {
MAJOR(4),
IMPORTANT(3),
MEDIUM(2),
SMALL(1),
MINOR(0);
private final int priority;
Priority(int priority) {
this.priority = priority;
}
public int getPriority() {
return priority;
}
public static List<Priority> getOrderedPriorities() {
return Arrays.stream(values()).sorted((p1, p2) -> p2.getPriority() - p1.getPriority()).collect(Collectors.toList());
}
}
/**
* Get priority of this namer.<br>
* Get first name that is not null, with this order: - MAJOR
*
*
* @return priority
*/
Priority getPriority();
/**
* Get the name of the item thanks to this namer.
*
* @param item the item to get the name
* @param storage the actual config
* @return the name or null if can't find a name
*/
String getName(Player p, ItemStack item, Storage storage);
public enum Priority {
MAJOR(4), IMPORTANT(3), MEDIUM(2), SMALL(1), MINOR(0);
private final int priority;
Priority(int priority) {
this.priority = priority;
}
public int getPriority() {
return priority;
}
public static List<Priority> getOrderedPriorities() {
return Arrays.stream(values()).sorted((p1, p2) -> p2.getPriority() - p1.getPriority())
.collect(Collectors.toList());
}
}
}
@@ -20,59 +20,78 @@ import me.dadus33.chatitem.itemnamer.hook.LangUtilsNamer;
public class NamerManager {
private static final HashMap<Priority, List<INamer>> NAMER_PER_PRIORITY = new HashMap<>();
private static final HashMap<Priority, List<INamer>> NAMER_PER_PRIORITY = new HashMap<>();
public static void load(ChatItem pl) {
NAMER_PER_PRIORITY.clear();
StringJoiner sj = new StringJoiner(", ");
PluginManager pm = Bukkit.getPluginManager();
if (pm.getPlugin("LangUtils") != null) {
addNamer(new LangUtilsNamer());
sj.add("LangUtils");
}
if (sj.length() > 0)
pl.getLogger().info("Loaded namer for plugin " + sj.toString() + ".");
addNamer(new ChatItemTranslationNamer());
addNamer(new ItemDisplayNamer());
addNamer(new DefaultNamer());
}
/**
* Add namer according to his {@link INamer#getPriority()}'s value
*
* @param namer the namer to add
*/
public static void addNamer(INamer namer) {
getOrCreate(namer.getPriority()).add(namer);
}
private static List<INamer> getOrCreate(Priority p) {
return NAMER_PER_PRIORITY.computeIfAbsent(p, (a) -> new ArrayList<>());
}
/**
* Get the name of this item, according to this storage.
*
* @param p the player that will see the name
* @param item the item to show
* @param storage the storage
* @return the name (should NOT return null)
*/
public static String getName(Player p, ItemStack item, Storage storage) {
for (Priority pr : Priority.getOrderedPriorities()) {
List<INamer> allNamers = NAMER_PER_PRIORITY.get(pr);
if (allNamers == null || allNamers.isEmpty())
continue;
for (INamer namer : allNamers) {
String tmpName = namer.getName(p, item, storage);
if (tmpName != null && tmpName != "") {
ChatItem.debug("Using namer " + namer.getClass().getSimpleName() + ", value: " + tmpName);
return tmpName;
}
}
}
return null; // this should NEVER append
}
public static void load(ChatItem pl) {
NAMER_PER_PRIORITY.clear();
StringJoiner sj = new StringJoiner(", ");
PluginManager pm = Bukkit.getPluginManager();
if(pm.getPlugin("LangUtils") != null) {
addNamer(new LangUtilsNamer());
sj.add("LangUtils");
}
if(sj.length() > 0)
pl.getLogger().info("Loaded namer for plugin " + sj.toString() + ".");
addNamer(new ChatItemTranslationNamer());
addNamer(new ItemDisplayNamer());
addNamer(new DefaultNamer());
}
/**
* Add namer according to his {@link INamer#getPriority()}'s value
*
* @param namer the namer to add
*/
public static void addNamer(INamer namer) {
getOrCreate(namer.getPriority()).add(namer);
}
private static List<INamer> getOrCreate(Priority p){
return NAMER_PER_PRIORITY.computeIfAbsent(p, (a) -> new ArrayList<>());
}
/**
* Get the name of this item, according to this storage.
*
* @param p the player that will see the name
* @param item the item to show
* @param storage the storage
* @return the name (should NOT return null)
*/
public static String getName(Player p, ItemStack item, Storage storage) {
for(Priority pr : Priority.getOrderedPriorities()) {
List<INamer> allNamers = NAMER_PER_PRIORITY.get(pr);
if(allNamers == null || allNamers.isEmpty())
continue;
for(INamer namer : allNamers) {
String tmpName = namer.getName(p, item, storage);
if(tmpName != null && tmpName != "") {
ChatItem.debug("Using namer " + namer.getClass().getSimpleName() + ", value: " + tmpName);
return tmpName;
}
}
}
return null; // this should NEVER append
}
}
@@ -9,14 +9,18 @@ import me.dadus33.chatitem.itemnamer.INamer;
public class ChatItemTranslationNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.SMALL;
}
@Override
public Priority getPriority() {
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return Translation.getOr(item, null);
}
return Priority.SMALL;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return Translation.getOr(item, null);
}
}
@@ -10,14 +10,19 @@ import me.dadus33.chatitem.itemnamer.INamer;
public class DefaultNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MINOR;
}
@Override
public Priority getPriority() {
return Priority.MINOR;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
Material m = item.getType();
return m.equals(Material.TNT) ? "TNT" : WordUtils.capitalize(m.name().replaceAll("_", " ").toLowerCase());
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
Material m = item.getType();
return m.equals(Material.TNT) ? "TNT" : WordUtils.capitalize(m.name().replaceAll("_", " ").toLowerCase());
}
}
@@ -11,17 +11,21 @@ import me.dadus33.chatitem.itemnamer.INamer;
@SuppressWarnings("deprecation")
public class ItemDisplayNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MEDIUM;
}
@Override
public Priority getPriority() {
@Override
public String getName(Player p, ItemStack item, Storage storage) {
String name = ChatItem.getPlatform().getItemDisplayName(item);
if(name != null && name != "")
return storage.colorIfColored ? ChatColor.stripColor(name) : name;
return null;
}
return Priority.MEDIUM;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
String name = ChatItem.getPlatform().getItemDisplayName(item);
if (name != null && name != "")
return storage.colorIfColored ? ChatColor.stripColor(name) : name;
return null;
}
}
@@ -10,14 +10,18 @@ import me.dadus33.chatitem.itemnamer.INamer;
public class LangUtilsNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.IMPORTANT;
}
@Override
public Priority getPriority() {
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return LanguageHelper.getItemName(item, p);
}
return Priority.IMPORTANT;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return LanguageHelper.getItemName(item, p);
}
}
@@ -24,128 +24,184 @@ import me.dadus33.chatitem.utils.Utils;
public class InventoryListener implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e) {
if (!(e.getWhoClicked() instanceof Player))
return;
Player p = (Player) e.getWhoClicked();
@EventHandler
public void onClick(InventoryClickEvent e) {
Inventory topInventory = Utils.getTopInventory(e);
InventoryHolder openInventoryHolder = topInventory == null ? null : topInventory.getHolder();
if (!(e.getWhoClicked() instanceof Player))
return;
Player p = (Player) e.getWhoClicked();
if (openInventoryHolder != null && openInventoryHolder instanceof CustomInventoryHolder) {
e.setCancelled(true);
return;
}
if (e.getClickedInventory() == null)
return;
Inventory topInventory = Utils.getTopInventory(e);
InventoryHolder openInventoryHolder = topInventory == null ? null : topInventory.getHolder();
InventoryHolder holder = e.getClickedInventory().getHolder();
if (holder == null || !(holder instanceof ChatItemHolder)) {
if (e.getClick().equals(ClickType.DOUBLE_CLICK) && topInventory != null) {
if (openInventoryHolder != null && openInventoryHolder instanceof ChatItemHolder) {
e.setCancelled(true);
}
}
return;
}
if (holder instanceof CustomInventoryHolder) {
e.setCancelled(true);
return;
}
if (!(holder instanceof AdminHolder))
return;
e.setCancelled(true);
if (e.getCurrentItem() == null)
return;
ItemStack item = e.getCurrentItem();
Material type = item.getType();
Storage c = ChatItem.getInstance().getStorage();
if (type.equals(ItemUtils.MATERIAL_CLOSE)) {
p.closeInventory();
} else if (type.equals(Material.BOOK)) {
TranslationInventoryListener.open(p, 0);
} else if (type.equals(Material.PAPER)) {
String key = ((AdminHolder) holder).keyBySlot.get(e.getSlot());
if (key != null) {
setInConfig("manager", key);
p.closeInventory();
ChatItem.reload(p);
}
} else if (type.equals(ItemUtils.INK_SAC)) {
setInConfig("general.color-if-already-colored", c.colorIfColored = !c.colorIfColored);
open(p);
} else if (type.equals(Material.STICK)) {
setInConfig("general.hand.disabled", c.handDisabled = !c.handDisabled);
open(p);
} else if (type.equals(Material.BLAZE_ROD)) {
setInConfig("general.check-update", c.checkUpdate = !c.checkUpdate);
open(p);
} else if (type.equals(ItemUtils.FIREWORK_CHARGE)) {
setInConfig("debug", c.debug = !c.debug);
open(p);
} else if (type.equals(Material.IRON_DOOR)) {
if (e.getClick().equals(ClickType.RIGHT))
c.limit--;
else if (e.getClick().equals(ClickType.LEFT))
c.limit++;
setInConfig("general.limit-per-message", c.limit);
open(p);
} else if (type.equals(Material.APPLE)) {
if (e.getClick().equals(ClickType.RIGHT))
c.cooldown--;
else if (e.getClick().equals(ClickType.LEFT))
c.cooldown++;
setInConfig("general.cooldown", c.cooldown);
open(p);
}
}
if (openInventoryHolder != null && openInventoryHolder instanceof CustomInventoryHolder) {
public static void setInConfig(String key, Object val) {
ChatItem pl = ChatItem.getInstance();
pl.getConfig().set(key, val);
pl.saveConfig();
}
e.setCancelled(true);
return;
public static void open(Player p) {
AdminHolder holder = new AdminHolder();
Storage c = ChatItem.getInstance().getStorage();
Inventory inv = ChatItem.getPlatform().createInventory(holder, 27, Messages.getMessage("admin-inv.name"));
for (int i = 0; i < inv.getSize(); i++)
inv.setItem(i, ChatItem.getPlatform().createItemStack(ItemUtils.WHITE_STAINED_GLASS, "-"));
}
int slot = 0;
for (String manager : Arrays.asList("all", "packet", "chat", "paper")) { //, "ownformatter")) {
if ((manager == "paper" || manager == "ownformatter") && !Utils.IS_PAPER)
continue;
holder.keyBySlot.put(slot, manager);
inv.setItem(slot++, getManagerItem(manager));
}
inv.setItem(slot + 1, getManagerItem("actual", "%manager%", Messages.getMessage("admin-inv.manager." + c.manager + ".name")));
if (e.getClickedInventory() == null)
return;
inv.setItem(8, getBoolChangeItem(ItemUtils.FIREWORK_CHARGE, "debug", c.debug));
InventoryHolder holder = e.getClickedInventory().getHolder();
if (holder == null || !(holder instanceof ChatItemHolder)) {
inv.setItem(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.colorIfColored));
inv.setItem(20, getBoolChangeItem(Material.STICK, "hand-disabled", c.handDisabled));
inv.setItem(21, getAmountChangeItem(Material.IRON_DOOR, "limit-per-message", c.limit));
inv.setItem(22, getAmountChangeItem(Material.APPLE, "cooldown", c.cooldown));
inv.setItem(23, getBoolChangeItem(Material.BLAZE_ROD, "check-update", c.checkUpdate));
inv.setItem(24, ChatItem.getPlatform().createTranslatedItemStack(Material.BOOK, "admin-inv.language", "%name%", Translation.getMessage("language.name")));
if (e.getClick().equals(ClickType.DOUBLE_CLICK) && topInventory != null) {
inv.setItem(26, ChatItem.getPlatform().createItemStack(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
p.openInventory(inv);
}
if (openInventoryHolder != null && openInventoryHolder instanceof ChatItemHolder) {
private static ItemStack getBoolChangeItem(Material type, String key, boolean b) {
return ChatItem.getPlatform().createItemStack(type, Messages.getMessage("admin-inv." + key, "%state%", Messages.getMessage(b ? "enabled" : "disabled")),
Messages.getMessageList("admin-inv.bool-lore"));
}
e.setCancelled(true);
private static ItemStack getAmountChangeItem(Material type, String key, int amount) {
return ChatItem.getPlatform().createItemStack(type, Messages.getMessage("admin-inv." + key, "%state%", amount), Messages.getMessageList("admin-inv.amount-lore"));
}
}
}
return;
}
if (holder instanceof CustomInventoryHolder) {
e.setCancelled(true);
return;
}
if (!(holder instanceof AdminHolder))
return;
e.setCancelled(true);
if (e.getCurrentItem() == null)
return;
ItemStack item = e.getCurrentItem();
Material type = item.getType();
Storage c = ChatItem.getInstance().getStorage();
if (type.equals(ItemUtils.MATERIAL_CLOSE)) {
p.closeInventory();
} else if (type.equals(Material.BOOK)) {
TranslationInventoryListener.open(p, 0);
} else if (type.equals(Material.PAPER)) {
String key = ((AdminHolder) holder).keyBySlot.get(e.getSlot());
if (key != null) {
setInConfig("manager", key);
p.closeInventory();
ChatItem.reload(p);
}
} else if (type.equals(ItemUtils.INK_SAC)) {
setInConfig("general.color-if-already-colored", c.colorIfColored = !c.colorIfColored);
open(p);
} else if (type.equals(Material.STICK)) {
setInConfig("general.hand.disabled", c.handDisabled = !c.handDisabled);
open(p);
} else if (type.equals(Material.BLAZE_ROD)) {
setInConfig("general.check-update", c.checkUpdate = !c.checkUpdate);
open(p);
} else if (type.equals(ItemUtils.FIREWORK_CHARGE)) {
setInConfig("debug", c.debug = !c.debug);
open(p);
} else if (type.equals(Material.IRON_DOOR)) {
if (e.getClick().equals(ClickType.RIGHT))
c.limit--;
else if (e.getClick().equals(ClickType.LEFT))
c.limit++;
setInConfig("general.limit-per-message", c.limit);
open(p);
} else if (type.equals(Material.APPLE)) {
if (e.getClick().equals(ClickType.RIGHT))
c.cooldown--;
else if (e.getClick().equals(ClickType.LEFT))
c.cooldown++;
setInConfig("general.cooldown", c.cooldown);
open(p);
}
}
public static void setInConfig(String key, Object val) {
ChatItem pl = ChatItem.getInstance();
pl.getConfig().set(key, val);
pl.saveConfig();
}
public static void open(Player p) {
AdminHolder holder = new AdminHolder();
Storage c = ChatItem.getInstance().getStorage();
Inventory inv = ChatItem.getPlatform().createInventory(holder, 27, Messages.getMessage("admin-inv.name"));
for (int i = 0; i < inv.getSize(); i++)
inv.setItem(i, ChatItem.getPlatform().createItemStack(ItemUtils.WHITE_STAINED_GLASS, "-"));
int slot = 0;
for (String manager : Arrays.asList("all", "packet", "chat", "paper")) { // , "ownformatter")) {
if ((manager == "paper" || manager == "ownformatter") && !Utils.IS_PAPER)
continue;
holder.keyBySlot.put(slot, manager);
inv.setItem(slot++, getManagerItem(manager));
}
inv.setItem(slot + 1,
getManagerItem("actual", "%manager%", Messages.getMessage("admin-inv.manager." + c.manager + ".name")));
inv.setItem(8, getBoolChangeItem(ItemUtils.FIREWORK_CHARGE, "debug", c.debug));
inv.setItem(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.colorIfColored));
inv.setItem(20, getBoolChangeItem(Material.STICK, "hand-disabled", c.handDisabled));
inv.setItem(21, getAmountChangeItem(Material.IRON_DOOR, "limit-per-message", c.limit));
inv.setItem(22, getAmountChangeItem(Material.APPLE, "cooldown", c.cooldown));
inv.setItem(23, getBoolChangeItem(Material.BLAZE_ROD, "check-update", c.checkUpdate));
inv.setItem(24, ChatItem.getPlatform().createTranslatedItemStack(Material.BOOK, "admin-inv.language", "%name%",
Translation.getMessage("language.name")));
inv.setItem(26, ChatItem.getPlatform().createItemStack(ItemUtils.MATERIAL_CLOSE,
Messages.getMessage("admin-inv.close")));
p.openInventory(inv);
}
private static ItemStack getBoolChangeItem(Material type, String key, boolean b) {
return ChatItem.getPlatform().createItemStack(type,
Messages.getMessage("admin-inv." + key, "%state%", Messages.getMessage(b ? "enabled" : "disabled")),
Messages.getMessageList("admin-inv.bool-lore"));
}
private static ItemStack getAmountChangeItem(Material type, String key, int amount) {
return ChatItem.getPlatform().createItemStack(type, Messages.getMessage("admin-inv." + key, "%state%", amount),
Messages.getMessageList("admin-inv.amount-lore"));
}
private static ItemStack getManagerItem(String manager, Object... placeholders) {
return ChatItem.getPlatform().createTranslatedItemStack(Material.PAPER, "admin-inv.manager." + manager,
placeholders);
}
private static ItemStack getManagerItem(String manager, Object... placeholders) {
return ChatItem.getPlatform().createTranslatedItemStack(Material.PAPER, "admin-inv.manager." + manager, placeholders);
}
}
@@ -14,23 +14,30 @@ import net.md_5.bungee.api.chat.TextComponent;
public class JoinListener implements Listener {
@SuppressWarnings("deprecation")
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
if(!p.isOp())
return;
ChatItem pl = ChatItem.getInstance();
if(pl.isHasNewVersion()) {
TextComponent text = new TextComponent(pl.getStorage().updateMessage);
text.setHoverEvent(Utils.createTextHover(pl.getStorage().updateHover));
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/19064/"));
p.spigot().sendMessage(text);
}
}
@EventHandler
public void onLeft(PlayerQuitEvent e) {
ChatManager.clear(e.getPlayer());
}
@SuppressWarnings("deprecation")
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
if (!p.isOp())
return;
ChatItem pl = ChatItem.getInstance();
if (pl.isHasNewVersion()) {
TextComponent text = new TextComponent(pl.getStorage().updateMessage);
text.setHoverEvent(Utils.createTextHover(pl.getStorage().updateHover));
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/19064/"));
p.spigot().sendMessage(text);
}
}
@EventHandler
public void onLeft(PlayerQuitEvent e) {
ChatManager.clear(e.getPlayer());
}
}
@@ -22,70 +22,87 @@ import me.dadus33.chatitem.utils.Messages;
public class TranslationInventoryListener implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e) {
if(e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player) || e.getCurrentItem() == null
|| !(e.getClickedInventory().getHolder() instanceof TranslationHolder))
return;
e.setCancelled(true);
Player p = (Player) e.getWhoClicked();
ItemStack item = e.getCurrentItem();
Material type = item.getType();
TranslationHolder holder = (TranslationHolder) e.getClickedInventory().getHolder();
if(type.equals(Material.ARROW)) {
if(e.getSlot() == 0)
InventoryListener.open(p);
else if(e.getSlot() == 3)
open(p, holder.getPage() - 1);
else if(e.getSlot() == 5)
open(p, holder.getPage() + 1);
} else if(type.equals(ItemUtils.MATERIAL_CLOSE))
p.closeInventory();
else if(type.equals(Material.PAPER)) {
String lang = holder.langBySlot.get(e.getSlot());
if(lang == null)
return;
p.closeInventory();
ChatItem pl = ChatItem.getInstance();
pl.getStorage().language = lang;
pl.getConfig().set("general.language", lang);
pl.saveConfig();
Translation.loadLang(lang);
p.sendMessage(Colors.GREEN + "Language changed to " + Translation.getMessages().get("language.name").getAsString());
}
}
@EventHandler
public void onClick(InventoryClickEvent e) {
public static void open(Player p, int page) {
int perPage = 45;
List<String> langs = new ArrayList<>(Translation.getAllLangs().keySet());
TranslationHolder holder = new TranslationHolder(page);
Inventory inv = ChatItem.getPlatform().createInventory(holder, 54, "Change language - " + Colors.GOLD + " Page " + (page + 1) + " / " + ((langs.size() / perPage) + 1));
for(int i = 0; i < 9; i ++)
inv.setItem(i, new ItemStack(ItemUtils.GRAY_STAINED_GLASS_PANE));
inv.setItem(0, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.GRAY + "Back"));
if (e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player) || e.getCurrentItem() == null
|| !(e.getClickedInventory().getHolder() instanceof TranslationHolder))
return;
e.setCancelled(true);
Player p = (Player) e.getWhoClicked();
ItemStack item = e.getCurrentItem();
Material type = item.getType();
TranslationHolder holder = (TranslationHolder) e.getClickedInventory().getHolder();
if (type.equals(Material.ARROW)) {
if (e.getSlot() == 0)
InventoryListener.open(p);
else if (e.getSlot() == 3)
open(p, holder.getPage() - 1);
else if (e.getSlot() == 5)
open(p, holder.getPage() + 1);
} else if (type.equals(ItemUtils.MATERIAL_CLOSE))
p.closeInventory();
else if (type.equals(Material.PAPER)) {
String lang = holder.langBySlot.get(e.getSlot());
if (lang == null)
return;
p.closeInventory();
ChatItem pl = ChatItem.getInstance();
pl.getStorage().language = lang;
pl.getConfig().set("general.language", lang);
pl.saveConfig();
Translation.loadLang(lang);
p.sendMessage(Colors.GREEN + "Language changed to "
+ Translation.getMessages().get("language.name").getAsString());
}
}
public static void open(Player p, int page) {
int perPage = 45;
List<String> langs = new ArrayList<>(Translation.getAllLangs().keySet());
TranslationHolder holder = new TranslationHolder(page);
Inventory inv = ChatItem.getPlatform().createInventory(holder, 54,
"Change language - " + Colors.GOLD + " Page " + (page + 1) + " / " + ((langs.size() / perPage) + 1));
for (int i = 0; i < 9; i++)
inv.setItem(i, new ItemStack(ItemUtils.GRAY_STAINED_GLASS_PANE));
inv.setItem(0, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.GRAY + "Back"));
if (page > 0)
inv.setItem(3, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.RED + "Previous page"));
if (langs.size() > (perPage * (page + 1)))
inv.setItem(5, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.GREEN + "Next page"));
inv.setItem(8, ChatItem.getPlatform().createItemStack(ItemUtils.MATERIAL_CLOSE,
Messages.getMessage("admin-inv.close")));
int slot = 9;
for (int i = (page * perPage); i < langs.size() && (i < ((page + 1) * perPage)); i++) {
String lang = langs.get(i);
holder.langBySlot.put(slot, lang);
ItemStack item = ChatItem.getPlatform().createItemStack(Material.PAPER,
Colors.GOLD + Translation.getAllLangs().get(lang), Colors.GRAY + "Clic to select this language");
if (lang.equalsIgnoreCase(ChatItem.getInstance().getStorage().language)) {
item.addUnsafeEnchantment(ItemUtils.getEnchant("DURABILITY", "UNBREAKING"), 1);
ItemMeta meta = item.getItemMeta();
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
item.setItemMeta(meta);
}
inv.setItem(slot++, item);
}
p.openInventory(inv);
}
if(page > 0)
inv.setItem(3, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.RED + "Previous page"));
if(langs.size() > (perPage * (page + 1)))
inv.setItem(5, ChatItem.getPlatform().createItemStack(Material.ARROW, Colors.GREEN + "Next page"));
inv.setItem(8, ChatItem.getPlatform().createItemStack(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
int slot = 9;
for(int i = (page * perPage); i < langs.size() && (i < ((page + 1) * perPage)); i++) {
String lang = langs.get(i);
holder.langBySlot.put(slot, lang);
ItemStack item = ChatItem.getPlatform().createItemStack(Material.PAPER, Colors.GOLD + Translation.getAllLangs().get(lang), Colors.GRAY + "Clic to select this language");
if(lang.equalsIgnoreCase(ChatItem.getInstance().getStorage().language)) {
item.addUnsafeEnchantment(ItemUtils.getEnchant("DURABILITY", "UNBREAKING"), 1);
ItemMeta meta = item.getItemMeta();
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
item.setItemMeta(meta);
}
inv.setItem(slot++, item);
}
p.openInventory(inv);
}
}
@@ -3,7 +3,7 @@ package me.dadus33.chatitem.listeners.holder;
import java.util.HashMap;
public class AdminHolder extends ChatItemHolder {
public final HashMap<Integer, String> keyBySlot = new HashMap<>();
public final HashMap<Integer, String> keyBySlot = new HashMap<>();
}
@@ -4,9 +4,12 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
public abstract class ChatItemHolder implements InventoryHolder {
@Override
public Inventory getInventory() {
return null;
}
}
@@ -3,15 +3,20 @@ package me.dadus33.chatitem.listeners.holder;
import java.util.HashMap;
public class TranslationHolder extends ChatItemHolder {
public final HashMap<Integer, String> langBySlot = new HashMap<>();
private final int page;
public TranslationHolder(int page) {
this.page = page;
}
public int getPage() {
return page;
}
public final HashMap<Integer, String> langBySlot = new HashMap<>();
private final int page;
public TranslationHolder(int page) {
this.page = page;
}
public int getPage() {
return page;
}
}
@@ -15,38 +15,44 @@ import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Version;
public interface IPlatform {
String getName();
Inventory createInventory(InventoryHolder holder, int slot, String name);
String getName();
Inventory createInventory(InventoryHolder holder, int slot, String name);
ItemStack createItemStack(Material type, String name);
default ItemStack createTranslatedItemStack(Material type, String key, Object... placeholders) {
return createItemStack(type, Messages.getMessage(key + ".name", placeholders),
Messages.getMessageList(key + ".lore", placeholders));
}
default ItemStack createItemStack(Material type, String name, String... lore) {
return createItemStack(type, name, Arrays.asList(lore));
}
ItemStack createItemStack(Material type, String name, List<String> lore);
String getItemDisplayName(ItemStack item);
String getPluginVersion(Plugin plugin);
Version getMinecraftVersion();
String getNMSVersion();
boolean hasBaseComponentSerializer();
String baseComponentToJson(Object obj);
Object jsonToBaseComponent(String json);
void sendMessage(Player to, Player origin, ChatAction action, String msg);
String stringifyItem(ItemStack item);
ItemStack createItemStack(Material type, String name);
default ItemStack createTranslatedItemStack(Material type, String key, Object... placeholders) {
return createItemStack(type, Messages.getMessage(key + ".name", placeholders), Messages.getMessageList(key + ".lore", placeholders));
}
default ItemStack createItemStack(Material type, String name, String... lore) {
return createItemStack(type, name, Arrays.asList(lore));
}
ItemStack createItemStack(Material type, String name, List<String> lore);
String getItemDisplayName(ItemStack item);
String getPluginVersion(Plugin plugin);
Version getMinecraftVersion();
String getNMSVersion();
boolean hasBaseComponentSerializer();
String baseComponentToJson(Object obj);
Object jsonToBaseComponent(String json);
void sendMessage(Player to, Player origin, ChatAction action, String msg);
String stringifyItem(ItemStack item);
}
@@ -32,149 +32,219 @@ import net.kyori.adventure.text.format.NamedTextColor;
public class PaperPlatform implements IPlatform {
@Override
public String getName() {
return "PaperMC";
}
@Override
public String getName() {
@Override
public Inventory createInventory(InventoryHolder holder, int slot, String name) {
return Bukkit.createInventory(holder, slot, C.text(name));
}
return "PaperMC";
@Override
public ItemStack createItemStack(Material type, String name) {
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.displayName(C.text(name).color(NamedTextColor.WHITE));
item.setItemMeta(meta);
return item;
}
}
@Override
public ItemStack createItemStack(Material type, String name, List<String> lore) {
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.displayName(C.text(name).color(NamedTextColor.WHITE));
meta.lore(lore.stream().map(C::text).collect(Collectors.toList()));
item.setItemMeta(meta);
return item;
}
@Override
public Inventory createInventory(InventoryHolder holder, int slot, String name) {
@SuppressWarnings("deprecation")
@Override
public String getItemDisplayName(ItemStack item) {
// actually the get Displayname for better ... See:
// https://github.com/KyoriPowered/adventure-platform/issues/185
// return
// LegacyComponentSerializer.legacySection().serialize(item.displayName());
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : null;
}
return Bukkit.createInventory(holder, slot, C.text(name));
@Override
public String getPluginVersion(Plugin plugin) {
return plugin.getPluginMeta().getVersion();
}
}
@Override
public Version getMinecraftVersion() {
return Version.getVersionByName("v" + Bukkit.getMinecraftVersion().replace(".", "_"));
}
@Override
public ItemStack createItemStack(Material type, String name) {
@Override
public String getNMSVersion() {
String[] parts = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",");
return parts.length <= 3 ? "" : parts[3];
}
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.displayName(C.text(name).color(NamedTextColor.WHITE));
item.setItemMeta(meta);
return item;
@Override
public boolean hasBaseComponentSerializer() {
return SpigotPlatform.getBaseComponentToJsonMethod() != null;
}
}
private Object getRegistry() throws Exception {
Class<?> serverClass = Class.forName("net.minecraft.server.MinecraftServer");
return serverClass.getDeclaredMethod("registryAccess").invoke(serverClass.getDeclaredMethod("getServer").invoke(null));
}
@Override
public String baseComponentToJson(Object obj) {
Method m = SpigotPlatform.getBaseComponentToJsonMethod();
if (m == null)
return null;
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = obj;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$Provider")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$Provider");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return (String) m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public ItemStack createItemStack(Material type, String name, List<String> lore) {
@Override
public Object jsonToBaseComponent(String json) {
Method m = SpigotPlatform.getJsonToBaseComponentMethod();
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = json;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$Provider")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$Provider");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
ItemStack item = new ItemStack(type);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.displayName(C.text(name).color(NamedTextColor.WHITE));
meta.lore(lore.stream().map(C::text).collect(Collectors.toList()));
item.setItemMeta(meta);
return item;
@Override
public void sendMessage(Player to, Player origin, ChatAction action, String msg) {
HoverEventSource<?> hoverEvent = null;
if (action.hasItem()) {
if (!action.getItem().getType().equals(Material.AIR))
hoverEvent = action.getItem().asHoverEvent();
else {
Component t = null;
for (String line : Messages.getMessageList("general.hand.tooltip", "%cible%", origin.getName())) {
if (t == null) {
t = Component.text("");
} else
t.append(Component.newline());
t.append(C.text(line));
}
hoverEvent = HoverEvent.showText(t);
}
} else
hoverEvent = HoverEvent.showText(C.text(Messages.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", origin.getName())));
TextComponent like = Component.text(ChatManager.getNameForChatAction(origin, action, ChatItem.getInstance().getStorage())).hoverEvent(hoverEvent);
if (action.hasCommand())
like = like.clickEvent(ClickEvent.runCommand(action.getCommand()));
}
to.sendMessage(C.text(msg).replaceText(TextReplacementConfig.builder().matchLiteral(ChatManager.SEPARATOR + "").replacement(like).build()));
}
@SuppressWarnings("deprecation")
@Override
public String getItemDisplayName(ItemStack item) {
// actually the get Displayname for better ... See:
// https://github.com/KyoriPowered/adventure-platform/issues/185
// return
// LegacyComponentSerializer.legacySection().serialize(item.displayName());
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : null;
}
@Override
public String getPluginVersion(Plugin plugin) {
return plugin.getPluginMeta().getVersion();
}
@Override
public Version getMinecraftVersion() {
return Version.getVersionByName("v" + Bukkit.getMinecraftVersion().replace(".", "_"));
}
@Override
public String getNMSVersion() {
String[] parts = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",");
return parts.length <= 3 ? "" : parts[3];
}
@Override
public boolean hasBaseComponentSerializer() {
return SpigotPlatform.getBaseComponentToJsonMethod() != null;
}
private Object getRegistry() throws Exception {
Class<?> serverClass = Class.forName("net.minecraft.server.MinecraftServer");
return serverClass.getDeclaredMethod("registryAccess")
.invoke(serverClass.getDeclaredMethod("getServer").invoke(null));
}
@Override
public String baseComponentToJson(Object obj) {
Method m = SpigotPlatform.getBaseComponentToJsonMethod();
if (m == null)
return null;
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = obj;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$Provider")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$Provider");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return (String) m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Object jsonToBaseComponent(String json) {
Method m = SpigotPlatform.getJsonToBaseComponentMethod();
try {
Object[] args = new Object[m.getParameterCount()];
args[0] = json;
if (args.length > 1 && ReflectionUtils.isClassExist("net.minecraft.core.HolderLookup$Provider")) {
Class<?> c = Class.forName("net.minecraft.core.HolderLookup$Provider");
if (m.getParameterTypes()[1].isAssignableFrom(c)) {
args[1] = getRegistry();
}
}
return m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void sendMessage(Player to, Player origin, ChatAction action, String msg) {
HoverEventSource<?> hoverEvent = null;
if (action.hasItem()) {
if (!action.getItem().getType().equals(Material.AIR))
hoverEvent = action.getItem().asHoverEvent();
else {
Component t = null;
for (String line : Messages.getMessageList("general.hand.tooltip", "%cible%", origin.getName())) {
if (t == null) {
t = Component.text("");
} else
t.append(Component.newline());
t.append(C.text(line));
}
hoverEvent = HoverEvent.showText(t);
}
} else
hoverEvent = HoverEvent.showText(C.text(Messages
.getMessage(action.getSlot().name().toLowerCase() + ".hover", "%cible%", origin.getName())));
TextComponent like = Component
.text(ChatManager.getNameForChatAction(origin, action, ChatItem.getInstance().getStorage()))
.hoverEvent(hoverEvent);
if (action.hasCommand())
like = like.clickEvent(ClickEvent.runCommand(action.getCommand()));
to.sendMessage(C.text(msg).replaceText(
TextReplacementConfig.builder().matchLiteral(ChatManager.SEPARATOR + "").replacement(like).build()));
}
@SuppressWarnings("deprecation")
@Override
public String stringifyItem(ItemStack item) {
ShowItem si = item.asHoverEvent().value();
String json = "{id:\"" + si.item().asString() + "\",count:" + item.getAmount();
if (si.nbt() != null) {
json += ",tag:{" + si.nbt().string() + "}";
} else if (Version.getVersion().isNewerOrEquals(Version.V1_20_6)) { // since MC 1.20.5 in fact
json += ",components:" + (item.hasItemMeta() ? item.getItemMeta().getAsString() : "{}");
}
json += "}";
ChatItem.debug("Item stringified: " + json);
return json;
}
@SuppressWarnings("deprecation")
@Override
public String stringifyItem(ItemStack item) {
ShowItem si = item.asHoverEvent().value();
String json = "{id:\"" + si.item().asString() + "\",count:" + item.getAmount();
if(si.nbt() != null) {
json += ",tag:{" + si.nbt().string() + "}";
} else if(Version.getVersion().isNewerOrEquals(Version.V1_20_6)) { // since MC 1.20.5 in fact
json += ",components:" + (item.hasItemMeta() ? item.getItemMeta().getAsString() : "{}");
}
json += "}";
ChatItem.debug("Item stringified: " + json);
return json;
}
}
File diff suppressed because it is too large. Load diff
@@ -6,6 +6,6 @@ import net.md_5.bungee.api.chat.BaseComponent;
public interface IPlayerNamer {
public BaseComponent[] getName(Player p);
public BaseComponent[] getName(Player p);
}
@@ -10,33 +10,40 @@ import org.bukkit.plugin.Plugin;
public class PlayerNamerManager {
private static IPlayerNamer playerNamer;
public static IPlayerNamer getPlayerNamer() {
return playerNamer;
}
public static void setPlayerNamer(IPlayerNamer playerNamer) {
PlayerNamerManager.playerNamer = playerNamer;
}
public static void load(ChatItem pl) {
Plugin plugin = Bukkit.getPluginManager().getPlugin("HexNicks");
private static IPlayerNamer playerNamer;
public static IPlayerNamer getPlayerNamer() {
if (plugin != null) {
char majorVersion = ChatItem.getPlatform().getPluginVersion(plugin).charAt(0);
return playerNamer;
if (majorVersion == '3')
setPlayerNamer(new HexNicksV3PlayerNamer());
else
setPlayerNamer(new HexNicksV2PlayerNamer());
}
pl.getLogger().info("Enable support for HexNicks plugin v" + majorVersion);
return;
}
public static void setPlayerNamer(IPlayerNamer playerNamer) {
PlayerNamerManager.playerNamer = playerNamer;
}
setPlayerNamer(new DefaultPlayerNamer());
public static void load(ChatItem pl) {
Plugin plugin = Bukkit.getPluginManager().getPlugin("HexNicks");
if (plugin != null) {
char majorVersion = ChatItem.getPlatform().getPluginVersion(plugin).charAt(0);
if (majorVersion == '3')
setPlayerNamer(new HexNicksV3PlayerNamer());
else
setPlayerNamer(new HexNicksV2PlayerNamer());
pl.getLogger().info("Enable support for HexNicks plugin v" + majorVersion);
return;
}
setPlayerNamer(new DefaultPlayerNamer());
}
}
}
@@ -8,8 +8,11 @@ import net.md_5.bungee.api.chat.ComponentBuilder;
public class DefaultPlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
return new ComponentBuilder(p.getName()).create();
}
@Override
public BaseComponent[] getName(Player p) {
return new ComponentBuilder(p.getName()).create();
}
}
@@ -11,16 +11,24 @@ import net.md_5.bungee.api.chat.BaseComponent;
public class HexNicksV2PlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
try {
Object api = Class.forName("dev.majek.hexnicks.Nicks").getDeclaredMethod("api").invoke(null);
CompletableFuture<Component> storedNick = (CompletableFuture<Component>) api.getClass().getDeclaredMethod("getStoredNick", Player.class).invoke(api, p);
return BungeeComponentSerializer.get().serialize(storedNick.join());
} catch (Exception e) {
e.printStackTrace();
}
return new BaseComponent[0];
}
@Override
public BaseComponent[] getName(Player p) {
try {
Object api = Class.forName("dev.majek.hexnicks.Nicks").getDeclaredMethod("api").invoke(null);
CompletableFuture<Component> storedNick = (CompletableFuture<Component>) api.getClass()
.getDeclaredMethod("getStoredNick", Player.class).invoke(api, p);
return BungeeComponentSerializer.get().serialize(storedNick.join());
} catch (Exception e) {
e.printStackTrace();
}
return new BaseComponent[0];
}
}
@@ -11,7 +11,9 @@ public class HexNicksV3PlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
return BungeeComponentSerializer.get().serialize(HexNicks.api().getStoredNick(p).join());
}
}
@@ -5,10 +5,13 @@ import org.bukkit.entity.Player;
import me.dadus33.chatitem.utils.Version;
public interface IPlayerVersion {
public int getProtocolVersion(Player p);
default Version getPlayerVersion(Player p) {
return Version.getVersion(getProtocolVersion(p), Version.getVersion());
}
public int getProtocolVersion(Player p);
default Version getPlayerVersion(Player p) {
return Version.getVersion(getProtocolVersion(p), Version.getVersion());
}
}
@@ -11,19 +11,30 @@ public class PlayerVersionManager {
private static final IPlayerVersion playerVersionAdapter;
static {
ChatItem pl = ChatItem.getInstance();
if (Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null) {
playerVersionAdapter = new ProtocolSupportHook();
pl.getLogger().info("Loading ProtocolSupport support ...");
} else if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
playerVersionAdapter = new ViaVersionHook();
pl.getLogger().info("Loading ViaVersion support ...");
} else {
playerVersionAdapter = new DefaultVersionHook();
}
}
public static IPlayerVersion getPlayerVersionAdapter() {
return playerVersionAdapter;
}
}
@@ -7,8 +7,11 @@ import me.dadus33.chatitem.utils.Version;
public class DefaultVersionHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return Version.getVersion().MAX_VER;
}
@Override
public int getProtocolVersion(Player p) {
return Version.getVersion().MAX_VER;
}
}
@@ -6,10 +6,12 @@ import me.dadus33.chatitem.playerversion.IPlayerVersion;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupportHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return ProtocolSupportAPI.getProtocolVersion(p).getId();
}
@Override
public int getProtocolVersion(Player p) {
return ProtocolSupportAPI.getProtocolVersion(p).getId();
}
}
@@ -8,8 +8,11 @@ import me.dadus33.chatitem.playerversion.IPlayerVersion;
public class ViaVersionHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return Via.getAPI().getPlayerVersion(p.getUniqueId());
}
@Override
public int getProtocolVersion(Player p) {
return Via.getAPI().getPlayerVersion(p.getUniqueId());
}
}
@@ -8,115 +8,170 @@ import net.md_5.bungee.api.ChatColor;
public class ColorManager {
public static final char COLOR_CHAR = '§';
public static final List<String> COLORS = Arrays.asList("4", "c", "6", "e", "2", "a", "b", "3", "1", "9", "d", "5", "f", "7", "8", "0", "k", "l", "m", "n", "o", "r");
public static boolean isHexColor(ChatColor c) {
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.getName().startsWith("#");
}
public static boolean isHexColor(String c) {
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.startsWith("x");
}
public static final char COLOR_CHAR = '§';
public static final List<String> COLORS = Arrays.asList("4", "c", "6", "e", "2", "a", "b", "3", "1", "9", "d", "5",
"f", "7", "8", "0", "k", "l", "m", "n", "o", "r");
public static String removeColorAtBegin(String s) {
if(s == null || s.isEmpty())
return "";
boolean wasColorChar = s.startsWith(Character.toString(ChatColor.COLOR_CHAR));
if(!wasColorChar)
return s;
String next = "";
for(int i = 1; i < s.length(); i++) {
char c = s.charAt(i);
if(wasColorChar) {
if(!COLORS.contains(Character.toString(c)))
next = next + ChatColor.COLOR_CHAR + "" + c;
wasColorChar = false;
} else {
wasColorChar = c == ChatColor.COLOR_CHAR;
if(!wasColorChar) { // something other than color code
next += s.substring(i);
break;
}
}
}
if(next.isEmpty())
next = s;
return next;
}
public static String getColorString(String input) {
if (input == null || input.isEmpty())
return "";
StringBuilder str = new StringBuilder();
if (isHexColor(input)) { // x mean it's an hex
input = input.substring(1);
if (input.length() >= 6) { // at least hex
str.append(ChatColor.of("#" + input.substring(0, 6))); // get first hex color code
ChatItem.debug("Str with hex: " + str);
if (input.length() > 6) // if as another color code
str.append(getColorString(input.substring(6))); // get color for after
return str.toString();
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
for (char c : input.toCharArray())
str.append(ChatColor.getByChar(c));
return str.toString();
}
public static boolean isHexColor(ChatColor c) {
public static ChatColor getColor(String input) {
if (input == null || input.isEmpty())
return ChatColor.RESET;
if (isHexColor(input)) { // x mean it's an hex
if (input.length() >= 7) { // at least hex, and 7 because we count the "x"
return ChatColor.of("#" + input.substring(1, 7)); // get first hex color code
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
return ChatColor.getByChar(input.charAt(0));
}
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.getName().startsWith("#");
}
public static boolean isHexColor(String c) {
return Version.getVersion().isNewerOrEquals(Version.V1_16) && c.startsWith("x");
}
public static String removeColorAtBegin(String s) {
if (s == null || s.isEmpty())
return "";
boolean wasColorChar = s.startsWith(Character.toString(ChatColor.COLOR_CHAR));
if (!wasColorChar)
return s;
String next = "";
for (int i = 1; i < s.length(); i++) {
char c = s.charAt(i);
if (wasColorChar) {
if (!COLORS.contains(Character.toString(c)))
next = next + ChatColor.COLOR_CHAR + "" + c;
wasColorChar = false;
} else {
wasColorChar = c == ChatColor.COLOR_CHAR;
if (!wasColorChar) { // something other than color code
next += s.substring(i);
break;
}
}
}
if (next.isEmpty())
next = s;
return next;
}
public static String getColorString(String input) {
if (input == null || input.isEmpty())
return "";
StringBuilder str = new StringBuilder();
if (isHexColor(input)) { // x mean it's an hex
input = input.substring(1);
if (input.length() >= 6) { // at least hex
str.append(ChatColor.of("#" + input.substring(0, 6))); // get first hex color code
ChatItem.debug("Str with hex: " + str);
if (input.length() > 6) // if as another color code
str.append(getColorString(input.substring(6))); // get color for after
return str.toString();
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
for (char c : input.toCharArray())
str.append(ChatColor.getByChar(c));
return str.toString();
}
public static ChatColor getColor(String input) {
if (input == null || input.isEmpty())
return ChatColor.RESET;
if (isHexColor(input)) { // x mean it's an hex
if (input.length() >= 7) { // at least hex, and 7 because we count the "x"
return ChatColor.of("#" + input.substring(1, 7)); // get first hex color code
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
return ChatColor.getByChar(input.charAt(0));
}
public static String fixColor(String message) {
String colorCode = "", text = "";
boolean waiting = false;
for (char args : message.toCharArray()) {
if (args == COLOR_CHAR) { // begin of color
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
text += ChatColor.RESET;
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else if (Character.digit(Character.toLowerCase(args), 16) != -1)
colorCode += args; // a color by itself
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (isHexColor(colorCode) && colorCode.length() >= 7) {
if (colorCode.length() == 7)
text += ColorManager.getColor(colorCode);
else {
text += ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
text += ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
return text;
}
public static String fixColor(String message) {
String colorCode = "", text = "";
boolean waiting = false;
for (char args : message.toCharArray()) {
if (args == COLOR_CHAR) { // begin of color
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if (args == 'r' && colorCode.isEmpty()) {
text += ChatColor.RESET;
continue;
}
if (args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else if(Character.digit(Character.toLowerCase(args), 16) != -1)
colorCode += args; // a color by itself
} else {
waiting = false;
if (!colorCode.isEmpty()) {
if (isHexColor(colorCode) && colorCode.length() >= 7) {
if (colorCode.length() == 7)
text += ColorManager.getColor(colorCode);
else {
text += ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if (colorCode.length() == 1) // if only one color code
text += ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
// basic text, not waiting for code after '§'
text += args;
}
}
return text;
}
}
@@ -10,33 +10,45 @@ import net.md_5.bungee.api.ChatColor;
public class Colors {
public static final String YELLOW = ColorManager.COLOR_CHAR + "e";
public static final String AQUA = ColorManager.COLOR_CHAR + "b";
public static final String GOLD = ColorManager.COLOR_CHAR + "6";
public static final String GRAY = ColorManager.COLOR_CHAR + "7";
public static final String RED = ColorManager.COLOR_CHAR + "c";
public static final String GREEN = ColorManager.COLOR_CHAR + "a";
public static final String RESET = ColorManager.COLOR_CHAR + "r";
public static final String YELLOW = ColorManager.COLOR_CHAR + "e";
public static final String AQUA = ColorManager.COLOR_CHAR + "b";
public static final String GOLD = ColorManager.COLOR_CHAR + "6";
public static final String GRAY = ColorManager.COLOR_CHAR + "7";
public static final String RED = ColorManager.COLOR_CHAR + "c";
public static final String GREEN = ColorManager.COLOR_CHAR + "a";
public static final String RESET = ColorManager.COLOR_CHAR + "r";
public static String color(String s) {
return s == null || s.isEmpty() ? s : translateAlternateColorCodes('&', s);
}
public static String color(String s) {
return s == null || s.isEmpty() ? s : translateAlternateColorCodes('&', s);
}
public static String translateAlternateColorCodes(char altColorChar, @NotNull String textToTranslate) {
Preconditions.checkArgument(textToTranslate != null, "Cannot translate null text");
char[] b = textToTranslate.toCharArray();
for (int i = 0; i < b.length - 1; i++) {
if (b[i] == altColorChar && ColorManager.COLORS.contains(b[i + 1] + "")) {
b[i] = ColorManager.COLOR_CHAR;
b[i + 1] = Character.toLowerCase(b[i + 1]);
}
}
return new String(b);
}
public static boolean isFormatting(ChatColor c) {
return Arrays.asList(ChatColor.RESET, ChatColor.BOLD, ChatColor.MAGIC, ChatColor.UNDERLINE, ChatColor.ITALIC, ChatColor.STRIKETHROUGH).contains(c);
return Arrays.asList(ChatColor.RESET, ChatColor.BOLD, ChatColor.MAGIC, ChatColor.UNDERLINE, ChatColor.ITALIC,
ChatColor.STRIKETHROUGH).contains(c);
}
}
@@ -11,80 +11,121 @@ import me.dadus33.chatitem.ChatItem;
public class ItemUtils {
public static final Material MATERIAL_CLOSE = getMaterialWithCompatibility("BARRIER", "REDSTONE_BLOCK");
// items
public static final Material EMPTY_MAP = getMaterialWithCompatibility("EMPTY_MAP", "MAP");
public static final Material BOOK_AND_QUILL = getMaterialWithCompatibility("BOOK_AND_QUILL", "WRITTEN_BOOK");
public static final Material WEB = getMaterialWithCompatibility("WEB", "COBWEB");
public static final Material FIREBALL = getMaterialWithCompatibility("FIREBALL", "FIRE_CHARGE");
public static final Material INK_SAC = getMaterialWithCompatibility("INK_SAC", "INK_SACK", "DYE", "GRAY_DYE");
public static final Material FIREWORK_CHARGE = getMaterialWithCompatibility("FIREWORK_CHARGE", "FIRE_CHARGE");
public static final Material MATERIAL_CLOSE = getMaterialWithCompatibility("BARRIER", "REDSTONE_BLOCK");
public static final Material BIRCH_WOOD_STAIRS = getMaterialWithCompatibility("BIRCH_WOOD_STAIRS", "BIRCH_STAIRS");
// colored items
public static final Material BROWN_STAINED_GLASS_PANE = getMaterialWithCompatibility("BROWN_STAINED_GLASS_PANE", "STAINED_GLASS_PANE");
public static final Material GRAY_STAINED_GLASS_PANE = getMaterialWithCompatibility("GRAY_STAINED_GLASS_PANE", "STAINED_GLASS_PANE");
public static final Material WHITE_STAINED_GLASS = getMaterialWithCompatibility("WHITE_STAINED_GLASS_PANE", "STAINED_GLASS_PANE");
public static final ItemStack ITEM_EMPTY_BROWN = ChatItem.getPlatform().createItemStack(BROWN_STAINED_GLASS_PANE, "");
public static Material getMaterialWithCompatibility(String... tempMat) {
for(String s : tempMat) {
try {
Material m = (Material) Material.class.getField(s).get(Material.class);
if(m != null)
return m;
} catch (IllegalArgumentException | IllegalAccessException | SecurityException e2) {
e2.printStackTrace();
} catch (NoSuchFieldException e) {}
}
return null;
}
public static ItemStack hideAttributes(ItemStack stack) {
ItemMeta meta = stack.getItemMeta();
// All ItemFlags are used to hide attributes, their javadoc says so too.
meta.addItemFlags(ItemFlag.values());
stack.setItemMeta(meta);
return stack;
}
public static ItemStack copyIfExist(ItemStack item) {
return isEmpty(item) ? null : item.clone();
}
public static boolean isEmpty(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
// items
public static final Material EMPTY_MAP = getMaterialWithCompatibility("EMPTY_MAP", "MAP");
public static final Material BOOK_AND_QUILL = getMaterialWithCompatibility("BOOK_AND_QUILL", "WRITTEN_BOOK");
public static final Material WEB = getMaterialWithCompatibility("WEB", "COBWEB");
public static final Material FIREBALL = getMaterialWithCompatibility("FIREBALL", "FIRE_CHARGE");
public static final Material INK_SAC = getMaterialWithCompatibility("INK_SAC", "INK_SACK", "DYE", "GRAY_DYE");
public static final Material FIREWORK_CHARGE = getMaterialWithCompatibility("FIREWORK_CHARGE", "FIRE_CHARGE");
public static final Material BIRCH_WOOD_STAIRS = getMaterialWithCompatibility("BIRCH_WOOD_STAIRS", "BIRCH_STAIRS");
// colored items
public static final Material BROWN_STAINED_GLASS_PANE = getMaterialWithCompatibility("BROWN_STAINED_GLASS_PANE",
"STAINED_GLASS_PANE");
public static final Material GRAY_STAINED_GLASS_PANE = getMaterialWithCompatibility("GRAY_STAINED_GLASS_PANE",
"STAINED_GLASS_PANE");
public static final Material WHITE_STAINED_GLASS = getMaterialWithCompatibility("WHITE_STAINED_GLASS_PANE",
"STAINED_GLASS_PANE");
public static final ItemStack ITEM_EMPTY_BROWN = ChatItem.getPlatform().createItemStack(BROWN_STAINED_GLASS_PANE,
"");
public static Material getMaterialWithCompatibility(String... tempMat) {
for (String s : tempMat) {
try {
Material m = (Material) Material.class.getField(s).get(Material.class);
if (m != null)
return m;
} catch (IllegalArgumentException | IllegalAccessException | SecurityException e2) {
e2.printStackTrace();
} catch (NoSuchFieldException e) {
}
}
return null;
}
public static ItemStack hideAttributes(ItemStack stack) {
ItemMeta meta = stack.getItemMeta();
// All ItemFlags are used to hide attributes, their javadoc says so too.
meta.addItemFlags(ItemFlag.values());
stack.setItemMeta(meta);
return stack;
}
public static ItemStack copyIfExist(ItemStack item) {
return isEmpty(item) ? null : item.clone();
}
public static boolean isEmpty(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
@SuppressWarnings("deprecation")
public static void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
@SuppressWarnings("deprecation")
public static Enchantment getEnchant(String... names) {
for (String name : names) {
Enchantment possible = Enchantment.getByName(name);
if (possible != null)
return possible;
}
return null;
}
@SuppressWarnings("deprecation")
public static void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
@SuppressWarnings("deprecation")
public static Enchantment getEnchant(String... names) {
for(String name : names) {
Enchantment possible = Enchantment.getByName(name);
if(possible != null)
return possible;
}
return null;
}
}
@@ -11,32 +11,47 @@ import me.dadus33.chatitem.Storage;
public class Messages {
public static void sendMessage(CommandSender p, String key, Object... placeholders) {
getMessageList(key, placeholders).forEach(p::sendMessage);
}
public static String getMessage(String key, Object... placeholders) {
return colorAndPlaceholders(ChatItem.getInstance().getConfig().getString("messages." + key, key), placeholders);
}
public static List<String> getMessageList(String key, Object... placeholders) {
Object obj = ChatItem.getInstance().getConfig().get("messages." + key);
if(obj == null)
return Arrays.asList(key);
if(obj instanceof List) {
return ((List<String>) obj).stream().map((s) -> colorAndPlaceholders(s, placeholders)).collect(Collectors.toList());
} else if(obj instanceof String)
return Arrays.asList(colorAndPlaceholders((String) obj, placeholders));
else
return Arrays.asList(colorAndPlaceholders(obj.toString(), placeholders));
}
private static String colorAndPlaceholders(String msg, Object... placeholders) {
if(msg == null)
return "";
for (int index = 0; index <= placeholders.length - 1; index += 2) {
msg = msg.replace(String.valueOf(placeholders[index]), String.valueOf(placeholders[index + 1]));
}
return Storage.color(msg);
}
public static void sendMessage(CommandSender p, String key, Object... placeholders) {
getMessageList(key, placeholders).forEach(p::sendMessage);
}
public static String getMessage(String key, Object... placeholders) {
return colorAndPlaceholders(ChatItem.getInstance().getConfig().getString("messages." + key, key), placeholders);
}
public static List<String> getMessageList(String key, Object... placeholders) {
Object obj = ChatItem.getInstance().getConfig().get("messages." + key);
if (obj == null)
return Arrays.asList(key);
if (obj instanceof List) {
return ((List<String>) obj).stream().map((s) -> colorAndPlaceholders(s, placeholders))
.collect(Collectors.toList());
} else if (obj instanceof String)
return Arrays.asList(colorAndPlaceholders((String) obj, placeholders));
else
return Arrays.asList(colorAndPlaceholders(obj.toString(), placeholders));
}
private static String colorAndPlaceholders(String msg, Object... placeholders) {
if (msg == null)
return "";
for (int index = 0; index <= placeholders.length - 1; index += 2) {
msg = msg.replace(String.valueOf(placeholders[index]), String.valueOf(placeholders[index + 1]));
}
return Storage.color(msg);
}
}
@@ -15,204 +15,295 @@ import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulator;
public class PacketUtils {
public static final String NMS_PREFIX;
public static final String OBC_PREFIX;
public static final boolean IS_THERMOS = Utils.isClassExist("thermos.Thermos");
public static final Class<?> COMPONENT_CLASS;
public static final String NMS_PREFIX;
public static final String OBC_PREFIX;
public static final boolean IS_THERMOS = Utils.isClassExist("thermos.Thermos");
public static final Class<?> COMPONENT_CLASS;
private static Method getNbtMethod, sendPacketMethod;
private static Method getNbtMethod, sendPacketMethod;
/**
* This Map is to reduce Reflection action which take more resources than just
* RAM action
*/
private static final Map<String, Class<?>> ALL_CLASS = Collections.synchronizedMap(new HashMap<String, Class<?>>());
/**
* This Map is to reduce Reflection action which take more resources than just
* RAM action
*/
private static final Map<String, Class<?>> ALL_CLASS = Collections.synchronizedMap(new HashMap<String, Class<?>>());
static {
String version = ChatItem.getPlatform().getNMSVersion();
NMS_PREFIX = Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? "net.minecraft." : "net.minecraft.server." + (version == "" ? "" : version + ".");
OBC_PREFIX = "org.bukkit.craftbukkit." + (version == "" ? "" : version + ".");
COMPONENT_CLASS = getNmsClass("IChatBaseComponent", "network.chat.");
}
static {
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because it's NMS)
* @return clazz the searched class
*/
public static Class<?> getNmsClass(String name, String packagePrefix, String... alias) {
return ALL_CLASS.computeIfAbsent(name, (a) -> {
String fullPrefix = NMS_PREFIX + (Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? packagePrefix : "");
try {
Class<?> clazz = Class.forName(fullPrefix + name);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {}
String version = ChatItem.getPlatform().getNMSVersion();
NMS_PREFIX = Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? "net.minecraft."
: "net.minecraft.server." + (version == "" ? "" : version + ".");
OBC_PREFIX = "org.bukkit.craftbukkit." + (version == "" ? "" : version + ".");
COMPONENT_CLASS = getNmsClass("IChatBaseComponent", "network.chat.");
for (String className : alias) {
try {
Class<?> clazz = Class.forName(fullPrefix + className);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {}
}
return null;
});
}
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because
* it's NMS)
* @return clazz the searched class
*/
public static Class<?> getObcClass(String name, String... alias) {
return ALL_CLASS.computeIfAbsent(name, (a) -> {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + name);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because
* it's NMS)
* @return clazz the searched class
*/
public static Class<?> getNmsClass(String name, String packagePrefix, String... alias) {
for (String className : alias) {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + className);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
return ALL_CLASS.computeIfAbsent(name, (a) -> {
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getEntityPlayer(Player p) {
try {
return getObcClass("entity.CraftPlayer").getMethod("getHandle").invoke(p);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
String fullPrefix = NMS_PREFIX
+ (Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? packagePrefix : "");
try {
/**
* Get NMS player connection of specified player
*
* @param p Player of which we want to get the player connection
* @return the NMS player connection
*/
public static Object getPlayerConnection(Player p) {
try {
Object entityPlayer = getEntityPlayer(p);
return ReflectionUtils.getFirstWith(entityPlayer, entityPlayer.getClass(), getNmsClass("PlayerConnection", "server.network."));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Class<?> clazz = Class.forName(fullPrefix + name);
if (clazz != null)
return clazz;
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getCraftServer() {
try {
return getObcClass("CraftServer").getMethod("getHandle").invoke(Bukkit.getServer());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
} catch (ClassNotFoundException e) {
/**
* Send the packet to the specified player
*
* @param p which will receive the packet
* @param packet the packet to sent
*/
public static void sendPacket(Player p, Object packet) {
try {
Object playerConnection = getPlayerConnection(p);
if(sendPacketMethod == null) {
Version v = Version.getVersion();
if(v.isNewerOrEquals(Version.V1_20)) {
Class<?> packetSrvClass = getNmsClass("ServerCommonPacketListenerImpl", "server.network.");
if(packetSrvClass != null)
sendPacketMethod = packetSrvClass.getDeclaredMethod("b", getNmsClass("Packet", "network.protocol."));
}
if(sendPacketMethod == null)
sendPacketMethod = playerConnection.getClass().getMethod(Version.getVersion().isNewerOrEquals(Version.V1_18) ? "a" : "sendPacket", getNmsClass("Packet", "network.protocol."));
}
sendPacketMethod.invoke(playerConnection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Converts an {@link org.bukkit.inventory.ItemStack} to a Json string for
* sending with {@link net.md_5.bungee.api.chat.BaseComponent}'s.
*
* @param item the item to convert
* @return the Json string representation of the item
*/
public static String getNbtTag(ItemStack item) {
try {
if (getNbtMethod == null) {
Class<?> itemClass = getNmsClass("ItemStack", "world.item.");
Version v = Version.getVersion();
if(v.isNewerOrEquals(Version.V1_20_6))
getNbtMethod = itemClass.getDeclaredMethod("d"); // return DataComponentPatch's object
else if (v.equals(Version.V1_20))
getNbtMethod = itemClass.getDeclaredMethod("w");
else if (v.equals(Version.V1_19))
getNbtMethod = itemClass.getDeclaredMethod("u");
else if (v.equals(Version.V1_18))
getNbtMethod = itemClass.getDeclaredMethod("t");
else
getNbtMethod = itemClass.getDeclaredMethod("getTag");
for (String className : alias) {
try {
Class<?> clazz = Class.forName(fullPrefix + className);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
}
}
return null;
});
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because
* it's NMS)
* @return clazz the searched class
*/
public static Class<?> getObcClass(String name, String... alias) {
return ALL_CLASS.computeIfAbsent(name, (a) -> {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + name);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
for (String className : alias) {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + className);
if (clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if (className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getEntityPlayer(Player p) {
try {
return getObcClass("entity.CraftPlayer").getMethod("getHandle").invoke(p);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get NMS player connection of specified player
*
* @param p Player of which we want to get the player connection
* @return the NMS player connection
*/
public static Object getPlayerConnection(Player p) {
try {
Object entityPlayer = getEntityPlayer(p);
return ReflectionUtils.getFirstWith(entityPlayer, entityPlayer.getClass(),
getNmsClass("PlayerConnection", "server.network."));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getCraftServer() {
try {
return getObcClass("CraftServer").getMethod("getHandle").invoke(Bukkit.getServer());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Send the packet to the specified player
*
* @param p which will receive the packet
* @param packet the packet to sent
*/
public static void sendPacket(Player p, Object packet) {
try {
Object playerConnection = getPlayerConnection(p);
if (sendPacketMethod == null) {
Version v = Version.getVersion();
if (v.isNewerOrEquals(Version.V1_20)) {
Class<?> packetSrvClass = getNmsClass("ServerCommonPacketListenerImpl", "server.network.");
if (packetSrvClass != null)
sendPacketMethod = packetSrvClass.getDeclaredMethod("b",
getNmsClass("Packet", "network.protocol."));
}
if (sendPacketMethod == null)
sendPacketMethod = playerConnection.getClass().getMethod(
Version.getVersion().isNewerOrEquals(Version.V1_18) ? "a" : "sendPacket",
getNmsClass("Packet", "network.protocol."));
}
sendPacketMethod.invoke(playerConnection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Converts an {@link org.bukkit.inventory.ItemStack} to a Json string for
* sending with {@link net.md_5.bungee.api.chat.BaseComponent}'s.
*
* @param item the item to convert
* @return the Json string representation of the item
*/
public static String getNbtTag(ItemStack item) {
try {
if (getNbtMethod == null) {
Class<?> itemClass = getNmsClass("ItemStack", "world.item.");
Version v = Version.getVersion();
if (v.isNewerOrEquals(Version.V1_20_6))
getNbtMethod = itemClass.getDeclaredMethod("d"); // return DataComponentPatch's object
else if (v.equals(Version.V1_20))
getNbtMethod = itemClass.getDeclaredMethod("w");
else if (v.equals(Version.V1_19))
getNbtMethod = itemClass.getDeclaredMethod("u");
else if (v.equals(Version.V1_18))
getNbtMethod = itemClass.getDeclaredMethod("t");
else
getNbtMethod = itemClass.getDeclaredMethod("getTag");
getNbtMethod.setAccessible(true);
}
Object tag = getNbtMethod.invoke(JSONManipulator.AS_NMS_COPY.invoke(null, item));
return tag == null ? "{}" : tag.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "{}";
}
public static void printPacketToDebug(Object packet) {
if (!ChatItem.hasDebug())
return;
if (packet == null) {
ChatItem.debug("Packet is null");
return;
}
ChatItem.debug("Packet with Class: " + packet.getClass().getSimpleName());
for (Field f : packet.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
ChatItem.debug(f.getName() + ": " + f.get(packet));
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
getNbtMethod.setAccessible(true);
}
Object tag = getNbtMethod.invoke(JSONManipulator.AS_NMS_COPY.invoke(null, item));
return tag == null ? "{}" : tag.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "{}";
}
public static void printPacketToDebug(Object packet) {
if(!ChatItem.hasDebug())
return;
if(packet == null) {
ChatItem.debug("Packet is null");
return;
}
ChatItem.debug("Packet with Class: " + packet.getClass().getSimpleName());
for (Field f : packet.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
ChatItem.debug(f.getName() + ": " + f.get(packet));
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
}
@@ -11,221 +11,330 @@ import me.dadus33.chatitem.ChatItem;
public class ReflectionUtils {
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
try {
return clazz.getMethod(methodName, params);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Method getMethodByName(Class<?> clazz, String methodName) {
try {
for(Method m : clazz.getDeclaredMethods())
if(m.getName().equals(methodName))
return m;
for (Method m : clazz.getDeclaredMethods())
if (m.getName().equals(methodName))
return m;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Method getMethod(Class<?> clazz, Class<?> returned, Class<?>... params) {
try {
for(Method m : clazz.getDeclaredMethods()) {
if(returned.equals(m.getReturnType()) && areParamsEquals(m.getParameterTypes(), params))
return m;
}
for (Method m : clazz.getDeclaredMethods()) {
if (returned.equals(m.getReturnType()) && areParamsEquals(m.getParameterTypes(), params))
return m;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean areParamsEquals(Class<?>[] p1, Class<?>[] p2) {
if(p1.length != p2.length)
return false;
for(int i = 0; i < p1.length; i++) {
if(!p1[i].equals(p2[i]))
return false;
}
return true;
if (p1.length != p2.length)
return false;
for (int i = 0; i < p1.length; i++) {
if (!p1[i].equals(p2[i]))
return false;
}
return true;
}
public static Field getField(Class<?> clazz, String... fieldNames){
for(String field : fieldNames) {
try{
Field f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (NoSuchFieldException e) {
// go to next
}
}
ChatItem.getInstance().getLogger().severe("Failed to find field: " + Arrays.asList(fieldNames) + " in class: " + clazz.getCanonicalName());
public static Field getField(Class<?> clazz, String... fieldNames) {
for (String field : fieldNames) {
try {
Field f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (NoSuchFieldException e) {
// go to next
}
}
ChatItem.getInstance().getLogger().severe(
"Failed to find field: " + Arrays.asList(fieldNames) + " in class: " + clazz.getCanonicalName());
return null;
}
public static Object getPrivateField(Object object, String field)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field objectField = object.getClass().getDeclaredField(field);
objectField.setAccessible(true);
return objectField.get(object);
}
public static void setField(Object src, String fieldName, Object value) {
try {
Field field = src.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(src, value);
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean hasObject(Object source, String... field) {
if(source == null)
return false;
for(String fieldName : field) {
try {
source.getClass().getDeclaredField(fieldName);
return true;
} catch (NoSuchFieldException e) {
// ignore because going to next item
}
}
return false;
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested object of the field
*/
public static Object getObject(Object source, String... field) {
if(source == null)
return null;
try {
for(String fieldName : field) {
try {
Field f = source.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(source);
} catch (NoSuchFieldException e) {
// ignore because going to next item
}
}
ChatItem.getInstance().getLogger().severe("Failed to find fields: " + String.join(", ", field) + " in " + source.getClass().getSimpleName());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested field
*/
public static Field getField(Object source, String field) {
if(source == null)
return null;
try {
Field f = source.getClass().getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Call method. Return the method return.
*
* @param source the object where we want to run the method
* @param method the name of the method to call
* @return the return of the method called
*/
public static Object callMethod(Object source, String method) {
try {
return source.getClass().getDeclaredMethod(method).invoke(source);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static <T> T getFirstWith(Object from, Class<T> searchingFor) throws Exception {
return getFirstWith(from, from.getClass(), searchingFor);
}
public static Object getPrivateField(Object object, String field)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
{
/**
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static <T> T getFirstWith(Object from, Class<?> clazz, Class<T> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return (T) f.get(from);
}
}
if(!clazz.getSuperclass().equals(Object.class))
return getFirstWith(from, clazz.getSuperclass(), searchingFor);
return null;
}
Field objectField = object.getClass().getDeclaredField(field);
objectField.setAccessible(true);
return objectField.get(object);
}
public static void setField(Object src, String fieldName, Object value) {
try {
Field field = src.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(src, value);
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean hasObject(Object source, String... field) {
if (source == null)
return false;
for (String fieldName : field) {
try {
source.getClass().getDeclaredField(fieldName);
return true;
} catch (NoSuchFieldException e) {
// ignore because going to next item
}
}
return false;
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested object of the field
*/
public static Object getObject(Object source, String... field) {
if (source == null)
return null;
try {
for (String fieldName : field) {
try {
Field f = source.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(source);
} catch (NoSuchFieldException e) {
// ignore because going to next item
}
}
ChatItem.getInstance().getLogger().severe(
"Failed to find fields: " + String.join(", ", field) + " in " + source.getClass().getSimpleName());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested field
*/
public static Field getField(Object source, String field) {
if (source == null)
return null;
try {
Field f = source.getClass().getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Call method. Return the method return.
*
* @param source the object where we want to run the method
* @param method the name of the method to call
* @return the return of the method called
*/
public static Object callMethod(Object source, String method) {
try {
return source.getClass().getDeclaredMethod(method).invoke(source);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static <T> T getFirstWith(Object from, Class<T> searchingFor) throws Exception {
return getFirstWith(from, from.getClass(), searchingFor);
}
/**
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static <T> T getFirstWith(Object from, Class<?> clazz, Class<T> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return (T) f.get(from);
}
}
if (!clazz.getSuperclass().equals(Object.class))
return getFirstWith(from, clazz.getSuperclass(), searchingFor);
return null;
}
/**
* Get the first field which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static Field getFirstFieldWith(Class<?> clazz, Class<?> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return f;
}
}
return null;
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... params) {
try {
return clazz.getConstructor(params);
} catch (Exception e) {
}
return null;
}
/**
* Get the first field which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static Field getFirstFieldWith(Class<?> clazz, Class<?> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return f;
}
}
return null;
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... params) {
try {
return clazz.getConstructor(params);
} catch (Exception e) {}
return null;
}
}
@@ -6,203 +6,296 @@ import java.util.Objects;
import javax.annotation.Nullable;
/**
* Represents the simplified SemVer schema Negativity uses for its plugin versions.
* Represents the simplified SemVer schema Negativity uses for its plugin
* versions.
*/
public final class SemVer implements Comparable<SemVer> {
private final int major;
private final int minor;
private final int patch;
private final @Nullable Suffix suffix;
public SemVer(int major, int minor, int patch, @Nullable Suffix suffix) {
this.major = major;
this.minor = minor;
this.patch = patch;
this.suffix = suffix;
}
public boolean isNewerThan(SemVer other) {
return this.compareTo(other) > 0;
}
public boolean isOlderThan(SemVer other) {
return this.compareTo(other) < 0;
}
/**
* Slightly different from {@link #equals} in that this method will return
* true if the suffix has the same {@link Suffix#getWeight() weight}
* but not the same {@link Suffix#getText()} text
*/
public boolean isEquivalentTo(SemVer other) {
return this.compareTo(other) == 0;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
public @Nullable Suffix getSuffix() {
return suffix;
}
@Override
public int compareTo(SemVer o) {
int majorDelta = Integer.compare(this.major, o.major);
if (majorDelta != 0) {
return majorDelta;
}
int minorDelta = Integer.compare(this.minor, o.minor);
if (minorDelta != 0) {
return minorDelta;
}
int patchDelta = Integer.compare(this.patch, o.patch);
if (patchDelta != 0) {
return patchDelta;
}
if (this.suffix != null) {
return o.suffix != null ? this.suffix.compareTo(o.suffix) : -1;
}
if (o.suffix != null) {
return 1;
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SemVer semVer = (SemVer) o;
return major == semVer.major && minor == semVer.minor && patch == semVer.patch && Objects.equals(suffix, semVer.suffix);
}
@Override
public int hashCode() {
return Objects.hash(major, minor, patch, suffix);
}
@Override
public String toString() {
return "SemVer{major=" + major + ", minor=" + minor + ", patch=" + patch + ", suffix=" + suffix + '}';
}
public String toFormattedString() {
if (suffix == null) {
if(patch > 0)
return major + "." + minor + (patch > 0 ? "." + patch : "");
}
return major + "." + minor + (patch > 0 ? "." + patch : "") + (suffix == null ? "" : "-" + suffix.getText());
}
public static @Nullable SemVer parse(String text) {
if (text == null || text.isEmpty()) {
return null;
}
String[] suffixSplit = text.split("-", 2);
Suffix suffix = null;
if (suffixSplit.length > 1) {
suffix = Suffix.of(suffixSplit[1]);
}
String[] parts = suffixSplit[0].split("\\.");
int major;
try {
major = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
return null;
}
int minor = 0;
if (parts.length > 1) {
try {
minor = Integer.parseInt(parts[1]);
} catch (NumberFormatException ignore) {
}
}
int patch = 0;
if (parts.length > 2) {
try {
patch = Integer.parseInt(parts[2]);
} catch (NumberFormatException ignore) {
}
}
return new SemVer(major, minor, patch, suffix);
}
public static final class Suffix implements Comparable<Suffix> {
public static final Suffix SNAPSHOT = new Suffix(0, "SNAPSHOT");
public static final Suffix ALPHA = new Suffix(1, "ALPHA");
public static final Suffix BETA = new Suffix(2, "BETA");
public static final Suffix GAMMA = new Suffix(3, "GAMMA");
public static final Suffix DELTA = new Suffix(4, "DELTA");
private final int weight;
private final String text;
public Suffix(int weight, String text) {
this.weight = weight;
this.text = text;
}
public int getWeight() {
return weight;
}
public String getText() {
return text;
}
@Override
public int compareTo(Suffix o) {
return Integer.compare(this.weight, o.weight);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Suffix suffix = (Suffix) o;
return weight == suffix.weight && text.equals(suffix.text);
}
@Override
public int hashCode() {
return Objects.hash(weight, text);
}
@Override
public String toString() {
return "Suffix{weight=" + weight + ", text='" + text + "'}";
}
public static Suffix of(String text) {
String uppercaseText = text.toUpperCase(Locale.ROOT);
switch (uppercaseText) {
case "SNAPSHOT":
return SNAPSHOT;
case "ALPHA":
return ALPHA;
case "BETA":
return BETA;
case "GAMMA":
return GAMMA;
case "DELTA":
return DELTA;
default:
return new Suffix(-1, uppercaseText);
}
}
}
private final int major;
private final int minor;
private final int patch;
private final @Nullable Suffix suffix;
public SemVer(int major, int minor, int patch, @Nullable Suffix suffix) {
this.major = major;
this.minor = minor;
this.patch = patch;
this.suffix = suffix;
}
public boolean isNewerThan(SemVer other) {
return this.compareTo(other) > 0;
}
public boolean isOlderThan(SemVer other) {
return this.compareTo(other) < 0;
}
/**
* Slightly different from {@link #equals} in that this method will return true
* if the suffix has the same {@link Suffix#getWeight() weight} but not the same
* {@link Suffix#getText()} text
*/
public boolean isEquivalentTo(SemVer other) {
return this.compareTo(other) == 0;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
public @Nullable Suffix getSuffix() {
return suffix;
}
@Override
public int compareTo(SemVer o) {
int majorDelta = Integer.compare(this.major, o.major);
if (majorDelta != 0) {
return majorDelta;
}
int minorDelta = Integer.compare(this.minor, o.minor);
if (minorDelta != 0) {
return minorDelta;
}
int patchDelta = Integer.compare(this.patch, o.patch);
if (patchDelta != 0) {
return patchDelta;
}
if (this.suffix != null) {
return o.suffix != null ? this.suffix.compareTo(o.suffix) : -1;
}
if (o.suffix != null) {
return 1;
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
SemVer semVer = (SemVer) o;
return major == semVer.major && minor == semVer.minor && patch == semVer.patch
&& Objects.equals(suffix, semVer.suffix);
}
@Override
public int hashCode() {
return Objects.hash(major, minor, patch, suffix);
}
@Override
public String toString() {
return "SemVer{major=" + major + ", minor=" + minor + ", patch=" + patch + ", suffix=" + suffix + '}';
}
public String toFormattedString() {
if (suffix == null) {
if (patch > 0)
return major + "." + minor + (patch > 0 ? "." + patch : "");
}
return major + "." + minor + (patch > 0 ? "." + patch : "") + (suffix == null ? "" : "-" + suffix.getText());
}
public static @Nullable SemVer parse(String text) {
if (text == null || text.isEmpty()) {
return null;
}
String[] suffixSplit = text.split("-", 2);
Suffix suffix = null;
if (suffixSplit.length > 1) {
suffix = Suffix.of(suffixSplit[1]);
}
String[] parts = suffixSplit[0].split("\\.");
int major;
try {
major = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
return null;
}
int minor = 0;
if (parts.length > 1) {
try {
minor = Integer.parseInt(parts[1]);
} catch (NumberFormatException ignore) {
}
}
int patch = 0;
if (parts.length > 2) {
try {
patch = Integer.parseInt(parts[2]);
} catch (NumberFormatException ignore) {
}
}
return new SemVer(major, minor, patch, suffix);
}
public static final class Suffix implements Comparable<Suffix> {
public static final Suffix SNAPSHOT = new Suffix(0, "SNAPSHOT");
public static final Suffix ALPHA = new Suffix(1, "ALPHA");
public static final Suffix BETA = new Suffix(2, "BETA");
public static final Suffix GAMMA = new Suffix(3, "GAMMA");
public static final Suffix DELTA = new Suffix(4, "DELTA");
private final int weight;
private final String text;
public Suffix(int weight, String text) {
this.weight = weight;
this.text = text;
}
public int getWeight() {
return weight;
}
public String getText() {
return text;
}
@Override
public int compareTo(Suffix o) {
return Integer.compare(this.weight, o.weight);
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Suffix suffix = (Suffix) o;
return weight == suffix.weight && text.equals(suffix.text);
}
@Override
public int hashCode() {
return Objects.hash(weight, text);
}
@Override
public String toString() {
return "Suffix{weight=" + weight + ", text='" + text + "'}";
}
public static Suffix of(String text) {
String uppercaseText = text.toUpperCase(Locale.ROOT);
switch (uppercaseText) {
case "SNAPSHOT":
return SNAPSHOT;
case "ALPHA":
return ALPHA;
case "BETA":
return BETA;
case "GAMMA":
return GAMMA;
case "DELTA":
return DELTA;
default:
return new Suffix(-1, uppercaseText);
}
}
}
}
+357 -243
View File
@@ -42,260 +42,374 @@ import net.md_5.bungee.api.chat.hover.content.Text;
public class Utils {
public static final boolean IS_PAPER = isClassExist("io.papermc.paper.event.player.AsyncChatEvent");
private static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
private static final TreeMap<Integer, String> ROMAN_KEYS = new TreeMap<>();
private static final HashMap<String, String> ENCHANTS_NAMES = new HashMap<>();
public static final boolean IS_PAPER = isClassExist("io.papermc.paper.event.player.AsyncChatEvent");
private static final Pattern UUID_PATTERN = Pattern
.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
private static final TreeMap<Integer, String> ROMAN_KEYS = new TreeMap<>();
private static final HashMap<String, String> ENCHANTS_NAMES = new HashMap<>();
static {
ROMAN_KEYS.put(1000, "M");
ROMAN_KEYS.put(900, "CM");
ROMAN_KEYS.put(500, "D");
ROMAN_KEYS.put(400, "CD");
ROMAN_KEYS.put(100, "C");
ROMAN_KEYS.put(90, "XC");
ROMAN_KEYS.put(50, "L");
ROMAN_KEYS.put(40, "XL");
ROMAN_KEYS.put(10, "X");
ROMAN_KEYS.put(9, "IX");
ROMAN_KEYS.put(5, "V");
ROMAN_KEYS.put(4, "IV");
ROMAN_KEYS.put(1, "I");
static {
ENCHANTS_NAMES.put("ARROW_DAMAGE", "Power");
ENCHANTS_NAMES.put("ARROW_FIRE", "Flame");
ENCHANTS_NAMES.put("ARROW_INFINITE", "Infinity");
ENCHANTS_NAMES.put("ARROW_KNOCKBACK", "Punch");
ENCHANTS_NAMES.put("BINDING_CURSE", "Curse of Binding");
ENCHANTS_NAMES.put("DAMAGE_ALL", "Sharpness");
ENCHANTS_NAMES.put("DAMAGE_ARTHROPODS", "Bane of Arthropods");
ENCHANTS_NAMES.put("DAMAGE_UNDEAD", "Smite");
ENCHANTS_NAMES.put("DEPTH_STRIDER", "Depth Strider");
ENCHANTS_NAMES.put("DIG_SPEED", "Efficiency");
ENCHANTS_NAMES.put("DURABILITY", "Unbreaking");
ENCHANTS_NAMES.put("FIRE_ASPECT", "Fire Aspect");
ENCHANTS_NAMES.put("FROST_WALKER", "Frost Walker");
ENCHANTS_NAMES.put("KNOCKBACK", "Knockback");
ENCHANTS_NAMES.put("LOOT_BONUS_BLOCKS", "Fortune");
ENCHANTS_NAMES.put("LOOT_BONUS_MOBS", "Looting");
ENCHANTS_NAMES.put("LUCK", "Luck of the Sea");
ENCHANTS_NAMES.put("LURE", "Lure");
ENCHANTS_NAMES.put("MENDING", "Mending");
ENCHANTS_NAMES.put("OXYGEN", "Respiration");
ENCHANTS_NAMES.put("PROTECTION_ENVIRONMENTAL", "Protection");
ENCHANTS_NAMES.put("PROTECTION_EXPLOSIONS", "Blast Protection");
ENCHANTS_NAMES.put("PROTECTION_FALL", "Feather Falling");
ENCHANTS_NAMES.put("PROTECTION_FIRE", "Fire Protection");
ENCHANTS_NAMES.put("PROTECTION_PROJECTILE", "Projectile Protection");
ENCHANTS_NAMES.put("SILK_TOUCH", "Silk Touch");
ENCHANTS_NAMES.put("SWEEPING_EDGE", "Sweeping Edge");
ENCHANTS_NAMES.put("THORNS", "Thorns");
ENCHANTS_NAMES.put("VANISHING_CURSE", "Cure of Vanishing");
ENCHANTS_NAMES.put("WATER_WORKER", "Aqua Affinity");
}
ROMAN_KEYS.put(1000, "M");
ROMAN_KEYS.put(900, "CM");
ROMAN_KEYS.put(500, "D");
ROMAN_KEYS.put(400, "CD");
ROMAN_KEYS.put(100, "C");
ROMAN_KEYS.put(90, "XC");
ROMAN_KEYS.put(50, "L");
ROMAN_KEYS.put(40, "XL");
ROMAN_KEYS.put(10, "X");
ROMAN_KEYS.put(9, "IX");
ROMAN_KEYS.put(5, "V");
ROMAN_KEYS.put(4, "IV");
ROMAN_KEYS.put(1, "I");
public static List<Player> getOnlinePlayers() {
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
ENCHANTS_NAMES.put("ARROW_DAMAGE", "Power");
ENCHANTS_NAMES.put("ARROW_FIRE", "Flame");
ENCHANTS_NAMES.put("ARROW_INFINITE", "Infinity");
ENCHANTS_NAMES.put("ARROW_KNOCKBACK", "Punch");
ENCHANTS_NAMES.put("BINDING_CURSE", "Curse of Binding");
ENCHANTS_NAMES.put("DAMAGE_ALL", "Sharpness");
ENCHANTS_NAMES.put("DAMAGE_ARTHROPODS", "Bane of Arthropods");
ENCHANTS_NAMES.put("DAMAGE_UNDEAD", "Smite");
ENCHANTS_NAMES.put("DEPTH_STRIDER", "Depth Strider");
ENCHANTS_NAMES.put("DIG_SPEED", "Efficiency");
ENCHANTS_NAMES.put("DURABILITY", "Unbreaking");
ENCHANTS_NAMES.put("FIRE_ASPECT", "Fire Aspect");
ENCHANTS_NAMES.put("FROST_WALKER", "Frost Walker");
ENCHANTS_NAMES.put("KNOCKBACK", "Knockback");
ENCHANTS_NAMES.put("LOOT_BONUS_BLOCKS", "Fortune");
ENCHANTS_NAMES.put("LOOT_BONUS_MOBS", "Looting");
ENCHANTS_NAMES.put("LUCK", "Luck of the Sea");
ENCHANTS_NAMES.put("LURE", "Lure");
ENCHANTS_NAMES.put("MENDING", "Mending");
ENCHANTS_NAMES.put("OXYGEN", "Respiration");
ENCHANTS_NAMES.put("PROTECTION_ENVIRONMENTAL", "Protection");
ENCHANTS_NAMES.put("PROTECTION_EXPLOSIONS", "Blast Protection");
ENCHANTS_NAMES.put("PROTECTION_FALL", "Feather Falling");
ENCHANTS_NAMES.put("PROTECTION_FIRE", "Fire Protection");
ENCHANTS_NAMES.put("PROTECTION_PROJECTILE", "Projectile Protection");
ENCHANTS_NAMES.put("SILK_TOUCH", "Silk Touch");
ENCHANTS_NAMES.put("SWEEPING_EDGE", "Sweeping Edge");
ENCHANTS_NAMES.put("THORNS", "Thorns");
ENCHANTS_NAMES.put("VANISHING_CURSE", "Cure of Vanishing");
ENCHANTS_NAMES.put("WATER_WORKER", "Aqua Affinity");
public static String toRoman(int number) {
int l = ROMAN_KEYS.floorKey(number);
if (number == l) {
return ROMAN_KEYS.get(number);
}
return ROMAN_KEYS.get(l) + toRoman(number - l);
}
}
@SuppressWarnings("deprecation")
public static String getEnchantName(Enchantment enchant) {
String name = ENCHANTS_NAMES.get(enchant.getName());
if (name == null) {
ChatItem.getInstance().getLogger()
.warning("Unknown enchant " + enchant.getName() + ". Please report this to Elikill58.");
}
return name;
}
public static List<Player> getOnlinePlayers() {
public static String getFromURL(String urlName) {
ChatItem pl = ChatItem.getInstance();
try {
URL url = new URL(urlName);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "ChatItem");
connection.setDoOutput(true);
connection.setRequestMethod("GET");
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder content = new StringBuilder();
String input;
while ((input = br.readLine()) != null)
content.append(input);
br.close();
return content.toString();
} catch (SocketTimeoutException e) {
pl.getLogger().info("Failed to access to " + urlName + " (Reason: timed out).");
} catch (UnknownHostException | MalformedURLException e) {
pl.getLogger().info("Could not use the internet connection to check for update or send stats");
} catch (ConnectException e) {
pl.getLogger().warning("Cannot connect to " + urlName + " (Reason: " + e.getMessage() + ").");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
return new ArrayList<>(Bukkit.getOnlinePlayers());
public static int indexOf(CharSequence s, CharSequence searched, int i) {
return s.toString().indexOf(searched.toString(), i);
}
}
public static boolean isEmpty(CharSequence s) {
return (s == null || s.length() == 0);
}
public static String toRoman(int number) {
public static int countMatches(CharSequence str, CharSequence searched) {
if (isEmpty(str) || isEmpty(searched))
return 0;
byte b = 0;
int i = 0;
while ((i = indexOf(str, searched, i)) != -1) {
b++;
i += searched.length();
}
return b;
}
public static boolean isBeforeChatJson(Player p) {
return !PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p).isNewerOrEquals(Version.V1_16) && Version.getVersion().isNewerOrEquals(Version.V1_16);
}
@SuppressWarnings("deprecation")
public static HoverEvent createItemHover(ItemStack item, Player to) {
if(isBeforeChatJson(to)) {
ComponentBuilder comp = new ComponentBuilder("");
for(String line : ChatManager.getMaxLinesFromItem(to, item))
comp.append(line + "\n");
return createTextHover(comp.create());
}
if(Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM, new Item(item.getType().getKey().getKey(), item.getAmount(), ItemTag.ofNbt(PacketUtils.getNbtTag(item))));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM, new ComponentBuilder(ChatItem.getPlatform().stringifyItem(item)).create());
}
}
int l = ROMAN_KEYS.floorKey(number);
if (number == l) {
public static HoverEvent createTextHover(String text) {
return createTextHover(new ComponentBuilder(text).create());
}
@SuppressWarnings("deprecation")
public static HoverEvent createTextHover(BaseComponent[] comps) {
if(Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(comps));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, comps);
}
}
public static ClickEvent createRunCommand(String command) {
return new ClickEvent(ClickEvent.Action.RUN_COMMAND, command);
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isByte(String s) {
try {
Byte.parseByte(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isShort(String s) {
try {
Short.parseShort(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isLong(String s) {
try {
Long.parseLong(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isUUID(String s) {
return s != null && UUID_PATTERN.matcher(s.toLowerCase()).matches();
}
return ROMAN_KEYS.get(number);
public static YamlConfiguration copyLoadFile(File folder, String filename, String baseFile) {
File legacyConfig = new File(folder, filename);
if(!legacyConfig.exists())
copyFile(baseFile, legacyConfig);
return YamlConfiguration.loadConfiguration(legacyConfig);
}
public static void copyFile(String fileName, File dir) {
try (InputStream stream = ChatItem.getInstance().getResource(fileName)) {
Files.copy(stream, dir.toPath());
} catch(Exception e) {
e.printStackTrace();
}
}
public static String arrayToString(Object[] a) {
StringJoiner sj = new StringJoiner(", ");
for(Object o : a)
sj.add(o == null ? "null" : o.toString());
return sj.toString();
}
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
return ROMAN_KEYS.get(l) + toRoman(number - l);
}
@SuppressWarnings("deprecation")
public static String getEnchantName(Enchantment enchant) {
String name = ENCHANTS_NAMES.get(enchant.getName());
if (name == null) {
ChatItem.getInstance().getLogger()
.warning("Unknown enchant " + enchant.getName() + ". Please report this to Elikill58.");
}
return name;
}
public static String getFromURL(String urlName) {
ChatItem pl = ChatItem.getInstance();
try {
URL url = new URL(urlName);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "ChatItem");
connection.setDoOutput(true);
connection.setRequestMethod("GET");
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder content = new StringBuilder();
String input;
while ((input = br.readLine()) != null)
content.append(input);
br.close();
return content.toString();
} catch (SocketTimeoutException e) {
pl.getLogger().info("Failed to access to " + urlName + " (Reason: timed out).");
} catch (UnknownHostException | MalformedURLException e) {
pl.getLogger().info("Could not use the internet connection to check for update or send stats");
} catch (ConnectException e) {
pl.getLogger().warning("Cannot connect to " + urlName + " (Reason: " + e.getMessage() + ").");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static int indexOf(CharSequence s, CharSequence searched, int i) {
return s.toString().indexOf(searched.toString(), i);
}
public static boolean isEmpty(CharSequence s) {
return (s == null || s.length() == 0);
}
public static int countMatches(CharSequence str, CharSequence searched) {
if (isEmpty(str) || isEmpty(searched))
return 0;
byte b = 0;
int i = 0;
while ((i = indexOf(str, searched, i)) != -1) {
b++;
i += searched.length();
}
return b;
}
public static boolean isBeforeChatJson(Player p) {
return !PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p).isNewerOrEquals(Version.V1_16)
&& Version.getVersion().isNewerOrEquals(Version.V1_16);
}
@SuppressWarnings("deprecation")
public static HoverEvent createItemHover(ItemStack item, Player to) {
if (isBeforeChatJson(to)) {
ComponentBuilder comp = new ComponentBuilder("");
for (String line : ChatManager.getMaxLinesFromItem(to, item))
comp.append(line + "\n");
return createTextHover(comp.create());
}
if (Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM, new Item(item.getType().getKey().getKey(),
item.getAmount(), ItemTag.ofNbt(PacketUtils.getNbtTag(item))));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_ITEM,
new ComponentBuilder(ChatItem.getPlatform().stringifyItem(item)).create());
}
}
public static HoverEvent createTextHover(String text) {
return createTextHover(new ComponentBuilder(text).create());
}
@SuppressWarnings("deprecation")
public static HoverEvent createTextHover(BaseComponent[] comps) {
if (Version.getVersion().isNewerOrEquals(Version.V1_13)) {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(comps));
} else {
return new HoverEvent(HoverEvent.Action.SHOW_TEXT, comps);
}
}
public static ClickEvent createRunCommand(String command) {
return new ClickEvent(ClickEvent.Action.RUN_COMMAND, command);
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isByte(String s) {
try {
Byte.parseByte(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isShort(String s) {
try {
Short.parseShort(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isLong(String s) {
try {
Long.parseLong(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isUUID(String s) {
return s != null && UUID_PATTERN.matcher(s.toLowerCase()).matches();
}
public static YamlConfiguration copyLoadFile(File folder, String filename, String baseFile) {
File legacyConfig = new File(folder, filename);
if (!legacyConfig.exists())
copyFile(baseFile, legacyConfig);
return YamlConfiguration.loadConfiguration(legacyConfig);
}
public static void copyFile(String fileName, File dir) {
try (InputStream stream = ChatItem.getInstance().getResource(fileName)) {
Files.copy(stream, dir.toPath());
} catch (Exception e) {
e.printStackTrace();
}
}
public static String arrayToString(Object[] a) {
StringJoiner sj = new StringJoiner(", ");
for (Object o : a)
sj.add(o == null ? "null" : o.toString());
return sj.toString();
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
public static String cleanStr(String s) {
return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
}
/**
* In API versions 1.20.6 and earlier, InventoryView is a class. In versions
* 1.21 and later, it is an interface. This method uses reflection to get the
* top Inventory object from the InventoryView associated with an
* InventoryEvent, to avoid runtime errors.
*
* @param event The generic InventoryEvent with an InventoryView to inspect.
* @return The top Inventory object from the event's InventoryView.
*/
public static Inventory getTopInventory(InventoryEvent event) {
try {
Object view = event.getView();
if (view == null)
return null;
Method getTopInventory = view.getClass().getMethod("getTopInventory");
getTopInventory.setAccessible(true);
return (Inventory) getTopInventory.invoke(view);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static String cleanStr(String s) {
return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
}
/**
* In API versions 1.20.6 and earlier, InventoryView is a class.
* In versions 1.21 and later, it is an interface.
* This method uses reflection to get the top Inventory object from the
* InventoryView associated with an InventoryEvent, to avoid runtime errors.
* @param event The generic InventoryEvent with an InventoryView to inspect.
* @return The top Inventory object from the event's InventoryView.
*/
public static Inventory getTopInventory(InventoryEvent event) {
try {
Object view = event.getView();
if(view == null)
return null;
Method getTopInventory = view.getClass().getMethod("getTopInventory");
getTopInventory.setAccessible(true);
return (Inventory) getTopInventory.invoke(view);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
@@ -5,82 +5,97 @@ import java.net.InetSocketAddress;
import me.dadus33.chatitem.ChatItem;
public enum Version {
// http://wiki.vg/Protocol_version_numbers
UNSUPPORTED(0, 5, 7),
V1_8(6, 47, 8),
V1_9(49, 110, 9), // 1.9.X - Starts with 49 as 48 was an april fools update
V1_10(201, 210, 10), // 1.10.X - Starts with 201 because why not.
V1_11(301, 316, 11),
V1_12(317, 340, 12),
V1_13(341, 440, 13),
V1_14(441, 500, 14),
V1_15(550, 578, 15),
V1_16(700, 754, 16),
V1_17(755, 756, 17),
V1_18(757, 758, 18),
V1_19(759, 762, 19),
V1_20(763, 765, 20),
V1_20_6(766, 766, 20.6),
V1_21(767, 1000, 21),
HIGHER(Integer.MAX_VALUE, -1, Integer.MAX_VALUE);
// Latest version should always have the upper limit set to Integer.MAX_VALUE so
// I don't have to update the plugin for every minor protocol change
// http://wiki.vg/Protocol_version_numbers
UNSUPPORTED(0, 5, 7), V1_8(6, 47, 8), V1_9(49, 110, 9), // 1.9.X - Starts with 49 as 48 was an april fools update
V1_10(201, 210, 10), // 1.10.X - Starts with 201 because why not.
V1_11(301, 316, 11), V1_12(317, 340, 12), V1_13(341, 440, 13), V1_14(441, 500, 14), V1_15(550, 578, 15),
V1_16(700, 754, 16), V1_17(755, 756, 17), V1_18(757, 758, 18), V1_19(759, 762, 19), V1_20(763, 765, 20),
V1_20_6(766, 766, 20.6), V1_21(767, 1000, 21), HIGHER(Integer.MAX_VALUE, -1, Integer.MAX_VALUE);
public final int MIN_VER;
public final int MAX_VER;
public final double index; // Represents how new the version is (0 - extremely old)
// Latest version should always have the upper limit set to Integer.MAX_VALUE so
// I don't have to update the plugin for every minor protocol change
private static final Version SERVER_VERSION = ChatItem.getPlatform().getMinecraftVersion();
public final int MIN_VER;
public final int MAX_VER;
public final double index; // Represents how new the version is (0 - extremely old)
Version(int min, int max, double index) {
this.MIN_VER = min;
this.MAX_VER = max;
this.index = index;
}
public boolean isNewerOrEquals(Version other) {
return index >= other.index;
}
private static final Version SERVER_VERSION = ChatItem.getPlatform().getMinecraftVersion();
public boolean isNewerThan(Version other) {
return index > other.index;
}
Version(int min, int max, double index) {
public static Version getVersionByName(String name) {
try {
return Version.valueOf(name.toUpperCase());
} catch (Exception e) {}
for (Version v : Version.values())
if (name.toLowerCase().startsWith(v.name().toLowerCase()))
return v;
return HIGHER;
}
this.MIN_VER = min;
this.MAX_VER = max;
this.index = index;
public static Version getVersion(int protocolVersion) {
return getVersion(protocolVersion, HIGHER);
}
}
public static Version getVersion(int protocolVersion, Version def) {
for (Version ver : Version.values()) {
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
return ver;
}
}
ChatItem.debug("Failed to find version for protocol " + protocolVersion);
return def;
}
public boolean isNewerOrEquals(Version other) {
public static Version getVersion() {
return SERVER_VERSION;
}
return index >= other.index;
}
public boolean isNewerThan(Version other) {
return index > other.index;
}
public static Version getVersionByName(String name) {
try {
return Version.valueOf(name.toUpperCase());
} catch (Exception e) {
}
for (Version v : Version.values())
if (name.toLowerCase().startsWith(v.name().toLowerCase()))
return v;
return HIGHER;
}
public static Version getVersion(int protocolVersion) {
return getVersion(protocolVersion, HIGHER);
}
public static Version getVersion(int protocolVersion, Version def) {
for (Version ver : Version.values()) {
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
return ver;
}
}
ChatItem.debug("Failed to find version for protocol " + protocolVersion);
return def;
}
public static Version getVersion() {
return SERVER_VERSION;
}
public static String stringifyAdress(InetSocketAddress address) {
if (address == null)
return "0.0.0.0:0";
String port = String.valueOf(address.getPort());
String ip = address.getAddress().getHostAddress();
return ip + ":" + port;
}
public static String stringifyAdress(InetSocketAddress address) {
if(address == null)
return "0.0.0.0:0";
String port = String.valueOf(address.getPort());
String ip = address.getAddress().getHostAddress();
return ip + ":" + port;
}
}